From ea3d51de6adcd26411d8220cd9954e753cb9b1a9 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Mon, 1 Oct 2018 15:23:28 -0400 Subject: [PATCH 001/372] Script to start the next ehcache version --- .../docs/asciidoc/user/getting-started.adoc | 3 +- docs/src/docs/asciidoc/user/index.adoc | 5 +- docs/src/docs/asciidoc/user/xsds.adoc | 4 ++ start_next_version.sh | 47 +++++++++++++++++++ 4 files changed, 56 insertions(+), 3 deletions(-) create mode 100755 start_next_version.sh diff --git a/docs/src/docs/asciidoc/user/getting-started.adoc b/docs/src/docs/asciidoc/user/getting-started.adoc index ee1534dd6a..77d8a48578 100644 --- a/docs/src/docs/asciidoc/user/getting-started.adoc +++ b/docs/src/docs/asciidoc/user/getting-started.adoc @@ -1,6 +1,7 @@ --- +version: 3.6 --- -= Ehcache 3.6 Documentation += Ehcache {{page.version}} Documentation ifndef::sourcedir36[] include::common.adoc[] endif::sourcedir36[] diff --git a/docs/src/docs/asciidoc/user/index.adoc b/docs/src/docs/asciidoc/user/index.adoc index 027ac12425..f5fda9f8ab 100644 --- a/docs/src/docs/asciidoc/user/index.adoc +++ b/docs/src/docs/asciidoc/user/index.adoc @@ -1,6 +1,7 @@ --- +version: 3.6 --- -= Ehcache 3.6 Documentation Overview += Ehcache {{page.version}} Documentation Overview ifndef::sourcedir36[] include::common.adoc[] endif::sourcedir36[] @@ -11,7 +12,7 @@ endif::notBuildingForSite[] == Table of Contents -The Table of Contents provides an overview of the Ehcache 3.6 documentation on this site. +The Table of Contents provides an overview of the Ehcache {{page.version}} documentation on this site. Each topic below corresponds to a menu item at the left. === Basic Topics diff --git a/docs/src/docs/asciidoc/user/xsds.adoc b/docs/src/docs/asciidoc/user/xsds.adoc index 1c2e425821..47f800b61d 100644 --- a/docs/src/docs/asciidoc/user/xsds.adoc +++ b/docs/src/docs/asciidoc/user/xsds.adoc @@ -19,6 +19,7 @@ endif::notBuildingForSite[] ** Location for 3.4: `http://www.ehcache.org/schema/ehcache-core-3.4.xsd` ** Location for 3.5: `http://www.ehcache.org/schema/ehcache-core-3.5.xsd` ** Location for 3.6: `http://www.ehcache.org/schema/ehcache-core-3.6.xsd` +// needle_for_core_xsd * JSR-107 namespace: `http://www.ehcache.org/v3/jsr107` ** Location for 3.0: `http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd` ** Location for 3.1: `http://www.ehcache.org/schema/ehcache-107-ext-3.1.xsd` @@ -27,6 +28,7 @@ endif::notBuildingForSite[] ** Location for 3.4: `http://www.ehcache.org/schema/ehcache-107-ext-3.4.xsd` ** Location for 3.5: `http://www.ehcache.org/schema/ehcache-107-ext-3.5.xsd` ** Location for 3.6: `http://www.ehcache.org/schema/ehcache-107-ext-3.6.xsd` +// needle_for_107_xsd * Transactions namespace: `http://www.ehcache.org/v3/tx` ** Location for 3.0: `http://www.ehcache.org/schema/ehcache-tx-ext-3.0.xsd` ** Location for 3.1: `http://www.ehcache.org/schema/ehcache-tx-ext-3.1.xsd` @@ -35,6 +37,7 @@ endif::notBuildingForSite[] ** Location for 3.4: `http://www.ehcache.org/schema/ehcache-tx-ext-3.4.xsd` ** Location for 3.5: `http://www.ehcache.org/schema/ehcache-tx-ext-3.5.xsd` ** Location for 3.6: `http://www.ehcache.org/schema/ehcache-tx-ext-3.6.xsd` +// needle_for_transactions_xsd * Clustering namespace: `http://www.ehcache.org/v3/clustered` ** Location for 3.1: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.1.xsd` ** Location for 3.2: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.2.xsd` @@ -42,6 +45,7 @@ endif::notBuildingForSite[] ** Location for 3.4: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.4.xsd` ** Location for 3.5: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.5.xsd` ** Location for 3.6: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.6.xsd` +// needle_for_clustered_xsd === Usage example diff --git a/start_next_version.sh b/start_next_version.sh new file mode 100755 index 0000000000..325a68cc63 --- /dev/null +++ b/start_next_version.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +### +# Call this script when starting a new major or minor version. +# It will create the branch for the previous version and update all the required files to start the new version. +# +# See https://github.com/ehcache/ehcache3/wiki/dev.release for details. +# +### + +# to exit in case of error +set -e +# to see what's going on +set -v + +function pause { + echo + read -p "Press [enter] to continue" +} + +echo 'Welcome to the Ehcache next version wizard' +echo +echo 'This wizard will guide you through moving from a major.minor version to another. Some steps will be performed automatically, some will require your help' +echo + +read -e -p "Enter the next version (x.y): " version + +short_version=${version//[.]/} + +echo "Upgrading gradle.properties to ${version}" +sed -i '' "s/ehcacheVersion = .*/ehcacheVersion = ${version}-SNAPSHOT/" gradle.properties + +echo "Update docs sourcedir to sourcedir${short_version}" +find docs -type f -name '*.adoc' -exec sed -i '' "s/sourcedir[0-9][0-9]/sourcedir${short_version}/g" {} \; + +echo "Update version in site content to ${version}" +find docs -type f -name '*.adoc' -exec sed -i '' "s/version: [0-9]\.[0-9]/version: ${version}/" {} \; + +echo "Add new XSDs for ${version}" +sed -i '' "s/\/\/ needle_for_core_xsd/** Location for ${version}: \`http:\/\/www.ehcache.org\/schema\/ehcache-core-${version}.xsd\`\\ +\/\/ needle_for_core_xsd/" docs/src/docs/asciidoc/user/xsds.adoc +sed -i '' "s/\/\/ needle_for_107_xsd/** Location for ${version}: \`http:\/\/www.ehcache.org\/schema\/ehcache-107-ext-${version}.xsd\`\\ +\/\/ needle_for_107_xsd/" docs/src/docs/asciidoc/user/xsds.adoc +sed -i '' "s/\/\/ needle_for_transactions_xsd/** Location for ${version}: \`http:\/\/www.ehcache.org\/schema\/ehcache-tx-ext-${version}.xsd\`\\ +\/\/ needle_for_transactions_xsd/" docs/src/docs/asciidoc/user/xsds.adoc +sed -i '' "s/\/\/ needle_for_clustered_xsd/** Location for ${version}: \`http:\/\/www.ehcache.org\/schema\/ehcache-clustered-ext-${version}.xsd\`\\ +\/\/ needle_for_clustered_xsd/" docs/src/docs/asciidoc/user/xsds.adoc From ae62f676f27b0f2a9aabd069865d564cdc10f89d Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Mon, 1 Oct 2018 15:27:03 -0400 Subject: [PATCH 002/372] Add the missing dash to JSR 107 XSD --- .../jsr107/internal/Jsr107CacheConfigurationParser.java | 2 +- .../jsr107/internal/Jsr107ServiceConfigurationParser.java | 2 +- .../resources/{ehcache-107ext.xsd => ehcache-107-ext.xsd} | 0 107/src/test/resources/ehcache-107-listeners.xml | 4 ++-- 107/src/test/resources/ehcache-107-mbeans-cache-config.xml | 4 ++-- 107/src/test/resources/ehcache-107-mbeans-template-config.xml | 4 ++-- 107/src/test/resources/ehcache-107-serializer.xml | 4 ++-- 107/src/test/resources/ehcache-107-stats.xml | 4 ++-- 107/src/test/resources/ehcache-107.xml | 4 ++-- docs/src/docs/asciidoc/user/xsds.adoc | 2 +- .../src/test/resources/org/ehcache/osgi/ehcache-107-osgi.xml | 4 ++-- 11 files changed, 17 insertions(+), 17 deletions(-) rename 107/src/main/resources/{ehcache-107ext.xsd => ehcache-107-ext.xsd} (100%) diff --git a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java b/107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java index 835b2a36f6..fd01b7b146 100644 --- a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java +++ b/107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java @@ -38,7 +38,7 @@ public class Jsr107CacheConfigurationParser implements CacheServiceConfigurationParser { private static final URI NAMESPACE = URI.create("http://www.ehcache.org/v3/jsr107"); - private static final URL XML_SCHEMA = Jsr107CacheConfigurationParser.class.getResource("/ehcache-107ext.xsd"); + private static final URL XML_SCHEMA = Jsr107CacheConfigurationParser.class.getResource("/ehcache-107-ext.xsd"); private static final String MANAGEMENT_ENABLED_ATTRIBUTE = "enable-management"; private static final String STATISTICS_ENABLED_ATTRIBUTE = "enable-statistics"; diff --git a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java b/107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java index a80c67bf5d..d465058dd6 100644 --- a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java +++ b/107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java @@ -42,7 +42,7 @@ public class Jsr107ServiceConfigurationParser implements CacheManagerServiceConfigurationParser { private static final URI NAMESPACE = URI.create("http://www.ehcache.org/v3/jsr107"); - private static final URL XML_SCHEMA = Jsr107ServiceConfigurationParser.class.getResource("/ehcache-107ext.xsd"); + private static final URL XML_SCHEMA = Jsr107ServiceConfigurationParser.class.getResource("/ehcache-107-ext.xsd"); private static final String ENABLE_MANAGEMENT_ALL_ATTRIBUTE = "enable-management"; private static final String JSR_107_COMPLIANT_ATOMICS_ATTRIBUTE = "jsr-107-compliant-atomics"; private static final String ENABLE_STATISTICS_ALL_ATTRIBUTE = "enable-statistics"; diff --git a/107/src/main/resources/ehcache-107ext.xsd b/107/src/main/resources/ehcache-107-ext.xsd similarity index 100% rename from 107/src/main/resources/ehcache-107ext.xsd rename to 107/src/main/resources/ehcache-107-ext.xsd diff --git a/107/src/test/resources/ehcache-107-listeners.xml b/107/src/test/resources/ehcache-107-listeners.xml index a32743e097..27cd72c308 100644 --- a/107/src/test/resources/ehcache-107-listeners.xml +++ b/107/src/test/resources/ehcache-107-listeners.xml @@ -20,7 +20,7 @@ xmlns='http://www.ehcache.org/v3' xmlns:jsr107='http://www.ehcache.org/v3/jsr107' xsi:schemaLocation="http://www.ehcache.org/v3 ../../../../xml/src/main/resources/ehcache-core.xsd - http://www.ehcache.org/v3/jsr107 ../../main/resources/ehcache-107ext.xsd"> + http://www.ehcache.org/v3/jsr107 ../../main/resources/ehcache-107-ext.xsd"> @@ -42,4 +42,4 @@ 2000 - \ No newline at end of file + diff --git a/107/src/test/resources/ehcache-107-mbeans-cache-config.xml b/107/src/test/resources/ehcache-107-mbeans-cache-config.xml index 1e39955b8f..8310e2c1fe 100644 --- a/107/src/test/resources/ehcache-107-mbeans-cache-config.xml +++ b/107/src/test/resources/ehcache-107-mbeans-cache-config.xml @@ -19,7 +19,7 @@ xmlns='http://www.ehcache.org/v3' xmlns:jsr107='http://www.ehcache.org/v3/jsr107' xsi:schemaLocation="http://www.ehcache.org/v3 ../../../../xml/src/main/resources/ehcache-core.xsd - http://www.ehcache.org/v3/jsr107 ../../main/resources/ehcache-107ext.xsd"> + http://www.ehcache.org/v3/jsr107 ../../main/resources/ehcache-107-ext.xsd"> java.lang.String @@ -28,4 +28,4 @@ - \ No newline at end of file + diff --git a/107/src/test/resources/ehcache-107-mbeans-template-config.xml b/107/src/test/resources/ehcache-107-mbeans-template-config.xml index 8824829628..dd34c9d2c3 100644 --- a/107/src/test/resources/ehcache-107-mbeans-template-config.xml +++ b/107/src/test/resources/ehcache-107-mbeans-template-config.xml @@ -19,7 +19,7 @@ xmlns='http://www.ehcache.org/v3' xmlns:jsr107='http://www.ehcache.org/v3/jsr107' xsi:schemaLocation="http://www.ehcache.org/v3 ../../../../xml/src/main/resources/ehcache-core.xsd - http://www.ehcache.org/v3/jsr107 ../../main/resources/ehcache-107ext.xsd"> + http://www.ehcache.org/v3/jsr107 ../../main/resources/ehcache-107-ext.xsd"> @@ -38,4 +38,4 @@ - \ No newline at end of file + diff --git a/107/src/test/resources/ehcache-107-serializer.xml b/107/src/test/resources/ehcache-107-serializer.xml index 5722c36df1..b46cf8f7d4 100644 --- a/107/src/test/resources/ehcache-107-serializer.xml +++ b/107/src/test/resources/ehcache-107-serializer.xml @@ -4,7 +4,7 @@ xmlns:jsr107='http://www.ehcache.org/v3/jsr107' xmlns:ehcache='http://www.ehcache.org/v3' xsi:schemaLocation="http://www.ehcache.org/v3 ../../../../xml/src/main/resources/ehcache-core.xsd - http://www.ehcache.org/v3/jsr107 ../../main/resources/ehcache-107ext.xsd"> + http://www.ehcache.org/v3/jsr107 ../../main/resources/ehcache-107-ext.xsd"> org.ehcache.impl.serialization.CompactJavaSerializer @@ -27,4 +27,4 @@ 1 - \ No newline at end of file + diff --git a/107/src/test/resources/ehcache-107-stats.xml b/107/src/test/resources/ehcache-107-stats.xml index 0c58cadef3..2d66203801 100644 --- a/107/src/test/resources/ehcache-107-stats.xml +++ b/107/src/test/resources/ehcache-107-stats.xml @@ -3,7 +3,7 @@ xmlns='http://www.ehcache.org/v3' xmlns:jsr107='http://www.ehcache.org/v3/jsr107' xsi:schemaLocation="http://www.ehcache.org/v3 ../../../../xml/src/main/resources/ehcache-core.xsd - http://www.ehcache.org/v3/jsr107 ../../main/resources/ehcache-107ext.xsd"> + http://www.ehcache.org/v3/jsr107 ../../main/resources/ehcache-107-ext.xsd"> @@ -35,4 +35,4 @@ 10 - \ No newline at end of file + diff --git a/107/src/test/resources/ehcache-107.xml b/107/src/test/resources/ehcache-107.xml index f018320e1e..fa18f703e4 100644 --- a/107/src/test/resources/ehcache-107.xml +++ b/107/src/test/resources/ehcache-107.xml @@ -3,7 +3,7 @@ xmlns='http://www.ehcache.org/v3' xmlns:jsr107='http://www.ehcache.org/v3/jsr107' xsi:schemaLocation="http://www.ehcache.org/v3 ../../../../xml/src/main/resources/ehcache-core.xsd - http://www.ehcache.org/v3/jsr107 ../../main/resources/ehcache-107ext.xsd"> + http://www.ehcache.org/v3/jsr107 ../../main/resources/ehcache-107-ext.xsd"> @@ -21,4 +21,4 @@ 20 - \ No newline at end of file + diff --git a/docs/src/docs/asciidoc/user/xsds.adoc b/docs/src/docs/asciidoc/user/xsds.adoc index 47f800b61d..7a31a282ee 100644 --- a/docs/src/docs/asciidoc/user/xsds.adoc +++ b/docs/src/docs/asciidoc/user/xsds.adoc @@ -67,7 +67,7 @@ include::{sourcedir36}/xml/src/main/resources/ehcache-core.xsd[lines=18..-1] [source,xsd,indent=0] ---- -include::{sourcedir36}/107/src/main/resources/ehcache-107ext.xsd[lines=18..-1] +include::{sourcedir36}/107/src/main/resources/ehcache-107-ext.xsd[lines=18..-1] ---- == XA transactions extension diff --git a/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-107-osgi.xml b/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-107-osgi.xml index 4a6c31aec9..43633160f3 100644 --- a/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-107-osgi.xml +++ b/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-107-osgi.xml @@ -19,7 +19,7 @@ xmlns='http://www.ehcache.org/v3' xmlns:jsr107='http://www.ehcache.org/v3/jsr107' xsi:schemaLocation="http://www.ehcache.org/v3 ../../../../../../../xml/src/main/resources/ehcache-core.xsd - http://www.ehcache.org/v3/jsr107 ../../../../../../../107/src/main/resources/ehcache-107ext.xsd"> + http://www.ehcache.org/v3/jsr107 ../../../../../../../107/src/main/resources/ehcache-107-ext.xsd"> @@ -40,4 +40,4 @@ 20 - \ No newline at end of file + From 8bfe681f42b9de7ac7b256fbe2cb36c968970006 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Wed, 3 Oct 2018 16:44:03 -0400 Subject: [PATCH 003/372] Script Ehcache deployment --- deploy.sh | 388 +++++++++++++++++++++++++ dist/templates/github-release-issue.md | 11 + dist/templates/github-release.md | 48 +++ 3 files changed, 447 insertions(+) create mode 100755 deploy.sh create mode 100644 dist/templates/github-release-issue.md create mode 100644 dist/templates/github-release.md diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000000..88f53dda29 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,388 @@ +#!/usr/bin/env bash + +### +# Call this script to perform a release of Ehcache (Maven central, website, kit and all). +# +# See https://github.com/ehcache/ehcache3/wiki/dev.release for details. +# +# Set a dryRun variable if you want to skip commits and pushes +### + +# to exit in case of error +set -e +# to see what's going on +#set -v + +function pause { + echo + read -p "Press [enter] to continue" +} + +echo 'Welcome to the Ehcache release wizard' +echo +echo 'This wizard will guide you through an Ehcache release. Some steps will be performed automatically, some will require your help' +echo + +if [ -z "$git_origin" ]; then + git_origin=git@github.com:ehcache/ehcache3.git +fi +current_branch=$(git branch | grep '^\*' | cut -d ' ' -f 2) + +read -e -p "You want to deploy from the git branch named ${current_branch}, is that right? (Y/n): " YN +[[ $YN != "y" && $YN != "Y" && $YN != "" ]] && (echo "Please checkout the correct branch and restart this script" && exit 1) + +echo +echo 'We will now make sure you are up-to-date with the origin' +echo + +git pull $git_origin $current_branch + +if [ ! -z "$(git status --porcelain)" ]; then + echo 'You have local changes. Please remove them and relaunch this script' + exit 1 +fi + +echo +echo 'All good' +echo + +read -e -p "Which version do you want to release? " version + +# A major release will end with 0. e.g. 3.7.0, 3.8.0 +if [ "$(echo $version | cut -d '.' -f 3)" == "0" ]; then + is_major=1 +else + is_major=0 +fi + +# A latest version will always be deployed from master. Bugfix of ealier versions will be from a release/x.y branch +if [ "$current_branch" == "master" ]; then + is_latest_version=1 +else + is_latest_version=0 +fi + +read -e -p "You want to deploy version ${version} from branch ${current_branch}. Is that correct? (Y/n)" YN +[[ $YN != "y" && $YN != "Y" && $YN != "" ]] && (echo "Aborting due to wrong input" && exit 1) + +major_version="$(echo $version | cut -d'.' -f 1).$(echo $version | cut -d'.' -f 2)" +short_major_version=${major_version//[.]/} + +echo +echo 'We will start by configuring GitHub correctly' +echo "First make sure you have a milestone for version ${version} at https://github.com/ehcache/ehcache3/milestones" +echo "If you don't, create it. Name it ${version}" + +read -e -p "What is the milestone number? (look at the URL) " milestone + +echo +echo 'Now attach any closed issues and PR since the last version' +read -e -p 'What was the previous version? ' previous_version +echo 'A helpful git log will now be printed' +echo +git --no-pager log v${previous_version}..HEAD +pause + +echo "Now, let's create an issue for the release" +echo "It contains checkboxes that you will check along the release" +echo "Open https://github.com/ehcache/ehcache3/issues" +echo "Press 'New Issue'" +echo "Set the title to 'Release ${version}'" +echo "Attach the issue to the milestone ${version}" +echo "Assign the issue to you" +echo "Set the description to the content of dist/templates/github-release-issue.md" +echo "Create the issue" +pause + +echo "We will now" +echo "1- Create a local release branch named release-${version}." +echo "2- Commit the final version and tag it." +echo "Only the tag will be pushed to origin (not the branch)." +echo + +sed -i '' "s/%VERSION%/${version}/g" dist/templates/github-release.md +sed -i '' "s/%MILESTONE%/${milestone}/g" dist/templates/github-release.md +sed -i '' "s/%MAJORVERSION%/${major_version}/g" dist/templates/github-release.md +echo "Please add a little description for the release in dist/templates/github-release.md" +pause + +sed -i '' "s/ehcacheVersion = .*/ehcacheVersion = ${version}/" gradle.properties +if [ -z "$dryRun" ]; then + git checkout -b release-${version} + git add gradle.properties dist/templates/github-release.md + git commit -m "Version ${version}" + git tag -m ":ship: Release ${version}" -v${version} + git push $git_origin v${version} +else + echo git checkout -b release-${version} + echo git add gradle.properties dist/templates/github-release.md + echo git commit -m "Version ${version}" + echo git tag -m ":ship: Release ${version}" -v${version} + echo git push $git_origin v${version} +fi + +echo +echo 'Now launch the release to Maven central' +echo '1- Open http://jenkins.terracotta.eur.ad.sag:8080/view/All%20Pipelines/job/publishers-10.2.0/job/ehcache-releaser-3.x/' +echo '2- Press "Build with parameters' +echo "3- Enter v${version} in the git_tag field" +echo "4- Come back here when it's done" +pause + +echo +echo "We will now create a GitHub release" +echo "Open https://github.com/ehcache/ehcache3/tags" +echo "On our new tag v${version}, you will see three dots at the far right" +echo "Click on it and select 'Create Release'" +echo "Set the Tag version to v${version}" +echo "Set the Release title to 'Ehcache ${version}'" +echo "Set the following in the description" +release_description=$(< dist/templates/github-release.md) +echo "$release_description" +pause + +echo "Add the binaries from Maven central to the release" +echo "They will be downloaded in dist/build/binaries" +mkdir -p dist/build/binaries +pushd dist/build/binaries +wget https://repo1.maven.org/maven2/org/ehcache/ehcache/${version}/ehcache-${version}-javadoc.jar +wget https://repo1.maven.org/maven2/org/ehcache/ehcache/${version}/ehcache-${version}-spi-javadoc.jar +wget https://repo1.maven.org/maven2/org/ehcache/ehcache/${version}/ehcache-${version}.jar +wget https://repo1.maven.org/maven2/org/ehcache/ehcache-clustered/${version}/ehcache-clustered-${version}-javadoc.jar +wget https://repo1.maven.org/maven2/org/ehcache/ehcache-clustered/${version}/ehcache-clustered-${version}-kit.tgz +wget https://repo1.maven.org/maven2/org/ehcache/ehcache-clustered/${version}/ehcache-clustered-${version}-kit.zip +wget https://repo1.maven.org/maven2/org/ehcache/ehcache-clustered/${version}/ehcache-clustered-${version}.jar +wget https://repo1.maven.org/maven2/org/ehcache/ehcache-transactions/${version}/ehcache-transactions-${version}-javadoc.jar +wget https://repo1.maven.org/maven2/org/ehcache/ehcache-transactions/${version}/ehcache-transactions-${version}.jar +popd +pause + +echo "Create the release" +pause + +echo "We are doing good. Now let's attack the website" +read -e -p "Where is the ehcache.org-site clone located? (default:../ehcache.org-site): " site_dir + +if [ "$site_dir" == "" ]; then + site_dir='../ehcache.org-site' +fi + +if [ $is_major ]; then + echo "Adding XSDs since this is a major version" + cp xml/src/main/resources/ehcache-core.xsd $site_dir/schema/ehcache-core.xsd + cp xml/src/main/resources/ehcache-core.xsd $site_dir/schema/ehcache-core-${major_version}.xsd + cp 107/src/main/resources/ehcache-107-ext.xsd $site_dir/schema/ehcache-107-ext.xsd + cp 107/src/main/resources/ehcache-107-ext.xsd $site_dir/schema/ehcache-107-ext-${major_version}.xsd + cp clustered/client/src/main/resources/ehcache-clustered-ext.xsd $site_dir/schema/ehcache-clustered-ext.xsd + cp clustered/client/src/main/resources/ehcache-clustered-ext.xsd $site_dir/schema/ehcache-clustered-ext-${major_version}.xsd + cp transactions/src/main/resources/ehcache-tx-ext.xsd $site_dir/schema/ehcache-tx-ext.xsd + cp transactions/src/main/resources/ehcache-tx-ext.xsd $site_dir/schema/ehcache-tx-ext-${major_version}.xsd +fi + +echo "Copy the javadoc from Maven central" +unzip "dist/build/binaries/ehcache-${version}-javadoc.jar" -d "${site_dir}/apidocs/${version}" +unzip "dist/build/binaries/ehcache-clustered-${version}-javadoc.jar" -d "${site_dir}/apidocs/${version}/clustered" +unzip "dist/build/binaries/ehcache-transactions-${version}-javadoc.jar" -d "${site_dir}/apidocs/${version}/transactions" + +echo "Remove Manifests" +rm -rf "${site_dir}/apidocs/${version}/META-INF" "${site_dir}/apidocs/${version}/clustered/META-INF" "${site_dir}/apidocs/${version}/transactions/META-INF" + +pushd $site_dir +if [ -z "$dryRun" ]; then + git checkout master + git pull origin master + git checkout -b "ehcache${version}" +else + echo git checkout master + echo git pull origin master + echo git checkout -b "ehcache${version}" +fi + +if [ $is_major ]; then + echo "Update _config.yml" + echo " -" >> _config.yml + echo " scope:" >> _config.yml + echo " path: \"documentation/${major_version}\"" >> _config.yml + echo " type: \"pages\"" >> _config.yml + echo " values:" >> _config.yml + echo " layout: \"docs35_page\"" >> _config.yml + echo " ehc_version: \"${major_version}\"" >> _config.yml + echo " ehc_javadoc_version: \"${version}\"" >> _config.yml + echo " ehc_checkout_dir_var: \"sourcedir36\"" >> _config.yml + + sed -i '' "s/#needle\_for\_sourcedir/ - sourcedir${short_major_version}=\/_eh${short_major_version}\\ +#needle_for_sourcedir/" _config.yml + sed -i '' "s/current: \"[0-9]\.[0-9]\"/current: \"${major_version}\"/" _config.yml + read -e -p "What is the future version? " future_version + sed -i '' "s/future: \"[0-9]\.[0-9]\"/future: \"${future_version}\"/" _config.yml + + echo "Update home_announcement.html" + sed -i '' "s/Ehcache [0-9]\.[0-9] is now available/Ehcache ${major_version} is now available/" _includes/home_announcement.html + + echo "Update documentation/index.md" + echo "Please add the following line in the current documentation section and move the existing one to history" + echo "|[Ehcache ${major_version} User Guide](/documentation/${major_version}/) |[Core JavaDoc](/apidocs/${version}/index.html){:target=\"_blank\"}
[Clustered Module JavaDoc](/apidocs/${version}/clustered/index.html){:target=\"_blank\"}
[Transactions Module JavaDoc](/apidocs/${version}/transactions/index.html){:target=\"_blank\"}|" + + echo "Update schema/index.md" + sed -i '' "s/\[\/\/\]: # (needle_core)/ * [ehcache-core-${major_version}.xsd](\/schema\/ehcache-core-${major_version}.xsd)\\ +[\/\/]: # (needle_core)/" schema/index.md + sed -i '' "s/\[\/\/\]: # (needle_107)/ * [ehcache-107-ext-${major_version}.xsd](\/schema\/ehcache-107-ext-${major_version}.xsd)\\ +[\/\/]: # (needle_107)/" schema/index.md + sed -i '' "s/\[\/\/\]: # (needle_tx)/ * [ehcache-tx-ext-${major_version}.xsd](\/schema\/ehcache-tx-ext-${major_version}.xsd)\\ +[\/\/]: # (needle_tx)/" schema/index.md + sed -i '' "s/\[\/\/\]: # (needle_clustered)/ * [ehcache-clustered-ext-${major_version}.xsd](\/schema\/ehcache-clustered-ext-${major_version}.xsd)\\ +[\/\/]: # (needle_clustered)/" schema/index.md + +else + echo "Update _config.yml" + sed -i '' "s/ehc_javadoc_version: \"${major_version}\.[0-9]\"/ehc_javadoc_version: \"${version}\"/" _config.yml + + echo "Update documentation/index.md" + echo "Update with the following line in the current documentation section" + echo "|[Ehcache ${major_version} User Guide](/documentation/${major_version}/) |[Core JavaDoc](/apidocs/${version}/index.html){:target=\"_blank\"}
[Clustered Module JavaDoc](/apidocs/${version}/clustered/index.html){:target=\"_blank\"}
[Transactions Module JavaDoc](/apidocs/${version}/transactions/index.html){:target=\"_blank\"}|" +fi + +if [ $is_latest_version ]; then + echo "Update ehc3_quickstart.html" + sed -i '' "s/version>[0-9]\.[0-9]\.[0-9]<\/version/version\>${version}\<\/version/" _includes/ehc3_quickstart.html +fi + +echo "Please make sur the docs35_page layout in _config.yml is still valid" +pause + +echo "Check that README.md table about version, version_dir and branch is still accurate" +pause + +read -e -p "What is the upstream repository name? " samples_upstream + +if [ -z "$dryRun" ]; then + git add . + git commit -m "Release ${version}" + git push --set-upstream ${samples_upstream} "ehcache${version}" +else + echo git add . + echo git commit -m "Release ${version}" + echo git push --set-upstream ${samples_upstream} "ehcache${version}" +fi +popd + +echo "Now please open a PR over branch ehcache${version} https://github.com/ehcache/ehcache3.org-site/pulls" +pause +popd + +echo "Website deployment is done every 15 minutes" +echo "If you want to start it manually: http://jenkins.terracotta.eur.ad.sag:8080/job/websites/job/ehcache.org-site-publisher/" + +echo +echo "Now please update the current and next release version in README.adoc" +echo +pause + +echo +echo "Finally, close the GitHub issue and the milestone" +echo +pause + +echo +echo "We now need to deploy the docker images" +echo +read -e -p "What is the terracotta platform version to deploy?" terracotta_version +read -e -p "What is the Terracotta-OSS docker clone located (default:../docker)?" docker_dir +read -e -p "Which previous image do you want to base your image on?" template_image + +escaped_template_image=${template_image//./\\.} + +echo "You now need to create the appropriate triggers on Docker hub" + +echo "Open https://hub.docker.com/r/terracotta/sample-ehcache-client/~/settings/automated-builds/" +echo "Change the Dockerfile location of the latest tag to /${terracotta_version}/sample-ehcache-client" +echo "Add a line with tag ${terracotta_version} and Dockerfile location /${terracotta_version}/sample-ehcache-client" + +echo "Open https://hub.docker.com/r/terracotta/terracotta-server-oss/~/settings/automated-builds/" +echo "Change the Dockerfile location of the latest tag to /${terracotta_version}/server" +echo "Add a line with tag ${terracotta_version} and Dockerfile location /${terracotta_version}/server" + +pushd $docker_dir + +cp -r $template_image $terracotta_version +sed -i '' "s/${escaped_template_image}/${terracotta_version}/g" ${terracotta_version}/sample-ehcache-client/README.md +sed -i '' "s/ehcache-clustered-[0-9]\.[0-9]\.[0-9]-kit.tgz/ehcache-clustered-${version}-kit.tgz/g" ${terracotta_version}/sample-ehcache-client/Dockerfile +sed -i '' "s/ehcache-clustered\/[0-9]\.[0-9]\.[0-9]/ehcache-clustered\/${version}/" ${terracotta_version}/sample-ehcache-client/Dockerfile + +sed -i '' "s/${escaped_template_image}/${terracotta_version}/g" ${terracotta_version}/server/README.md +sed -i '' "s/ehcache-clustered-[0-9]\.[0-9]\.[0-9]-kit.tgz/ehcache-clustered-${version}-kit.tgz/g" ${terracotta_version}/server/Dockerfile +sed -i '' "s/ehcache-clustered\/[0-9]\.[0-9]\.[0-9]/ehcache-clustered\/${version}/" ${terracotta_version}/server/Dockerfile + +sed -i '' "s/${escaped_template_image}/${terracotta_version}/g" ${terracotta_version}/README.md +sed -i '' "s/${escaped_template_image}/${terracotta_version}/g" ${terracotta_version}/docker-compose.yml + +sed -i '' "s/ehcache [0-9]\.[0-9]\.[0-9] \/ Terracotta Server OSS ${escaped_template_image}/ehcache ${version} \/ Terracotta Server OSS ${terracotta_version}/" README.md +sed -i '' "s/\[\/\/\]: # (needle_version)/* [${terracotta_version}](\/${terracotta_version}), matches Ehcache ${version}, available from : https:\/\/github.com\/ehcache\/ehcache3\/releases\\ +[\/\/]: # (needle_version)/g" README.md + +if [ -z "$dryRun" ]; then + git add . + git commit -m "Release $terracotta_version using Ehcache $version" + git push origin master +else + echo git add . + echo git commit -m "Release $terracotta_version using Ehcache $version" + echo git push origin master +fi +popd + +echo "Images should appear on Docker Hub in https://hub.docker.com/r/terracotta" +echo "Please check" +pause + +if [ $is_latest_version ]; then + echo + echo "And last but not least, upgrade the samples" + echo + read -e -p "Where is the ehcache3-samples clone located? (default:../ehcache3-samples): " samples_dir + + if [ "$samples_dir" == "" ]; then + samples_dir='../ehcache3-samples' + fi + + pushd $samples_dir + + if [ -z "$dryRun" ]; then + git checkout master + git pull origin master + git checkout -b "ehcache${version}" + else + echo git checkout master + echo git pull origin master + echo git checkout -b "ehcache${version}" + fi + + sed -i '' "s/.*<\/ehcache3\.version>/${version}<\/ehcache3.version>/" pom.xml + + sed -i '' "s/terracotta-server-oss:.*/terracotta-server-oss:${terracotta_version}/g" fullstack/README.md + sed -i '' "s/terracotta-server-oss:.*/terracotta-server-oss:${terracotta_version}/g" fullstack/src/main/docker/terracotta-server-ha.yml + sed -i '' "s/terracotta-server-oss:.*/terracotta-server-oss:${terracotta_version}/g" fullstack/src/main/docker/terracotta-server-single.yml + + echo "Make sure the JCache version hasn't changed. If yes, update $samples_dir/pom.xml" + pause + + git add . + read -e -p "What is the upstream repository name? " samples_upstream + + if [ -z "$dryRun" ]; then + git commit -m "Upgrade to Ehcache ${version}" + git push --set-upstream ${samples_upstream} "ehcache${version}" + else + echo git commit -m "Upgrade to Ehcache ${version}" + echo git push --set-upstream ${samples_upstream} "ehcache${version}" + fi + popd + + echo "Now please open a PR over branch ehcache${version} https://github.com/ehcache/ehcache3-samples/pulls" + pause +fi + +echo "All done!" +echo "If needed, call ./start_next_version.sh to bump the version to the next one" +echo +echo "Have a good day!" diff --git a/dist/templates/github-release-issue.md b/dist/templates/github-release-issue.md new file mode 100644 index 0000000000..f11d907566 --- /dev/null +++ b/dist/templates/github-release-issue.md @@ -0,0 +1,11 @@ +- [] Tag release +- [] Build and verify release + - includes checking javadoc and source jars +- [] Prepare release on GitHub +- [] Prepare website update + - includes checking XSDs +- [] Publish jars to Maven Central +- [] Publish release on GitHub +- [] Publish website +- [] Update readme / bump version on release branch +- [] Email announcement diff --git a/dist/templates/github-release.md b/dist/templates/github-release.md new file mode 100644 index 0000000000..c4b3a17152 --- /dev/null +++ b/dist/templates/github-release.md @@ -0,0 +1,48 @@ +## Getting started + +=> Please add what this release is about here + +As usual, it contains numerous [bug fixes and enhancements](https://github.com/ehcache/ehcache3/milestone/%MILESTONE%?closed=1). + +Ehcache ${version} has been released to maven central under the following coordinates: + +### Main module + +``` xml + + org.ehcache + ehcache + %VERSION% + +``` + +### Transactions module + +``` xml + + org.ehcache + ehcache-transactions + %VERSION% + +``` + +### Clustering module + +``` xml + + org.ehcache + ehcache-clustered + %VERSION% + +``` + +Or can be downloaded below. +Note that if you download Ehcache jar you will need one additional jar in your classpath: +- [slf4j-api-1.7.25.jar](http://search.maven.org/#artifactdetails%7Corg.slf4j%7Cslf4j-api%7C1.7.25%7Cjar) + +## Clustering kit + +For clustering a kit is also provided that includes the Terracotta Server component. See below. + +## Further reading +- [Ehcache 3 documentation](http://www.ehcache.org/documentation/%MAJORVERSION%/) From 6c883614c4d9a6570063f2f11f6311f728080e51 Mon Sep 17 00:00:00 2001 From: Venkata Sairam Madduri Date: Tue, 30 Oct 2018 21:56:34 +0530 Subject: [PATCH 004/372] Move WriteBehindProvider lookup to LoaderWriterStoreProvider --- ...icClusteredWriteBehindWithPassiveTest.java | 4 +- .../java/org/ehcache/core/EhcacheManager.java | 29 +++----------- .../LoaderWriterStoreProvider.java | 40 +++++++++++++++++-- .../loaderwriter/LocalLoaderWriterStore.java | 1 + 4 files changed, 46 insertions(+), 28 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java index 8dceaca796..e85fc6e8ef 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java @@ -137,7 +137,7 @@ private void checkValueFromLoaderWriter(Cache cache, String expect List keyRecords = records.get(KEY); int index = keyRecords.size() - 1; - while (index >= 0 && keyRecords.get(index) != null && keyRecords.get(index).startsWith("flush_")) { + while (index >= 0 && keyRecords.get(index) != null && keyRecords.get(index).startsWith("flush_queue")) { index--; } @@ -190,7 +190,7 @@ private void tryFlushingUpdatesToSOR(Cache cache) { } catch (InterruptedException e) { e.printStackTrace(); } - if (value.equals(loaderWriter.load(KEY))) break; + if (loaderWriter.load(KEY).startsWith("flush_queue")) break; if (i > retryCount) { throw new RuntimeException("Couldn't flush updates to SOR after " + retryCount + " tries"); } diff --git a/core/src/main/java/org/ehcache/core/EhcacheManager.java b/core/src/main/java/org/ehcache/core/EhcacheManager.java index 5c066c77cc..6ee54d9973 100644 --- a/core/src/main/java/org/ehcache/core/EhcacheManager.java +++ b/core/src/main/java/org/ehcache/core/EhcacheManager.java @@ -318,26 +318,9 @@ InternalCache createNewEhcache(String alias, CacheConfiguration lifeCycledList = new ArrayList<>(); CacheLoaderWriterProvider cacheLoaderWriterProvider = serviceLocator.getService(CacheLoaderWriterProvider.class); - CacheLoaderWriter decorator ; + CacheLoaderWriter loaderWriter; if(cacheLoaderWriterProvider != null) { - CacheLoaderWriter loaderWriter; loaderWriter = cacheLoaderWriterProvider.createCacheLoaderWriter(alias, config); - WriteBehindConfiguration writeBehindConfiguration = - ServiceUtils.findSingletonAmongst(WriteBehindConfiguration.class, config.getServiceConfigurations()); - if(writeBehindConfiguration == null) { - decorator = loaderWriter; - } else { - WriteBehindProvider factory = serviceLocator.getService(WriteBehindProvider.class); - decorator = factory.createWriteBehindLoaderWriter(loaderWriter, writeBehindConfiguration); - if(decorator != null) { - lifeCycledList.add(new LifeCycledAdapter() { - @Override - public void close() { - factory.releaseWriteBehindLoaderWriter(decorator); - } - }); - } - } if (loaderWriter != null) { lifeCycledList.add(new LifeCycledAdapter() { @@ -348,10 +331,10 @@ public void close() throws Exception { }); } } else { - decorator = null; + loaderWriter = null; } - Store store = getStore(alias, config, keyType, valueType, adjustedServiceConfigs, lifeCycledList, decorator); + Store store = getStore(alias, config, keyType, valueType, adjustedServiceConfigs, lifeCycledList, loaderWriter); CacheEventDispatcherFactory cenlProvider = serviceLocator.getService(CacheEventDispatcherFactory.class); @@ -367,12 +350,12 @@ public void close() { ResilienceStrategyProvider resilienceProvider = serviceLocator.getService(ResilienceStrategyProvider.class); ResilienceStrategy resilienceStrategy; - if (decorator == null) { + if (loaderWriter == null) { resilienceStrategy = resilienceProvider.createResilienceStrategy(alias, config, new DefaultRecoveryStore<>(store)); } else { - resilienceStrategy = resilienceProvider.createResilienceStrategy(alias, config, new DefaultRecoveryStore<>(store), decorator); + resilienceStrategy = resilienceProvider.createResilienceStrategy(alias, config, new DefaultRecoveryStore<>(store), loaderWriter); } - InternalCache cache = new Ehcache<>(config, store, resilienceStrategy, evtService, LoggerFactory.getLogger(Ehcache.class + "-" + alias), decorator); + InternalCache cache = new Ehcache<>(config, store, resilienceStrategy, evtService, LoggerFactory.getLogger(Ehcache.class + "-" + alias), loaderWriter); CacheEventListenerProvider evntLsnrFactory = serviceLocator.getService(CacheEventListenerProvider.class); if (evntLsnrFactory != null) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java index 4fb4e61b58..324db182d5 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java @@ -17,11 +17,16 @@ import org.ehcache.config.ResourceType; import org.ehcache.core.internal.store.StoreSupport; +import org.ehcache.core.spi.LifeCycledAdapter; +import org.ehcache.core.spi.service.ServiceUtils; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.WrapperStore; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; +import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.loaderwriter.CacheLoaderWriterConfiguration; import org.ehcache.spi.loaderwriter.CacheLoaderWriterProvider; +import org.ehcache.spi.loaderwriter.WriteBehindConfiguration; +import org.ehcache.spi.loaderwriter.WriteBehindProvider; import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.spi.service.ServiceDependencies; @@ -34,21 +39,43 @@ import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; -@ServiceDependencies({CacheLoaderWriterProvider.class}) +@ServiceDependencies({CacheLoaderWriterProvider.class, WriteBehindProvider.class}) public class LoaderWriterStoreProvider implements WrapperStore.Provider { private volatile ServiceProvider serviceProvider; private final Map, StoreRef> createdStores = new ConcurrentHashMap<>(); + private volatile LifeCycledAdapter writeBehindLifecycleAdapter; + @Override public Store createStore(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { Store.Provider underlyingStoreProvider = StoreSupport.selectStoreProvider(serviceProvider, storeConfig.getResourcePools().getResourceTypeSet(), Arrays.asList(serviceConfigs)); Store store = underlyingStoreProvider.createStore(storeConfig, serviceConfigs); - LocalLoaderWriterStore loaderWriterStore = new LocalLoaderWriterStore<>(store, storeConfig.getCacheLoaderWriter(), - storeConfig.useLoaderInAtomics(), storeConfig.getExpiry()); + CacheLoaderWriter cacheLoaderWriter = storeConfig.getCacheLoaderWriter(); + CacheLoaderWriter decorator; + + WriteBehindConfiguration writeBehindConfiguration = + ServiceUtils.findSingletonAmongst(WriteBehindConfiguration.class, serviceConfigs); + if(writeBehindConfiguration == null) { + decorator = cacheLoaderWriter; + } else { + WriteBehindProvider factory = serviceProvider.getService(WriteBehindProvider.class); + decorator = factory.createWriteBehindLoaderWriter(cacheLoaderWriter, writeBehindConfiguration); + if(decorator != null) { + writeBehindLifecycleAdapter = new LifeCycledAdapter() { + @Override + public void close() { + factory.releaseWriteBehindLoaderWriter(decorator); + } + }; + } + } + + LocalLoaderWriterStore loaderWriterStore = new LocalLoaderWriterStore<>(store, decorator, + storeConfig.useLoaderInAtomics(), storeConfig.getExpiry()); createdStores.put(loaderWriterStore, new StoreRef<>(store, underlyingStoreProvider)); return loaderWriterStore; } @@ -57,6 +84,13 @@ public Store createStore(Store.Configuration storeConfig, Ser public void releaseStore(Store resource) { StoreRef storeRef = createdStores.remove(resource); storeRef.getUnderlyingStoreProvider().releaseStore(storeRef.getUnderlyingStore()); + if (writeBehindLifecycleAdapter != null) { + try { + writeBehindLifecycleAdapter.close(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } } @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java index c25aff48b6..3e3bf43341 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java @@ -63,6 +63,7 @@ public LocalLoaderWriterStore(Store delegate, CacheLoaderWriter expiry) { this.delegate = delegate; this.cacheLoaderWriter = cacheLoaderWriter; + this.useLoaderInAtomics = useLoaderInAtomics; this.expiry = expiry; ContextManager.associate(delegate).withParent(this); From 67f083c2af4c1bc0074fa24bf1aa55ac11957fd4 Mon Sep 17 00:00:00 2001 From: Venkata Sairam Madduri Date: Tue, 30 Oct 2018 22:55:06 +0530 Subject: [PATCH 005/372] Address review comments --- .../operations/codecs/OperationsCodec.java | 7 +- .../Store/operations/OperationCodeTest.java | 10 +-- ...icClusteredWriteBehindWithPassiveTest.java | 70 +++++++++++-------- .../loaderwriter/LocalLoaderWriterStore.java | 1 - 4 files changed, 50 insertions(+), 38 deletions(-) diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/codecs/OperationsCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/codecs/OperationsCodec.java index 4ce754ae55..bc4a48868f 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/codecs/OperationsCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/codecs/OperationsCodec.java @@ -38,12 +38,13 @@ public ByteBuffer encode(Operation operation) { } public static OperationCode getOperationCode(ByteBuffer buffer) { - return OperationCode.valueOf(buffer.duplicate().get()); + OperationCode opCode = OperationCode.valueOf(buffer.get()); + buffer.rewind(); + return opCode; } public Operation decode(ByteBuffer buffer) { - OperationCode opCode = OperationCode.valueOf(buffer.get()); - buffer.rewind(); + OperationCode opCode = getOperationCode(buffer); return opCode.decode(buffer, keySerializer, valueSerializer); } diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/operations/OperationCodeTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/operations/OperationCodeTest.java index f332d01894..2eebae5e70 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/operations/OperationCodeTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/operations/OperationCodeTest.java @@ -18,6 +18,8 @@ import org.ehcache.clustered.common.internal.store.operations.OperationCode; import org.junit.Test; +import java.util.Arrays; + import static org.hamcrest.Matchers.is; import static org.junit.Assert.*; @@ -27,10 +29,8 @@ public class OperationCodeTest { public void testPinning() { assertThat(OperationCode.PUT.shouldBePinned(), is(false)); - for (OperationCode operationCode : OperationCode.values()) { - if (OperationCode.PUT != operationCode) { - assertThat(operationCode.shouldBePinned(), is(true)); - } - } + Arrays.stream(OperationCode.values()) + .filter(operationCode -> operationCode != OperationCode.PUT) + .forEach((operationCode -> assertThat(operationCode + " must be pinned", operationCode.shouldBePinned(), is(true)))); } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java index e85fc6e8ef..4c8dd6d6ae 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java @@ -82,13 +82,16 @@ public void testBasicClusteredWriteBehind() throws Exception { cache.put(KEY, String.valueOf(i)); } - assertValue(cache, String.valueOf(9)); + assertValue(cache, "9"); CLUSTER.getClusterControl().terminateActive(); CLUSTER.getClusterControl().waitForActive(); CLUSTER.getClusterControl().startOneServer(); - assertValue(cache, String.valueOf(9)); + // wait for fail-over + Thread.sleep(1000); + + assertValue(cache, "9"); checkValueFromLoaderWriter(cache, String.valueOf(9)); cache.clear(); @@ -102,19 +105,22 @@ public void testWriteBehindMultipleClients() throws Exception { Cache client2 = cacheManager2.getCache(CACHE_NAME, Long.class, String.class); client1.put(KEY, "The one from client1"); - client2.put(KEY, "The one one from client2"); - assertValue(client1, "The one one from client2"); + client2.put(KEY, "The one from client2"); + assertValue(client1, "The one from client2"); client1.remove(KEY); client2.put(KEY, "The one from client2"); - client1.put(KEY, "The one one from client1"); - assertValue(client2, "The one one from client1"); + client1.put(KEY, "The one from client1"); + assertValue(client2, "The one from client1"); client2.remove(KEY); assertValue(client1, null); client1.put(KEY, "The one from client1"); client1.put(KEY, "The one one from client1"); + assertValue(client2, "The one one from client1"); client2.remove(KEY); + assertValue(client1, null); client2.put(KEY, "The one from client2"); client2.put(KEY, "The one one from client2"); + assertValue(client1, "The one one from client2"); client1.remove(KEY); assertValue(client2, null); @@ -122,6 +128,9 @@ public void testWriteBehindMultipleClients() throws Exception { CLUSTER.getClusterControl().waitForActive(); CLUSTER.getClusterControl().startOneServer(); + // wait for fail-over + Thread.sleep(1000); + assertValue(client1, null); assertValue(client2, null); checkValueFromLoaderWriter(client1, null); @@ -129,22 +138,6 @@ public void testWriteBehindMultipleClients() throws Exception { client1.clear(); } - private void checkValueFromLoaderWriter(Cache cache, String expected) { - - tryFlushingUpdatesToSOR(cache); - - Map> records = loaderWriter.getRecords(); - List keyRecords = records.get(KEY); - - int index = keyRecords.size() - 1; - while (index >= 0 && keyRecords.get(index) != null && keyRecords.get(index).startsWith("flush_queue")) { - index--; - } - - assertThat(keyRecords.get(index), is(expected)); - - } - @Test public void testClusteredWriteBehindCAS() throws Exception { PersistentCacheManager cacheManager = createCacheManager(); @@ -172,6 +165,12 @@ public void testClusteredWriteBehindCAS() throws Exception { CLUSTER.getClusterControl().waitForActive(); CLUSTER.getClusterControl().startOneServer(); + // wait for fail-over + Thread.sleep(1000); + + assertValue(cache, "new value"); + checkValueFromLoaderWriter(cache, "new value"); + cache.clear(); } @@ -179,20 +178,33 @@ private void assertValue(Cache cache, String value) { assertThat(cache.get(KEY), is(value)); } - private void tryFlushingUpdatesToSOR(Cache cache) { + private void checkValueFromLoaderWriter(Cache cache, String expected) throws Exception { + tryFlushingUpdatesToSOR(cache); + + Map> records = loaderWriter.getRecords(); + List keyRecords = records.get(KEY); + + int index = keyRecords.size() - 1; + while (index >= 0 && keyRecords.get(index) != null && keyRecords.get(index).startsWith("flush_queue")) { + index--; + } + + assertThat(keyRecords.get(index), is(expected)); + } + + private void tryFlushingUpdatesToSOR(Cache cache) throws Exception { int retryCount = 1000; int i = 0; while (true) { String value = "flush_queue_" + i; cache.put(KEY, value); - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); + Thread.sleep(100); + String loadedValue = loaderWriter.load(KEY); + if (loadedValue != null && loadedValue.startsWith("flush_queue")) { + break; } - if (loaderWriter.load(KEY).startsWith("flush_queue")) break; if (i > retryCount) { - throw new RuntimeException("Couldn't flush updates to SOR after " + retryCount + " tries"); + throw new AssertionError("Couldn't flush updates to SOR after " + retryCount + " tries"); } i++; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java index 3e3bf43341..c25aff48b6 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java @@ -63,7 +63,6 @@ public LocalLoaderWriterStore(Store delegate, CacheLoaderWriter expiry) { this.delegate = delegate; this.cacheLoaderWriter = cacheLoaderWriter; - this.useLoaderInAtomics = useLoaderInAtomics; this.expiry = expiry; ContextManager.associate(delegate).withParent(this); From bd809688149524e662773dc6d3145feaf9cc420f Mon Sep 17 00:00:00 2001 From: Venkata Sairam Madduri Date: Wed, 31 Oct 2018 18:33:45 +0530 Subject: [PATCH 006/372] javadoc for replaceHeader/removeHeader --- .../server/offheap/OffHeapChainStorageEngine.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java index 8601790d64..accbb335b9 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java @@ -532,6 +532,10 @@ public boolean replace(Chain expected, Chain replacement) { } } + + /** + * @return false if storage can't be allocated for new header when whole chain is not removed, true otherwise + */ public boolean removeHeader(Chain header) { long suffixHead = chain + OffHeapChainStorageEngine.this.totalChainHeaderSize; long prefixTail; @@ -583,6 +587,10 @@ public boolean removeHeader(Chain header) { } } + /** + * @return false if storage can't be allocated for new header when head of the current chain matches expected + * chain, true otherwise + */ public boolean replaceHeader(Chain expected, Chain replacement) { long suffixHead = chain + OffHeapChainStorageEngine.this.totalChainHeaderSize; long prefixTail; From 86e174a918cd58c90218d08ca1aafce9876b36ea Mon Sep 17 00:00:00 2001 From: Anthony Dahanne Date: Mon, 5 Nov 2018 12:27:06 -0500 Subject: [PATCH 007/372] Upgrade to 3.7-SNAPSHOT --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index f058c020a8..870c7d5d6d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # Ehcache version -ehcacheVersion = 3.6-SNAPSHOT +ehcacheVersion = 3.7-SNAPSHOT # Terracotta third parties offheapVersion = 2.4.0 From 74a50bc51a8853de1f7c1201074281e62f9bf1d2 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Mon, 5 Nov 2018 01:44:05 -0800 Subject: [PATCH 008/372] bump platform versions --- gradle.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index f058c020a8..1826001fef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,10 +9,10 @@ slf4jVersion = 1.7.25 sizeofVersion = 0.3.0 # Terracotta clustered -terracottaPlatformVersion = 5.5.1 -terracottaApisVersion = 1.5.1 -terracottaCoreVersion = 5.5.1 -terracottaPassthroughTestingVersion = 1.5.1 +terracottaPlatformVersion = 5.5.2-pre2 +terracottaApisVersion = 1.5.2-pre1 +terracottaCoreVersion = 5.5.2-pre1 +terracottaPassthroughTestingVersion = 1.5.2-pre1 # Test lib versions junitVersion = 4.12 From 9e55a361630df37f089ad52fbc8baa12306fa723 Mon Sep 17 00:00:00 2001 From: Abhilash Date: Thu, 8 Nov 2018 16:07:14 +0530 Subject: [PATCH 009/372] Register deleating store for stats --- .../internal/loaderwriter/DelegatingLoaderWriterStore.java | 2 ++ .../org/ehcache/clustered/ClusteredLoaderWriterTest.java | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java index 920ea16c42..0d71b775e3 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java @@ -22,6 +22,7 @@ import org.ehcache.core.spi.store.WrapperStore; import org.ehcache.core.spi.store.events.StoreEventSource; import org.ehcache.spi.resilience.StoreAccessException; +import org.terracotta.context.ContextManager; import java.util.Collections; import java.util.List; @@ -38,6 +39,7 @@ public class DelegatingLoaderWriterStore implements WrapperStore { public DelegatingLoaderWriterStore(Store store) { this.delegate = store; + ContextManager.associate(delegate).withParent(this); } @Override diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java index a59acfd07a..92c8d94204 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java @@ -27,6 +27,9 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.management.ManagementRegistryService; +import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; +import org.ehcache.management.registry.DefaultManagementRegistryService; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -85,10 +88,13 @@ public static void waitForActive() throws Exception { } private static PersistentCacheManager newCacheManager() { + DefaultManagementRegistryConfiguration registryConfiguration = new DefaultManagementRegistryConfiguration().setCacheManagerAlias("myCacheManager1"); + ManagementRegistryService managementRegistry = new DefaultManagementRegistryService(registryConfiguration); return CacheManagerBuilder.newCacheManagerBuilder() .with(cluster(CLUSTER.getConnectionURI()) .autoCreate() .build()) + .using(managementRegistry) .build(true); } From c279687c6356e2f144d3327194e8f24d19b95fce Mon Sep 17 00:00:00 2001 From: Abhilash Date: Thu, 8 Nov 2018 17:13:06 +0530 Subject: [PATCH 010/372] Handle pre loaderwriter store config #2513 --- .../internal/messages/CommonConfigCodec.java | 7 ++- .../messages/CommonConfigCodecTest.java | 48 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodec.java index 0edc019597..1175b5b38d 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodec.java @@ -32,6 +32,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Optional; import static org.terracotta.runnel.EnumMappingBuilder.newEnumMappingBuilder; import static org.terracotta.runnel.StructBuilder.newStructBuilder; @@ -164,7 +165,11 @@ public ServerStoreConfiguration decodeServerStoreConfiguration(PrimitiveDecoding } return new ServerStoreConfiguration(poolAllocation, keyType, valueType, keySerializer, valueSerializer, consistency, - loaderWriterConfigured, writeBehindConfigured); + getNonNullBoolean(loaderWriterConfigured), getNonNullBoolean(writeBehindConfigured)); + } + + private static Boolean getNonNullBoolean(Boolean loaderWriterConfigured) { + return Optional.ofNullable(loaderWriterConfigured).orElse(false); } @Override diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodecTest.java index 879960b2af..677c98aa5e 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodecTest.java @@ -22,6 +22,7 @@ import org.ehcache.clustered.common.internal.ServerStoreConfiguration; import org.junit.Test; import org.mockito.Mockito; +import org.terracotta.runnel.EnumMapping; import org.terracotta.runnel.Struct; import org.terracotta.runnel.StructBuilder; import org.terracotta.runnel.encoding.StructEncoder; @@ -29,10 +30,12 @@ import java.nio.ByteBuffer; import java.util.Collections; +import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.SERVER_STORE_NAME_FIELD; import static org.hamcrest.Matchers.hasKey; import static org.hamcrest.Matchers.is; import static org.junit.Assert.*; import static org.mockito.Mockito.mock; +import static org.terracotta.runnel.EnumMappingBuilder.newEnumMappingBuilder; import static org.terracotta.runnel.StructBuilder.newStructBuilder; public class CommonConfigCodecTest { @@ -72,4 +75,49 @@ public void testInjectServerStoreConfiguration() { } + @Test + public void testDecodeNonLoaderWriterServerStoreConfiguration() { + EnumMapping consistencyEnumMapping = newEnumMappingBuilder(Consistency.class) + .mapping(Consistency.EVENTUAL, 1) + .mapping(Consistency.STRONG, 2) + .build(); + int index = 30; + StructBuilder builder = newStructBuilder() + .string("identifier", 10) + .string(SERVER_STORE_NAME_FIELD, 20) + .string("keyType", index) + .string("keySerializerType", index + 10) + .string("valueType", index + 11) + .string("valueSerializerType", index + 15) + .enm("consistency", index + 16, consistencyEnumMapping) + .int64("poolSize", index + 20) + .string("resourceName", index + 30); + + Struct struct = builder.build(); + + ByteBuffer encodedStoreConfig = struct.encoder() + .string("identifier", "test") + .string(SERVER_STORE_NAME_FIELD, "testStore") + .string("keyType", "Long") + .string("keySerializerType", "Long") + .string("valueType", "Long") + .string("valueSerializerType", "Long") + .enm("consistency", Consistency.STRONG) + .int64("poolSize", 20) + .string("resourceName", "primary").encode(); + + Struct newStruct = CODEC.injectServerStoreConfiguration(newStructBuilder() + .string("identifier", 10) + .string(SERVER_STORE_NAME_FIELD, 20), index) + .getUpdatedBuilder() + .build(); + encodedStoreConfig.flip(); + ServerStoreConfiguration serverStoreConfiguration = + CODEC.decodeServerStoreConfiguration(newStruct.decoder(encodedStoreConfig)); + + assertThat(serverStoreConfiguration.isLoaderWriterConfigured(), is(false)); + assertThat(serverStoreConfiguration.isWriteBehindConfigured(), is(false)); + + } + } From cf73f505af8b8be7a3501b4d94827d072402d26a Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Thu, 8 Nov 2018 09:40:24 -0500 Subject: [PATCH 011/372] Upgrade documentation plugins --- docs/build.gradle | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/build.gradle b/docs/build.gradle index 8a4551e0c7..f0f744c5d1 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -15,13 +15,14 @@ */ plugins { - id 'org.asciidoctor.convert' version '1.5.3' + // Use 1.5.9.1 for now and wait for 1.5.9.3. The 1.5.9.2 prints annoying false warnings + id 'org.asciidoctor.convert' version '1.5.9.1' id 'org.kordamp.gradle.livereload' version '0.2.1' - id 'com.github.jruby-gradle.base' version '1.5.0' + id 'com.github.jruby-gradle.base' version '1.6.0' } dependencies { - gems 'rubygems:asciidoctor-diagram:1.5.4' + gems 'rubygems:asciidoctor-diagram:1.5.11' } configurations.asciidoctor.dependencies.matching({it.group == 'org.asciidoctor' && it.name == 'asciidoctorj-groovy-dsl'}).all { @@ -45,7 +46,7 @@ task copyImages(type: Copy) { asciidoctor.dependsOn copyCSS, copyImages asciidoctorj { - version = '1.5.5' + version = '1.5.8.1' } asciidoctor { From 989c5a483ad6fe4d19ae1743f7178b5fc61cba10 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Thu, 8 Nov 2018 12:58:31 -0500 Subject: [PATCH 012/372] Fix compilation warnings --- .../ehcache/impl/internal/classes/ClassInstanceProvider.java | 4 ++-- .../store/loaderwriter/LoaderWriterStoreProvider.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java b/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java index 8b6104cebc..c2c5cf5c4c 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java @@ -89,10 +89,10 @@ protected T newInstance(K alias, CacheConfiguration cacheConfiguration) { return newInstance(alias, config); } - protected T newInstance(K alias, ServiceConfiguration... serviceConfigurations) { + protected T newInstance(K alias, ServiceConfiguration... serviceConfigurations) { ClassInstanceConfiguration config = null; Iterator> iterator = - findAmongst(cacheLevelConfig, serviceConfigurations).iterator(); + findAmongst(cacheLevelConfig, (Object[]) serviceConfigurations).iterator(); if (iterator.hasNext()) { config = iterator.next(); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java index 324db182d5..76c71b165d 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java @@ -58,7 +58,7 @@ public Store createStore(Store.Configuration storeConfig, Ser CacheLoaderWriter decorator; WriteBehindConfiguration writeBehindConfiguration = - ServiceUtils.findSingletonAmongst(WriteBehindConfiguration.class, serviceConfigs); + ServiceUtils.findSingletonAmongst(WriteBehindConfiguration.class, (Object[]) serviceConfigs); if(writeBehindConfiguration == null) { decorator = cacheLoaderWriter; } else { From 8b8f864148584c59d0c04ca83835d50cfb4cfe4d Mon Sep 17 00:00:00 2001 From: Albin Suresh Date: Tue, 13 Nov 2018 13:19:20 +0530 Subject: [PATCH 013/372] Bump up terracotta dependencies --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index ca605878c3..f37e676359 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,9 +9,9 @@ slf4jVersion = 1.7.25 sizeofVersion = 0.3.0 # Terracotta clustered -terracottaPlatformVersion = 5.5.2-pre2 +terracottaPlatformVersion = 5.5.2-pre3 terracottaApisVersion = 1.5.2-pre1 -terracottaCoreVersion = 5.5.2-pre1 +terracottaCoreVersion = 5.5.2-pre2 terracottaPassthroughTestingVersion = 1.5.2-pre1 # Test lib versions From 1541cd435095c5141134f6d2e3bcb6ee027c8a30 Mon Sep 17 00:00:00 2001 From: Gary Keim Date: Tue, 13 Nov 2018 14:08:52 -0500 Subject: [PATCH 014/372] https://github.com/ehcache/ehcache3/issues/2523: use System.nanoTime for better timing. --- .../statistics/StandardEhcacheStatisticsTest.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java index e439bee67e..732878faf3 100755 --- a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java @@ -224,19 +224,18 @@ private > LatencyHistogramStatistic getHistogram(T type, Strin // In fact, on Windows, it does not sleep for long enough. // This method keeps sleeping until the full time has passed. private void minimumSleep(long millis) { - long start = System.currentTimeMillis(); + long nanos = TimeUnit.MILLISECONDS.toNanos(millis); + long start = System.nanoTime(); while (true) { - long now = System.currentTimeMillis(); - long elapsed = now - start; - long millisLeft = millis - elapsed; + long nanosLeft = nanos - (System.nanoTime() - start); - if (millisLeft <= 0) { + if (nanosLeft <= 0) { break; } try { - Thread.sleep(millisLeft); + Thread.sleep(TimeUnit.NANOSECONDS.toMillis(nanosLeft)); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; From aa67cde5ea106f2d62be4555cdb9e9acafbb8ee5 Mon Sep 17 00:00:00 2001 From: Gary Keim Date: Tue, 13 Nov 2018 17:03:04 -0500 Subject: [PATCH 015/372] Documented the switch from System.currentTimeMillis to System.nanoTime. --- .../statistics/StandardEhcacheStatisticsTest.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java index 732878faf3..74a4d6bac7 100755 --- a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java @@ -220,9 +220,13 @@ private > LatencyHistogramStatistic getHistogram(T type, Strin return histogram; } - // Java does not provide a guarantee that Thread.sleep will actually sleep long enough + // Java does not provide a guarantee that Thread.sleep will actually sleep long enough. // In fact, on Windows, it does not sleep for long enough. // This method keeps sleeping until the full time has passed. + // + // Using System.nanoTime (accurate to 1 micro-second or better) in lieu of System.currentTimeMillis (on Windows + // accurate to ~16ms), the inaccuracy of which compounds when invoked multiple times, as in this method. + private void minimumSleep(long millis) { long nanos = TimeUnit.MILLISECONDS.toNanos(millis); long start = System.nanoTime(); @@ -235,7 +239,7 @@ private void minimumSleep(long millis) { } try { - Thread.sleep(TimeUnit.NANOSECONDS.toMillis(nanosLeft)); + TimeUnit.NANOSECONDS.sleep(nanosLeft); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; From 80db5cc6deb2b6501079d2765c16198d95c8893c Mon Sep 17 00:00:00 2001 From: Venkata Sairam Madduri Date: Fri, 9 Nov 2018 14:45:24 +0530 Subject: [PATCH 016/372] Increase read/write operation timeouts for clustered loader-writer and write-behind tests #2517 --- .../BasicClusteredLoaderWriterTest.java | 11 +-- .../util/ThrowingResilienceStrategy.java | 89 ------------------- .../clustered/ClusteredLoaderWriterTest.java | 7 ++ .../BasicClusteredWriteBehindTest.java | 6 +- ...icClusteredWriteBehindWithPassiveTest.java | 15 ++-- .../ThrowingResilienceStrategy.java | 89 +++++++++++++++++++ 6 files changed, 109 insertions(+), 108 deletions(-) delete mode 100644 clustered/client/src/test/java/org/ehcache/clustered/util/ThrowingResilienceStrategy.java create mode 100644 core/src/main/java/org/ehcache/core/internal/resilience/ThrowingResilienceStrategy.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java index 1dd41248bf..0b04121358 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java @@ -20,20 +20,15 @@ import org.ehcache.CacheManager; import org.ehcache.CachePersistenceException; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; -import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.internal.UnitTestConnectionService; import org.ehcache.clustered.client.internal.service.ClusterTierValidationException; -import org.ehcache.clustered.util.ThrowingResilienceStrategy; import org.ehcache.config.CacheConfiguration; -import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.spi.loaderwriter.CacheLoaderWriter; -import org.hamcrest.Matchers; +import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -81,7 +76,7 @@ public void testAllClientsNeedToHaveLoaderWriterConfigured() { ResourcePoolsBuilder .newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).offheap(1, MemoryUnit.MB) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) - .withResilienceStrategy(new ThrowingResilienceStrategy()) + .withResilienceStrategy(new ThrowingResilienceStrategy<>()) .build(); try { @@ -279,7 +274,7 @@ private CacheConfiguration getCacheConfiguration(TestCacheLoaderWr .newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).offheap(1, MemoryUnit.MB) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) .withLoaderWriter(loaderWriter) - .withResilienceStrategy(new ThrowingResilienceStrategy()) + .withResilienceStrategy(new ThrowingResilienceStrategy<>()) .build(); } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/util/ThrowingResilienceStrategy.java b/clustered/client/src/test/java/org/ehcache/clustered/util/ThrowingResilienceStrategy.java deleted file mode 100644 index 0708ff3934..0000000000 --- a/clustered/client/src/test/java/org/ehcache/clustered/util/ThrowingResilienceStrategy.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.ehcache.clustered.util; - -import org.ehcache.Cache; -import org.ehcache.spi.resilience.ResilienceStrategy; -import org.ehcache.spi.resilience.StoreAccessException; - -import java.util.Map; - -public class ThrowingResilienceStrategy implements ResilienceStrategy { - @Override - public String getFailure(Long key, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public boolean containsKeyFailure(Long key, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public void putFailure(Long key, String value, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public void removeFailure(Long key, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public void clearFailure(StoreAccessException e) { - throw new AssertionError("Cache op failed", e); - } - - @Override - public Cache.Entry iteratorFailure(StoreAccessException e) { - throw new AssertionError("Cache op failed", e); - } - - @Override - public String putIfAbsentFailure(Long key, String value, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public boolean removeFailure(Long key, String value, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public String replaceFailure(Long key, String value, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public boolean replaceFailure(Long key, String value, String newValue, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public Map getAllFailure(Iterable keys, StoreAccessException e) { - throw new AssertionError("Cache op failed", e); - } - - @Override - public void putAllFailure(Map entries, StoreAccessException e) { - throw new AssertionError("Cache op failed", e); - } - - @Override - public void removeAllFailure(Iterable keys, StoreAccessException e) { - throw new AssertionError("Cache op failed", e); - } -} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java index 92c8d94204..dfd8e54614 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java @@ -20,6 +20,7 @@ import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteredStoreConfigurationBuilder; +import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.common.Consistency; import org.ehcache.clustered.util.TestCacheLoaderWriter; import org.ehcache.config.CacheConfiguration; @@ -27,6 +28,7 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; import org.ehcache.management.ManagementRegistryService; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; import org.ehcache.management.registry.DefaultManagementRegistryService; @@ -39,6 +41,7 @@ import org.terracotta.testing.rules.Cluster; import java.io.File; +import java.time.Duration; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -92,6 +95,9 @@ private static PersistentCacheManager newCacheManager() { ManagementRegistryService managementRegistry = new DefaultManagementRegistryService(registryConfiguration); return CacheManagerBuilder.newCacheManagerBuilder() .with(cluster(CLUSTER.getConnectionURI()) + .timeouts(TimeoutsBuilder.timeouts() + .read(Duration.ofSeconds(30)) + .write(Duration.ofSeconds(30))) .autoCreate() .build()) .using(managementRegistry) @@ -113,6 +119,7 @@ private CacheConfiguration getCacheConfig() { .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) .withLoaderWriter(new TestCacheLoaderWriter(sor)) .add(ClusteredStoreConfigurationBuilder.withConsistency(cacheConsistency)) + .withResilienceStrategy(new ThrowingResilienceStrategy<>()) .build(); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java index 6e47b882a5..979f8936e4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java @@ -22,6 +22,7 @@ import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; +import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.common.Consistency; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheManagerBuilder; @@ -29,6 +30,7 @@ import org.ehcache.config.builders.WriteBehindConfigurationBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -36,6 +38,7 @@ import org.terracotta.testing.rules.Cluster; import java.io.File; +import java.time.Duration; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -251,12 +254,13 @@ private PersistentCacheManager createCacheManager() { .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) .withLoaderWriter(loaderWriter) .add(WriteBehindConfigurationBuilder.newUnBatchedWriteBehindConfiguration()) + .withResilienceStrategy(new ThrowingResilienceStrategy<>()) .add(new ClusteredStoreConfiguration(Consistency.STRONG)) .build(); return CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER.getConnectionURI().resolve("/cm-wb")).autoCreate()) + .with(cluster(CLUSTER.getConnectionURI().resolve("/cm-wb")).timeouts(TimeoutsBuilder.timeouts().read(Duration.ofSeconds(30)).write(Duration.ofSeconds(30))).autoCreate()) .withCache(CACHE_NAME, cacheConfiguration) .build(true); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java index 4c8dd6d6ae..7d20df05c6 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java @@ -21,6 +21,7 @@ import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; +import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.common.Consistency; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheManagerBuilder; @@ -28,6 +29,7 @@ import org.ehcache.config.builders.WriteBehindConfigurationBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -35,6 +37,7 @@ import org.terracotta.testing.rules.Cluster; import java.io.File; +import java.time.Duration; import java.util.List; import java.util.Map; @@ -88,9 +91,6 @@ public void testBasicClusteredWriteBehind() throws Exception { CLUSTER.getClusterControl().waitForActive(); CLUSTER.getClusterControl().startOneServer(); - // wait for fail-over - Thread.sleep(1000); - assertValue(cache, "9"); checkValueFromLoaderWriter(cache, String.valueOf(9)); @@ -128,9 +128,6 @@ public void testWriteBehindMultipleClients() throws Exception { CLUSTER.getClusterControl().waitForActive(); CLUSTER.getClusterControl().startOneServer(); - // wait for fail-over - Thread.sleep(1000); - assertValue(client1, null); assertValue(client2, null); checkValueFromLoaderWriter(client1, null); @@ -165,9 +162,6 @@ public void testClusteredWriteBehindCAS() throws Exception { CLUSTER.getClusterControl().waitForActive(); CLUSTER.getClusterControl().startOneServer(); - // wait for fail-over - Thread.sleep(1000); - assertValue(cache, "new value"); checkValueFromLoaderWriter(cache, "new value"); @@ -218,12 +212,13 @@ private PersistentCacheManager createCacheManager() { .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) .withLoaderWriter(loaderWriter) .add(WriteBehindConfigurationBuilder.newUnBatchedWriteBehindConfiguration()) + .withResilienceStrategy(new ThrowingResilienceStrategy<>()) .add(new ClusteredStoreConfiguration(Consistency.STRONG)) .build(); return CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER.getConnectionURI().resolve("/cm-wb")).autoCreate()) + .with(cluster(CLUSTER.getConnectionURI().resolve("/cm-wb")).timeouts(TimeoutsBuilder.timeouts().read(Duration.ofMinutes(1)).write(Duration.ofMinutes(1))).autoCreate()) .withCache(CACHE_NAME, cacheConfiguration) .build(true); } diff --git a/core/src/main/java/org/ehcache/core/internal/resilience/ThrowingResilienceStrategy.java b/core/src/main/java/org/ehcache/core/internal/resilience/ThrowingResilienceStrategy.java new file mode 100644 index 0000000000..b8a6b0cae9 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/internal/resilience/ThrowingResilienceStrategy.java @@ -0,0 +1,89 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.internal.resilience; + +import org.ehcache.Cache; +import org.ehcache.spi.resilience.ResilienceStrategy; +import org.ehcache.spi.resilience.StoreAccessException; + +import java.util.Map; + +public class ThrowingResilienceStrategy implements ResilienceStrategy { + @Override + public V getFailure(K key, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public boolean containsKeyFailure(K key, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public void putFailure(K key, V value, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public void removeFailure(K key, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public void clearFailure(StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public Cache.Entry iteratorFailure(StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public V putIfAbsentFailure(K key, V value, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public boolean removeFailure(K key, V value, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public V replaceFailure(K key, V value, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public boolean replaceFailure(K key, V value, V newValue, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public Map getAllFailure(Iterable keys, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public void putAllFailure(Map entries, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public void removeAllFailure(Iterable keys, StoreAccessException e) { + throw new RuntimeException(e); + } +} From 02bc6e3c73697c90e3a6662594b6153a4421aa36 Mon Sep 17 00:00:00 2001 From: Ludovic Orban Date: Wed, 14 Nov 2018 11:00:55 +0100 Subject: [PATCH 017/372] Fix for bugs happening in EE MnM code for certain config settings --- .../ClusteringServiceConfiguration.java | 20 +++-- .../ClusteringServiceConfigurationTest.java | 15 ++++ .../clustered/BasicEntityInteractionTest.java | 83 +++++++++++++++++++ .../DefaultClusteringManagementService.java | 10 ++- .../DefaultManagementRegistryService.java | 8 +- 5 files changed, 123 insertions(+), 13 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java b/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java index 7f07e1fffa..8c486ea821 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java @@ -346,19 +346,23 @@ public String readableString() { getConnectionSource() + "\n " + "timeouts: " + getTimeouts()+ "\n " + "autoCreate: " + isAutoCreate() + "\n " + - "defaultServerResource: " + serverConfiguration.getDefaultServerResource() + "\n " + + "defaultServerResource: " + (serverConfiguration == null ? null : serverConfiguration.getDefaultServerResource()) + "\n " + readablePoolsString(); } private String readablePoolsString() { StringBuilder pools = new StringBuilder("resourcePools:\n"); - serverConfiguration.getResourcePools().forEach((key, value) -> { - pools.append(" "); - pools.append(key); - pools.append(": "); - pools.append(value); - pools.append("\n"); - }); + if (serverConfiguration != null) { + serverConfiguration.getResourcePools().forEach((key, value) -> { + pools.append(" "); + pools.append(key); + pools.append(": "); + pools.append(value); + pools.append("\n"); + }); + } else { + pools.append(" None."); + } return pools.toString(); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java index 31c4fbc91c..ec7921e3f7 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java @@ -165,4 +165,19 @@ public void testBuilderWithServers() { assertThat(new ClusteringServiceConfiguration(SERVERS, CACHE_MANAGER) .builder(CacheManagerBuilder.newCacheManagerBuilder())).isExactlyInstanceOf(CacheManagerBuilder.class); } + + @Test + public void testReadableString() { + ClusteringServiceConfiguration cfg; + + cfg = new ClusteringServiceConfiguration(SERVERS, CACHE_MANAGER); + assertThat(cfg.readableString()).isNotNull(); + + cfg = new ClusteringServiceConfiguration(DEFAULT_URI); + assertThat(cfg.readableString()).isNotNull(); + + cfg = new ClusteringServiceConfiguration(DEFAULT_URI, TimeoutsBuilder.timeouts().build()); + assertThat(cfg.readableString()).isNotNull(); + } + } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java index 8f3227cee3..3a4f1c412e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java @@ -16,10 +16,21 @@ package org.ehcache.clustered; import java.io.File; +import java.net.URI; + +import org.ehcache.Cache; +import org.ehcache.CacheManager; +import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntity; import org.ehcache.clustered.common.EhcacheEntityVersion; import org.ehcache.clustered.common.ServerSideConfiguration; import org.ehcache.clustered.common.internal.ClusterTierManagerConfiguration; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.config.units.MemoryUnit; +import org.ehcache.impl.internal.statistics.DefaultStatisticsService; +import org.ehcache.management.cluster.DefaultClusteringManagementService; import org.hamcrest.Matchers; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -34,6 +45,8 @@ import org.terracotta.testing.rules.Cluster; import static java.util.Collections.emptyMap; +import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; +import static org.ehcache.config.units.EntryUnit.ENTRIES; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; @@ -61,6 +74,76 @@ public static void waitForActive() throws Exception { @Rule public TestName testName= new TestName(); + @Test + public void testClusteringServiceConfigurationBuilderThrowsNPE() throws Exception { + String cacheName = "myCACHE"; + String offheap = "primary-server-resource"; + URI tsaUri = CLUSTER.getConnectionURI(); + + try (CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() + .withCache(cacheName, CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() + .heap(100, ENTRIES) + .with(clusteredDedicated(offheap, 2, MemoryUnit.MB))) + ).with(ClusteringServiceConfigurationBuilder.cluster(tsaUri) + .autoCreate() + .defaultServerResource(offheap) + ).build(true)) { + Cache cache = cacheManager.getCache(cacheName, Long.class, String.class); + cache.put(1L, "one"); + } + + try (CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() + .withCache(cacheName, CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() + .heap(100, ENTRIES) + .with(clusteredDedicated(offheap, 2, MemoryUnit.MB)) + ) + ).with(ClusteringServiceConfigurationBuilder.cluster(tsaUri) + // these two shouldn't be needed as the clustered cache entity has already been created +// .autoCreate() +// .defaultServerResource(offheap) + ).using(new DefaultStatisticsService() + ).using(new DefaultClusteringManagementService() + ).build(true)) { + Cache cache = cacheManager.getCache(cacheName, Long.class, String.class); + cache.get(1L); + } + + } + + @Test + public void testServicesStoppedTwice() throws Exception { + String cacheName = "myCACHE"; + String offheap = "primary-server-resource"; + URI tsaUri = CLUSTER.getConnectionURI(); + + try (CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() + .withCache(cacheName, CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() + .heap(100, ENTRIES) + .with(clusteredDedicated(offheap, 2, MemoryUnit.MB))) + ).with(ClusteringServiceConfigurationBuilder.cluster(tsaUri) + .autoCreate() + .defaultServerResource(offheap) + // manually adding the following two services should work + ).using(new DefaultStatisticsService() + ).using(new DefaultClusteringManagementService() + ).build(true)) { + Cache cache = cacheManager.getCache(cacheName, Long.class, String.class); + cache.put(1L, "one"); + } + + try (CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() + .withCache(cacheName, CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() + .heap(100, ENTRIES) + .with(clusteredDedicated(offheap, 2, MemoryUnit.MB)) + ) + ).with(ClusteringServiceConfigurationBuilder.cluster(tsaUri) + ).build(true)) { + Cache cache = cacheManager.getCache(cacheName, Long.class, String.class); + cache.get(1L); + } + + } + @Test public void testAbsentEntityRetrievalFails() throws Throwable { try (Connection client = CLUSTER.newConnection()) { diff --git a/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java b/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java index 60a4a03e33..d35b1a1642 100644 --- a/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java +++ b/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java @@ -92,17 +92,21 @@ public void start(ServiceProvider serviceProvider) { public void stop() { if (collectorService != null) { collectorService.stop(); + collectorService = null; + } + + if (managementCallExecutor != null) { + shutdownNow(managementCallExecutor); + managementCallExecutor = null; } - shutdownNow(managementCallExecutor); // nullify so that no further actions are done with them (see null-checks below) if (nmsAgentService != null) { nmsAgentService.close(); - managementRegistryService = null; nmsAgentService = null; } - managementCallExecutor = null; + managementRegistryService = null; } @Override diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java index 0e239171b3..d9bb1d4f79 100644 --- a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java +++ b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java @@ -55,6 +55,7 @@ public class DefaultManagementRegistryService extends DefaultManagementRegistry private final ManagementRegistryServiceConfiguration configuration; private volatile InternalCacheManager cacheManager; private volatile ClusteringManagementService clusteringManagementService; + private volatile boolean clusteringManagementServiceAutoStarted; public DefaultManagementRegistryService() { this(new DefaultManagementRegistryConfiguration()); @@ -86,15 +87,18 @@ public void start(final ServiceProvider serviceProvider) { if (this.clusteringManagementService == null && Clustering.isAvailable(serviceProvider)) { this.clusteringManagementService = Clustering.newClusteringManagementService(new DefaultClusteringManagementServiceConfiguration()); this.clusteringManagementService.start(serviceProvider); + this.clusteringManagementServiceAutoStarted = true; + } else { + this.clusteringManagementServiceAutoStarted = false; } } @Override public void stop() { - if (this.clusteringManagementService != null) { + if (this.clusteringManagementService != null && this.clusteringManagementServiceAutoStarted) { this.clusteringManagementService.stop(); - this.clusteringManagementService = null; } + this.clusteringManagementService = null; super.close(); } From e4380cf84c2494b59415716f69055cc6f6f69be9 Mon Sep 17 00:00:00 2001 From: Venkata Sairam Madduri Date: Fri, 9 Nov 2018 14:45:24 +0530 Subject: [PATCH 018/372] Increase read/write operation timeouts for clustered loader-writer and write-behind tests #2517 --- .../BasicClusteredLoaderWriterTest.java | 11 +-- .../util/ThrowingResilienceStrategy.java | 89 ------------------- .../clustered/ClusteredLoaderWriterTest.java | 7 ++ .../BasicClusteredWriteBehindTest.java | 6 +- ...icClusteredWriteBehindWithPassiveTest.java | 15 ++-- .../ThrowingResilienceStrategy.java | 89 +++++++++++++++++++ 6 files changed, 109 insertions(+), 108 deletions(-) delete mode 100644 clustered/client/src/test/java/org/ehcache/clustered/util/ThrowingResilienceStrategy.java create mode 100644 core/src/main/java/org/ehcache/core/internal/resilience/ThrowingResilienceStrategy.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java index 1dd41248bf..0b04121358 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java @@ -20,20 +20,15 @@ import org.ehcache.CacheManager; import org.ehcache.CachePersistenceException; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; -import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.internal.UnitTestConnectionService; import org.ehcache.clustered.client.internal.service.ClusterTierValidationException; -import org.ehcache.clustered.util.ThrowingResilienceStrategy; import org.ehcache.config.CacheConfiguration; -import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.spi.loaderwriter.CacheLoaderWriter; -import org.hamcrest.Matchers; +import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -81,7 +76,7 @@ public void testAllClientsNeedToHaveLoaderWriterConfigured() { ResourcePoolsBuilder .newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).offheap(1, MemoryUnit.MB) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) - .withResilienceStrategy(new ThrowingResilienceStrategy()) + .withResilienceStrategy(new ThrowingResilienceStrategy<>()) .build(); try { @@ -279,7 +274,7 @@ private CacheConfiguration getCacheConfiguration(TestCacheLoaderWr .newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).offheap(1, MemoryUnit.MB) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) .withLoaderWriter(loaderWriter) - .withResilienceStrategy(new ThrowingResilienceStrategy()) + .withResilienceStrategy(new ThrowingResilienceStrategy<>()) .build(); } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/util/ThrowingResilienceStrategy.java b/clustered/client/src/test/java/org/ehcache/clustered/util/ThrowingResilienceStrategy.java deleted file mode 100644 index 0708ff3934..0000000000 --- a/clustered/client/src/test/java/org/ehcache/clustered/util/ThrowingResilienceStrategy.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.ehcache.clustered.util; - -import org.ehcache.Cache; -import org.ehcache.spi.resilience.ResilienceStrategy; -import org.ehcache.spi.resilience.StoreAccessException; - -import java.util.Map; - -public class ThrowingResilienceStrategy implements ResilienceStrategy { - @Override - public String getFailure(Long key, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public boolean containsKeyFailure(Long key, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public void putFailure(Long key, String value, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public void removeFailure(Long key, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public void clearFailure(StoreAccessException e) { - throw new AssertionError("Cache op failed", e); - } - - @Override - public Cache.Entry iteratorFailure(StoreAccessException e) { - throw new AssertionError("Cache op failed", e); - } - - @Override - public String putIfAbsentFailure(Long key, String value, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public boolean removeFailure(Long key, String value, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public String replaceFailure(Long key, String value, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public boolean replaceFailure(Long key, String value, String newValue, StoreAccessException e) { - throw new AssertionError("Cache op failed for key " + key, e); - } - - @Override - public Map getAllFailure(Iterable keys, StoreAccessException e) { - throw new AssertionError("Cache op failed", e); - } - - @Override - public void putAllFailure(Map entries, StoreAccessException e) { - throw new AssertionError("Cache op failed", e); - } - - @Override - public void removeAllFailure(Iterable keys, StoreAccessException e) { - throw new AssertionError("Cache op failed", e); - } -} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java index 92c8d94204..dfd8e54614 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java @@ -20,6 +20,7 @@ import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteredStoreConfigurationBuilder; +import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.common.Consistency; import org.ehcache.clustered.util.TestCacheLoaderWriter; import org.ehcache.config.CacheConfiguration; @@ -27,6 +28,7 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; import org.ehcache.management.ManagementRegistryService; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; import org.ehcache.management.registry.DefaultManagementRegistryService; @@ -39,6 +41,7 @@ import org.terracotta.testing.rules.Cluster; import java.io.File; +import java.time.Duration; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -92,6 +95,9 @@ private static PersistentCacheManager newCacheManager() { ManagementRegistryService managementRegistry = new DefaultManagementRegistryService(registryConfiguration); return CacheManagerBuilder.newCacheManagerBuilder() .with(cluster(CLUSTER.getConnectionURI()) + .timeouts(TimeoutsBuilder.timeouts() + .read(Duration.ofSeconds(30)) + .write(Duration.ofSeconds(30))) .autoCreate() .build()) .using(managementRegistry) @@ -113,6 +119,7 @@ private CacheConfiguration getCacheConfig() { .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) .withLoaderWriter(new TestCacheLoaderWriter(sor)) .add(ClusteredStoreConfigurationBuilder.withConsistency(cacheConsistency)) + .withResilienceStrategy(new ThrowingResilienceStrategy<>()) .build(); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java index 6e47b882a5..979f8936e4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java @@ -22,6 +22,7 @@ import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; +import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.common.Consistency; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheManagerBuilder; @@ -29,6 +30,7 @@ import org.ehcache.config.builders.WriteBehindConfigurationBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -36,6 +38,7 @@ import org.terracotta.testing.rules.Cluster; import java.io.File; +import java.time.Duration; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -251,12 +254,13 @@ private PersistentCacheManager createCacheManager() { .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) .withLoaderWriter(loaderWriter) .add(WriteBehindConfigurationBuilder.newUnBatchedWriteBehindConfiguration()) + .withResilienceStrategy(new ThrowingResilienceStrategy<>()) .add(new ClusteredStoreConfiguration(Consistency.STRONG)) .build(); return CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER.getConnectionURI().resolve("/cm-wb")).autoCreate()) + .with(cluster(CLUSTER.getConnectionURI().resolve("/cm-wb")).timeouts(TimeoutsBuilder.timeouts().read(Duration.ofSeconds(30)).write(Duration.ofSeconds(30))).autoCreate()) .withCache(CACHE_NAME, cacheConfiguration) .build(true); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java index 4c8dd6d6ae..7d20df05c6 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java @@ -21,6 +21,7 @@ import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; +import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.common.Consistency; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheManagerBuilder; @@ -28,6 +29,7 @@ import org.ehcache.config.builders.WriteBehindConfigurationBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -35,6 +37,7 @@ import org.terracotta.testing.rules.Cluster; import java.io.File; +import java.time.Duration; import java.util.List; import java.util.Map; @@ -88,9 +91,6 @@ public void testBasicClusteredWriteBehind() throws Exception { CLUSTER.getClusterControl().waitForActive(); CLUSTER.getClusterControl().startOneServer(); - // wait for fail-over - Thread.sleep(1000); - assertValue(cache, "9"); checkValueFromLoaderWriter(cache, String.valueOf(9)); @@ -128,9 +128,6 @@ public void testWriteBehindMultipleClients() throws Exception { CLUSTER.getClusterControl().waitForActive(); CLUSTER.getClusterControl().startOneServer(); - // wait for fail-over - Thread.sleep(1000); - assertValue(client1, null); assertValue(client2, null); checkValueFromLoaderWriter(client1, null); @@ -165,9 +162,6 @@ public void testClusteredWriteBehindCAS() throws Exception { CLUSTER.getClusterControl().waitForActive(); CLUSTER.getClusterControl().startOneServer(); - // wait for fail-over - Thread.sleep(1000); - assertValue(cache, "new value"); checkValueFromLoaderWriter(cache, "new value"); @@ -218,12 +212,13 @@ private PersistentCacheManager createCacheManager() { .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) .withLoaderWriter(loaderWriter) .add(WriteBehindConfigurationBuilder.newUnBatchedWriteBehindConfiguration()) + .withResilienceStrategy(new ThrowingResilienceStrategy<>()) .add(new ClusteredStoreConfiguration(Consistency.STRONG)) .build(); return CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER.getConnectionURI().resolve("/cm-wb")).autoCreate()) + .with(cluster(CLUSTER.getConnectionURI().resolve("/cm-wb")).timeouts(TimeoutsBuilder.timeouts().read(Duration.ofMinutes(1)).write(Duration.ofMinutes(1))).autoCreate()) .withCache(CACHE_NAME, cacheConfiguration) .build(true); } diff --git a/core/src/main/java/org/ehcache/core/internal/resilience/ThrowingResilienceStrategy.java b/core/src/main/java/org/ehcache/core/internal/resilience/ThrowingResilienceStrategy.java new file mode 100644 index 0000000000..b8a6b0cae9 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/internal/resilience/ThrowingResilienceStrategy.java @@ -0,0 +1,89 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.internal.resilience; + +import org.ehcache.Cache; +import org.ehcache.spi.resilience.ResilienceStrategy; +import org.ehcache.spi.resilience.StoreAccessException; + +import java.util.Map; + +public class ThrowingResilienceStrategy implements ResilienceStrategy { + @Override + public V getFailure(K key, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public boolean containsKeyFailure(K key, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public void putFailure(K key, V value, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public void removeFailure(K key, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public void clearFailure(StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public Cache.Entry iteratorFailure(StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public V putIfAbsentFailure(K key, V value, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public boolean removeFailure(K key, V value, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public V replaceFailure(K key, V value, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public boolean replaceFailure(K key, V value, V newValue, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public Map getAllFailure(Iterable keys, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public void putAllFailure(Map entries, StoreAccessException e) { + throw new RuntimeException(e); + } + + @Override + public void removeAllFailure(Iterable keys, StoreAccessException e) { + throw new RuntimeException(e); + } +} From 1b3e312f005d6a5ffb3ed8491f4569907baf71df Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 14 Nov 2018 16:54:56 -0500 Subject: [PATCH 019/372] Fixes #2526 : Exclude api module from clustered-dist uberjar --- clustered/clustered-dist/build.gradle | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clustered/clustered-dist/build.gradle b/clustered/clustered-dist/build.gradle index f49a141127..3edc1af40d 100644 --- a/clustered/clustered-dist/build.gradle +++ b/clustered/clustered-dist/build.gradle @@ -29,8 +29,9 @@ ext { } dependencies { - compileOnly project(':clustered:client') - compileOnly project(':clustered:common') + compileOnly(project(':clustered:client')) { + exclude group: 'org.ehcache.modules', module: 'api' + } // Needed because declared as provided in the different projects compileOnly "org.terracotta:runnel:$parent.terracottaPlatformVersion" } From 1ac842905a35af27cd2ac1d570557dbb50eab73c Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Thu, 15 Nov 2018 09:38:45 -0500 Subject: [PATCH 020/372] Timeout the test and perform a thread dump --- .../BasicClusteredWriteBehindTest.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java index 979f8936e4..0b503c5ab7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java @@ -31,18 +31,26 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; +import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.Timeout; import org.terracotta.testing.rules.Cluster; import java.io.File; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; import java.time.Duration; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; @@ -60,6 +68,11 @@ public class BasicClusteredWriteBehindTest extends ClusteredTests { + "" + "\n"; + @Rule + public Timeout timeout = new Timeout(1, TimeUnit.MINUTES); + + private boolean doThreadDump = true; + @ClassRule public static Cluster CLUSTER = newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); @@ -69,6 +82,16 @@ public static void waitForActive() throws Exception { CLUSTER.getClusterControl().waitForActive(); } + @After + public void threadDump() { + if(doThreadDump) { + System.out.println("Performing thread dump"); + ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); + ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true); + Arrays.stream(threadInfos).forEach(System.out::println); + } + } + private final List cacheRecords = new ArrayList<>(); private static final String CACHE_NAME = "cache-1"; @@ -94,6 +117,8 @@ public void testBasicClusteredWriteBehind() { verifyRecords(cache); cache.clear(); + + doThreadDump = false; } @Test @@ -122,6 +147,8 @@ public void testWriteBehindMultipleClients() { verifyRecords(client1); client1.clear(); + + doThreadDump = false; } @Test @@ -150,6 +177,8 @@ public void testClusteredWriteBehindCAS() { verifyRecords(cache); cache.clear(); + + doThreadDump = false; } @Test @@ -164,6 +193,8 @@ public void testClusteredWriteBehindLoading() { assertThat(cache.get(KEY), notNullValue()); cache.clear(); + + doThreadDump = false; } private void assertValue(Cache cache, String value) { From 6f0cd6d5df7fcb704e8efc2e71156f12482e445d Mon Sep 17 00:00:00 2001 From: Venkata Sairam Madduri Date: Fri, 16 Nov 2018 11:27:49 +0530 Subject: [PATCH 021/372] Ensure both active and passive up before running each test --- .../BasicClusteredWriteBehindWithPassiveTest.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java index 7d20df05c6..8afce234b7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java @@ -31,7 +31,6 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; @@ -60,8 +59,9 @@ public class BasicClusteredWriteBehindWithPassiveTest extends ClusteredTests { public static Cluster CLUSTER = newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); - @BeforeClass - public static void waitForActive() throws Exception { + @Before + public void waitForActive() throws Exception { + CLUSTER.getClusterControl().startAllServers(); CLUSTER.getClusterControl().waitForActive(); CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); } @@ -89,7 +89,6 @@ public void testBasicClusteredWriteBehind() throws Exception { CLUSTER.getClusterControl().terminateActive(); CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().startOneServer(); assertValue(cache, "9"); checkValueFromLoaderWriter(cache, String.valueOf(9)); @@ -126,7 +125,6 @@ public void testWriteBehindMultipleClients() throws Exception { CLUSTER.getClusterControl().terminateActive(); CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().startOneServer(); assertValue(client1, null); assertValue(client2, null); @@ -160,7 +158,6 @@ public void testClusteredWriteBehindCAS() throws Exception { CLUSTER.getClusterControl().terminateActive(); CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().startOneServer(); assertValue(cache, "new value"); checkValueFromLoaderWriter(cache, "new value"); From 126d3e21a06acf04ed67a0664a19d9aeecc6a345 Mon Sep 17 00:00:00 2001 From: Venkata Sairam Madduri Date: Fri, 16 Nov 2018 16:22:24 +0530 Subject: [PATCH 022/372] Refactor clustered write-behind tests --- ...icClusteredWriteBehindMultiClientTest.java | 88 ++++++ .../BasicClusteredWriteBehindTest.java | 260 +++--------------- ...WriteBehindWithPassiveMultiClientTest.java | 98 +++++++ ...icClusteredWriteBehindWithPassiveTest.java | 158 ++--------- .../writebehind/RecordingLoaderWriter.java | 6 +- .../writebehind/WriteBehindTestBase.java | 116 ++++++++ 6 files changed, 359 insertions(+), 367 deletions(-) create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java new file mode 100644 index 0000000000..bb638b5e2f --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java @@ -0,0 +1,88 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered.writebehind; + +import org.ehcache.Cache; +import org.ehcache.PersistentCacheManager; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.terracotta.testing.rules.Cluster; + +import java.io.File; + +import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + +public class BasicClusteredWriteBehindMultiClientTest extends WriteBehindTestBase { + + @ClassRule + public static Cluster CLUSTER = + newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + + private PersistentCacheManager cacheManager1; + private PersistentCacheManager cacheManager2; + + private Cache client1; + private Cache client2; + + @Before + public void setUp() throws Exception { + super.setUp(); + + CLUSTER.getClusterControl().startAllServers(); + CLUSTER.getClusterControl().waitForActive(); + + cacheManager1 = createCacheManager(CLUSTER.getConnectionURI()); + cacheManager2 = createCacheManager(CLUSTER.getConnectionURI()); + + client1 = cacheManager1.getCache(CACHE_NAME, Long.class, String.class); + client2 = cacheManager2.getCache(CACHE_NAME, Long.class, String.class); + } + + @After + public void tearDown() throws Exception { + if (cacheManager1 != null) { + cacheManager1.close(); + } + + if (cacheManager2 != null) { + cacheManager2.close(); + cacheManager2.destroy(); + } + } + + @Test + public void testWriteBehindMultipleClients() throws Exception { + client1.put(KEY, "The one from client1"); + client2.put(KEY, "The one from client2"); + assertValue(client1, "The one from client2"); + client1.remove(KEY); + client2.put(KEY, "The one from client2"); + client1.put(KEY, "The one from client1"); + assertValue(client2, "The one from client1"); + client2.remove(KEY); + assertValue(client1, null); + client1.put(KEY, "The one from client1"); + client1.put(KEY, "The one one from client1"); + client2.remove(KEY); + client2.put(KEY, "The one from client2"); + client2.put(KEY, "The one one from client2"); + + checkValueFromLoaderWriter(client1, "The one one from client2"); + } +} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java index 0b503c5ab7..d89351e168 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java @@ -17,23 +17,9 @@ package org.ehcache.clustered.writebehind; import org.ehcache.Cache; -import org.ehcache.CacheManager; import org.ehcache.PersistentCacheManager; -import org.ehcache.clustered.ClusteredTests; -import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; -import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; -import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; -import org.ehcache.clustered.common.Consistency; -import org.ehcache.config.CacheConfiguration; -import org.ehcache.config.builders.CacheManagerBuilder; -import org.ehcache.config.builders.ResourcePoolsBuilder; -import org.ehcache.config.builders.WriteBehindConfigurationBuilder; -import org.ehcache.config.units.EntryUnit; -import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; import org.junit.After; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; @@ -44,29 +30,14 @@ import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; -import java.time.Duration; -import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.concurrent.TimeUnit; -import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; -import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; -import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class BasicClusteredWriteBehindTest extends ClusteredTests { - - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" + - "\n"; +public class BasicClusteredWriteBehindTest extends WriteBehindTestBase { @Rule public Timeout timeout = new Timeout(1, TimeUnit.MINUTES); @@ -77,240 +48,83 @@ public class BasicClusteredWriteBehindTest extends ClusteredTests { public static Cluster CLUSTER = newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); - @BeforeClass - public static void waitForActive() throws Exception { + private PersistentCacheManager cacheManager; + private Cache cache; + + @Before + public void setUp() throws Exception { + super.setUp(); + + CLUSTER.getClusterControl().startAllServers(); CLUSTER.getClusterControl().waitForActive(); + + cacheManager = createCacheManager(CLUSTER.getConnectionURI()); + cache = cacheManager.getCache(CACHE_NAME, Long.class, String.class); } @After - public void threadDump() { - if(doThreadDump) { + public void tearDown() throws Exception { + if (doThreadDump) { System.out.println("Performing thread dump"); ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true); Arrays.stream(threadInfos).forEach(System.out::println); } - } - - private final List cacheRecords = new ArrayList<>(); - - private static final String CACHE_NAME = "cache-1"; - private static final long KEY = 1L; - - private RecordingLoaderWriter loaderWriter; - @Before - public void setUp() { - loaderWriter = new RecordingLoaderWriter<>(); + if (cacheManager != null) { + cacheManager.close(); + cacheManager.destroy(); + } } @Test - public void testBasicClusteredWriteBehind() { - PersistentCacheManager cacheManager = createCacheManager(); - Cache cache = cacheManager.getCache(CACHE_NAME, Long.class, String.class); - + public void testBasicClusteredWriteBehind() throws Exception { for (int i = 0; i < 10; i++) { - put(cache, String.valueOf(i)); + cache.put(KEY, String.valueOf(i)); } - assertValue(cache, String.valueOf(9)); + assertValue(cache, "9"); - verifyRecords(cache); - cache.clear(); + checkValueFromLoaderWriter(cache, "9"); doThreadDump = false; } @Test - public void testWriteBehindMultipleClients() { - PersistentCacheManager cacheManager1 = createCacheManager(); - PersistentCacheManager cacheManager2 = createCacheManager(); - Cache client1 = cacheManager1.getCache(CACHE_NAME, Long.class, String.class); - Cache client2 = cacheManager2.getCache(CACHE_NAME, Long.class, String.class); - - put(client1, "The one from client1"); - put(client2, "The one one from client2"); - assertValue(client1, "The one one from client2"); - remove(client1); - put(client2, "The one from client2"); - put(client1, "The one one from client1"); - assertValue(client2, "The one one from client1"); - remove(client2); - assertValue(client1, null); - put(client1, "The one from client1"); - put(client1, "The one one from client1"); - remove(client2); - put(client2, "The one from client2"); - put(client2, "The one one from client2"); - remove(client1); - assertValue(client2, null); - - verifyRecords(client1); - client1.clear(); - - doThreadDump = false; - } - - @Test - public void testClusteredWriteBehindCAS() { - PersistentCacheManager cacheManager = createCacheManager(); - Cache cache = cacheManager.getCache(CACHE_NAME, Long.class, String.class); - putIfAbsent(cache, "First value", true); + public void testClusteredWriteBehindCAS() throws Exception { + cache.putIfAbsent(KEY, "First value"); assertValue(cache,"First value"); - putIfAbsent(cache, "Second value", false); + cache.putIfAbsent(KEY, "Second value"); assertValue(cache, "First value"); - put(cache, "First value again"); + cache.put(KEY, "First value again"); assertValue(cache, "First value again"); - replace(cache, "Replaced First value", true); + cache.replace(KEY, "Replaced First value"); assertValue(cache, "Replaced First value"); - replace(cache, "Replaced First value", "Replaced First value again", true); + cache.replace(KEY, "Replaced First value", "Replaced First value again"); assertValue(cache, "Replaced First value again"); - replace(cache, "Replaced First", "Tried Replacing First value again", false); + cache.replace(KEY, "Replaced First", "Tried Replacing First value again"); assertValue(cache, "Replaced First value again"); - condRemove(cache, "Replaced First value again", true); + cache.remove(KEY, "Replaced First value again"); assertValue(cache, null); - replace(cache, "Trying to replace value", false); + cache.replace(KEY, "Trying to replace value"); assertValue(cache, null); - put(cache, "new value", true); + cache.put(KEY, "new value"); assertValue(cache, "new value"); - condRemove(cache, "new value", false); + cache.remove(KEY); - verifyRecords(cache); - cache.clear(); + checkValueFromLoaderWriter(cache, null); doThreadDump = false; } @Test - public void testClusteredWriteBehindLoading() { - CacheManager cacheManager = createCacheManager(); - Cache cache = cacheManager.getCache(CACHE_NAME, Long.class, String.class); - - put(cache,"Some value"); - tryFlushingUpdatesToSOR(cache); + public void testClusteredWriteBehindLoading() throws Exception { + cache.put(KEY, "Some value"); + checkValueFromLoaderWriter(cache, "Some value"); cache.clear(); assertThat(cache.get(KEY), notNullValue()); - cache.clear(); - doThreadDump = false; } - - private void assertValue(Cache cache, String value) { - assertThat(cache.get(KEY), is(value)); - } - - private void put(Cache cache, String value) { - put(cache, value, true); - } - - private void put(Cache cache, String value, boolean addToCacheRecords) { - cache.put(KEY, value); - if (addToCacheRecords) { - cacheRecords.add(new Record(KEY, cache.get(KEY))); - } - } - - private void putIfAbsent(Cache cache, String value, boolean addToCacheRecords) { - cache.putIfAbsent(KEY, value); - if (addToCacheRecords) { - cacheRecords.add(new Record(KEY, cache.get(KEY))); - } - } - - private void replace(Cache cache, String value, boolean addToCacheRecords) { - cache.replace(KEY, value); - if (addToCacheRecords) { - cacheRecords.add(new Record(KEY, cache.get(KEY))); - } - } - - private void replace(Cache cache, String oldValue, String newValue, boolean addToCacheRecords) { - cache.replace(KEY, oldValue, newValue); - if (addToCacheRecords) { - cacheRecords.add(new Record(KEY, cache.get(KEY))); - } - } - - private void remove(Cache cache) { - cache.remove(KEY); - cacheRecords.add(new Record(KEY, null)); - } - - private void condRemove(Cache cache, String value, boolean addToCacheRecords) { - cache.remove(KEY, value); - if (addToCacheRecords) { - cacheRecords.add(new Record(KEY, null)); - } - } - - private void verifyRecords(Cache cache) { - tryFlushingUpdatesToSOR(cache); - - Map> loaderWriterRecords = loaderWriter.getRecords(); - - Map track = new HashMap<>(); - for (Record cacheRecord : cacheRecords) { - Long key = cacheRecord.getKey(); - int next = track.compute(key, (k, v) -> v == null ? 0 : v + 1); - assertThat(loaderWriterRecords.get(key).get(next), is(cacheRecord.getValue())); - } - } - - private void tryFlushingUpdatesToSOR(Cache cache) { - int retryCount = 1000; - int i = 0; - while (true) { - String value = "flush_queue_" + i; - put(cache, value, false); - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - if (value.equals(loaderWriter.load(KEY))) break; - if (i > retryCount) { - throw new RuntimeException("Couldn't flush updates to SOR after " + retryCount + " tries"); - } - i++; - } - } - - private PersistentCacheManager createCacheManager() { - CacheConfiguration cacheConfiguration = - newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() - .heap(10, EntryUnit.ENTRIES) - .offheap(1, MemoryUnit.MB) - .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) - .withLoaderWriter(loaderWriter) - .add(WriteBehindConfigurationBuilder.newUnBatchedWriteBehindConfiguration()) - .withResilienceStrategy(new ThrowingResilienceStrategy<>()) - .add(new ClusteredStoreConfiguration(Consistency.STRONG)) - .build(); - - return CacheManagerBuilder - .newCacheManagerBuilder() - .with(cluster(CLUSTER.getConnectionURI().resolve("/cm-wb")).timeouts(TimeoutsBuilder.timeouts().read(Duration.ofSeconds(30)).write(Duration.ofSeconds(30))).autoCreate()) - .withCache(CACHE_NAME, cacheConfiguration) - .build(true); - } - - private static final class Record { - private final Long key; - private final String value; - - private Record(Long key, String value) { - this.key = key; - this.value = value; - } - - Long getKey() { - return key; - } - - String getValue() { - return value; - } - } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java new file mode 100644 index 0000000000..73e2de1cf1 --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java @@ -0,0 +1,98 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered.writebehind; + +import org.ehcache.Cache; +import org.ehcache.PersistentCacheManager; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.terracotta.testing.rules.Cluster; + +import java.io.File; + +import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + +public class BasicClusteredWriteBehindWithPassiveMultiClientTest extends WriteBehindTestBase { + + @ClassRule + public static Cluster CLUSTER = + newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + + private PersistentCacheManager cacheManager1; + private PersistentCacheManager cacheManager2; + + private Cache client1; + private Cache client2; + + @Before + public void setUp() throws Exception { + super.setUp(); + + CLUSTER.getClusterControl().startAllServers(); + CLUSTER.getClusterControl().waitForActive(); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); + + cacheManager1 = createCacheManager(CLUSTER.getConnectionURI()); + cacheManager2 = createCacheManager(CLUSTER.getConnectionURI()); + + client1 = cacheManager1.getCache(CACHE_NAME, Long.class, String.class); + client2 = cacheManager2.getCache(CACHE_NAME, Long.class, String.class); + } + + @After + public void tearDown() throws Exception { + if (cacheManager1 != null) { + cacheManager1.close(); + } + + if (cacheManager2 != null) { + cacheManager2.close(); + cacheManager2.destroy(); + } + } + + @Test + public void testWriteBehindMultipleClients() throws Exception { + client1.put(KEY, "The one from client1"); + client2.put(KEY, "The one from client2"); + assertValue(client1, "The one from client2"); + client1.remove(KEY); + client2.put(KEY, "The one from client2"); + client1.put(KEY, "The one from client1"); + assertValue(client2, "The one from client1"); + client2.remove(KEY); + assertValue(client1, null); + client1.put(KEY, "The one from client1"); + client1.put(KEY, "The one one from client1"); + assertValue(client2, "The one one from client1"); + client2.remove(KEY); + assertValue(client1, null); + client2.put(KEY, "The one from client2"); + client2.put(KEY, "The one one from client2"); + assertValue(client1, "The one one from client2"); + + CLUSTER.getClusterControl().terminateActive(); + CLUSTER.getClusterControl().waitForActive(); + + assertValue(client1, "The one one from client2"); + assertValue(client2, "The one one from client2"); + + checkValueFromLoaderWriter(client1, "The one one from client2"); + } +} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java index 8afce234b7..bc57ff166b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java @@ -18,69 +18,47 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; -import org.ehcache.clustered.ClusteredTests; -import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; -import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; -import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; -import org.ehcache.clustered.common.Consistency; -import org.ehcache.config.CacheConfiguration; -import org.ehcache.config.builders.CacheManagerBuilder; -import org.ehcache.config.builders.ResourcePoolsBuilder; -import org.ehcache.config.builders.WriteBehindConfigurationBuilder; -import org.ehcache.config.units.EntryUnit; -import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; +import org.junit.After; import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; import java.io.File; -import java.time.Duration; -import java.util.List; -import java.util.Map; - -import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; -import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class BasicClusteredWriteBehindWithPassiveTest extends ClusteredTests { +import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" + - "\n"; +public class BasicClusteredWriteBehindWithPassiveTest extends WriteBehindTestBase { @ClassRule public static Cluster CLUSTER = newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + private PersistentCacheManager cacheManager; + private Cache cache; + @Before - public void waitForActive() throws Exception { + public void setUp() throws Exception { + super.setUp(); + CLUSTER.getClusterControl().startAllServers(); CLUSTER.getClusterControl().waitForActive(); CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); - } - private static final String CACHE_NAME = "cache-1"; - private static final long KEY = 1L; - - private RecordingLoaderWriter loaderWriter; + cacheManager = createCacheManager(CLUSTER.getConnectionURI()); + cache = cacheManager.getCache(CACHE_NAME, Long.class, String.class); + } - @Before - public void setUp() { - loaderWriter = new RecordingLoaderWriter<>(); + @After + public void tearDown() throws Exception { + if (cacheManager != null) { + cacheManager.close(); + cacheManager.destroy(); + } } @Test public void testBasicClusteredWriteBehind() throws Exception { - PersistentCacheManager cacheManager = createCacheManager(); - Cache cache = cacheManager.getCache(CACHE_NAME, Long.class, String.class); - for (int i = 0; i < 10; i++) { cache.put(KEY, String.valueOf(i)); } @@ -92,51 +70,10 @@ public void testBasicClusteredWriteBehind() throws Exception { assertValue(cache, "9"); checkValueFromLoaderWriter(cache, String.valueOf(9)); - - cache.clear(); - } - - @Test - public void testWriteBehindMultipleClients() throws Exception { - PersistentCacheManager cacheManager1 = createCacheManager(); - PersistentCacheManager cacheManager2 = createCacheManager(); - Cache client1 = cacheManager1.getCache(CACHE_NAME, Long.class, String.class); - Cache client2 = cacheManager2.getCache(CACHE_NAME, Long.class, String.class); - - client1.put(KEY, "The one from client1"); - client2.put(KEY, "The one from client2"); - assertValue(client1, "The one from client2"); - client1.remove(KEY); - client2.put(KEY, "The one from client2"); - client1.put(KEY, "The one from client1"); - assertValue(client2, "The one from client1"); - client2.remove(KEY); - assertValue(client1, null); - client1.put(KEY, "The one from client1"); - client1.put(KEY, "The one one from client1"); - assertValue(client2, "The one one from client1"); - client2.remove(KEY); - assertValue(client1, null); - client2.put(KEY, "The one from client2"); - client2.put(KEY, "The one one from client2"); - assertValue(client1, "The one one from client2"); - client1.remove(KEY); - assertValue(client2, null); - - CLUSTER.getClusterControl().terminateActive(); - CLUSTER.getClusterControl().waitForActive(); - - assertValue(client1, null); - assertValue(client2, null); - checkValueFromLoaderWriter(client1, null); - - client1.clear(); } @Test public void testClusteredWriteBehindCAS() throws Exception { - PersistentCacheManager cacheManager = createCacheManager(); - Cache cache = cacheManager.getCache(CACHE_NAME, Long.class, String.class); cache.putIfAbsent(KEY, "First value"); assertValue(cache,"First value"); cache.putIfAbsent(KEY, "Second value"); @@ -160,63 +97,6 @@ public void testClusteredWriteBehindCAS() throws Exception { CLUSTER.getClusterControl().waitForActive(); assertValue(cache, "new value"); - checkValueFromLoaderWriter(cache, "new value"); - - cache.clear(); - } - - private void assertValue(Cache cache, String value) { - assertThat(cache.get(KEY), is(value)); - } - - private void checkValueFromLoaderWriter(Cache cache, String expected) throws Exception { - tryFlushingUpdatesToSOR(cache); - - Map> records = loaderWriter.getRecords(); - List keyRecords = records.get(KEY); - - int index = keyRecords.size() - 1; - while (index >= 0 && keyRecords.get(index) != null && keyRecords.get(index).startsWith("flush_queue")) { - index--; - } - - assertThat(keyRecords.get(index), is(expected)); - } - - private void tryFlushingUpdatesToSOR(Cache cache) throws Exception { - int retryCount = 1000; - int i = 0; - while (true) { - String value = "flush_queue_" + i; - cache.put(KEY, value); - Thread.sleep(100); - String loadedValue = loaderWriter.load(KEY); - if (loadedValue != null && loadedValue.startsWith("flush_queue")) { - break; - } - if (i > retryCount) { - throw new AssertionError("Couldn't flush updates to SOR after " + retryCount + " tries"); - } - i++; - } - } - - private PersistentCacheManager createCacheManager() { - CacheConfiguration cacheConfiguration = - newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() - .heap(10, EntryUnit.ENTRIES) - .offheap(1, MemoryUnit.MB) - .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) - .withLoaderWriter(loaderWriter) - .add(WriteBehindConfigurationBuilder.newUnBatchedWriteBehindConfiguration()) - .withResilienceStrategy(new ThrowingResilienceStrategy<>()) - .add(new ClusteredStoreConfiguration(Consistency.STRONG)) - .build(); - - return CacheManagerBuilder - .newCacheManagerBuilder() - .with(cluster(CLUSTER.getConnectionURI().resolve("/cm-wb")).timeouts(TimeoutsBuilder.timeouts().read(Duration.ofMinutes(1)).write(Duration.ofMinutes(1))).autoCreate()) - .withCache(CACHE_NAME, cacheConfiguration) - .build(true); + checkValueFromLoaderWriter(cache,"new value"); } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/RecordingLoaderWriter.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/RecordingLoaderWriter.java index e37557687c..c24a9736f6 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/RecordingLoaderWriter.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/RecordingLoaderWriter.java @@ -62,11 +62,7 @@ private void record(K key, V value) { records.computeIfAbsent(key, k -> new ArrayList<>()).add(value); } - public synchronized Map> getRecords() { + synchronized Map> getRecords() { return Collections.unmodifiableMap(records); } - - public void clear() { - records.clear(); - } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java new file mode 100644 index 0000000000..ea7b04bf33 --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java @@ -0,0 +1,116 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered.writebehind; + +import org.ehcache.Cache; +import org.ehcache.PersistentCacheManager; +import org.ehcache.clustered.ClusteredTests; +import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; +import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; +import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; +import org.ehcache.clustered.common.Consistency; +import org.ehcache.config.CacheConfiguration; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.config.builders.WriteBehindConfigurationBuilder; +import org.ehcache.config.units.EntryUnit; +import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; +import org.junit.Before; + +import java.net.URI; +import java.time.Duration; +import java.util.List; +import java.util.Map; + +import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; +import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +public class WriteBehindTestBase extends ClusteredTests { + + static final String RESOURCE_CONFIG = + "" + + "" + + "64" + + "" + + "\n"; + + static final String CACHE_NAME = "cache-1"; + static final long KEY = 1L; + + private static final String FLUSH_QUEUE_MARKER = "FLUSH_QUEUE"; + + private RecordingLoaderWriter loaderWriter; + + @Before + public void setUp() throws Exception { + loaderWriter = new RecordingLoaderWriter<>(); + } + + void checkValueFromLoaderWriter(Cache cache, + String expected) throws Exception { + tryFlushingUpdatesToSOR(cache); + + Map> records = loaderWriter.getRecords(); + List keyRecords = records.get(KEY); + + int index = keyRecords.size() - 1; + while (index >= 0 && keyRecords.get(index) != null && keyRecords.get(index).equals(FLUSH_QUEUE_MARKER)) { + index--; + } + + assertThat(keyRecords.get(index), is(expected)); + } + + private void tryFlushingUpdatesToSOR(Cache cache) throws Exception { + int retryCount = 1000; + while (retryCount-- != 0) { + cache.put(KEY, FLUSH_QUEUE_MARKER); + Thread.sleep(100); + String loadedValue = loaderWriter.load(KEY); + if (loadedValue != null && loadedValue.equals(FLUSH_QUEUE_MARKER)) { + return; + } + } + throw new AssertionError("Couldn't flush updates to SOR after " + retryCount + " tries"); + } + + void assertValue(Cache cache, String value) { + assertThat(cache.get(KEY), is(value)); + } + + PersistentCacheManager createCacheManager(URI clusterUri) { + CacheConfiguration cacheConfiguration = + newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() + .heap(10, EntryUnit.ENTRIES) + .offheap(1, MemoryUnit.MB) + .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) + .withLoaderWriter(loaderWriter) + .add(WriteBehindConfigurationBuilder.newUnBatchedWriteBehindConfiguration()) + .withResilienceStrategy(new ThrowingResilienceStrategy<>()) + .add(new ClusteredStoreConfiguration(Consistency.STRONG)) + .build(); + + return CacheManagerBuilder + .newCacheManagerBuilder() + .with(cluster(clusterUri.resolve("/cm-wb")).timeouts(TimeoutsBuilder.timeouts().read(Duration.ofMinutes(1)).write(Duration.ofMinutes(1))).autoCreate()) + .withCache(CACHE_NAME, cacheConfiguration) + .build(true); + } +} From 3401f77c1ce6b6104a7af60a315ddb474f43bafd Mon Sep 17 00:00:00 2001 From: Venkata Sairam Madduri Date: Mon, 26 Nov 2018 11:55:58 +0530 Subject: [PATCH 023/372] Use CacheLoadingException instead of CacheIterationException --- .../internal/loaderwriter/ClusteredLoaderWriterStore.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java index 8acf69ff81..4083faa783 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java @@ -15,7 +15,6 @@ */ package org.ehcache.clustered.client.internal.loaderwriter; -import org.ehcache.CacheIterationException; import org.ehcache.clustered.client.internal.store.ClusteredStore; import org.ehcache.clustered.client.internal.store.ClusteredValueHolder; import org.ehcache.clustered.client.internal.store.ResolvedChain; @@ -40,6 +39,7 @@ import org.ehcache.core.spi.time.TimeSourceService; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.loaderwriter.CacheLoaderWriterConfiguration; +import org.ehcache.spi.loaderwriter.CacheLoadingException; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.spi.service.ServiceDependencies; @@ -92,7 +92,7 @@ protected ValueHolder getInternal(K key) throws StoreAccessException, Timeout try { value = cacheLoaderWriter.load(key); } catch (Exception e) { - throw new StorePassThroughException(new CacheIterationException(e)); + throw new StorePassThroughException(new CacheLoadingException(e)); } if (value == null) { return null; From d140e4585e221f28ce1ab2c61d0d9739176c6789 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 27 Nov 2018 11:12:05 -0500 Subject: [PATCH 024/372] Upgrade to Gradle 5, and upgrade all gradle plugins to latest for good measure --- build.gradle | 6 +++--- buildSrc/build.gradle | 2 +- demos/build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 56177 -> 56177 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 4 ---- xml/build.gradle | 2 +- 7 files changed, 7 insertions(+), 11 deletions(-) diff --git a/build.gradle b/build.gradle index 202ad17493..eeb52c5238 100644 --- a/build.gradle +++ b/build.gradle @@ -19,12 +19,12 @@ import org.gradle.internal.jvm.Jvm plugins { // This adds tasks to auto close or release nexus staging repos // see https://github.com/Codearte/gradle-nexus-staging-plugin/ - id 'io.codearte.nexus-staging' version '0.9.0' + id 'io.codearte.nexus-staging' version '0.12.0' // This adds the ability to print a taskTree // ./gradlew ... taskTree - id "com.dorongold.task-tree" version "1.3" + id "com.dorongold.task-tree" version "1.3.1" // Declare spotbugs at the top - id 'com.github.spotbugs' version '1.6.3' apply false + id 'com.github.spotbugs' version '1.6.5' apply false } wrapper { diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index abd602ec69..005e117967 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -20,5 +20,5 @@ repositories { jcenter() } dependencies { compile gradleApi() compile localGroovy() - compile 'com.github.jengelman.gradle.plugins:shadow:2.0.4' + compile 'com.github.jengelman.gradle.plugins:shadow:4.0.3' } diff --git a/demos/build.gradle b/demos/build.gradle index 4e40075d0a..8653acdb1f 100644 --- a/demos/build.gradle +++ b/demos/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'org.gretty' version '2.1.0' apply false + id 'org.gretty' version '2.2.0' apply false } subprojects { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 13536770052936a92b204cc34e72284a03a6903c..29953ea141f55e3b8fc691d31b5ca8816d89fa87 100644 GIT binary patch delta 75 zcmeykjrrp?<_YF3`^8VXPqdC<{aEy|h;iZp>5bcsPYN+H1bDM^WdGhdRg8gwK?H~= bKR6{bS>lv7Sp8=AQ}+Z|K+=;nZ+id$ib5We delta 75 zcmeykjrrp?<_YF3`MH@46Rl%dKNWo}Vw`wDdgFHElR_*E0p9E!7gufI5o2Ir5CP)J a4^GKUmN=yiR=?T()I9+fko08D+a3T#i5yt~ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4e974715fd..ee671127ff 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle index 3c3b31c74e..3d830fcd1e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,3 @@ include "api", "spi-tester", "core", "core-spi-test", "impl", "management", "transactions", "107", "xml", "clustered", "clustered:common", "clustered:client", "clustered:server", "clustered:integration-test", "clustered:clustered-dist", "clustered:ops-tool", "integration-test", "dist", "osgi-test", "demos", "demos:00-NoCache", "demos:01-CacheAside", "docs" - -// This is recommended to make sure publishing works correctly with the new default to be established -// in Gradle 5. It can be removed when moving to Gradle 5. -enableFeaturePreview('STABLE_PUBLISHING') diff --git a/xml/build.gradle b/xml/build.gradle index 966c2747a6..6b58528797 100644 --- a/xml/build.gradle +++ b/xml/build.gradle @@ -15,7 +15,7 @@ */ plugins { - id 'org.unbroken-dome.xjc' version '1.1.3' + id 'org.unbroken-dome.xjc' version '1.4.1' id 'com.github.hauner.jarTest' version '1.0.1' } From 7925d2a904c0368c9bf30152aee7f3809ff799a1 Mon Sep 17 00:00:00 2001 From: Albin Suresh Date: Mon, 3 Dec 2018 11:34:36 +0530 Subject: [PATCH 025/372] Bump up terracotta dependencies --- gradle.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index f37e676359..a9faa512ed 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,10 +9,10 @@ slf4jVersion = 1.7.25 sizeofVersion = 0.3.0 # Terracotta clustered -terracottaPlatformVersion = 5.5.2-pre3 -terracottaApisVersion = 1.5.2-pre1 -terracottaCoreVersion = 5.5.2-pre2 -terracottaPassthroughTestingVersion = 1.5.2-pre1 +terracottaPlatformVersion = 5.6.0-pre2 +terracottaApisVersion = 1.6.0-pre1 +terracottaCoreVersion = 5.6.0-pre3 +terracottaPassthroughTestingVersion = 1.6.0-pre1 # Test lib versions junitVersion = 4.12 From e7efdcd93e7392ab3305a25c6f6d20b73ab53c2a Mon Sep 17 00:00:00 2001 From: Albin Suresh Date: Mon, 3 Dec 2018 18:59:03 +0530 Subject: [PATCH 026/372] Bump up terracotta dependencies --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index a9faa512ed..106d512ea3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,9 +9,9 @@ slf4jVersion = 1.7.25 sizeofVersion = 0.3.0 # Terracotta clustered -terracottaPlatformVersion = 5.6.0-pre2 +terracottaPlatformVersion = 5.6.0-pre3 terracottaApisVersion = 1.6.0-pre1 -terracottaCoreVersion = 5.6.0-pre3 +terracottaCoreVersion = 5.6.0-pre4 terracottaPassthroughTestingVersion = 1.6.0-pre1 # Test lib versions From d15f4700cdfcb7339d6432f754046f29d1f25ecc Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Wed, 4 Jul 2018 16:04:55 -0400 Subject: [PATCH 027/372] Allow to pass functions when creating ExpiryPolicyBuilder --- .../config/builders/ExpiryPolicyBuilder.java | 113 +++++++++++------- .../builders/ExpiryPolicyBuilderTest.java | 36 +++++- 2 files changed, 100 insertions(+), 49 deletions(-) diff --git a/impl/src/main/java/org/ehcache/config/builders/ExpiryPolicyBuilder.java b/impl/src/main/java/org/ehcache/config/builders/ExpiryPolicyBuilder.java index 75c289b179..2249254b67 100644 --- a/impl/src/main/java/org/ehcache/config/builders/ExpiryPolicyBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/ExpiryPolicyBuilder.java @@ -20,6 +20,7 @@ import java.time.Duration; import java.util.Objects; +import java.util.function.BiFunction; import java.util.function.Supplier; /** @@ -64,6 +65,19 @@ public static ExpiryPolicy timeToIdleExpiration(Duration timeToI return new TimeToIdleExpiryPolicy(timeToIdle); } + @FunctionalInterface + public interface TriFunction { + /** + * Applies this function to the given arguments. + * + * @param t the first function argument + * @param u the second function argument + * @param v the third function argument + * @return the function result + */ + R apply(T t, U u, V v); + } + /** * Fluent API for creating an {@link ExpiryPolicy} instance where you can specify constant values for creation, access and update time. * Unspecified values will be set to {@link ExpiryPolicy#INFINITE INFINITE} for create and {@code null} for access and update, matching @@ -75,9 +89,9 @@ public static ExpiryPolicyBuilder expiry() { return new ExpiryPolicyBuilder(); } - private Duration create = ExpiryPolicy.INFINITE; - private Duration access = null; - private Duration update = null; + private BiFunction create = (key, value) -> ExpiryPolicy.INFINITE; + private BiFunction, Duration> access = (key, value) -> null; + private TriFunction, Object, Duration> update = (key, oldValue, newValue) -> null; private ExpiryPolicyBuilder() {} @@ -92,7 +106,17 @@ public ExpiryPolicyBuilder create(Duration create) { if (create.isNegative()) { throw new IllegalArgumentException("Create duration must be positive"); } - this.create = create; + this.create = (a, b) -> create; + return this; + } + + /** + * Set a function giving the TTL since creation + * @param create Function giving the TTL since creation + * @return this builder + */ + public ExpiryPolicyBuilder create(BiFunction create) { + this.create = Objects.requireNonNull(create); return this; } @@ -106,7 +130,17 @@ public ExpiryPolicyBuilder access(Duration access) { if (access != null && access.isNegative()) { throw new IllegalArgumentException("Access duration must be positive"); } - this.access = access; + this.access = (a, b) -> access; + return this; + } + + /** + * Set a function giving the TTL since last access + * @param access Function giving the TTL since last access + * @return this builder + */ + public ExpiryPolicyBuilder access(BiFunction, Duration> access) { + this.access = Objects.requireNonNull(access); return this; } @@ -120,7 +154,17 @@ public ExpiryPolicyBuilder update(Duration update) { if (update != null && update.isNegative()) { throw new IllegalArgumentException("Update duration must be positive"); } - this.update = update; + this.update = (a, b, c) -> update; + return this; + } + + /** + * Set a function giving the TTL since last update + * @param update Function giving the TTL since last update + * @return this builder + */ + public ExpiryPolicyBuilder update(TriFunction, Object, Duration> update) { + this.update = Objects.requireNonNull(update); return this; } @@ -137,71 +181,48 @@ public ExpiryPolicy build() { */ private static class BaseExpiryPolicy implements ExpiryPolicy { - private final Duration create; - private final Duration access; - private final Duration update; + private final BiFunction create; + private final BiFunction, Duration> access; + private final TriFunction, Object, Duration> update; - BaseExpiryPolicy(Duration create, Duration access, Duration update) { + BaseExpiryPolicy(BiFunction create, + BiFunction, Duration> access, + TriFunction, Object, Duration> update) { this.create = create; this.access = access; this.update = update; } @Override public Duration getExpiryForCreation(Object key, Object value) { - return create; + return create.apply(key, value); } @Override public Duration getExpiryForAccess(Object key, Supplier value) { - return access; + return access.apply(key, value); } @Override public Duration getExpiryForUpdate(Object key, Supplier oldValue, Object newValue) { - return update; - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - final BaseExpiryPolicy that = (BaseExpiryPolicy) o; - - if (!Objects.equals(access, that.access)) return false; - if (!Objects.equals(create, that.create)) return false; - if (!Objects.equals(update, that.update)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = Objects.hashCode(create); - result = 31 * result + Objects.hashCode(access); - result = 31 * result + Objects.hashCode(update); - return result; - } - - @Override - public String toString() { - return this.getClass().getSimpleName() + "{" + - "create=" + create + - ", access=" + access + - ", update=" + update + - '}'; + return update.apply(key, oldValue, newValue); } } private static final class TimeToLiveExpiryPolicy extends BaseExpiryPolicy { TimeToLiveExpiryPolicy(Duration ttl) { - super(ttl, null, ttl); + super( + (a, b) -> ttl, + (a, b) -> null, + (a, b, c) -> ttl); } } private static final class TimeToIdleExpiryPolicy extends BaseExpiryPolicy { TimeToIdleExpiryPolicy(Duration tti) { - super(tti, tti, tti); + super( + (a, b) -> tti, + (a, b) -> tti, + (a, b, c) -> tti); } } } diff --git a/impl/src/test/java/org/ehcache/config/builders/ExpiryPolicyBuilderTest.java b/impl/src/test/java/org/ehcache/config/builders/ExpiryPolicyBuilderTest.java index 5f7b65a0cf..0858c15ef0 100644 --- a/impl/src/test/java/org/ehcache/config/builders/ExpiryPolicyBuilderTest.java +++ b/impl/src/test/java/org/ehcache/config/builders/ExpiryPolicyBuilderTest.java @@ -19,6 +19,8 @@ import org.ehcache.expiry.ExpiryPolicy; import org.junit.Test; +import java.time.Duration; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.nullValue; @@ -64,12 +66,40 @@ public void testTTLExpiration() { @Test public void testExpiration() { - java.time.Duration creation = java.time.Duration.ofSeconds(1L); - java.time.Duration access = java.time.Duration.ofSeconds(2L); - java.time.Duration update = java.time.Duration.ofSeconds(3L); + Duration creation = Duration.ofSeconds(1L); + Duration access = Duration.ofSeconds(2L); + Duration update = Duration.ofSeconds(3L); ExpiryPolicy expiry = ExpiryPolicyBuilder.expiry().create(creation).access(access).update(update).build(); assertThat(expiry.getExpiryForCreation(this, this), equalTo(creation)); assertThat(expiry.getExpiryForAccess(this, () -> this), equalTo(access)); assertThat(expiry.getExpiryForUpdate(this, () -> this,this), equalTo(update)); } + + @Test + public void testExpirationFunctions() { + Duration creation = Duration.ofSeconds(1L); + Duration access = Duration.ofSeconds(2L); + Duration update = Duration.ofSeconds(3L); + ExpiryPolicy expiry = ExpiryPolicyBuilder.expiry() + .create((k, v) -> { + assertThat(k, equalTo(10L)); + assertThat(v, equalTo(20L)); + return creation; + }) + .access((k, v) -> { + assertThat(k, equalTo(10L)); + assertThat(v.get(), equalTo(20L)); + return access; + }) + .update((k, v1, v2) -> { + assertThat(k, equalTo(10L)); + assertThat(v1.get(), equalTo(20L)); + assertThat(v2, equalTo(30L)); + return update; + }) + .build(); + assertThat(expiry.getExpiryForCreation(10L, 20L), equalTo(creation)); + assertThat(expiry.getExpiryForAccess(10L, () -> 20L), equalTo(access)); + assertThat(expiry.getExpiryForUpdate(10L, () -> 20L,30L), equalTo(update)); + } } From 346c4c1840830c97a290524ef58aaf4b4f9a1b9c Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Sat, 1 Dec 2018 22:29:48 -0500 Subject: [PATCH 028/372] Use generics in expiry policy builder --- .../config/builders/ExpiryPolicyBuilder.java | 163 ++++++++++++------ 1 file changed, 110 insertions(+), 53 deletions(-) diff --git a/impl/src/main/java/org/ehcache/config/builders/ExpiryPolicyBuilder.java b/impl/src/main/java/org/ehcache/config/builders/ExpiryPolicyBuilder.java index 2249254b67..9d1a4b7006 100644 --- a/impl/src/main/java/org/ehcache/config/builders/ExpiryPolicyBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/ExpiryPolicyBuilder.java @@ -26,7 +26,7 @@ /** * Builder and utilities for getting predefined {@link ExpiryPolicy} instances. */ -public final class ExpiryPolicyBuilder implements Builder>{ +public final class ExpiryPolicyBuilder implements Builder>{ /** * Get an {@link ExpiryPolicy} instance for a non expiring (ie. "eternal") cache. @@ -85,144 +85,201 @@ public interface TriFunction { * * @return an {@link ExpiryPolicy} builder */ - public static ExpiryPolicyBuilder expiry() { - return new ExpiryPolicyBuilder(); + public static ExpiryPolicyBuilder expiry() { + return new ExpiryPolicyBuilder<>(); } - private BiFunction create = (key, value) -> ExpiryPolicy.INFINITE; - private BiFunction, Duration> access = (key, value) -> null; - private TriFunction, Object, Duration> update = (key, oldValue, newValue) -> null; + private final BiFunction create; + private final BiFunction, Duration> access; + private final TriFunction, ? super V, Duration> update; - private ExpiryPolicyBuilder() {} + private ExpiryPolicyBuilder() { + this((k, v) -> ExpiryPolicy.INFINITE, (k, v) -> null, (k, oldV, newV) -> null); + } + + private ExpiryPolicyBuilder(BiFunction create, + BiFunction, Duration> access, + TriFunction, ? super V, Duration> update) { + this.create = create; + this.access = access; + this.update = update; + } /** - * Set TTL since creation + * Set TTL since creation. + *

+ * Note: Calling this method on a builder with an existing TTL since creation will override the previous value or function. * * @param create TTL since creation - * @return this builder + * @return a new builder with the TTL since creation */ - public ExpiryPolicyBuilder create(Duration create) { + public ExpiryPolicyBuilder create(Duration create) { Objects.requireNonNull(create, "Create duration cannot be null"); if (create.isNegative()) { throw new IllegalArgumentException("Create duration must be positive"); } - this.create = (a, b) -> create; - return this; + return create((a, b) -> create); } /** - * Set a function giving the TTL since creation + * Set a function giving the TTL since creation. + *

+ * Note: Calling this method on a builder with an existing TTL since creation will override the previous value or function. + * * @param create Function giving the TTL since creation - * @return this builder + * @return a new builder with the TTL creation calculation function */ - public ExpiryPolicyBuilder create(BiFunction create) { - this.create = Objects.requireNonNull(create); - return this; + public ExpiryPolicyBuilder create(BiFunction create) { + return new ExpiryPolicyBuilder<>(Objects.requireNonNull(create), access, update); } /** - * Set TTL since last access + * Set TTI since last access. + *

+ * Note: Calling this method on a builder with an existing TTI since last access will override the previous value or function. * - * @param access TTL since last access - * @return this builder + * @param access TTI since last access + * @return a new builder with the TTI since last access */ - public ExpiryPolicyBuilder access(Duration access) { + public ExpiryPolicyBuilder access(Duration access) { if (access != null && access.isNegative()) { throw new IllegalArgumentException("Access duration must be positive"); } - this.access = (a, b) -> access; - return this; + return access((a, b) -> access); } /** - * Set a function giving the TTL since last access - * @param access Function giving the TTL since last access - * @return this builder + * Set a function giving the TTI since last access. + *

+ * Note: Calling this method on a builder with an existing TTI since last access will override the previous value or function. + * + * @param access Function giving the TTI since last access + * @return a new builder with the TTI since last access calculation function */ - public ExpiryPolicyBuilder access(BiFunction, Duration> access) { - this.access = Objects.requireNonNull(access); - return this; + public ExpiryPolicyBuilder access(BiFunction, Duration> access) { + return new ExpiryPolicyBuilder<>(create, Objects.requireNonNull(access), update); } /** - * Set TTL since last update + * Set TTL since last update. + *

+ * Note: Calling this method on a builder with an existing TTL since last access will override the previous value or function. * * @param update TTL since last update - * @return this builder + * @return a new builder with the TTL since last update */ - public ExpiryPolicyBuilder update(Duration update) { + public ExpiryPolicyBuilder update(Duration update) { if (update != null && update.isNegative()) { throw new IllegalArgumentException("Update duration must be positive"); } - this.update = (a, b, c) -> update; - return this; + return update((a, b, c) -> update); } /** - * Set a function giving the TTL since last update + * Set a function giving the TTL since last update. + *

+ * Note: Calling this method on a builder with an existing TTL since last update will override the previous value or function. + * * @param update Function giving the TTL since last update - * @return this builder + * @return a new builder with the TTL since last update calculation function */ - public ExpiryPolicyBuilder update(TriFunction, Object, Duration> update) { - this.update = Objects.requireNonNull(update); - return this; + public ExpiryPolicyBuilder update(TriFunction, V2, Duration> update) { + return new ExpiryPolicyBuilder<>(create, access, Objects.requireNonNull(update)); } /** + * Builds an expiry policy instance. * * @return an {@link ExpiryPolicy} */ - public ExpiryPolicy build() { - return new BaseExpiryPolicy(create, access, update); + public ExpiryPolicy build() { + return new BaseExpiryPolicy<>(create, access, update); } /** * Simple implementation of the {@link ExpiryPolicy} interface allowing to set constants to each expiry types. */ - private static class BaseExpiryPolicy implements ExpiryPolicy { + private static class BaseExpiryPolicy implements ExpiryPolicy { - private final BiFunction create; - private final BiFunction, Duration> access; - private final TriFunction, Object, Duration> update; + private final BiFunction create; + private final BiFunction, Duration> access; + private final TriFunction, ? super V, Duration> update; - BaseExpiryPolicy(BiFunction create, - BiFunction, Duration> access, - TriFunction, Object, Duration> update) { + BaseExpiryPolicy(BiFunction create, + BiFunction, Duration> access, + TriFunction, ? super V, Duration> update) { this.create = create; this.access = access; this.update = update; } + @Override - public Duration getExpiryForCreation(Object key, Object value) { + public Duration getExpiryForCreation(K key, V value) { return create.apply(key, value); } @Override - public Duration getExpiryForAccess(Object key, Supplier value) { + public Duration getExpiryForAccess(K key, Supplier value) { return access.apply(key, value); } @Override - public Duration getExpiryForUpdate(Object key, Supplier oldValue, Object newValue) { + public Duration getExpiryForUpdate(K key, Supplier oldValue, V newValue) { return update.apply(key, oldValue, newValue); } } - private static final class TimeToLiveExpiryPolicy extends BaseExpiryPolicy { + private static final class TimeToLiveExpiryPolicy extends BaseExpiryPolicy { + private final Duration ttl; + TimeToLiveExpiryPolicy(Duration ttl) { super( (a, b) -> ttl, (a, b) -> null, (a, b, c) -> ttl); + this.ttl = ttl; + } + + @Override + public int hashCode() { + return ttl.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof TimeToLiveExpiryPolicy && ttl.equals(((TimeToLiveExpiryPolicy) obj).ttl); + } + + @Override + public String toString() { + return "TTL of " + ttl; } } - private static final class TimeToIdleExpiryPolicy extends BaseExpiryPolicy { + private static final class TimeToIdleExpiryPolicy extends BaseExpiryPolicy { + private final Duration tti; + TimeToIdleExpiryPolicy(Duration tti) { super( (a, b) -> tti, (a, b) -> tti, (a, b, c) -> tti); + this.tti = tti; + } + + @Override + public int hashCode() { + return tti.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof TimeToIdleExpiryPolicy && tti.equals(((TimeToIdleExpiryPolicy) obj).tti); + } + + @Override + public String toString() { + return "TTI of " + tti; } } } From d50b7710bc37891c1a6d703585aade059d860811 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Thu, 5 Jul 2018 11:39:39 -0400 Subject: [PATCH 029/372] Add performance documentation --- docs/src/docs/asciidoc/user/index.adoc | 1 + docs/src/docs/asciidoc/user/menu.adoc | 1 + docs/src/docs/asciidoc/user/performance.adoc | 138 ++++++++++++++++++ .../java/org/ehcache/docs/Performance.java | 58 ++++++++ 4 files changed, 198 insertions(+) create mode 100644 docs/src/docs/asciidoc/user/performance.adoc create mode 100644 integration-test/src/test/java/org/ehcache/docs/Performance.java diff --git a/docs/src/docs/asciidoc/user/index.adoc b/docs/src/docs/asciidoc/user/index.adoc index f5fda9f8ab..5b7b55d3be 100644 --- a/docs/src/docs/asciidoc/user/index.adoc +++ b/docs/src/docs/asciidoc/user/index.adoc @@ -56,4 +56,5 @@ Each topic below corresponds to a menu item at the left. |link:cache-event-listeners{outfilesuffix}[Cache Event Listeners]|Getting notified about events within the cache |link:eviction-advisor{outfilesuffix}[Eviction Advisor]|Affecting the way entries are chosen for eviction |link:class-loading{outfilesuffix}[Class loading]|Ehcache and `ClassLoader` interactions +|link:performance{outfilesuffix}[Performance Tuning]|Ehcache Performance Tuning |=== diff --git a/docs/src/docs/asciidoc/user/menu.adoc b/docs/src/docs/asciidoc/user/menu.adoc index 8bd2d1c68e..0a1c35ac32 100644 --- a/docs/src/docs/asciidoc/user/menu.adoc +++ b/docs/src/docs/asciidoc/user/menu.adoc @@ -26,6 +26,7 @@ Advanced topics:: - link:./cache-event-listeners{outfilesuffix}[Cache Event Listeners] - link:./eviction-advisor{outfilesuffix}[Eviction Advisor] - link:./class-loading{outfilesuffix}[Class loading in Ehcache] +- link:./performance{outfilesuffix}[Performance Tuning] Not published:: - link:./management{outfilesuffix}[Management and Monitoring] diff --git a/docs/src/docs/asciidoc/user/performance.adoc b/docs/src/docs/asciidoc/user/performance.adoc new file mode 100644 index 0000000000..b611c808f8 --- /dev/null +++ b/docs/src/docs/asciidoc/user/performance.adoc @@ -0,0 +1,138 @@ +--- +--- += Performance Tuning +ifndef::sourcedir35[] +include::common.adoc[] +endif::sourcedir35[] + +ifdef::notBuildingForSite[] +include::menu.adoc[] +endif::notBuildingForSite[] + +== Introduction + +Ehcache is fast. Really fast. +It was thought and made to be. +For example, a straight `get(key)` from the cache should be under 500ns. +That's fast and way sufficient for most purpose. + +Keep that in mind. Especially when comparing caching frameworks with a benchmark. +If something looks 10% faster it actually means 50ns faster. +Do you care that much about these 50ns to lose your precious time in benchmarking? + +That said, the way you configure Ehcache can have an impact on performance. +This document is a work in progress. +It will give you the performance impact of classical Ehcache configuration. +It will also give you some advance tuning possibilities. + +In the future, we will add some figures of what "slower" means. +However, always do your own benchmark. + +== Stores + +We probably know that the faster store is on-heap. +Until you overwhelm the garbage collector. + +Your next best bet is off-heap. + +Try to avoid disk. +Use a remote drive or even an HDD at your own risk. + +We won't talk about clustering here because it's a different realm and its performance are based on many factors. + +The next question would be: "Should I use a single tier?" Is using a single-tier off-heap faster than two-tiers? +The answer depends on what you do with it. +Having two tiers is a bit slower on writing. +It is also a bit slower on reading when the data is not found in the caching tier (on-heap). +However, it will be faster for an entry found is indeed found there. + +So again, it depends. +The more you follow the caching hypothesis that the same data is always reused (and so in the caching +tier), the more interesting having two tiers will be. + +== Byte Sizing + +A on-heap tier can be limited to a number of entries or a number of bytes. +When using bytes, we need to calculated the size of every object added to the cache. +This is of course much slower than calculating the number of entries. + +Size calculation is done using the https://github.com/ehcache/sizeof[SizeOf] library. +This library uses multiple magic tricks to do so. It selects the fastest one for a given environment. +Make sure of what is used to confirm you can't use a faster way on your platform. + +== Serialization + +Off-heap, disk and clustering need to serialize keys and values before storing them. +By default, the Java serialization is used. +It is well-known for not being the fastest thing around. +Ehcache uses it because it is supported out of the box. +However, you can increase performances by provoding your own serializers. + +== Copier + +By default, on-heap storage stores the entries by reference. +You might want to use a copier for whatever reason. +This can be much slower so watch out. + +== Loader-Writer + +Loader-writer is interesting for many reasons. +First, it protects you against the Thundering Herd. +However, it needs to pass through more complicated code to do so. + +We are expecting it to be a tiny slower. +But nothing noticeable enough to prevent you from using it. + +== Expiration + +A cache with no expiration will always be faster. + +=== Time to Live + +If you need to set an expiration time, TTL will be the faster one. +This is because the expiration time is calculated once when the entry is inserted in the cache. +But it still requires an expiration check at access time. + +So you can expect a 2% drop in performance when using TTL. Not bad. + +=== Time to Idle + +TTI is slower than TTL. +We need to recalculate the expiration time each time the entry is accessed. + +=== Custom + +In general, using a custom `ExpiryPolicy` will be the slowest. +Ehcache uses intrinsics to handle other cases. +When using a custom policy, you are on your own. + +== Allocation rate + +Ehcache won't allocate any object during a simple `get()`. +However, keep in mind that your configuration might do so. + +For instance, let's say you define an expiry policy like this. + +[source,java,indent=0] +---- +include::{sourcedir35}/integration-test/src/test/java/org/ehcache/docs/Performance.java[tag=expiryAllocation] +---- + +<1> Will instantiate a `Duration` every time an entry is accessed + +In this case, putting the `Duration` as a constant would solve the problem. + +== Time Source + +By default, Ehcache uses a `TimeSource` that will retrieve the system time at every call. It is fast but not super +duper fast. But it is super duper accurate. + +You can trade accuracy for speed by using a `TickingTimeSource`. Please read the javadoc for details but the concept is +that a timer will increase time instead of always retrieving system time. + +Switching to `TickingTimeSource`, even with a granularity of 1ms can improve the performance of a `get` of a high as 30%. + +The drawback is that a timer will continuously run. +Also, time might drift from the real time a bit. +Especially if the granularity or the systemUpdatePeriod is big. +But in most cases, the drifting doesn't matter much. diff --git a/integration-test/src/test/java/org/ehcache/docs/Performance.java b/integration-test/src/test/java/org/ehcache/docs/Performance.java new file mode 100644 index 0000000000..5fe2d704a6 --- /dev/null +++ b/integration-test/src/test/java/org/ehcache/docs/Performance.java @@ -0,0 +1,58 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.docs; + +import org.ehcache.CacheManager; +import org.ehcache.config.CacheConfiguration; +import org.ehcache.config.builders.ExpiryPolicyBuilder; +import org.ehcache.expiry.ExpiryPolicy; +import org.junit.Test; + +import java.time.Duration; +import java.util.function.Supplier; + +import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; +import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; +import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; + +/** + * Samples showing performance strategies. + */ +public class Performance { + + @Test + public void expiryAllocation() { + // tag::expiryAllocation[] + new ExpiryPolicy() { + @Override + public Duration getExpiryForCreation(Object key, Object value) { + return null; + } + + @Override + public Duration getExpiryForAccess(Object key, Supplier value) { + return Duration.ofSeconds(10); // <1> + } + + @Override + public Duration getExpiryForUpdate(Object key, Supplier oldValue, Object newValue) { + return null; + } + }; + // end::expiryAllocation[] + } +} From 768a9ec20c7dff6ab4bb2e8e55017dbed8e87101 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Fri, 7 Dec 2018 13:28:22 -0500 Subject: [PATCH 030/372] Fix typos and add precisions --- docs/src/docs/asciidoc/user/performance.adoc | 21 ++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/src/docs/asciidoc/user/performance.adoc b/docs/src/docs/asciidoc/user/performance.adoc index b611c808f8..6d6ea37e5c 100644 --- a/docs/src/docs/asciidoc/user/performance.adoc +++ b/docs/src/docs/asciidoc/user/performance.adoc @@ -38,13 +38,13 @@ Your next best bet is off-heap. Try to avoid disk. Use a remote drive or even an HDD at your own risk. -We won't talk about clustering here because it's a different realm and its performance are based on many factors. +We won't talk about clustering here because it's a different realm and its performance is based on many factors. The next question would be: "Should I use a single tier?" Is using a single-tier off-heap faster than two-tiers? The answer depends on what you do with it. Having two tiers is a bit slower on writing. It is also a bit slower on reading when the data is not found in the caching tier (on-heap). -However, it will be faster for an entry found is indeed found there. +However, it will be faster for an entry that is indeed found there. So again, it depends. The more you follow the caching hypothesis that the same data is always reused (and so in the caching @@ -53,7 +53,7 @@ tier), the more interesting having two tiers will be. == Byte Sizing A on-heap tier can be limited to a number of entries or a number of bytes. -When using bytes, we need to calculated the size of every object added to the cache. +When using bytes, we need to calculate the size of every object added to the cache. This is of course much slower than calculating the number of entries. Size calculation is done using the https://github.com/ehcache/sizeof[SizeOf] library. @@ -71,7 +71,7 @@ However, you can increase performances by provoding your own serializers. == Copier By default, on-heap storage stores the entries by reference. -You might want to use a copier for whatever reason. +You might want to use a copier to store entries by value for whatever reason. This can be much slower so watch out. == Loader-Writer @@ -80,7 +80,7 @@ Loader-writer is interesting for many reasons. First, it protects you against the Thundering Herd. However, it needs to pass through more complicated code to do so. -We are expecting it to be a tiny slower. +We are expecting it to be a tiny bit slower. But nothing noticeable enough to prevent you from using it. == Expiration @@ -90,7 +90,7 @@ A cache with no expiration will always be faster. === Time to Live If you need to set an expiration time, TTL will be the faster one. -This is because the expiration time is calculated once when the entry is inserted in the cache. +This is because the expiration time of an entry is calculated and updated ony when the entry is inserted or updated in the cache. But it still requires an expiration check at access time. So you can expect a 2% drop in performance when using TTL. Not bad. @@ -98,12 +98,12 @@ So you can expect a 2% drop in performance when using TTL. Not bad. === Time to Idle TTI is slower than TTL. -We need to recalculate the expiration time each time the entry is accessed. +We need to recalculate and update the expiration time each time the entry is accessed. === Custom In general, using a custom `ExpiryPolicy` will be the slowest. -Ehcache uses intrinsics to handle other cases. +Ehcache had optimised the handling to handle other cases. When using a custom policy, you are on your own. == Allocation rate @@ -130,9 +130,10 @@ duper fast. But it is super duper accurate. You can trade accuracy for speed by using a `TickingTimeSource`. Please read the javadoc for details but the concept is that a timer will increase time instead of always retrieving system time. -Switching to `TickingTimeSource`, even with a granularity of 1ms can improve the performance of a `get` of a high as 30%. +Switching to `TickingTimeSource`, even with a granularity of 1ms, can improve the performance of a `get` as high as 30%. The drawback is that a timer will continuously run. Also, time might drift from the real time a bit. -Especially if the granularity or the systemUpdatePeriod is big. +Especially if the granularity of the `systemUpdatePeriod` is big. +Is your expiration needs to be really tightly linked with real time, it can be a problem. But in most cases, the drifting doesn't matter much. From 81165853be4b286add5bc707fdbb834db069369d Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Fri, 7 Dec 2018 14:27:02 -0500 Subject: [PATCH 031/372] Add missing types --- .../src/test/java/org/ehcache/docs/Performance.java | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/integration-test/src/test/java/org/ehcache/docs/Performance.java b/integration-test/src/test/java/org/ehcache/docs/Performance.java index 5fe2d704a6..90972788e7 100644 --- a/integration-test/src/test/java/org/ehcache/docs/Performance.java +++ b/integration-test/src/test/java/org/ehcache/docs/Performance.java @@ -16,19 +16,12 @@ package org.ehcache.docs; -import org.ehcache.CacheManager; -import org.ehcache.config.CacheConfiguration; -import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.expiry.ExpiryPolicy; import org.junit.Test; import java.time.Duration; import java.util.function.Supplier; -import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; -import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; -import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; - /** * Samples showing performance strategies. */ @@ -37,19 +30,19 @@ public class Performance { @Test public void expiryAllocation() { // tag::expiryAllocation[] - new ExpiryPolicy() { + new ExpiryPolicy() { @Override public Duration getExpiryForCreation(Object key, Object value) { return null; } @Override - public Duration getExpiryForAccess(Object key, Supplier value) { + public Duration getExpiryForAccess(Object key, Supplier value) { return Duration.ofSeconds(10); // <1> } @Override - public Duration getExpiryForUpdate(Object key, Supplier oldValue, Object newValue) { + public Duration getExpiryForUpdate(Object key, Supplier oldValue, Object newValue) { return null; } }; From f883aab1d583dda680415bdfdc450c2b5283afd7 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Sun, 5 Aug 2018 19:38:48 -0400 Subject: [PATCH 032/372] Use an expiration strategy depending on expiration policy --- .../impl/internal/store/heap/OnHeapStore.java | 61 ++---- .../internal/store/heap/OnHeapStrategy.java | 154 ++++++++++++++++ .../store/heap/OnHeapStrategyTest.java | 170 +++++++++++++++++ .../OnHeapEvictionStrategyTest.java | 174 ++++++++++++++++++ 4 files changed, 511 insertions(+), 48 deletions(-) create mode 100644 impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java create mode 100644 impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java create mode 100644 integration-test/src/test/java/org/ehcache/integration/OnHeapEvictionStrategyTest.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index 01be072a1a..c53dc67d9f 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -149,6 +149,7 @@ public class OnHeapStore extends BaseStore implements HigherCachingT private final Copier valueCopier; private final SizeOfEngine sizeOfEngine; + private final OnHeapStrategy strategy; private volatile long capacity; private final EvictionAdvisor evictionAdvisor; @@ -236,6 +237,8 @@ public OnHeapStore(Configuration config, TimeSource timeSource, Copier this.map = new KeyCopyBackend<>(byteSized, keyCopier, castBackend(backingMapSupplier)); } + strategy = OnHeapStrategy.strategy(this, expiry, timeSource); + getObserver = createObserver("get", StoreOperationOutcomes.GetOutcome.class, true); putObserver = createObserver("put", StoreOperationOutcomes.PutOutcome.class, true); removeObserver = createObserver("remove", StoreOperationOutcomes.RemoveOutcome.class, true); @@ -287,7 +290,7 @@ public ValueHolder get(K key) throws StoreAccessException { return null; } - setAccessTimeAndExpiryThenReturnMappingOutsideLock(key, mapping, timeSource.getTimeMillis()); + strategy.setAccessTimeAndExpiryThenReturnMappingOutsideLock(key, mapping, timeSource.getTimeMillis()); getObserver.end(StoreOperationOutcomes.GetOutcome.HIT); return mapping; @@ -303,7 +306,7 @@ private OnHeapValueHolder getQuiet(K key) throws StoreAccessException { return null; } - if (mapping.isExpired(timeSource.getTimeMillis(), TimeUnit.MILLISECONDS)) { + if (strategy.isExpired(mapping)) { expireMappingUnderLock(key, mapping); return null; } @@ -453,7 +456,7 @@ public ValueHolder putIfAbsent(K key, V value, Consumer put) throws entryActuallyAdded.set(holder != null); } else { returnValue.set(mappedValue); - holder = setAccessTimeAndExpiryThenReturnMappingUnderLock(key, mappedValue, now, eventSink); + holder = strategy.setAccessTimeAndExpiryThenReturnMappingUnderLock(key, mappedValue, now, eventSink); if (holder == null) { delta -= mappedValue.size(); } @@ -505,7 +508,7 @@ public RemoveStatus remove(K key, V value) throws StoreAccessException { return null; } else { outcome.set(RemoveStatus.KEY_PRESENT); - OnHeapValueHolder holder = setAccessTimeAndExpiryThenReturnMappingUnderLock(key, mappedValue, now, eventSink); + OnHeapValueHolder holder = strategy.setAccessTimeAndExpiryThenReturnMappingUnderLock(key, mappedValue, now, eventSink); if (holder == null) { updateUsageInBytesIfRequired(- mappedValue.size()); } @@ -609,7 +612,7 @@ public ReplaceStatus replace(K key, V oldValue, V newValue) throws StoreAccessEx return holder; } else { outcome.set(ReplaceStatus.MISS_PRESENT); - OnHeapValueHolder holder = setAccessTimeAndExpiryThenReturnMappingUnderLock(key, mappedValue, now, eventSink); + OnHeapValueHolder holder = strategy.setAccessTimeAndExpiryThenReturnMappingUnderLock(key, mappedValue, now, eventSink); if (holder == null) { updateUsageInBytesIfRequired(- mappedValue.size()); } @@ -705,7 +708,7 @@ public ValueHolder getOrComputeIfAbsent(K key, Function> so } } else { - setAccessTimeAndExpiryThenReturnMappingOutsideLock(key, cachedValue, now); + strategy.setAccessTimeAndExpiryThenReturnMappingOutsideLock(key, cachedValue, now); } } @@ -1165,7 +1168,7 @@ public ValueHolder computeAndGet(K key, BiFunction computeIfAbsent(K key, Function ma } else { previousValue.set(mappedValue); outcome.set(StoreOperationOutcomes.ComputeIfAbsentOutcome.HIT); - holder = setAccessTimeAndExpiryThenReturnMappingUnderLock(key, mappedValue, now, eventSink); + holder = strategy.setAccessTimeAndExpiryThenReturnMappingUnderLock(key, mappedValue, now, eventSink); if (holder == null) { delta -= mappedValue.size(); } @@ -1352,45 +1355,7 @@ public StoreEventSource getStoreEventSource() { return storeEventDispatcher; } - private void setAccessTimeAndExpiryThenReturnMappingOutsideLock(K key, OnHeapValueHolder valueHolder, long now) { - Duration duration; - try { - duration = expiry.getExpiryForAccess(key, valueHolder); - if (duration != null && duration.isNegative()) { - duration = Duration.ZERO; - } - } catch (RuntimeException re) { - LOG.error("Expiry computation caused an exception - Expiry duration will be 0 ", re); - duration = Duration.ZERO; - } - valueHolder.accessed(now, duration); - if (Duration.ZERO.equals(duration)) { - // Expires mapping through computeIfPresent - expireMappingUnderLock(key, valueHolder); - } - } - - private OnHeapValueHolder setAccessTimeAndExpiryThenReturnMappingUnderLock(K key, OnHeapValueHolder valueHolder, long now, - StoreEventSink eventSink) { - Duration duration = Duration.ZERO; - try { - duration = expiry.getExpiryForAccess(key, valueHolder); - if (duration != null && duration.isNegative()) { - duration = Duration.ZERO; - } - } catch (RuntimeException re) { - LOG.error("Expiry computation caused an exception - Expiry duration will be 0 ", re); - } - valueHolder.accessed(now, duration); - if (Duration.ZERO.equals(duration)) { - // Fires event, must happen under lock - fireOnExpirationEvent(key, valueHolder, eventSink); - return null; - } - return valueHolder; - } - - private void expireMappingUnderLock(K key, ValueHolder value) { + void expireMappingUnderLock(K key, ValueHolder value) { StoreEventSink eventSink = storeEventDispatcher.eventSink(); try { @@ -1616,7 +1581,7 @@ boolean evict(StoreEventSink eventSink) { } } - private void fireOnExpirationEvent(K mappedKey, ValueHolder mappedValue, StoreEventSink eventSink) { + void fireOnExpirationEvent(K mappedKey, ValueHolder mappedValue, StoreEventSink eventSink) { expirationObserver.begin(); expirationObserver.end(StoreOperationOutcomes.ExpirationOutcome.SUCCESS); eventSink.expired(mappedKey, mappedValue); diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java new file mode 100644 index 0000000000..a57abcb9a4 --- /dev/null +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java @@ -0,0 +1,154 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.internal.store.heap; + +import org.ehcache.core.events.StoreEventSink; +import org.ehcache.core.spi.time.TimeSource; +import org.ehcache.expiry.ExpiryPolicy; +import org.ehcache.impl.internal.store.heap.holders.OnHeapValueHolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Duration; +import java.util.concurrent.TimeUnit; + +/** + * @author Henri Tremblay + */ +interface OnHeapStrategy { + + Logger LOG = LoggerFactory.getLogger(OnHeapStore.class); + + static OnHeapStrategy strategy(OnHeapStore store, ExpiryPolicy expiry, TimeSource timeSource) { + if(expiry == ExpiryPolicy.NO_EXPIRY) { + LOG.debug("No expiration strategy detected"); + return new NoExpirationStrategy<>(); + } + if(expiry.getClass().getName().equals("org.ehcache.config.builders.ExpiryPolicyBuilder$TimeToLiveExpiryPolicy")) { + LOG.debug("TTL expiration strategy detected"); + return new TTLStrategy<>(timeSource); + } + LOG.debug("TTI or custom expiration strategy detected"); + return new AllStrategy<>(store, expiry, timeSource); + } + + boolean isExpired(OnHeapValueHolder mapping); + + void setAccessTimeAndExpiryThenReturnMappingOutsideLock(K key, OnHeapValueHolder valueHolder, long now); + + OnHeapValueHolder setAccessTimeAndExpiryThenReturnMappingUnderLock(K key, OnHeapValueHolder valueHolder, long now, StoreEventSink eventSink); + + class AllStrategy implements OnHeapStrategy { + private final OnHeapStore store; + private final ExpiryPolicy expiry; + private final TimeSource timeSource; + + public AllStrategy(OnHeapStore store, ExpiryPolicy expiry, TimeSource timeSource) { + this.store = store; + this.expiry = expiry; + this.timeSource = timeSource; + } + + @Override + public boolean isExpired(OnHeapValueHolder mapping) { + return mapping.isExpired(timeSource.getTimeMillis(), TimeUnit.MILLISECONDS); + } + + @Override + public void setAccessTimeAndExpiryThenReturnMappingOutsideLock(K key, OnHeapValueHolder valueHolder, long now) { + Duration duration = getAccessDuration(key, valueHolder); + if (Duration.ZERO.equals(duration)) { + // Expires mapping through computeIfPresent + store.expireMappingUnderLock(key, valueHolder); + } else { + valueHolder.accessed(now, duration); + } + } + + private Duration getAccessDuration(K key, OnHeapValueHolder valueHolder) { + Duration duration; + try { + duration = expiry.getExpiryForAccess(key, valueHolder); + if (duration != null && duration.isNegative()) { + duration = Duration.ZERO; + } + } catch (RuntimeException re) { + LOG.error("Expiry computation caused an exception - Expiry duration will be 0 ", re); + duration = Duration.ZERO; + } + return duration; + } + + public OnHeapValueHolder setAccessTimeAndExpiryThenReturnMappingUnderLock(K key, OnHeapValueHolder valueHolder, long now, + StoreEventSink eventSink) { + Duration duration = getAccessDuration(key, valueHolder); + if (Duration.ZERO.equals(duration)) { + // Fires event, must happen under lock + store.fireOnExpirationEvent(key, valueHolder, eventSink); + return null; + } else { + valueHolder.accessed(now, duration); + } + return valueHolder; + } + + } + + class NoExpirationStrategy implements OnHeapStrategy { + + @Override + public boolean isExpired(OnHeapValueHolder mapping) { + return false; + } + + @Override + public void setAccessTimeAndExpiryThenReturnMappingOutsideLock(K key, OnHeapValueHolder valueHolder, long now) { + valueHolder.accessed(now, null); + } + + public OnHeapValueHolder setAccessTimeAndExpiryThenReturnMappingUnderLock(K key, OnHeapValueHolder valueHolder, long now, + StoreEventSink eventSink) { + valueHolder.accessed(now, null); + return valueHolder; + } + } + + class TTLStrategy implements OnHeapStrategy { + private final TimeSource timeSource; + + public TTLStrategy(TimeSource timeSource) { + this.timeSource = timeSource; + } + + @Override + public boolean isExpired(OnHeapValueHolder mapping) { + return mapping.isExpired(timeSource.getTimeMillis(), TimeUnit.MILLISECONDS); + } + + @Override + public void setAccessTimeAndExpiryThenReturnMappingOutsideLock(K key, OnHeapValueHolder valueHolder, long now) { + valueHolder.accessed(now, null); + } + + public OnHeapValueHolder setAccessTimeAndExpiryThenReturnMappingUnderLock(K key, OnHeapValueHolder valueHolder, long now, + StoreEventSink eventSink) { + valueHolder.accessed(now, null); + return valueHolder; + } + } + +} diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java new file mode 100644 index 0000000000..ac39015827 --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java @@ -0,0 +1,170 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.internal.store.heap; + +import org.ehcache.expiry.ExpiryPolicy; +import org.ehcache.impl.internal.store.heap.holders.OnHeapValueHolder; +import org.ehcache.internal.TestTimeSource; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.time.Duration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +/** + * @author Henri Tremblay + */ +public class OnHeapStrategyTest { + + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @Mock + private OnHeapStore store; + + @Mock + private ExpiryPolicy policy; + + private OnHeapStrategy strategy; + + private static class TestOnHeapValueHolder extends OnHeapValueHolder { + + long now; + Duration expiration; + + protected TestOnHeapValueHolder(long expirationTime) { + super(1, 0, expirationTime, true); + } + + @Override + public String get() { + return "test"; + } + + @Override + public void accessed(long now, Duration expiration) { + this.now = now; + this.expiration = expiration; + super.accessed(now, expiration); + } + } + + private TestTimeSource timeSource = new TestTimeSource(); + + @Test + public void isExpired_10seconds() { + strategy = OnHeapStrategy.strategy(store, policy, timeSource); + + TestOnHeapValueHolder mapping = new TestOnHeapValueHolder(10); + assertThat(strategy.isExpired(mapping)).isFalse(); + timeSource.advanceTime(10); + assertThat(strategy.isExpired(mapping)).isTrue(); + } + + @Test + public void isExpired_TTL10seconds() { + strategy = OnHeapStrategy.strategy(store, policy, timeSource); + + TestOnHeapValueHolder mapping = new TestOnHeapValueHolder(10); + assertThat(strategy.isExpired(mapping)).isFalse(); + timeSource.advanceTime(10); + assertThat(strategy.isExpired(mapping)).isTrue(); + } + + @Test + public void isExpired_neverExpires() { + strategy = OnHeapStrategy.strategy(store, ExpiryPolicy.NO_EXPIRY, timeSource); + + TestOnHeapValueHolder mapping = new TestOnHeapValueHolder(10); + assertThat(strategy.isExpired(mapping)).isFalse(); + timeSource.advanceTime(10); + assertThat(strategy.isExpired(mapping)).isFalse(); + } + + @Test + public void setAccessTimeAndExpiryThenReturnMappingOutsideLock_nullExpiryForAccess() { + strategy = OnHeapStrategy.strategy(store, ExpiryPolicy.NO_EXPIRY, timeSource); + + TestOnHeapValueHolder mapping = new TestOnHeapValueHolder(10); + when(policy.getExpiryForAccess(1, mapping)).thenReturn(null); + + strategy.setAccessTimeAndExpiryThenReturnMappingOutsideLock(1, mapping, timeSource.getTimeMillis()); + + assertThat(mapping.expiration).isNull(); + assertThat(mapping.now).isEqualTo(timeSource.getTimeMillis()); + + verifyZeroInteractions(store); + } + + @Test + public void setAccessTimeAndExpiryThenReturnMappingOutsideLock_zeroExpiryOnAccess() { + strategy = OnHeapStrategy.strategy(store, policy, timeSource); + + TestOnHeapValueHolder mapping = new TestOnHeapValueHolder(10); + when(policy.getExpiryForAccess(1, mapping)).thenReturn(Duration.ZERO); + + strategy.setAccessTimeAndExpiryThenReturnMappingOutsideLock(1, mapping, timeSource.getTimeMillis()); + + verify(store).expireMappingUnderLock(1, mapping); + } + + @Test + public void setAccessTimeAndExpiryThenReturnMappingOutsideLock_infiniteExpiryOnAccess() { + strategy = OnHeapStrategy.strategy(store, policy, timeSource); + + TestOnHeapValueHolder mapping = new TestOnHeapValueHolder(10); + when(policy.getExpiryForAccess(1, mapping)).thenReturn(ExpiryPolicy.INFINITE); + + strategy.setAccessTimeAndExpiryThenReturnMappingOutsideLock(1, mapping, timeSource.getTimeMillis()); + + assertThat(mapping.expiration).isEqualTo(ExpiryPolicy.INFINITE); + assertThat(mapping.now).isEqualTo(timeSource.getTimeMillis()); + + verifyZeroInteractions(store); + } + + @Test + public void setAccessTimeAndExpiryThenReturnMappingOutsideLock_movingTime() { + strategy = OnHeapStrategy.strategy(store, policy, timeSource); + + TestOnHeapValueHolder mapping = new TestOnHeapValueHolder(10); + when(policy.getExpiryForAccess(1, mapping)).thenReturn(Duration.ofMillis(20)); + + strategy.setAccessTimeAndExpiryThenReturnMappingOutsideLock(1, mapping, timeSource.getTimeMillis()); + + assertThat(mapping.expiration).isEqualTo(Duration.ofMillis(20)); + assertThat(mapping.now).isEqualTo(timeSource.getTimeMillis()); + + verifyZeroInteractions(store); + + timeSource.advanceTime(30); + + strategy.setAccessTimeAndExpiryThenReturnMappingOutsideLock(1, mapping, timeSource.getTimeMillis()); + + assertThat(mapping.expiration).isEqualTo(Duration.ofMillis(20)); + assertThat(mapping.now).isEqualTo(timeSource.getTimeMillis()); + + verifyZeroInteractions(store); + } +} diff --git a/integration-test/src/test/java/org/ehcache/integration/OnHeapEvictionStrategyTest.java b/integration-test/src/test/java/org/ehcache/integration/OnHeapEvictionStrategyTest.java new file mode 100644 index 0000000000..b628b45999 --- /dev/null +++ b/integration-test/src/test/java/org/ehcache/integration/OnHeapEvictionStrategyTest.java @@ -0,0 +1,174 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.integration; + +import org.ehcache.Cache; +import org.ehcache.CacheManager; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.config.builders.ExpiryPolicyBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.expiry.ExpiryPolicy; +import org.ehcache.impl.internal.TimeSourceConfiguration; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.time.Duration; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Henri Tremblay + */ +public class OnHeapEvictionStrategyTest { + + private final TestTimeSource timeSource = new TestTimeSource(); + private final TimeSourceConfiguration timeSourceConfiguration = new TimeSourceConfiguration(timeSource); + + private CacheManager cacheManager; + + @Before + public void before() { + cacheManager = CacheManagerBuilder.newCacheManagerBuilder() + .using(timeSourceConfiguration) + .build(true); + } + + @After + public void after() { + cacheManager.close(); + } + + @Test + public void noExpiryGet() { + Cache cache = createCache(ExpiryPolicyBuilder.noExpiration()); + + cache.put(1, "a"); + + timeSource.setTimeMillis(Long.MAX_VALUE); + + assertThat(cache.get(1)).isEqualTo("a"); + } + + @Test + public void ttlExpiryGet() { + Cache cache = createCache(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(100))); + + cache.put(1, "a"); + + assertThat(cache.get(1)).isEqualTo("a"); + + timeSource.setTimeMillis(100); + + assertThat(cache.get(1)).isNull(); + } + + @Test + public void ttiExpiryGet() { + Cache cache = createCache(ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofMillis(100))); + + cache.put(1, "a"); + + assertThat(cache.get(1)).isEqualTo("a"); + + timeSource.setTimeMillis(100); + + assertThat(cache.get(1)).isNull(); + } + + @Test + public void customExpiryGet() { + Cache cache = createCache( + ExpiryPolicyBuilder.expiry() + .create(ExpiryPolicy.INFINITE) + .update(Duration.ofMillis(100)) + .access(null) + .build()); + + cache.put(1, "a"); + + assertThat(cache.get(1)).isEqualTo("a"); + + cache.put(1, "b"); + + timeSource.setTimeMillis(100); + + assertThat(cache.get(1)).isNull(); + } + + @Test + public void noExpiryPut() { + Cache cache = createCache(ExpiryPolicyBuilder.noExpiration()); + + cache.put(1, "a"); + + timeSource.setTimeMillis(Long.MAX_VALUE); + + assertThat(cache.putIfAbsent(1, "b")).isEqualTo("a"); + } + + @Test + public void ttlExpiryPut() { + Cache cache = createCache(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(100))); + + cache.put(1, "a"); + + assertThat(cache.putIfAbsent(1, "b")).isEqualTo("a"); + + timeSource.setTimeMillis(100); + + assertThat(cache.putIfAbsent(1, "c")).isNull(); + } + + @Test + public void ttiExpiryPut() { + Cache cache = createCache(ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofMillis(100))); + + cache.put(1, "a"); + + assertThat(cache.putIfAbsent(1, "b")).isEqualTo("a"); + + timeSource.setTimeMillis(100); + + assertThat(cache.putIfAbsent(1, "c")).isNull(); + } + + @Test + public void customExpiryPut() { + Cache cache = createCache( + ExpiryPolicyBuilder.expiry() + .create(ExpiryPolicy.INFINITE) + .update(Duration.ofMillis(100)) + .access(null) + .build()); + + cache.put(1, "a"); // create + cache.put(1, "b"); // update that will expire + + timeSource.setTimeMillis(100); + + assertThat(cache.putIfAbsent(1, "d")).isNull(); // expires since update + } + + private Cache createCache(ExpiryPolicy expiryPolicy) { + return cacheManager.createCache("cache", + CacheConfigurationBuilder.newCacheConfigurationBuilder(Integer.class, String.class, + ResourcePoolsBuilder.heap(10)) + .withExpiry(expiryPolicy)); + } +} From 273c9964c2ecf9411ff8ec505b24be80b3ddaed0 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Sun, 5 Aug 2018 23:03:39 -0400 Subject: [PATCH 033/372] Move the duration retrievals to the strategy --- .../impl/internal/store/heap/OnHeapStore.java | 21 +--- .../internal/store/heap/OnHeapStrategy.java | 116 +++++++++++++++++- 2 files changed, 115 insertions(+), 22 deletions(-) diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index c53dc67d9f..d728c4426f 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -1378,15 +1378,8 @@ private OnHeapValueHolder newUpdateValueHolder(K key, OnHeapValueHolder ol Objects.requireNonNull(oldValue); Objects.requireNonNull(newValue); - Duration duration = Duration.ZERO; - try { - duration = expiry.getExpiryForUpdate(key, oldValue, newValue); - if (duration != null && duration.isNegative()) { - duration = Duration.ZERO; - } - } catch (RuntimeException re) { - LOG.error("Expiry computation caused an exception - Expiry duration will be 0 ", re); - } + Duration duration = strategy.getUpdateDuration(key, oldValue, newValue); + if (Duration.ZERO.equals(duration)) { eventSink.updated(key, oldValue, newValue); eventSink.expired(key, () -> newValue); @@ -1436,15 +1429,7 @@ private OnHeapValueHolder newCreateValueHolder(K key, V value, long now, Stor } private OnHeapValueHolder importValueFromLowerTier(K key, ValueHolder valueHolder, long now, Backend backEnd, Fault fault) { - Duration expiration = Duration.ZERO; - try { - expiration = expiry.getExpiryForAccess(key, valueHolder); - if (expiration != null && expiration.isNegative()) { - expiration = Duration.ZERO; - } - } catch (RuntimeException re) { - LOG.error("Expiry computation caused an exception - Expiry duration will be 0 ", re); - } + Duration expiration = strategy.getAccessDuration(key, valueHolder); if (Duration.ZERO.equals(expiration)) { invalidateInGetOrComputeIfAbsent(backEnd, key, valueHolder, fault, now, Duration.ZERO); diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java index a57abcb9a4..b565d43fb8 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java @@ -17,6 +17,7 @@ package org.ehcache.impl.internal.store.heap; import org.ehcache.core.events.StoreEventSink; +import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.store.heap.holders.OnHeapValueHolder; @@ -25,9 +26,13 @@ import java.time.Duration; import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; /** - * @author Henri Tremblay + * Specialized behavior for an OnHeapStore allowing optimization depending on the expiry policy used. + * + * @param type of the keys stored + * @param type of the values stored */ interface OnHeapStrategy { @@ -40,18 +45,67 @@ static OnHeapStrategy strategy(OnHeapStore store, ExpiryPolic } if(expiry.getClass().getName().equals("org.ehcache.config.builders.ExpiryPolicyBuilder$TimeToLiveExpiryPolicy")) { LOG.debug("TTL expiration strategy detected"); - return new TTLStrategy<>(timeSource); + return new TTLStrategy<>(expiry, timeSource); } LOG.debug("TTI or custom expiration strategy detected"); return new AllStrategy<>(store, expiry, timeSource); } + /** + * Tells if a given mapping is expired. + * + * @param mapping mapping to test for expiration + * @return if the mapping is expired + */ boolean isExpired(OnHeapValueHolder mapping); + /** + * Set the access time on the mapping and its expiry time if it is access sensitive (TTI). This action is thread-safe + * and doesn't require looking. + * + * @param key key of the mapping. Used to remove it form the map if needed + * @param valueHolder the mapping + * @param now the current time + */ void setAccessTimeAndExpiryThenReturnMappingOutsideLock(K key, OnHeapValueHolder valueHolder, long now); + /** + * Set the access time on the mapping and its expiry time if it is access sensitive (TTI). This action is thread-safe + * but is requiring a global lock to perform the removal of the entry from the store. + * + * @param key key of the mapping. Used to remove it form the map if needed + * @param valueHolder the mapping + * @param now the current time + * @param eventSink sink when the expiration request will be sent to do it under lock + * @return the mapping or null if it was removed + */ OnHeapValueHolder setAccessTimeAndExpiryThenReturnMappingUnderLock(K key, OnHeapValueHolder valueHolder, long now, StoreEventSink eventSink); + /** + * Get the new expiry duration as per {@link ExpiryPolicy#getExpiryForAccess(Object, Supplier)}. + * + * @param key key of the mapping + * @param valueHolder the mapping + * @return new access expiry duration + */ + Duration getAccessDuration(K key, Store.ValueHolder valueHolder); + + /** + * Get the new expiry duration as per {@link ExpiryPolicy#getExpiryForUpdate(Object, Supplier, Object)}. + * + * @param key key of the mapping + * @param oldValue the old mapping to be updated + * @param newValue the new value for the mapping + * @return new access expiry duration + */ + Duration getUpdateDuration(K key, OnHeapValueHolder oldValue, V newValue); + + /** + * All purpose strategy. Covers any case that can't be optimized due to the uncertainty of the expiry policy used. + * + * @param type of the keys stored + * @param type of the values stored + */ class AllStrategy implements OnHeapStrategy { private final OnHeapStore store; private final ExpiryPolicy expiry; @@ -79,7 +133,7 @@ public void setAccessTimeAndExpiryThenReturnMappingOutsideLock(K key, OnHeapValu } } - private Duration getAccessDuration(K key, OnHeapValueHolder valueHolder) { + public Duration getAccessDuration(K key, Store.ValueHolder valueHolder) { Duration duration; try { duration = expiry.getExpiryForAccess(key, valueHolder); @@ -93,6 +147,20 @@ private Duration getAccessDuration(K key, OnHeapValueHolder valueHolder) { return duration; } + public Duration getUpdateDuration(K key, OnHeapValueHolder oldValue, V newValue) { + Duration duration; + try { + duration = expiry.getExpiryForUpdate(key, oldValue, newValue); + if (duration != null && duration.isNegative()) { + duration = Duration.ZERO; + } + } catch (RuntimeException re) { + LOG.error("Expiry computation caused an exception - Expiry duration will be 0 ", re); + duration = Duration.ZERO; + } + return duration; + } + public OnHeapValueHolder setAccessTimeAndExpiryThenReturnMappingUnderLock(K key, OnHeapValueHolder valueHolder, long now, StoreEventSink eventSink) { Duration duration = getAccessDuration(key, valueHolder); @@ -108,6 +176,12 @@ public OnHeapValueHolder setAccessTimeAndExpiryThenReturnMappingUnderLock(K k } + /** + * Strategy used when entries are never expiring. + * + * @param type of the keys stored + * @param type of the values stored + */ class NoExpirationStrategy implements OnHeapStrategy { @Override @@ -125,13 +199,29 @@ public OnHeapValueHolder setAccessTimeAndExpiryThenReturnMappingUnderLock(K k valueHolder.accessed(now, null); return valueHolder; } + + public Duration getAccessDuration(K key, Store.ValueHolder valueHolder) { + return null; + } + + public Duration getUpdateDuration(K key, OnHeapValueHolder oldValue, V newValue) { + return null; + } } + /** + * Strategy used when entries are expiring due to TTL only. + * + * @param type of the keys stored + * @param type of the values stored + */ class TTLStrategy implements OnHeapStrategy { private final TimeSource timeSource; + private final ExpiryPolicy expiry; - public TTLStrategy(TimeSource timeSource) { + public TTLStrategy(ExpiryPolicy expiry, TimeSource timeSource) { this.timeSource = timeSource; + this.expiry = expiry; } @Override @@ -149,6 +239,24 @@ public OnHeapValueHolder setAccessTimeAndExpiryThenReturnMappingUnderLock(K k valueHolder.accessed(now, null); return valueHolder; } + + public Duration getAccessDuration(K key, Store.ValueHolder valueHolder) { + return null; + } + + public Duration getUpdateDuration(K key, OnHeapValueHolder oldValue, V newValue) { + Duration duration; + try { + duration = expiry.getExpiryForUpdate(key, oldValue, newValue); + if (duration != null && duration.isNegative()) { + duration = Duration.ZERO; + } + } catch (RuntimeException re) { + LOG.error("Expiry computation caused an exception - Expiry duration will be 0 ", re); + duration = Duration.ZERO; + } + return duration; + } } } From 3f9927344ce9ac88ae85ddda949afc574ba403a0 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Mon, 6 Aug 2018 14:29:24 -0400 Subject: [PATCH 034/372] When time starts at 0, the expiration time might be 0 --- .../java/org/ehcache/core/spi/store/AbstractValueHolder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java b/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java index cb3d0f3b58..9383aeaa1a 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java +++ b/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java @@ -63,7 +63,7 @@ public long creationTime(TimeUnit unit) { public void setExpirationTime(long expirationTime, TimeUnit unit) { if (expirationTime == NO_EXPIRE) { updateExpirationTime(NO_EXPIRE); - } else if (expirationTime <= 0) { + } else if (expirationTime < 0) { throw new IllegalArgumentException("invalid expiration time: " + expirationTime); } else { updateExpirationTime(nativeTimeUnit().convert(expirationTime, unit)); From a7ed409aa54b29fd5707c70a14c6f05637576c38 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Wed, 8 Aug 2018 13:55:29 -0400 Subject: [PATCH 035/372] Give more meaningful names to setAccessAndExpiryTime methods --- .../impl/internal/store/heap/OnHeapStore.java | 14 ++++---- .../internal/store/heap/OnHeapStrategy.java | 32 +++++++++---------- .../store/heap/OnHeapStrategyTest.java | 10 +++--- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index d728c4426f..30e8c47adc 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -290,7 +290,7 @@ public ValueHolder get(K key) throws StoreAccessException { return null; } - strategy.setAccessTimeAndExpiryThenReturnMappingOutsideLock(key, mapping, timeSource.getTimeMillis()); + strategy.setAccessAndExpiryTimeWhenCallerOutsideLock(key, mapping, timeSource.getTimeMillis()); getObserver.end(StoreOperationOutcomes.GetOutcome.HIT); return mapping; @@ -456,7 +456,7 @@ public ValueHolder putIfAbsent(K key, V value, Consumer put) throws entryActuallyAdded.set(holder != null); } else { returnValue.set(mappedValue); - holder = strategy.setAccessTimeAndExpiryThenReturnMappingUnderLock(key, mappedValue, now, eventSink); + holder = strategy.setAccessAndExpiryWhenCallerlUnderLock(key, mappedValue, now, eventSink); if (holder == null) { delta -= mappedValue.size(); } @@ -508,7 +508,7 @@ public RemoveStatus remove(K key, V value) throws StoreAccessException { return null; } else { outcome.set(RemoveStatus.KEY_PRESENT); - OnHeapValueHolder holder = strategy.setAccessTimeAndExpiryThenReturnMappingUnderLock(key, mappedValue, now, eventSink); + OnHeapValueHolder holder = strategy.setAccessAndExpiryWhenCallerlUnderLock(key, mappedValue, now, eventSink); if (holder == null) { updateUsageInBytesIfRequired(- mappedValue.size()); } @@ -612,7 +612,7 @@ public ReplaceStatus replace(K key, V oldValue, V newValue) throws StoreAccessEx return holder; } else { outcome.set(ReplaceStatus.MISS_PRESENT); - OnHeapValueHolder holder = strategy.setAccessTimeAndExpiryThenReturnMappingUnderLock(key, mappedValue, now, eventSink); + OnHeapValueHolder holder = strategy.setAccessAndExpiryWhenCallerlUnderLock(key, mappedValue, now, eventSink); if (holder == null) { updateUsageInBytesIfRequired(- mappedValue.size()); } @@ -708,7 +708,7 @@ public ValueHolder getOrComputeIfAbsent(K key, Function> so } } else { - strategy.setAccessTimeAndExpiryThenReturnMappingOutsideLock(key, cachedValue, now); + strategy.setAccessAndExpiryTimeWhenCallerOutsideLock(key, cachedValue, now); } } @@ -1168,7 +1168,7 @@ public ValueHolder computeAndGet(K key, BiFunction computeIfAbsent(K key, Function ma } else { previousValue.set(mappedValue); outcome.set(StoreOperationOutcomes.ComputeIfAbsentOutcome.HIT); - holder = strategy.setAccessTimeAndExpiryThenReturnMappingUnderLock(key, mappedValue, now, eventSink); + holder = strategy.setAccessAndExpiryWhenCallerlUnderLock(key, mappedValue, now, eventSink); if (holder == null) { delta -= mappedValue.size(); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java index b565d43fb8..b4b297cd97 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java @@ -60,26 +60,26 @@ static OnHeapStrategy strategy(OnHeapStore store, ExpiryPolic boolean isExpired(OnHeapValueHolder mapping); /** - * Set the access time on the mapping and its expiry time if it is access sensitive (TTI). This action is thread-safe - * and doesn't require looking. + * Set the access time on the mapping and its expiry time if it is access sensitive (TTI). We expect this action to + * be called when the caller isn't holding any lock. * * @param key key of the mapping. Used to remove it form the map if needed * @param valueHolder the mapping * @param now the current time */ - void setAccessTimeAndExpiryThenReturnMappingOutsideLock(K key, OnHeapValueHolder valueHolder, long now); + void setAccessAndExpiryTimeWhenCallerOutsideLock(K key, OnHeapValueHolder valueHolder, long now); /** - * Set the access time on the mapping and its expiry time if it is access sensitive (TTI). This action is thread-safe - * but is requiring a global lock to perform the removal of the entry from the store. + * Set the access time on the mapping and its expiry time if it is access sensitive (TTI). We expect this action to + * be called when the caller is currently holding a lock. * * @param key key of the mapping. Used to remove it form the map if needed * @param valueHolder the mapping * @param now the current time - * @param eventSink sink when the expiration request will be sent to do it under lock + * @param eventSink sink where the expiration request will be sent * @return the mapping or null if it was removed */ - OnHeapValueHolder setAccessTimeAndExpiryThenReturnMappingUnderLock(K key, OnHeapValueHolder valueHolder, long now, StoreEventSink eventSink); + OnHeapValueHolder setAccessAndExpiryWhenCallerlUnderLock(K key, OnHeapValueHolder valueHolder, long now, StoreEventSink eventSink); /** * Get the new expiry duration as per {@link ExpiryPolicy#getExpiryForAccess(Object, Supplier)}. @@ -123,7 +123,7 @@ public boolean isExpired(OnHeapValueHolder mapping) { } @Override - public void setAccessTimeAndExpiryThenReturnMappingOutsideLock(K key, OnHeapValueHolder valueHolder, long now) { + public void setAccessAndExpiryTimeWhenCallerOutsideLock(K key, OnHeapValueHolder valueHolder, long now) { Duration duration = getAccessDuration(key, valueHolder); if (Duration.ZERO.equals(duration)) { // Expires mapping through computeIfPresent @@ -161,8 +161,8 @@ public Duration getUpdateDuration(K key, OnHeapValueHolder oldValue, V newVal return duration; } - public OnHeapValueHolder setAccessTimeAndExpiryThenReturnMappingUnderLock(K key, OnHeapValueHolder valueHolder, long now, - StoreEventSink eventSink) { + public OnHeapValueHolder setAccessAndExpiryWhenCallerlUnderLock(K key, OnHeapValueHolder valueHolder, long now, + StoreEventSink eventSink) { Duration duration = getAccessDuration(key, valueHolder); if (Duration.ZERO.equals(duration)) { // Fires event, must happen under lock @@ -190,12 +190,12 @@ public boolean isExpired(OnHeapValueHolder mapping) { } @Override - public void setAccessTimeAndExpiryThenReturnMappingOutsideLock(K key, OnHeapValueHolder valueHolder, long now) { + public void setAccessAndExpiryTimeWhenCallerOutsideLock(K key, OnHeapValueHolder valueHolder, long now) { valueHolder.accessed(now, null); } - public OnHeapValueHolder setAccessTimeAndExpiryThenReturnMappingUnderLock(K key, OnHeapValueHolder valueHolder, long now, - StoreEventSink eventSink) { + public OnHeapValueHolder setAccessAndExpiryWhenCallerlUnderLock(K key, OnHeapValueHolder valueHolder, long now, + StoreEventSink eventSink) { valueHolder.accessed(now, null); return valueHolder; } @@ -230,12 +230,12 @@ public boolean isExpired(OnHeapValueHolder mapping) { } @Override - public void setAccessTimeAndExpiryThenReturnMappingOutsideLock(K key, OnHeapValueHolder valueHolder, long now) { + public void setAccessAndExpiryTimeWhenCallerOutsideLock(K key, OnHeapValueHolder valueHolder, long now) { valueHolder.accessed(now, null); } - public OnHeapValueHolder setAccessTimeAndExpiryThenReturnMappingUnderLock(K key, OnHeapValueHolder valueHolder, long now, - StoreEventSink eventSink) { + public OnHeapValueHolder setAccessAndExpiryWhenCallerlUnderLock(K key, OnHeapValueHolder valueHolder, long now, + StoreEventSink eventSink) { valueHolder.accessed(now, null); return valueHolder; } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java index ac39015827..41151cbf39 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java @@ -109,7 +109,7 @@ public void setAccessTimeAndExpiryThenReturnMappingOutsideLock_nullExpiryForAcce TestOnHeapValueHolder mapping = new TestOnHeapValueHolder(10); when(policy.getExpiryForAccess(1, mapping)).thenReturn(null); - strategy.setAccessTimeAndExpiryThenReturnMappingOutsideLock(1, mapping, timeSource.getTimeMillis()); + strategy.setAccessAndExpiryTimeWhenCallerOutsideLock(1, mapping, timeSource.getTimeMillis()); assertThat(mapping.expiration).isNull(); assertThat(mapping.now).isEqualTo(timeSource.getTimeMillis()); @@ -124,7 +124,7 @@ public void setAccessTimeAndExpiryThenReturnMappingOutsideLock_zeroExpiryOnAcces TestOnHeapValueHolder mapping = new TestOnHeapValueHolder(10); when(policy.getExpiryForAccess(1, mapping)).thenReturn(Duration.ZERO); - strategy.setAccessTimeAndExpiryThenReturnMappingOutsideLock(1, mapping, timeSource.getTimeMillis()); + strategy.setAccessAndExpiryTimeWhenCallerOutsideLock(1, mapping, timeSource.getTimeMillis()); verify(store).expireMappingUnderLock(1, mapping); } @@ -136,7 +136,7 @@ public void setAccessTimeAndExpiryThenReturnMappingOutsideLock_infiniteExpiryOnA TestOnHeapValueHolder mapping = new TestOnHeapValueHolder(10); when(policy.getExpiryForAccess(1, mapping)).thenReturn(ExpiryPolicy.INFINITE); - strategy.setAccessTimeAndExpiryThenReturnMappingOutsideLock(1, mapping, timeSource.getTimeMillis()); + strategy.setAccessAndExpiryTimeWhenCallerOutsideLock(1, mapping, timeSource.getTimeMillis()); assertThat(mapping.expiration).isEqualTo(ExpiryPolicy.INFINITE); assertThat(mapping.now).isEqualTo(timeSource.getTimeMillis()); @@ -151,7 +151,7 @@ public void setAccessTimeAndExpiryThenReturnMappingOutsideLock_movingTime() { TestOnHeapValueHolder mapping = new TestOnHeapValueHolder(10); when(policy.getExpiryForAccess(1, mapping)).thenReturn(Duration.ofMillis(20)); - strategy.setAccessTimeAndExpiryThenReturnMappingOutsideLock(1, mapping, timeSource.getTimeMillis()); + strategy.setAccessAndExpiryTimeWhenCallerOutsideLock(1, mapping, timeSource.getTimeMillis()); assertThat(mapping.expiration).isEqualTo(Duration.ofMillis(20)); assertThat(mapping.now).isEqualTo(timeSource.getTimeMillis()); @@ -160,7 +160,7 @@ public void setAccessTimeAndExpiryThenReturnMappingOutsideLock_movingTime() { timeSource.advanceTime(30); - strategy.setAccessTimeAndExpiryThenReturnMappingOutsideLock(1, mapping, timeSource.getTimeMillis()); + strategy.setAccessAndExpiryTimeWhenCallerOutsideLock(1, mapping, timeSource.getTimeMillis()); assertThat(mapping.expiration).isEqualTo(Duration.ofMillis(20)); assertThat(mapping.now).isEqualTo(timeSource.getTimeMillis()); From fc5eb2fd0f9fa943966e555992fcea065d9d2a74 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Fri, 7 Dec 2018 14:32:03 -0500 Subject: [PATCH 036/372] Now need to specify the right overload call to access() --- .../org/ehcache/integration/OnHeapEvictionStrategyTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-test/src/test/java/org/ehcache/integration/OnHeapEvictionStrategyTest.java b/integration-test/src/test/java/org/ehcache/integration/OnHeapEvictionStrategyTest.java index b628b45999..6dd83ab71c 100644 --- a/integration-test/src/test/java/org/ehcache/integration/OnHeapEvictionStrategyTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/OnHeapEvictionStrategyTest.java @@ -97,7 +97,7 @@ public void customExpiryGet() { ExpiryPolicyBuilder.expiry() .create(ExpiryPolicy.INFINITE) .update(Duration.ofMillis(100)) - .access(null) + .access((Duration) null) .build()); cache.put(1, "a"); @@ -154,7 +154,7 @@ public void customExpiryPut() { ExpiryPolicyBuilder.expiry() .create(ExpiryPolicy.INFINITE) .update(Duration.ofMillis(100)) - .access(null) + .access((Duration) null) .build()); cache.put(1, "a"); // create From 148d5f440dd42a830187ca28e229a33322ec3a74 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Fri, 10 Aug 2018 16:30:34 -0400 Subject: [PATCH 037/372] [TECH] Use milliseconds as the only time unit of value holders --- .../internal/store/ClusteredValueHolder.java | 7 - .../core/spi/store/AbstractValueHolder.java | 10 +- .../spi/store/AbstractValueHolderTest.java | 120 ++++-------------- .../impl/internal/store/heap/OnHeapStore.java | 4 +- .../heap/holders/CopiedOnHeapValueHolder.java | 4 +- .../store/heap/holders/OnHeapValueHolder.java | 7 - .../holders/SerializedOnHeapValueHolder.java | 5 +- .../loaderwriter/LoaderWriterValueHolder.java | 9 -- .../store/offheap/AbstractOffHeapStore.java | 10 +- .../offheap/BasicOffHeapValueHolder.java | 4 +- .../offheap/BinaryOffHeapValueHolder.java | 3 +- .../store/offheap/LazyOffHeapValueHolder.java | 6 +- .../store/offheap/OffHeapValueHolder.java | 7 - .../OffHeapValueHolderPortability.java | 7 +- .../store/heap/OnHeapStoreByValueTest.java | 5 - .../offheap/AbstractOffHeapStoreTest.java | 5 - .../transactions/xa/internal/XAStore.java | 3 +- .../xa/internal/XAValueHolder.java | 11 +- .../xa/internal/XATransactionContextTest.java | 32 ----- 19 files changed, 57 insertions(+), 202 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredValueHolder.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredValueHolder.java index 37359949dc..9b6c21d411 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredValueHolder.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredValueHolder.java @@ -22,8 +22,6 @@ public class ClusteredValueHolder extends AbstractValueHolder { - public static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS; - private final V value; public ClusteredValueHolder(V value) { @@ -38,11 +36,6 @@ public ClusteredValueHolder(V value, long expirationTime) { this.value = value; } - @Override - protected TimeUnit nativeTimeUnit() { - return TIME_UNIT; - } - @Override public V get() { return value; diff --git a/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java b/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java index 9383aeaa1a..133562f480 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java +++ b/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java @@ -53,7 +53,9 @@ protected AbstractValueHolder(long id, long creationTime, long expirationTime) { this.lastAccessTime = creationTime; } - protected abstract TimeUnit nativeTimeUnit(); + protected final TimeUnit nativeTimeUnit() { + return TimeUnit.MILLISECONDS; + } @Override public long creationTime(TimeUnit unit) { @@ -145,9 +147,9 @@ public boolean equals(Object obj) { if (obj instanceof AbstractValueHolder) { AbstractValueHolder other = (AbstractValueHolder) obj; return - other.creationTime(nativeTimeUnit()) == creationTime && creationTime(other.nativeTimeUnit()) == other.creationTime && - other.expirationTime(nativeTimeUnit()) == expirationTime && expirationTime(other.nativeTimeUnit()) == other.expirationTime && - other.lastAccessTime(nativeTimeUnit()) == lastAccessTime && lastAccessTime(other.nativeTimeUnit()) == other.lastAccessTime; + other.creationTime(nativeTimeUnit()) == creationTime && + other.expirationTime(nativeTimeUnit()) == expirationTime && + other.lastAccessTime(nativeTimeUnit()) == lastAccessTime; } return false; } diff --git a/core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java b/core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java index 5028f9d57d..5d88108104 100644 --- a/core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java +++ b/core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java @@ -31,7 +31,7 @@ public class AbstractValueHolderTest { @Test public void testCreationTime() throws Exception { - AbstractValueHolder valueHolder = newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L); + AbstractValueHolder valueHolder = newAbstractValueHolder(1000L); assertThat(valueHolder.creationTime(TimeUnit.SECONDS), is(1L)); assertThat(valueHolder.creationTime(TimeUnit.MILLISECONDS), is(1000L)); @@ -40,7 +40,7 @@ public void testCreationTime() throws Exception { @Test public void testExpirationTime() throws Exception { - AbstractValueHolder valueHolder = newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 1000L); + AbstractValueHolder valueHolder = newAbstractValueHolder(0L, 1000L); assertThat(valueHolder.expirationTime(TimeUnit.SECONDS), is(1L)); assertThat(valueHolder.expirationTime(TimeUnit.MILLISECONDS), is(1000L)); @@ -51,7 +51,7 @@ public void testExpirationTime() throws Exception { @Test public void testLastAccessTime() throws Exception { // last access time defaults to create time - AbstractValueHolder valueHolder = newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L); + AbstractValueHolder valueHolder = newAbstractValueHolder(1000L); assertThat(valueHolder.lastAccessTime(TimeUnit.SECONDS), is(1L)); assertThat(valueHolder.lastAccessTime(TimeUnit.MILLISECONDS), is(1000L)); @@ -67,54 +67,43 @@ public void testLastAccessTime() throws Exception { @Test public void testIsExpired() throws Exception { - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L).isExpired(1L, TimeUnit.SECONDS), is(false)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L).isExpired(1000L, TimeUnit.MILLISECONDS), is(false)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L).isExpired(1000000L, TimeUnit.MICROSECONDS), is(false)); + assertThat(newAbstractValueHolder(1000L).isExpired(1L, TimeUnit.SECONDS), is(false)); + assertThat(newAbstractValueHolder(1000L).isExpired(1000L, TimeUnit.MILLISECONDS), is(false)); + assertThat(newAbstractValueHolder(1000L).isExpired(1000000L, TimeUnit.MICROSECONDS), is(false)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 1001L).isExpired(1L, TimeUnit.SECONDS), is(false)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 1001L).isExpired(1000L, TimeUnit.MILLISECONDS), is(false)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 1001L).isExpired(1000000L, TimeUnit.MICROSECONDS), is(false)); + assertThat(newAbstractValueHolder(1000L, 1001L).isExpired(1L, TimeUnit.SECONDS), is(false)); + assertThat(newAbstractValueHolder(1000L, 1001L).isExpired(1000L, TimeUnit.MILLISECONDS), is(false)); + assertThat(newAbstractValueHolder(1000L, 1001L).isExpired(1000000L, TimeUnit.MICROSECONDS), is(false)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 1000L).isExpired(1L, TimeUnit.SECONDS), is(true)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 1000L).isExpired(1000L, TimeUnit.MILLISECONDS), is(true)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 1000L).isExpired(1000000L, TimeUnit.MICROSECONDS), is(true)); + assertThat(newAbstractValueHolder(1000L, 1000L).isExpired(1L, TimeUnit.SECONDS), is(true)); + assertThat(newAbstractValueHolder(1000L, 1000L).isExpired(1000L, TimeUnit.MILLISECONDS), is(true)); + assertThat(newAbstractValueHolder(1000L, 1000L).isExpired(1000000L, TimeUnit.MICROSECONDS), is(true)); } @Test public void testEquals() throws Exception { - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L)), is(true)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L)), is(false)); + assertThat(newAbstractValueHolder( 0L).equals(newAbstractValueHolder( 0L)), is(true)); + assertThat(newAbstractValueHolder( 1L).equals(newAbstractValueHolder( 0L)), is(false)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 2L, 0L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 2L, 0L)), is(true)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 2L, 0L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 2L, 1L)), is(false)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 2L, 0L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 3L, 0L)), is(false)); + assertThat(newAbstractValueHolder(2L, 0L).equals(newAbstractValueHolder(2L, 0L)), is(true)); + assertThat(newAbstractValueHolder(2L, 0L).equals(newAbstractValueHolder(2L, 1L)), is(false)); + assertThat(newAbstractValueHolder(2L, 0L).equals(newAbstractValueHolder(3L, 0L)), is(false)); assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L)), is(true)); assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1L, 2L, 1L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L)), is(false)); assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 3L, 1L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L)), is(false)); assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 3L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L)), is(false)); - - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1L).equals(newAbstractValueHolder(TimeUnit.SECONDS, 1L)), is(false)); - assertThat(newAbstractValueHolder(TimeUnit.NANOSECONDS, 1L).equals(newAbstractValueHolder(TimeUnit.SECONDS, 0L)), is(false)); - assertThat(newAbstractValueHolder(TimeUnit.SECONDS, 0L).equals(newAbstractValueHolder(TimeUnit.NANOSECONDS, 1L)), is(false)); - assertThat(newAbstractValueHolder(TimeUnit.SECONDS, 1L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L)), is(true)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L).equals(newAbstractValueHolder(TimeUnit.SECONDS, 1L)), is(true)); } @Test public void testSubclassEquals() throws Exception { - assertThat(new AbstractValueHolder(-1, 1000L) { + assertThat(new AbstractValueHolder(-1, 1L) { @Override public String get() { return "aaa"; } - @Override - protected TimeUnit nativeTimeUnit() { - return TimeUnit.MILLISECONDS; - } - @Override public int hashCode() { return super.hashCode() + get().hashCode(); @@ -133,11 +122,6 @@ public String get() { return "aaa"; } - @Override - protected TimeUnit nativeTimeUnit() { - return TimeUnit.SECONDS; - } - @Override public int hashCode() { return super.hashCode() + get().hashCode(); @@ -153,87 +137,27 @@ public boolean equals(Object obj) { } }), is(true)); - assertThat(new AbstractValueHolder(-1, 1000L) { - @Override - public String get() { - return "aaa"; - } - - @Override - protected TimeUnit nativeTimeUnit() { - return TimeUnit.MICROSECONDS; - } - - @Override - public int hashCode() { - return super.hashCode() + get().hashCode(); - } - @Override - public boolean equals(Object obj) { - if (obj instanceof AbstractValueHolder) { - AbstractValueHolder other = (AbstractValueHolder) obj; - return super.equals(obj) && get().equals(other.get()); - } - return false; - } - }.equals(new AbstractValueHolder(-1, 1L) { - @Override - public String get() { - return "bbb"; - } - - @Override - protected TimeUnit nativeTimeUnit() { - return TimeUnit.MILLISECONDS; - } - - @Override - public int hashCode() { - return super.hashCode() + get().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof AbstractValueHolder) { - AbstractValueHolder other = (AbstractValueHolder)obj; - return super.equals(obj) && get().equals(other.get()); - } - return false; - } - }), is(false)); } - private AbstractValueHolder newAbstractValueHolder(final TimeUnit timeUnit, long creationTime) { + private AbstractValueHolder newAbstractValueHolder(long creationTime) { return new AbstractValueHolder(-1, creationTime) { - @Override - protected TimeUnit nativeTimeUnit() { - return timeUnit; - } @Override public String get() { throw new UnsupportedOperationException(); } }; } - private AbstractValueHolder newAbstractValueHolder(final TimeUnit timeUnit, long creationTime, long expirationTime) { + + private AbstractValueHolder newAbstractValueHolder(long creationTime, long expirationTime) { return new AbstractValueHolder(-1, creationTime, expirationTime) { - @Override - protected TimeUnit nativeTimeUnit() { - return timeUnit; - } @Override public String get() { throw new UnsupportedOperationException(); } }; } - private AbstractValueHolder newAbstractValueHolder(final TimeUnit timeUnit, long creationTime, long expirationTime, long lastAccessTime) { + private AbstractValueHolder newAbstractValueHolder(TimeUnit timeUnit, long creationTime, long expirationTime, long lastAccessTime) { final AbstractValueHolder abstractValueHolder = new AbstractValueHolder(-1, creationTime, expirationTime) { - @Override - protected TimeUnit nativeTimeUnit() { - return timeUnit; - } - @Override public String get() { throw new UnsupportedOperationException(); diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index 30e8c47adc..91290ac259 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -1178,7 +1178,7 @@ public ValueHolder computeAndGet(K key, BiFunction newUpdateValueHolder(K key, OnHeapValueHolder ol long expirationTime; if (duration == null) { - expirationTime = oldValue.expirationTime(OnHeapValueHolder.TIME_UNIT); + expirationTime = oldValue.expirationTime(TimeUnit.MILLISECONDS); } else { if (isExpiryDurationInfinite(duration)) { expirationTime = ValueHolder.NO_EXPIRE; diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolder.java index 931e02513a..da7d491405 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolder.java @@ -20,6 +20,8 @@ import org.ehcache.core.spi.store.Store; import org.ehcache.spi.copy.Copier; +import java.util.concurrent.TimeUnit; + /** * @author Albin Suresh */ @@ -51,7 +53,7 @@ protected CopiedOnHeapValueHolder(long id, V value, long creationTime, long expi * @param expiration computed expiration duration */ public CopiedOnHeapValueHolder(Store.ValueHolder valueHolder, V value, boolean evictionAdvice, Copier valueCopier, long now, java.time.Duration expiration) { - super(valueHolder.getId(), valueHolder.creationTime(TIME_UNIT), valueHolder.expirationTime(TIME_UNIT), evictionAdvice); + super(valueHolder.getId(), valueHolder.creationTime(TimeUnit.MILLISECONDS), valueHolder.expirationTime(TimeUnit.MILLISECONDS), evictionAdvice); if (value == null) { throw new NullPointerException("null value"); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/OnHeapValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/OnHeapValueHolder.java index 5fc391b95c..947d7092db 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/OnHeapValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/OnHeapValueHolder.java @@ -25,8 +25,6 @@ */ public abstract class OnHeapValueHolder extends AbstractValueHolder { - public static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS; - private final boolean evictionAdvice; private long size; @@ -55,11 +53,6 @@ public void setSize(long size) { this.size = size; } - @Override - final protected TimeUnit nativeTimeUnit() { - return TIME_UNIT; - } - @Override public boolean equals(Object obj) { if (obj != null && this.getClass().equals(obj.getClass())) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolder.java index 7903d54d9e..df3e393ef9 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolder.java @@ -22,6 +22,7 @@ import org.ehcache.spi.serialization.Serializer; import java.nio.ByteBuffer; +import java.util.concurrent.TimeUnit; public class SerializedOnHeapValueHolder extends OnHeapValueHolder implements BinaryValueHolder { private final ByteBuffer buffer; @@ -49,12 +50,12 @@ public SerializedOnHeapValueHolder(V value, long creationTime, long expirationTi } public SerializedOnHeapValueHolder(Store.ValueHolder valueHolder, V value, boolean evictionAdvice, Serializer serializer, long now, java.time.Duration expiration) { - this(valueHolder.getId(), value, valueHolder.creationTime(TIME_UNIT), valueHolder.expirationTime(TIME_UNIT), evictionAdvice, serializer); + this(valueHolder.getId(), value, valueHolder.creationTime(TimeUnit.MILLISECONDS), valueHolder.expirationTime(TimeUnit.MILLISECONDS), evictionAdvice, serializer); this.accessed(now, expiration); } public SerializedOnHeapValueHolder(Store.ValueHolder valueHolder, ByteBuffer binaryValue, boolean evictionAdvice, Serializer serializer, long now, java.time.Duration expiration) { - super(valueHolder.getId(), valueHolder.creationTime(TIME_UNIT), valueHolder.expirationTime(TIME_UNIT), evictionAdvice); + super(valueHolder.getId(), valueHolder.creationTime(TimeUnit.MILLISECONDS), valueHolder.expirationTime(TimeUnit.MILLISECONDS), evictionAdvice); this.buffer = binaryValue; this.serializer = serializer; this.accessed(now, expiration); diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterValueHolder.java index 984084f7b3..70a80aa162 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterValueHolder.java @@ -17,12 +17,8 @@ import org.ehcache.core.spi.store.AbstractValueHolder; -import java.util.concurrent.TimeUnit; - public class LoaderWriterValueHolder extends AbstractValueHolder { - private static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS; - private final V value; public LoaderWriterValueHolder(V value) { @@ -33,11 +29,6 @@ public LoaderWriterValueHolder(V value) { this.value = value; } - @Override - protected TimeUnit nativeTimeUnit() { - return TIME_UNIT; - } - @Override public V get() { return value; diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java index 998e133db8..96b27b73d7 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java @@ -1086,7 +1086,7 @@ private OffHeapValueHolder newUpdatedValueHolder(K key, V value, OffHeapValue } if (duration == null) { - return new BasicOffHeapValueHolder<>(backingMap().nextIdFor(key), value, now, existing.expirationTime(OffHeapValueHolder.TIME_UNIT)); + return new BasicOffHeapValueHolder<>(backingMap().nextIdFor(key), value, now, existing.expirationTime(TimeUnit.MILLISECONDS)); } else if (isExpiryDurationInfinite(duration)) { return new BasicOffHeapValueHolder<>(backingMap().nextIdFor(key), value, now, OffHeapValueHolder.NO_EXPIRE); } else { @@ -1112,11 +1112,11 @@ private OffHeapValueHolder newCreateValueHolder(K key, V value, long now, Sto private OffHeapValueHolder newTransferValueHolder(ValueHolder valueHolder) { if (valueHolder instanceof BinaryValueHolder && ((BinaryValueHolder) valueHolder).isBinaryValueAvailable()) { return new BinaryOffHeapValueHolder<>(valueHolder.getId(), valueHolder.get(), ((BinaryValueHolder) valueHolder).getBinaryValue(), - valueHolder.creationTime(OffHeapValueHolder.TIME_UNIT), valueHolder.expirationTime(OffHeapValueHolder.TIME_UNIT), - valueHolder.lastAccessTime(OffHeapValueHolder.TIME_UNIT)); + valueHolder.creationTime(TimeUnit.MILLISECONDS), valueHolder.expirationTime(TimeUnit.MILLISECONDS), + valueHolder.lastAccessTime(TimeUnit.MILLISECONDS)); } else { - return new BasicOffHeapValueHolder<>(valueHolder.getId(), valueHolder.get(), valueHolder.creationTime(OffHeapValueHolder.TIME_UNIT), - valueHolder.expirationTime(OffHeapValueHolder.TIME_UNIT), valueHolder.lastAccessTime(OffHeapValueHolder.TIME_UNIT)); + return new BasicOffHeapValueHolder<>(valueHolder.getId(), valueHolder.get(), valueHolder.creationTime(TimeUnit.MILLISECONDS), + valueHolder.expirationTime(TimeUnit.MILLISECONDS), valueHolder.lastAccessTime(TimeUnit.MILLISECONDS)); } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolder.java index 56edba07ac..6c2d0752ef 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolder.java @@ -18,6 +18,8 @@ import org.ehcache.core.spi.store.Store; +import java.util.concurrent.TimeUnit; + /** * BasicOffHeapValueHolder */ @@ -31,7 +33,7 @@ public BasicOffHeapValueHolder(long id, V value, long creationTime, long expireT public BasicOffHeapValueHolder(long id, V value, long creationTime, long expireTime, long lastAccessTime) { super(id, creationTime, expireTime); - setLastAccessTime(lastAccessTime, TIME_UNIT); + setLastAccessTime(lastAccessTime, TimeUnit.MILLISECONDS); this.value = value; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolder.java index c4ba670664..7e03dde497 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolder.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.nio.ByteBuffer; +import java.util.concurrent.TimeUnit; /** * BinaryOffHeapValueHolder @@ -33,7 +34,7 @@ final class BinaryOffHeapValueHolder extends OffHeapValueHolder implements BinaryOffHeapValueHolder(long id, V value, ByteBuffer binaryValue, long creationTime, long expireTime, long lastAccessTime) { super(id, creationTime, expireTime); this.value = value; - setLastAccessTime(lastAccessTime, TIME_UNIT); + setLastAccessTime(lastAccessTime, TimeUnit.MILLISECONDS); this.binaryValue = binaryValue; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java index 5d44f16e30..3a47fbb081 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java @@ -40,7 +40,7 @@ public final class LazyOffHeapValueHolder extends OffHeapValueHolder imple public LazyOffHeapValueHolder(long id, ByteBuffer binaryValue, Serializer serializer, long creationTime, long expireTime, long lastAccessTime, WriteContext writeContext) { super(id, creationTime, expireTime); - setLastAccessTime(lastAccessTime, TIME_UNIT); + setLastAccessTime(lastAccessTime, TimeUnit.MILLISECONDS); this.binaryValue = binaryValue; this.valueSerializer = serializer; this.writeContext = writeContext; @@ -72,8 +72,8 @@ void updateMetadata(final Store.ValueHolder valueFlushed) { if(getId() != valueFlushed.getId()) { throw new IllegalArgumentException("Wrong id passed in [this.id != id] : " + getId() + " != " + valueFlushed.getId()); } - this.setLastAccessTime(valueFlushed.lastAccessTime(LazyOffHeapValueHolder.TIME_UNIT), LazyOffHeapValueHolder.TIME_UNIT); - this.setExpirationTime(valueFlushed.expirationTime(LazyOffHeapValueHolder.TIME_UNIT), LazyOffHeapValueHolder.TIME_UNIT); + this.setLastAccessTime(valueFlushed.lastAccessTime(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS); + this.setExpirationTime(valueFlushed.expirationTime(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS); } /** diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolder.java index daab162d26..66130cf2c2 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolder.java @@ -26,17 +26,10 @@ */ public abstract class OffHeapValueHolder extends AbstractValueHolder { - public static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS; - public OffHeapValueHolder(long id, long creationTime, long expireTime) { super(id, creationTime, expireTime); } - @Override - final protected TimeUnit nativeTimeUnit() { - return TIME_UNIT; - } - @Override public boolean equals(Object other) { if (this == other) return true; diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java index e37475dd78..1378206998 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java @@ -24,6 +24,7 @@ import org.terracotta.offheapstore.storage.portability.WriteContext; import java.nio.ByteBuffer; +import java.util.concurrent.TimeUnit; /** * OffHeapValueHolderPortability @@ -52,9 +53,9 @@ public ByteBuffer encode(OffHeapValueHolder valueHolder) { } ByteBuffer byteBuffer = ByteBuffer.allocate(serialized.remaining() + FIELDS_OVERHEAD); byteBuffer.putLong(valueHolder.getId()); - byteBuffer.putLong(valueHolder.creationTime(OffHeapValueHolder.TIME_UNIT)); - byteBuffer.putLong(valueHolder.lastAccessTime(OffHeapValueHolder.TIME_UNIT)); - byteBuffer.putLong(valueHolder.expirationTime(OffHeapValueHolder.TIME_UNIT)); + byteBuffer.putLong(valueHolder.creationTime(TimeUnit.MILLISECONDS)); + byteBuffer.putLong(valueHolder.lastAccessTime(TimeUnit.MILLISECONDS)); + byteBuffer.putLong(valueHolder.expirationTime(TimeUnit.MILLISECONDS)); byteBuffer.putLong(0L); // represent the hits on previous versions. It is kept for compatibility reasons with previously saved data byteBuffer.put(serialized); byteBuffer.flip(); diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueTest.java index bb9d373b21..6d9f5930f0 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueTest.java @@ -78,11 +78,6 @@ public void testKeyCopierCalledOnGetOrComputeIfAbsent() throws Exception { public Long get() { return key * 1000L; } - - @Override - protected TimeUnit nativeTimeUnit() { - return TimeUnit.MILLISECONDS; - } }); assertThat(computed.get(), is(1000L)); assertThat(keyCopier.copyForWriteCount, is(1)); diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java index f318ae35d7..4e864836c0 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java @@ -609,11 +609,6 @@ public SimpleValueHolder(T v, long creationTime, long expirationTime) { this.value = v; } - @Override - protected TimeUnit nativeTimeUnit() { - return TimeUnit.MILLISECONDS; - } - @Override public T get() { return value; diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java index a6a6588b5a..2764a40b44 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java @@ -68,6 +68,7 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiFunction; import java.util.function.Consumer; @@ -357,7 +358,7 @@ public ValueHolder replace(K key, V value) throws StoreAccessException { } else { V oldValue = softLock.getOldValue(); currentContext.addCommand(key, new StorePutCommand<>(oldValue, new XAValueHolder<>(value, timeSource.getTimeMillis()))); - return new XAValueHolder<>(oldValue, softLockValueHolder.creationTime(XAValueHolder.NATIVE_TIME_UNIT)); + return new XAValueHolder<>(oldValue, softLockValueHolder.creationTime(TimeUnit.MILLISECONDS)); } } else { return null; diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java index 5a76fafe21..56b9d328e2 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java @@ -36,8 +36,6 @@ @SuppressWarnings("serial") //this class has writeReplace/readResolve methods public class XAValueHolder extends AbstractValueHolder implements Serializable { - static final TimeUnit NATIVE_TIME_UNIT = TimeUnit.MILLISECONDS; - private final V value; private final byte[] valueSerialized; @@ -71,7 +69,7 @@ public XAValueHolder(XAValueHolder valueHolder, V value) { private XAValueHolder(long id, long creationTime, long lastAccessTime, long expirationTime, V value, byte[] valueSerialized) { super(id, creationTime, expirationTime); - setLastAccessTime(lastAccessTime, NATIVE_TIME_UNIT); + setLastAccessTime(lastAccessTime, TimeUnit.MILLISECONDS); this.value = value; this.valueSerialized = valueSerialized; } @@ -85,11 +83,6 @@ protected XAValueHolder copyAfterDeserialization(Serializer valueSerialize return new XAValueHolder<>(this, valueSerializer.read(ByteBuffer.wrap(valueSerialized))); } - @Override - protected TimeUnit nativeTimeUnit() { - return NATIVE_TIME_UNIT; - } - @Override public V get() { return value; @@ -115,7 +108,7 @@ public boolean equals(Object other) { } private Object writeReplace() { - return new SerializedXAValueHolder<>(getId(), creationTime(NATIVE_TIME_UNIT), lastAccessTime(NATIVE_TIME_UNIT), expirationTime(NATIVE_TIME_UNIT), + return new SerializedXAValueHolder<>(getId(), creationTime(TimeUnit.MILLISECONDS), lastAccessTime(TimeUnit.MILLISECONDS), expirationTime(TimeUnit.MILLISECONDS), get(), valueSerialized); } diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java index 35d75c83ef..724d5952d6 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java @@ -349,10 +349,6 @@ public void testCommitInOnePhase() throws Exception { public Object get() { return softLock1Ref.get(); } - @Override - protected TimeUnit nativeTimeUnit() { - return TimeUnit.MILLISECONDS; - } }); when(underlyingStore.putIfAbsent(eq(1L), isA(SoftLock.class), any(Consumer.class))).then(invocation -> { softLock1Ref.set((SoftLock) invocation.getArguments()[1]); @@ -370,10 +366,6 @@ protected TimeUnit nativeTimeUnit() { public Object get() { return softLock2Ref.get(); } - @Override - protected TimeUnit nativeTimeUnit() { - return TimeUnit.MILLISECONDS; - } }); when(underlyingStore.replace(eq(2L), isA(SoftLock.class), isA(SoftLock.class))).then(invocation -> { softLock2Ref.set((SoftLock) invocation.getArguments()[2]); @@ -428,20 +420,12 @@ public void testRollbackPhase2() throws Exception { when(journal.getInDoubtKeys(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(Arrays.asList(1L, 2L)); when(underlyingStore.get(1L)).thenReturn(new AbstractValueHolder>(-1, -1) { - @Override - protected TimeUnit nativeTimeUnit() { - return TimeUnit.MILLISECONDS; - } @Override public SoftLock get() { return new SoftLock<>(new TransactionId(new TestXid(0, 0)), "one", new XAValueHolder<>("un", timeSource.getTimeMillis())); } }); when(underlyingStore.get(2L)).thenReturn(new AbstractValueHolder>(-1, -1) { - @Override - protected TimeUnit nativeTimeUnit() { - return TimeUnit.MILLISECONDS; - } @Override public SoftLock get() { return new SoftLock<>(new TransactionId(new TestXid(0, 0)), "two", null); @@ -497,10 +481,6 @@ public void testCommitConflictsEvicts() throws Exception { when(journal.isInDoubt(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(true); when(journal.getInDoubtKeys(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(Arrays.asList(1L, 2L)); when(underlyingStore.get(eq(1L))).thenReturn(new AbstractValueHolder>(-1, -1) { - @Override - protected TimeUnit nativeTimeUnit() { - return TimeUnit.MILLISECONDS; - } @Override public SoftLock get() { return new SoftLock<>(new TransactionId(new TestXid(0, 0)), "old1", new XAValueHolder<>("new1", timeSource @@ -508,10 +488,6 @@ public SoftLock get() { } }); when(underlyingStore.get(eq(2L))).thenReturn(new AbstractValueHolder>(-1, -1) { - @Override - protected TimeUnit nativeTimeUnit() { - return TimeUnit.MILLISECONDS; - } @Override public SoftLock get() { return new SoftLock<>(new TransactionId(new TestXid(0, 0)), "old2", null); @@ -555,10 +531,6 @@ public void testRollbackConflictsEvicts() throws Exception { when(journal.isInDoubt(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(true); when(journal.getInDoubtKeys(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(Arrays.asList(1L, 2L)); when(underlyingStore.get(eq(1L))).thenReturn(new AbstractValueHolder>(-1, -1) { - @Override - protected TimeUnit nativeTimeUnit() { - return TimeUnit.MILLISECONDS; - } @Override public SoftLock get() { return new SoftLock<>(new TransactionId(new TestXid(0, 0)), "old1", new XAValueHolder<>("new1", timeSource @@ -566,10 +538,6 @@ public SoftLock get() { } }); when(underlyingStore.get(eq(2L))).thenReturn(new AbstractValueHolder>(-1, -1) { - @Override - protected TimeUnit nativeTimeUnit() { - return TimeUnit.MILLISECONDS; - } @Override public SoftLock get() { return new SoftLock<>(new TransactionId(new TestXid(0, 0)), "old2", null); From 2110072b88568bb8eb3b735b9db1d600c6315a08 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Sat, 11 Aug 2018 00:19:41 -0400 Subject: [PATCH 038/372] Everything is in milliseconds so no need to specify it --- ...che107ConfigurationIntegrationDocTest.java | 2 +- .../internal/store/ClusteredStoreTest.java | 4 +-- .../StoreValueHolderCreationTimeTest.java | 2 +- .../StoreValueHolderLastAccessTimeTest.java | 2 +- .../internal/tier/AuthoritativeTierFlush.java | 6 ++-- .../tier/CachingTierGetOrComputeIfAbsent.java | 2 +- .../internal/tier/CachingTierInvalidate.java | 8 ++--- .../core/spi/store/AbstractValueHolder.java | 26 +++++++------- .../org/ehcache/core/spi/store/Store.java | 20 +++++------ .../test/java/org/ehcache/core/CacheTest.java | 16 ++++----- .../ehcache/core/EhcacheBasicCrudBase.java | 12 +++---- .../ehcache/core/EhcacheBulkMethodsTest.java | 8 ++--- .../spi/store/AbstractValueHolderTest.java | 28 ++++----------- .../store/basic/EmptyValueHolder.java | 8 ++--- .../impl/internal/store/heap/OnHeapStore.java | 34 +++++++++--------- .../internal/store/heap/OnHeapStrategy.java | 4 +-- .../heap/holders/CopiedOnHeapValueHolder.java | 2 +- .../holders/SerializedOnHeapValueHolder.java | 5 ++- .../store/offheap/AbstractOffHeapStore.java | 36 +++++++++---------- .../store/offheap/LazyOffHeapValueHolder.java | 8 ++--- .../OffHeapValueHolderPortability.java | 6 ++-- .../store/heap/BaseOnHeapStoreTest.java | 30 ++++++++-------- .../offheap/AbstractOffHeapStoreTest.java | 30 ++++++++-------- .../store/tiering/TieredStoreSPITest.java | 10 +++--- .../store/tiering/TieredStoreTest.java | 21 ++++++----- .../tiering/TieredStoreWith3TiersSPITest.java | 8 ++--- .../transactions/xa/internal/XAStore.java | 2 +- .../xa/internal/XAValueHolder.java | 8 ++--- .../xa/internal/XAValueHolderTest.java | 6 ++-- 29 files changed, 167 insertions(+), 187 deletions(-) diff --git a/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java b/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java index d54c7ae2b7..ca4b570f72 100644 --- a/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java +++ b/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java @@ -259,7 +259,7 @@ public void testTemplateOverridingStoreByRef() throws Exception { MutableConfiguration mutableConfiguration = new MutableConfiguration<>(); mutableConfiguration.setTypes(Long.class, Client.class).setStoreByValue(false); - Cache myCache = null; + Cache myCache; Client client1 = new Client("client1", 1); myCache = cacheManager.createCache("anotherCache", mutableConfiguration); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java index beebc0dc29..7928b86eb6 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java @@ -878,7 +878,7 @@ public void testExpirationIsSentToHigherTiers() throws Exception { Store.ValueHolder vh = store.get(1L); - long expirationTime = vh.expirationTime(TimeUnit.MILLISECONDS); + long expirationTime = vh.expirationTime(); assertThat(expirationTime, is(1000L)); } @@ -908,7 +908,7 @@ public void testNoExpireIsSentToHigherTiers() throws Exception { Store.ValueHolder vh = store.get(1L); - long expirationTime = vh.expirationTime(TimeUnit.MILLISECONDS); + long expirationTime = vh.expirationTime(); assertThat(expirationTime, is(NO_EXPIRE)); } } diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreValueHolderCreationTimeTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreValueHolderCreationTimeTest.java index edd7130e7b..7978e54112 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreValueHolderCreationTimeTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreValueHolderCreationTimeTest.java @@ -43,7 +43,7 @@ public void creationTimeCanBeReturned() throws IllegalAccessException, InstantiationException { Store.ValueHolder valueHolder = factory.newValueHolder(factory.createValue(1)); - assertThat(valueHolder.creationTime(TimeUnit.MILLISECONDS), is(notNullValue())); + assertThat(valueHolder.creationTime(), is(notNullValue())); } } diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreValueHolderLastAccessTimeTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreValueHolderLastAccessTimeTest.java index 7564b4837e..bf5806bdd9 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreValueHolderLastAccessTimeTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreValueHolderLastAccessTimeTest.java @@ -43,6 +43,6 @@ public void lastAccessTimeCanBeReturned() throws IllegalAccessException, InstantiationException { Store.ValueHolder valueHolder = factory.newValueHolder(factory.createValue(1)); - assertThat(valueHolder.lastAccessTime(TimeUnit.MILLISECONDS), is(notNullValue())); + assertThat(valueHolder.lastAccessTime(), is(notNullValue())); } } diff --git a/core-spi-test/src/main/java/org/ehcache/internal/tier/AuthoritativeTierFlush.java b/core-spi-test/src/main/java/org/ehcache/internal/tier/AuthoritativeTierFlush.java index 0b1c16e036..e4c31512f3 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/tier/AuthoritativeTierFlush.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/tier/AuthoritativeTierFlush.java @@ -60,7 +60,7 @@ public void entryIsFlushed() throws LegalSPITesterException { K key = factory.createKey(1); final V value = factory.createValue(1); Store.ValueHolder valueHolder = mock(Store.ValueHolder.class); - when(valueHolder.expirationTime(any(TimeUnit.class))).thenReturn(1L); + when(valueHolder.expirationTime()).thenReturn(1L); tier = factory.newStoreWithCapacity(1L); @@ -81,7 +81,7 @@ public void entryIsNotFlushed() throws LegalSPITesterException { K key = factory.createKey(1); final V value = factory.createValue(1); Store.ValueHolder valueHolder = mock(Store.ValueHolder.class); - when(valueHolder.expirationTime(any(TimeUnit.class))).thenReturn(1L); + when(valueHolder.expirationTime()).thenReturn(1L); tier = factory.newStoreWithCapacity(1L); @@ -99,7 +99,7 @@ public void entryIsNotFlushed() throws LegalSPITesterException { public void entryDoesNotExist() { K key = factory.createKey(1); Store.ValueHolder valueHolder = mock(Store.ValueHolder.class); - when(valueHolder.expirationTime(any(TimeUnit.class))).thenReturn(1L); + when(valueHolder.expirationTime()).thenReturn(1L); tier = factory.newStoreWithCapacity(1L); diff --git a/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierGetOrComputeIfAbsent.java b/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierGetOrComputeIfAbsent.java index 8799027d56..912e7b4c42 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierGetOrComputeIfAbsent.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierGetOrComputeIfAbsent.java @@ -83,7 +83,7 @@ public void returnTheValueHolderCurrentlyInTheCachingTier() throws LegalSPITeste V value = factory.createValue(1); final Store.ValueHolder computedValueHolder = mock(Store.ValueHolder.class); when(computedValueHolder.get()).thenReturn(value); - when(computedValueHolder.expirationTime(any(TimeUnit.class))).thenReturn(Store.ValueHolder.NO_EXPIRE); + when(computedValueHolder.expirationTime()).thenReturn(Store.ValueHolder.NO_EXPIRE); tier = factory.newCachingTier(); diff --git a/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierInvalidate.java b/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierInvalidate.java index 1e3f1f3b12..e71f8550fa 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierInvalidate.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierInvalidate.java @@ -137,22 +137,22 @@ public V get() { } @Override - public long creationTime(TimeUnit unit) { + public long creationTime() { return 0L; } @Override - public long expirationTime(TimeUnit unit) { + public long expirationTime() { return 0L; } @Override - public boolean isExpired(long expirationTime, TimeUnit unit) { + public boolean isExpired(long expirationTime) { return false; } @Override - public long lastAccessTime(TimeUnit unit) { + public long lastAccessTime() { return 0L; } diff --git a/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java b/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java index 133562f480..6977b07e73 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java +++ b/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java @@ -58,8 +58,8 @@ protected final TimeUnit nativeTimeUnit() { } @Override - public long creationTime(TimeUnit unit) { - return unit.convert(creationTime, nativeTimeUnit()); + public long creationTime() { + return creationTime; } public void setExpirationTime(long expirationTime, TimeUnit unit) { @@ -98,26 +98,26 @@ public void accessed(long now, Duration expiration) { } @Override - public long expirationTime(TimeUnit unit) { - final long expire = this.expirationTime; + public long expirationTime() { + long expire = this.expirationTime; if (expire == NO_EXPIRE) { return NO_EXPIRE; } - return unit.convert(expire, nativeTimeUnit()); + return expire; } @Override - public boolean isExpired(long expirationTime, TimeUnit unit) { - final long expire = this.expirationTime; + public boolean isExpired(long expirationTime) { + long expire = this.expirationTime; if (expire == NO_EXPIRE) { return false; } - return expire <= nativeTimeUnit().convert(expirationTime, unit); + return expire <= expirationTime; } @Override - public long lastAccessTime(TimeUnit unit) { - return unit.convert(lastAccessTime, nativeTimeUnit()); + public long lastAccessTime() { + return lastAccessTime; } public void setLastAccessTime(long lastAccessTime, TimeUnit unit) { @@ -147,9 +147,9 @@ public boolean equals(Object obj) { if (obj instanceof AbstractValueHolder) { AbstractValueHolder other = (AbstractValueHolder) obj; return - other.creationTime(nativeTimeUnit()) == creationTime && - other.expirationTime(nativeTimeUnit()) == expirationTime && - other.lastAccessTime(nativeTimeUnit()) == lastAccessTime; + other.creationTime == creationTime && + other.expirationTime == expirationTime && + other.lastAccessTime == lastAccessTime; } return false; } diff --git a/core/src/main/java/org/ehcache/core/spi/store/Store.java b/core/src/main/java/org/ehcache/core/spi/store/Store.java index 82695686fb..5b9b195d57 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/Store.java +++ b/core/src/main/java/org/ehcache/core/spi/store/Store.java @@ -470,35 +470,31 @@ interface ValueHolder extends Supplier { /** * Accessor to the creation time of this ValueHolder * - * @param unit the timeUnit to return the creation time in - * @return the creation time in the given unit + * @return the creation time in milliseconds */ - long creationTime(TimeUnit unit); + long creationTime(); /** * Accessor to the expiration time of this ValueHolder * - * @param unit the timeUnit to return the creation time in - * @return the expiration time in the given unit. A value of {@link #NO_EXPIRE} means that the ValueHolder will never expire. + * @return the expiration time in milliseconds. A value of {@link #NO_EXPIRE} means that the ValueHolder will never expire. */ - long expirationTime(TimeUnit unit); + long expirationTime(); /** * Check if the ValueHolder is expired relative to the specified time * - * @param expirationTime the expiration time relative to which the expiry check must be made - * @param unit the unit of the expiration time + * @param expirationTime the expiration time (in ms) relative to which the expiry check must be made * @return true if the ValueHolder expired relative to the given expiration time */ - boolean isExpired(long expirationTime, TimeUnit unit); + boolean isExpired(long expirationTime); /** * Accessor to the last access time of the Value held in this ValueHolder * - * @param unit the timeUnit to return the last access time in - * @return the last access time in the given unit + * @return the last access time in milliseconds */ - long lastAccessTime(TimeUnit unit); + long lastAccessTime(); /** * The combination of this identifier and the key that ValueHolder is mapped to should to be diff --git a/core/src/test/java/org/ehcache/core/CacheTest.java b/core/src/test/java/org/ehcache/core/CacheTest.java index 8317638e26..0d48d911c2 100644 --- a/core/src/test/java/org/ehcache/core/CacheTest.java +++ b/core/src/test/java/org/ehcache/core/CacheTest.java @@ -230,22 +230,22 @@ public Object get() { } @Override - public long creationTime(final TimeUnit unit) { + public long creationTime() { throw new UnsupportedOperationException("Implement me!"); } @Override - public long expirationTime(TimeUnit unit) { + public long expirationTime() { throw new UnsupportedOperationException("Implement me!"); } @Override - public boolean isExpired(long expirationTime, TimeUnit unit) { + public boolean isExpired(long expirationTime) { throw new UnsupportedOperationException("Implement me!"); } @Override - public long lastAccessTime(final TimeUnit unit) { + public long lastAccessTime() { throw new UnsupportedOperationException("Implement me!"); } @@ -267,22 +267,22 @@ public Object get() { } @Override - public long creationTime(final TimeUnit unit) { + public long creationTime() { throw new UnsupportedOperationException("Implement me!"); } @Override - public long expirationTime(TimeUnit unit) { + public long expirationTime() { throw new UnsupportedOperationException("Implement me!"); } @Override - public boolean isExpired(long expirationTime, TimeUnit unit) { + public boolean isExpired(long expirationTime) { throw new UnsupportedOperationException("Implement me!"); } @Override - public long lastAccessTime(final TimeUnit unit) { + public long lastAccessTime() { throw new UnsupportedOperationException("Implement me!"); } diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java b/core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java index 400b4b6959..72d2e7a985 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java @@ -600,23 +600,23 @@ public String get() { } @Override - public long creationTime(final TimeUnit unit) { - return unit.convert(this.creationTime, TimeUnit.MICROSECONDS); + public long creationTime() { + return creationTime; } @Override - public long expirationTime(TimeUnit unit) { + public long expirationTime() { return 0; } @Override - public boolean isExpired(long expirationTime, TimeUnit unit) { + public boolean isExpired(long expirationTime) { return false; } @Override - public long lastAccessTime(final TimeUnit unit) { - return unit.convert(this.lastAccessTime, TimeUnit.MICROSECONDS); + public long lastAccessTime() { + return lastAccessTime; } @Override diff --git a/core/src/test/java/org/ehcache/core/EhcacheBulkMethodsTest.java b/core/src/test/java/org/ehcache/core/EhcacheBulkMethodsTest.java index 1ad07817b5..493dde3052 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBulkMethodsTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBulkMethodsTest.java @@ -159,22 +159,22 @@ public V get() { } @Override - public long creationTime(TimeUnit unit) { + public long creationTime() { throw new AssertionError(); } @Override - public long expirationTime(TimeUnit unit) { + public long expirationTime() { return 0; } @Override - public boolean isExpired(long expirationTime, TimeUnit unit) { + public boolean isExpired(long expirationTime) { return false; } @Override - public long lastAccessTime(TimeUnit unit) { + public long lastAccessTime() { throw new AssertionError(); } diff --git a/core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java b/core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java index 5d88108104..18533b22ba 100644 --- a/core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java +++ b/core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java @@ -33,18 +33,14 @@ public class AbstractValueHolderTest { public void testCreationTime() throws Exception { AbstractValueHolder valueHolder = newAbstractValueHolder(1000L); - assertThat(valueHolder.creationTime(TimeUnit.SECONDS), is(1L)); - assertThat(valueHolder.creationTime(TimeUnit.MILLISECONDS), is(1000L)); - assertThat(valueHolder.creationTime(TimeUnit.MICROSECONDS), is(1000000L)); + assertThat(valueHolder.creationTime(), is(1000L)); } @Test public void testExpirationTime() throws Exception { AbstractValueHolder valueHolder = newAbstractValueHolder(0L, 1000L); - assertThat(valueHolder.expirationTime(TimeUnit.SECONDS), is(1L)); - assertThat(valueHolder.expirationTime(TimeUnit.MILLISECONDS), is(1000L)); - assertThat(valueHolder.expirationTime(TimeUnit.MICROSECONDS), is(1000000L)); + assertThat(valueHolder.expirationTime(), is(1000L)); } @@ -53,31 +49,21 @@ public void testLastAccessTime() throws Exception { // last access time defaults to create time AbstractValueHolder valueHolder = newAbstractValueHolder(1000L); - assertThat(valueHolder.lastAccessTime(TimeUnit.SECONDS), is(1L)); - assertThat(valueHolder.lastAccessTime(TimeUnit.MILLISECONDS), is(1000L)); - assertThat(valueHolder.lastAccessTime(TimeUnit.MICROSECONDS), is(1000000L)); + assertThat(valueHolder.lastAccessTime(), is(1000L)); valueHolder = newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 0L, 2000L); - assertThat(valueHolder.lastAccessTime(TimeUnit.SECONDS), is(2L)); - assertThat(valueHolder.lastAccessTime(TimeUnit.MILLISECONDS), is(2000L)); - assertThat(valueHolder.lastAccessTime(TimeUnit.MICROSECONDS), is(2000000L)); + assertThat(valueHolder.lastAccessTime(), is(2000L)); } @Test public void testIsExpired() throws Exception { - assertThat(newAbstractValueHolder(1000L).isExpired(1L, TimeUnit.SECONDS), is(false)); - assertThat(newAbstractValueHolder(1000L).isExpired(1000L, TimeUnit.MILLISECONDS), is(false)); - assertThat(newAbstractValueHolder(1000L).isExpired(1000000L, TimeUnit.MICROSECONDS), is(false)); + assertThat(newAbstractValueHolder(1000L).isExpired(1000L), is(false)); - assertThat(newAbstractValueHolder(1000L, 1001L).isExpired(1L, TimeUnit.SECONDS), is(false)); - assertThat(newAbstractValueHolder(1000L, 1001L).isExpired(1000L, TimeUnit.MILLISECONDS), is(false)); - assertThat(newAbstractValueHolder(1000L, 1001L).isExpired(1000000L, TimeUnit.MICROSECONDS), is(false)); + assertThat(newAbstractValueHolder(1000L, 1001L).isExpired(1000L), is(false)); - assertThat(newAbstractValueHolder(1000L, 1000L).isExpired(1L, TimeUnit.SECONDS), is(true)); - assertThat(newAbstractValueHolder(1000L, 1000L).isExpired(1000L, TimeUnit.MILLISECONDS), is(true)); - assertThat(newAbstractValueHolder(1000L, 1000L).isExpired(1000000L, TimeUnit.MICROSECONDS), is(true)); + assertThat(newAbstractValueHolder(1000L, 1000L).isExpired(1000L), is(true)); } @Test diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/basic/EmptyValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/basic/EmptyValueHolder.java index b6d8b2da7a..1146ee26bb 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/basic/EmptyValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/basic/EmptyValueHolder.java @@ -39,22 +39,22 @@ public V get() { } @Override - public long creationTime(TimeUnit unit) { + public long creationTime() { return 0; } @Override - public long expirationTime(TimeUnit unit) { + public long expirationTime() { return 0; } @Override - public boolean isExpired(long expirationTime, TimeUnit unit) { + public boolean isExpired(long expirationTime) { return false; } @Override - public long lastAccessTime(TimeUnit unit) { + public long lastAccessTime() { return 0; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index 91290ac259..f04e4ec77a 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -135,7 +135,7 @@ public class OnHeapStore extends BaseStore implements HigherCachingT } else if (u instanceof Fault) { return 1; } else { - return Long.signum(u.lastAccessTime(TimeUnit.NANOSECONDS) - t.lastAccessTime(TimeUnit.NANOSECONDS)); + return Long.signum(u.lastAccessTime() - t.lastAccessTime()); } }; @@ -338,7 +338,7 @@ public PutStatus put(K key, V value) throws StoreAccessException { long delta = 0; - if (mappedValue != null && mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue != null && mappedValue.isExpired(now)) { delta -= mappedValue.size(); mappedValue = null; } @@ -399,7 +399,7 @@ public boolean remove(K key) throws StoreAccessException { map.computeIfPresent(key, (mappedKey, mappedValue) -> { updateUsageInBytesIfRequired(- mappedValue.size()); - if (mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue.isExpired(now)) { fireOnExpirationEvent(mappedKey, mappedValue, eventSink); return null; } @@ -443,7 +443,7 @@ public ValueHolder putIfAbsent(K key, V value, Consumer put) throws OnHeapValueHolder holder; - if (mappedValue == null || mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue == null || mappedValue.isExpired(now)) { if (mappedValue != null) { delta -= mappedValue.size(); fireOnExpirationEvent(mappedKey, mappedValue, eventSink); @@ -497,7 +497,7 @@ public RemoveStatus remove(K key, V value) throws StoreAccessException { map.computeIfPresent(key, (mappedKey, mappedValue) -> { long now = timeSource.getTimeMillis(); - if (mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue.isExpired(now)) { updateUsageInBytesIfRequired(- mappedValue.size()); fireOnExpirationEvent(mappedKey, mappedValue, eventSink); return null; @@ -550,7 +550,7 @@ public ValueHolder replace(K key, V value) throws StoreAccessException { map.computeIfPresent(key, (mappedKey, mappedValue) -> { long now = timeSource.getTimeMillis(); - if (mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue.isExpired(now)) { updateUsageInBytesIfRequired(- mappedValue.size()); fireOnExpirationEvent(mappedKey, mappedValue, eventSink); return null; @@ -597,7 +597,7 @@ public ReplaceStatus replace(K key, V oldValue, V newValue) throws StoreAccessEx long now = timeSource.getTimeMillis(); V existingValue = mappedValue.get(); - if (mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue.isExpired(now)) { fireOnExpirationEvent(mappedKey, mappedValue, eventSink); updateUsageInBytesIfRequired(- mappedValue.size()); return null; @@ -696,7 +696,7 @@ public ValueHolder getOrComputeIfAbsent(K key, Function> so // If we have a real value (not a fault), we make sure it is not expired // If yes, we remove it and ask the source just in case. If no, we return it (below) if (!(cachedValue instanceof Fault)) { - if (cachedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (cachedValue.isExpired(now)) { expireMappingUnderLock(key, cachedValue); // On expiration, we might still be able to get a value from the fault. For instance, when a load-writer is used @@ -756,7 +756,7 @@ private ValueHolder resolveFault(K key, Backend backEnd, long now, Faul ValueHolder p = getValue(invalidatedValue.get()); if (p != null) { - if (p.isExpired(now, TimeUnit.MILLISECONDS)) { + if (p.isExpired(now)) { getOrComputeIfAbsentObserver.end(CachingTierOperationOutcomes.GetOrComputeIfAbsentOutcome.FAULT_FAILED_MISS); return null; } @@ -1012,7 +1012,7 @@ public V get() { } @Override - public long creationTime(TimeUnit unit) { + public long creationTime() { throw new UnsupportedOperationException(); } @@ -1022,17 +1022,17 @@ public void setExpirationTime(long expirationTime, TimeUnit unit) { } @Override - public long expirationTime(TimeUnit unit) { + public long expirationTime() { throw new UnsupportedOperationException(); } @Override - public boolean isExpired(long expirationTime, TimeUnit unit) { + public boolean isExpired(long expirationTime) { throw new UnsupportedOperationException(); } @Override - public long lastAccessTime(TimeUnit unit) { + public long lastAccessTime() { return Long.MAX_VALUE; } @@ -1151,7 +1151,7 @@ public ValueHolder computeAndGet(K key, BiFunction computeResult = map.compute(key, (mappedKey, mappedValue) -> { long delta = 0L; - if (mappedValue != null && mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue != null && mappedValue.isExpired(now)) { fireOnExpirationEvent(mappedKey, mappedValue, eventSink); delta -= mappedValue.size(); mappedValue = null; @@ -1178,7 +1178,7 @@ public ValueHolder computeAndGet(K key, BiFunction computeIfAbsent(K key, Function ma long delta = 0; OnHeapValueHolder holder; - if (mappedValue == null || mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue == null || mappedValue.isExpired(now)) { if (mappedValue != null) { delta -= mappedValue.size(); fireOnExpirationEvent(mappedKey, mappedValue, eventSink); @@ -1388,7 +1388,7 @@ private OnHeapValueHolder newUpdateValueHolder(K key, OnHeapValueHolder ol long expirationTime; if (duration == null) { - expirationTime = oldValue.expirationTime(TimeUnit.MILLISECONDS); + expirationTime = oldValue.expirationTime(); } else { if (isExpiryDurationInfinite(duration)) { expirationTime = ValueHolder.NO_EXPIRE; diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java index b4b297cd97..7910481e39 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java @@ -119,7 +119,7 @@ public AllStrategy(OnHeapStore store, ExpiryPolicy e @Override public boolean isExpired(OnHeapValueHolder mapping) { - return mapping.isExpired(timeSource.getTimeMillis(), TimeUnit.MILLISECONDS); + return mapping.isExpired(timeSource.getTimeMillis()); } @Override @@ -226,7 +226,7 @@ public TTLStrategy(ExpiryPolicy expiry, TimeSource timeSou @Override public boolean isExpired(OnHeapValueHolder mapping) { - return mapping.isExpired(timeSource.getTimeMillis(), TimeUnit.MILLISECONDS); + return mapping.isExpired(timeSource.getTimeMillis()); } @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolder.java index da7d491405..554b2f6b8f 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolder.java @@ -53,7 +53,7 @@ protected CopiedOnHeapValueHolder(long id, V value, long creationTime, long expi * @param expiration computed expiration duration */ public CopiedOnHeapValueHolder(Store.ValueHolder valueHolder, V value, boolean evictionAdvice, Copier valueCopier, long now, java.time.Duration expiration) { - super(valueHolder.getId(), valueHolder.creationTime(TimeUnit.MILLISECONDS), valueHolder.expirationTime(TimeUnit.MILLISECONDS), evictionAdvice); + super(valueHolder.getId(), valueHolder.creationTime(), valueHolder.expirationTime(), evictionAdvice); if (value == null) { throw new NullPointerException("null value"); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolder.java index df3e393ef9..a5dcaf8d9d 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolder.java @@ -22,7 +22,6 @@ import org.ehcache.spi.serialization.Serializer; import java.nio.ByteBuffer; -import java.util.concurrent.TimeUnit; public class SerializedOnHeapValueHolder extends OnHeapValueHolder implements BinaryValueHolder { private final ByteBuffer buffer; @@ -50,12 +49,12 @@ public SerializedOnHeapValueHolder(V value, long creationTime, long expirationTi } public SerializedOnHeapValueHolder(Store.ValueHolder valueHolder, V value, boolean evictionAdvice, Serializer serializer, long now, java.time.Duration expiration) { - this(valueHolder.getId(), value, valueHolder.creationTime(TimeUnit.MILLISECONDS), valueHolder.expirationTime(TimeUnit.MILLISECONDS), evictionAdvice, serializer); + this(valueHolder.getId(), value, valueHolder.creationTime(), valueHolder.expirationTime(), evictionAdvice, serializer); this.accessed(now, expiration); } public SerializedOnHeapValueHolder(Store.ValueHolder valueHolder, ByteBuffer binaryValue, boolean evictionAdvice, Serializer serializer, long now, java.time.Duration expiration) { - super(valueHolder.getId(), valueHolder.creationTime(TimeUnit.MILLISECONDS), valueHolder.expirationTime(TimeUnit.MILLISECONDS), evictionAdvice); + super(valueHolder.getId(), valueHolder.creationTime(), valueHolder.expirationTime(), evictionAdvice); this.buffer = binaryValue; this.serializer = serializer; this.accessed(now, expiration); diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java index 96b27b73d7..044c7a39e3 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java @@ -181,7 +181,7 @@ private Store.ValueHolder internalGet(K key, final boolean updateAccess, fina OffHeapValueHolder result = backingMap().computeIfPresent(key, (mappedKey, mappedValue) -> { long now = timeSource.getTimeMillis(); - if (mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue.isExpired(now)) { onExpiration(mappedKey, mappedValue, eventSink); return null; } @@ -230,7 +230,7 @@ public PutStatus put(final K key, final V value) throws StoreAccessException { try { BiFunction, OffHeapValueHolder> mappingFunction = (mappedKey, mappedValue) -> { - if (mappedValue != null && mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue != null && mappedValue.isExpired(now)) { mappedValue = null; } @@ -274,7 +274,7 @@ public Store.ValueHolder putIfAbsent(final K key, final V value, Consumer, OffHeapValueHolder> mappingFunction = (mappedKey, mappedValue) -> { long now = timeSource.getTimeMillis(); - if (mappedValue == null || mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue == null || mappedValue.isExpired(now)) { if (mappedValue != null) { onExpiration(mappedKey, mappedValue, eventSink); } @@ -316,7 +316,7 @@ public boolean remove(final K key) throws StoreAccessException { backingMap().computeIfPresent(key, (mappedKey, mappedValue) -> { - if (mappedValue != null && mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue != null && mappedValue.isExpired(now)) { onExpiration(mappedKey, mappedValue, eventSink); return null; } @@ -357,7 +357,7 @@ public RemoveStatus remove(final K key, final V value) throws StoreAccessExcepti backingMap().computeIfPresent(key, (mappedKey, mappedValue) -> { long now = timeSource.getTimeMillis(); - if (mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue.isExpired(now)) { onExpiration(mappedKey, mappedValue, eventSink); return null; } else if (mappedValue.get().equals(value)) { @@ -402,7 +402,7 @@ public ValueHolder replace(final K key, final V value) throws NullPointerExce BiFunction, OffHeapValueHolder> mappingFunction = (mappedKey, mappedValue) -> { long now = timeSource.getTimeMillis(); - if (mappedValue == null || mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue == null || mappedValue.isExpired(now)) { if (mappedValue != null) { onExpiration(mappedKey, mappedValue, eventSink); } @@ -443,7 +443,7 @@ public ReplaceStatus replace(final K key, final V oldValue, final V newValue) th BiFunction, OffHeapValueHolder> mappingFunction = (mappedKey, mappedValue) -> { long now = timeSource.getTimeMillis(); - if (mappedValue == null || mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue == null || mappedValue.isExpired(now)) { if (mappedValue != null) { onExpiration(mappedKey, mappedValue, eventSink); } @@ -601,7 +601,7 @@ public ValueHolder computeAndGet(final K key, final BiFunction, OffHeapValueHolder> computeFunction = (mappedKey, mappedValue) -> { long now = timeSource.getTimeMillis(); V existingValue = null; - if (mappedValue == null || mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue == null || mappedValue.isExpired(now)) { if (mappedValue != null) { onExpiration(mappedKey, mappedValue, eventSink); } @@ -685,7 +685,7 @@ private Store.ValueHolder internalComputeIfAbsent(final K key, final Function final StoreEventSink eventSink = eventDispatcher.eventSink(); BiFunction, OffHeapValueHolder> computeFunction = (mappedKey, mappedValue) -> { long now = timeSource.getTimeMillis(); - if (mappedValue == null || mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue == null || mappedValue.isExpired(now)) { if (mappedValue != null) { onExpiration(mappedKey, mappedValue, eventSink); } @@ -820,7 +820,7 @@ public ValueHolder getAndFault(K key) throws StoreAccessException { final StoreEventSink eventSink = eventDispatcher.eventSink(); try { mappedValue = backingMap().computeIfPresentAndPin(key, (mappedKey, mappedValue1) -> { - if(mappedValue1.isExpired(timeSource.getTimeMillis(), TimeUnit.MILLISECONDS)) { + if(mappedValue1.isExpired(timeSource.getTimeMillis())) { onExpiration(mappedKey, mappedValue1, eventSink); return null; } @@ -857,7 +857,7 @@ public boolean flush(K key, final ValueHolder valueFlushed) { try { boolean result = backingMap().computeIfPinned(key, (k, valuePresent) -> { if (valuePresent.getId() == valueFlushed.getId()) { - if (valueFlushed.isExpired(timeSource.getTimeMillis(), TimeUnit.MILLISECONDS)) { + if (valueFlushed.isExpired(timeSource.getTimeMillis())) { onExpiration(k, valuePresent, eventSink); return null; } @@ -964,7 +964,7 @@ public ValueHolder getAndRemove(final K key) throws StoreAccessException { final AtomicReference> valueHolderAtomicReference = new AtomicReference<>(); BiFunction, OffHeapValueHolder> computeFunction = (mappedKey, mappedValue) -> { long now = timeSource.getTimeMillis(); - if (mappedValue == null || mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue == null || mappedValue.isExpired(now)) { if (mappedValue != null) { onExpirationInCachingTier(mappedValue, key); } @@ -998,7 +998,7 @@ public ValueHolder installMapping(final K key, final Function valueHolder = source.apply(k); if (valueHolder != null) { - if (valueHolder.isExpired(timeSource.getTimeMillis(), TimeUnit.MILLISECONDS)) { + if (valueHolder.isExpired(timeSource.getTimeMillis())) { onExpirationInCachingTier(valueHolder, key); return null; } else { @@ -1086,7 +1086,7 @@ private OffHeapValueHolder newUpdatedValueHolder(K key, V value, OffHeapValue } if (duration == null) { - return new BasicOffHeapValueHolder<>(backingMap().nextIdFor(key), value, now, existing.expirationTime(TimeUnit.MILLISECONDS)); + return new BasicOffHeapValueHolder<>(backingMap().nextIdFor(key), value, now, existing.expirationTime()); } else if (isExpiryDurationInfinite(duration)) { return new BasicOffHeapValueHolder<>(backingMap().nextIdFor(key), value, now, OffHeapValueHolder.NO_EXPIRE); } else { @@ -1112,11 +1112,11 @@ private OffHeapValueHolder newCreateValueHolder(K key, V value, long now, Sto private OffHeapValueHolder newTransferValueHolder(ValueHolder valueHolder) { if (valueHolder instanceof BinaryValueHolder && ((BinaryValueHolder) valueHolder).isBinaryValueAvailable()) { return new BinaryOffHeapValueHolder<>(valueHolder.getId(), valueHolder.get(), ((BinaryValueHolder) valueHolder).getBinaryValue(), - valueHolder.creationTime(TimeUnit.MILLISECONDS), valueHolder.expirationTime(TimeUnit.MILLISECONDS), - valueHolder.lastAccessTime(TimeUnit.MILLISECONDS)); + valueHolder.creationTime(), valueHolder.expirationTime(), + valueHolder.lastAccessTime()); } else { - return new BasicOffHeapValueHolder<>(valueHolder.getId(), valueHolder.get(), valueHolder.creationTime(TimeUnit.MILLISECONDS), - valueHolder.expirationTime(TimeUnit.MILLISECONDS), valueHolder.lastAccessTime(TimeUnit.MILLISECONDS)); + return new BasicOffHeapValueHolder<>(valueHolder.getId(), valueHolder.get(), valueHolder.creationTime(), + valueHolder.expirationTime(), valueHolder.lastAccessTime()); } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java index 3a47fbb081..301612c2fe 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java @@ -72,8 +72,8 @@ void updateMetadata(final Store.ValueHolder valueFlushed) { if(getId() != valueFlushed.getId()) { throw new IllegalArgumentException("Wrong id passed in [this.id != id] : " + getId() + " != " + valueFlushed.getId()); } - this.setLastAccessTime(valueFlushed.lastAccessTime(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS); - this.setExpirationTime(valueFlushed.expirationTime(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS); + this.setLastAccessTime(valueFlushed.lastAccessTime(), TimeUnit.MILLISECONDS); + this.setExpirationTime(valueFlushed.expirationTime(), TimeUnit.MILLISECONDS); } /** @@ -81,8 +81,8 @@ void updateMetadata(final Store.ValueHolder valueFlushed) { */ @Override void writeBack() { - writeContext.setLong(OffHeapValueHolderPortability.ACCESS_TIME_OFFSET, lastAccessTime(TimeUnit.MILLISECONDS)); - writeContext.setLong(OffHeapValueHolderPortability.EXPIRE_TIME_OFFSET, expirationTime(TimeUnit.MILLISECONDS)); + writeContext.setLong(OffHeapValueHolderPortability.ACCESS_TIME_OFFSET, lastAccessTime()); + writeContext.setLong(OffHeapValueHolderPortability.EXPIRE_TIME_OFFSET, expirationTime()); writeContext.flush(); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java index 1378206998..9eb825780e 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java @@ -53,9 +53,9 @@ public ByteBuffer encode(OffHeapValueHolder valueHolder) { } ByteBuffer byteBuffer = ByteBuffer.allocate(serialized.remaining() + FIELDS_OVERHEAD); byteBuffer.putLong(valueHolder.getId()); - byteBuffer.putLong(valueHolder.creationTime(TimeUnit.MILLISECONDS)); - byteBuffer.putLong(valueHolder.lastAccessTime(TimeUnit.MILLISECONDS)); - byteBuffer.putLong(valueHolder.expirationTime(TimeUnit.MILLISECONDS)); + byteBuffer.putLong(valueHolder.creationTime()); + byteBuffer.putLong(valueHolder.lastAccessTime()); + byteBuffer.putLong(valueHolder.expirationTime()); byteBuffer.putLong(0L); // represent the hits on previous versions. It is kept for compatibility reasons with previously saved data byteBuffer.put(serialized); byteBuffer.flip(); diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java index 3be124b237..b8cec4b59b 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java @@ -225,11 +225,11 @@ public void testAccessTime() throws Exception { OnHeapStore store = newStore(timeSource, ExpiryPolicyBuilder.noExpiration()); store.put("key", "value"); - long first = store.get("key").lastAccessTime(TimeUnit.MILLISECONDS); + long first = store.get("key").lastAccessTime(); assertThat(first, equalTo(timeSource.getTimeMillis())); final long advance = 5; timeSource.advanceTime(advance); - long next = store.get("key").lastAccessTime(TimeUnit.MILLISECONDS); + long next = store.get("key").lastAccessTime(); assertThat(next, equalTo(first + advance)); } @@ -297,7 +297,7 @@ public void testCreateTime() throws Exception { assertThat(store.containsKey("key"), is(false)); store.put("key", "value"); ValueHolder valueHolder = store.get("key"); - assertThat(timeSource.getTimeMillis(), equalTo(valueHolder.creationTime(TimeUnit.MILLISECONDS))); + assertThat(timeSource.getTimeMillis(), equalTo(valueHolder.creationTime())); } @Test @@ -339,9 +339,9 @@ public void testPutIfAbsentUpdatesAccessTime() throws Exception { OnHeapStore store = newStore(timeSource, ExpiryPolicyBuilder.noExpiration()); assertThat(store.get("key"), nullValue()); store.putIfAbsent("key", "value", b -> {}); - long first = store.get("key").lastAccessTime(TimeUnit.MILLISECONDS); + long first = store.get("key").lastAccessTime(); timeSource.advanceTime(1); - long next = store.putIfAbsent("key", "value2", b -> {}).lastAccessTime(TimeUnit.MILLISECONDS); + long next = store.putIfAbsent("key", "value2", b -> {}).lastAccessTime(); assertThat(next - first, equalTo(1L)); } @@ -573,15 +573,15 @@ public void testComputeReplaceTrue() throws Exception { store.put("key", "value"); ValueHolder installedHolder = store.get("key"); - long createTime = installedHolder.creationTime(TimeUnit.MILLISECONDS); - long accessTime = installedHolder.lastAccessTime(TimeUnit.MILLISECONDS); + long createTime = installedHolder.creationTime(); + long accessTime = installedHolder.lastAccessTime(); timeSource.advanceTime(1); ValueHolder newValue = store.computeAndGet("key", (mappedKey, mappedValue) -> mappedValue, () -> true, () -> false); assertThat(newValue.get(), equalTo("value")); - assertThat(createTime + 1, equalTo(newValue.creationTime(TimeUnit.MILLISECONDS))); - assertThat(accessTime + 1, equalTo(newValue.lastAccessTime(TimeUnit.MILLISECONDS))); + assertThat(createTime + 1, equalTo(newValue.creationTime())); + assertThat(accessTime + 1, equalTo(newValue.lastAccessTime())); verify(eventSink).updated(eq("key"), argThat(holding("value")), eq("value")); verifyListenerReleaseEventsInOrder(eventDispatcher); StatisticsTestUtils.validateStats(store, EnumSet.of(StoreOperationOutcomes.ComputeOutcome.PUT)); @@ -594,15 +594,15 @@ public void testComputeReplaceFalse() throws Exception { store.put("key", "value"); ValueHolder installedHolder = store.get("key"); - long createTime = installedHolder.creationTime(TimeUnit.MILLISECONDS); - long accessTime = installedHolder.lastAccessTime(TimeUnit.MILLISECONDS); + long createTime = installedHolder.creationTime(); + long accessTime = installedHolder.lastAccessTime(); timeSource.advanceTime(1); ValueHolder newValue = store.computeAndGet("key", (mappedKey, mappedValue) -> mappedValue, () -> false, () -> false); assertThat(newValue.get(), equalTo("value")); - assertThat(createTime, equalTo(newValue.creationTime(TimeUnit.MILLISECONDS))); - assertThat(accessTime + 1, equalTo(newValue.lastAccessTime(TimeUnit.MILLISECONDS))); + assertThat(createTime, equalTo(newValue.creationTime())); + assertThat(accessTime + 1, equalTo(newValue.lastAccessTime())); StatisticsTestUtils.validateStats(store, EnumSet.of(StoreOperationOutcomes.ComputeOutcome.HIT)); } @@ -945,7 +945,7 @@ public void testGetOfComputeIfAbsentExpiresWithLoaderWriter() throws Exception { @SuppressWarnings("unchecked") final ValueHolder vh = mock(ValueHolder.class); when(vh.get()).thenReturn("newvalue"); - when(vh.expirationTime(TimeUnit.MILLISECONDS)).thenReturn(2L); + when(vh.expirationTime()).thenReturn(2L); ValueHolder newValue = store.getOrComputeIfAbsent("key", s -> vh); @@ -1288,7 +1288,7 @@ private static Map observeAccessTimes(Iterator map = new HashMap<>(); while (iter.hasNext()) { Entry> entry = iter.next(); - map.put(entry.getKey(), entry.getValue().lastAccessTime(TimeUnit.MILLISECONDS)); + map.put(entry.getKey(), entry.getValue().lastAccessTime()); } return map; } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java index 4e864836c0..79584641e7 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java @@ -117,7 +117,7 @@ public void testGetAndRemoveExpiredElementReturnsNull() throws Exception { timeSource.advanceTime(20); assertThat(offHeapStore.getAndRemove("1"), is(nullValue())); assertThat(invalidated.get().get(), equalTo("one")); - assertThat(invalidated.get().isExpired(timeSource.getTimeMillis(), TimeUnit.MILLISECONDS), is(true)); + assertThat(invalidated.get().isExpired(timeSource.getTimeMillis()), is(true)); assertThat(getExpirationStatistic(offHeapStore).count(StoreOperationOutcomes.ExpirationOutcome.SUCCESS), is(1L)); } @@ -188,7 +188,7 @@ public void testWriteBackOfValueHolder() throws StoreAccessException { offHeapStore.put("key1", "value1"); timeSource.advanceTime(10); OffHeapValueHolder valueHolder = (OffHeapValueHolder)offHeapStore.get("key1"); - assertThat(valueHolder.lastAccessTime(TimeUnit.MILLISECONDS), is(10L)); + assertThat(valueHolder.lastAccessTime(), is(10L)); timeSource.advanceTime(10); assertThat(offHeapStore.get("key1"), notNullValue()); timeSource.advanceTime(16); @@ -231,7 +231,7 @@ public void testFlushUpdatesAccessStats() throws StoreAccessException { assertThat(offHeapStore.flush(key, new DelegatingValueHolder<>(firstValueHolder)), is(false)); assertThat(offHeapStore.flush(key, new DelegatingValueHolder<>(secondValueHolder)), is(true)); timeSource.advanceTime(10); // this should NOT affect - assertThat(offHeapStore.getAndFault(key).lastAccessTime(TimeUnit.MILLISECONDS), is(secondValueHolder.creationTime(TimeUnit.MILLISECONDS) + 20)); + assertThat(offHeapStore.getAndFault(key).lastAccessTime(), is(secondValueHolder.creationTime() + 20)); } finally { destroyStore(offHeapStore); } @@ -575,23 +575,23 @@ public T get() { } @Override - public long creationTime(final TimeUnit unit) { - return valueHolder.creationTime(unit); + public long creationTime() { + return valueHolder.creationTime(); } @Override - public long expirationTime(final TimeUnit unit) { - return valueHolder.expirationTime(unit); + public long expirationTime() { + return valueHolder.expirationTime(); } @Override - public boolean isExpired(final long expirationTime, final TimeUnit unit) { - return valueHolder.isExpired(expirationTime, unit); + public boolean isExpired(long expirationTime) { + return valueHolder.isExpired(expirationTime); } @Override - public long lastAccessTime(final TimeUnit unit) { - return valueHolder.lastAccessTime(unit); + public long lastAccessTime() { + return valueHolder.lastAccessTime(); } @Override @@ -615,22 +615,22 @@ public T get() { } @Override - public long creationTime(TimeUnit unit) { + public long creationTime() { return 0; } @Override - public long expirationTime(TimeUnit unit) { + public long expirationTime() { return 0; } @Override - public boolean isExpired(long expirationTime, TimeUnit unit) { + public boolean isExpired(long expirationTime) { return false; } @Override - public long lastAccessTime(TimeUnit unit) { + public long lastAccessTime() { return 0; } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java index 0a9c0e1830..a860c2968a 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java @@ -130,7 +130,7 @@ private Store newStore(Long capacity, EvictionAdvisor defaultCopier = IdentityCopier.identityCopier(); - OnHeapStore onHeapStore = new OnHeapStore<>(config, timeSource, defaultCopier, defaultCopier, new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher()); + OnHeapStore onHeapStore = new OnHeapStore<>(config, timeSource, defaultCopier, defaultCopier, new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher()); try { CacheConfiguration cacheConfiguration = mock(CacheConfiguration.class); when(cacheConfiguration.getResourcePools()).thenReturn(newResourcePoolsBuilder().disk(1, MB, false).build()); @@ -229,22 +229,22 @@ public String get() { } @Override - public long creationTime(TimeUnit unit) { + public long creationTime() { return creationTime; } @Override - public long expirationTime(TimeUnit unit) { + public long expirationTime() { return 0; } @Override - public boolean isExpired(long expirationTime, TimeUnit unit) { + public boolean isExpired(long expirationTime) { return false; } @Override - public long lastAccessTime(TimeUnit unit) { + public long lastAccessTime() { return 0; } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java index a0b3e79b1f..4760526da8 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java @@ -31,7 +31,6 @@ import org.ehcache.impl.internal.store.heap.OnHeapStore; import org.ehcache.impl.internal.store.offheap.OffHeapStore; import org.ehcache.spi.service.Service; -import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.spi.service.ServiceProvider; import org.hamcrest.Matchers; import org.junit.Assert; @@ -102,7 +101,7 @@ public void testGetHitsCachingTier() throws Exception { TieredStore tieredStore = new TieredStore<>(numberCachingTier, numberAuthoritativeTier); - assertThat(tieredStore.get(1).get(), Matchers.equalTo("one")); + assertThat(tieredStore.get(1).get(), Matchers.equalTo("one")); verify(numberAuthoritativeTier, times(0)).getAndFault(any(Number.class)); } @@ -120,7 +119,7 @@ public void testGetHitsAuthoritativeTier() throws Exception { TieredStore tieredStore = new TieredStore<>(numberCachingTier, numberAuthoritativeTier); - assertThat(tieredStore.get(1).get(), Matchers.equalTo("one")); + assertThat(tieredStore.get(1).get(), Matchers.equalTo("one")); verify(numberCachingTier, times(1)).getOrComputeIfAbsent(eq(1), any(Function.class)); verify(numberAuthoritativeTier, times(1)).getAndFault(any(Number.class)); @@ -561,7 +560,7 @@ public void CachingTierDoesNotSeeAnyOperationDuringClear() throws StoreAccessExc barrier.await(); t.join(); verify(stringCachingTier, never()).getOrComputeIfAbsent( - ArgumentMatchers.any(), ArgumentMatchers.>>any()); + ArgumentMatchers.any(), ArgumentMatchers.any()); } @Test @@ -580,7 +579,7 @@ public void testReleaseStoreFlushes() throws Exception { Set> singleton = Collections.>singleton( ResourceType.Core.HEAP); when(onHeapStoreProvider.rankCachingTier(eq(singleton), any(Collection.class))).thenReturn(1); when(onHeapStoreProvider.createCachingTier(any(Store.Configuration.class), - ArgumentMatchers.[]>any())) + ArgumentMatchers.any())) .thenReturn(stringCachingTier); SizedResourcePool offHeapPool = mock(SizedResourcePool.class); @@ -589,7 +588,7 @@ public void testReleaseStoreFlushes() throws Exception { OffHeapStore.Provider offHeapStoreProvider = mock(OffHeapStore.Provider.class); when(offHeapStoreProvider.rankAuthority(eq(ResourceType.Core.OFFHEAP), any(Collection.class))).thenReturn(1); when(offHeapStoreProvider.createAuthoritativeTier( - any(Store.Configuration.class), ArgumentMatchers.[]>any())) + any(Store.Configuration.class), ArgumentMatchers.any())) .thenReturn(stringAuthoritativeTier); Store.Configuration configuration = mock(Store.Configuration.class); @@ -669,7 +668,7 @@ public void testGetAuthoritativeTierProvider() { private void assertRank(final Store.Provider provider, final int expectedRank, final ResourceType... resources) { Assert.assertThat(provider.rank( new HashSet<>(Arrays.asList(resources)), - Collections.>emptyList()), + Collections.emptyList()), Matchers.is(expectedRank)); } @@ -686,22 +685,22 @@ public CharSequence get() { } @Override - public long creationTime(TimeUnit unit) { + public long creationTime() { return 0; } @Override - public long expirationTime(TimeUnit unit) { + public long expirationTime() { return 0; } @Override - public boolean isExpired(long expirationTime, TimeUnit unit) { + public boolean isExpired(long expirationTime) { return false; } @Override - public long lastAccessTime(TimeUnit unit) { + public long lastAccessTime() { return 0; } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java index 0ebcd8df15..f959636901 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java @@ -244,22 +244,22 @@ public String get() { } @Override - public long creationTime(TimeUnit unit) { + public long creationTime() { return creationTime; } @Override - public long expirationTime(TimeUnit unit) { + public long expirationTime() { return 0; } @Override - public boolean isExpired(long expirationTime, TimeUnit unit) { + public boolean isExpired(long expirationTime) { return false; } @Override - public long lastAccessTime(TimeUnit unit) { + public long lastAccessTime() { return 0; } diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java index 2764a40b44..97dfe789da 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java @@ -358,7 +358,7 @@ public ValueHolder replace(K key, V value) throws StoreAccessException { } else { V oldValue = softLock.getOldValue(); currentContext.addCommand(key, new StorePutCommand<>(oldValue, new XAValueHolder<>(value, timeSource.getTimeMillis()))); - return new XAValueHolder<>(oldValue, softLockValueHolder.creationTime(TimeUnit.MILLISECONDS)); + return new XAValueHolder<>(oldValue, softLockValueHolder.creationTime()); } } else { return null; diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java index 56b9d328e2..d50d97c5f6 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java @@ -40,7 +40,7 @@ public class XAValueHolder extends AbstractValueHolder implements Serializ private final byte[] valueSerialized; public XAValueHolder(Store.ValueHolder> valueHolder, V value) { - super(-1, valueHolder.creationTime(TimeUnit.MILLISECONDS), valueHolder.expirationTime(TimeUnit.MILLISECONDS)); + super(-1, valueHolder.creationTime(), valueHolder.expirationTime()); this.value = value; this.valueSerialized = null; } @@ -55,14 +55,14 @@ public XAValueHolder(V value, long creationTime) { } private XAValueHolder(XAValueHolder valueHolder, ByteBuffer serializedValue) { - super(-1, valueHolder.creationTime(TimeUnit.MILLISECONDS), valueHolder.expirationTime(TimeUnit.MILLISECONDS)); + super(-1, valueHolder.creationTime(), valueHolder.expirationTime()); this.value = null; this.valueSerialized = new byte[serializedValue.remaining()]; serializedValue.get(this.valueSerialized); } public XAValueHolder(XAValueHolder valueHolder, V value) { - super(-1, valueHolder.creationTime(TimeUnit.MILLISECONDS), valueHolder.expirationTime(TimeUnit.MILLISECONDS)); + super(-1, valueHolder.creationTime(), valueHolder.expirationTime()); this.value = value; this.valueSerialized = null; } @@ -108,7 +108,7 @@ public boolean equals(Object other) { } private Object writeReplace() { - return new SerializedXAValueHolder<>(getId(), creationTime(TimeUnit.MILLISECONDS), lastAccessTime(TimeUnit.MILLISECONDS), expirationTime(TimeUnit.MILLISECONDS), + return new SerializedXAValueHolder<>(getId(), creationTime(), lastAccessTime(), expirationTime(), get(), valueSerialized); } diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAValueHolderTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAValueHolderTest.java index 8cb646f9e4..f80ed61687 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAValueHolderTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAValueHolderTest.java @@ -49,9 +49,9 @@ public void testSerialization() throws Exception { XAValueHolder result = (XAValueHolder) new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())).readObject(); assertThat(result.getId(), is(valueHolder.getId())); - assertThat(result.creationTime(TimeUnit.MILLISECONDS), is(valueHolder.creationTime(TimeUnit.MILLISECONDS))); - assertThat(result.lastAccessTime(TimeUnit.MILLISECONDS), is(valueHolder.lastAccessTime(TimeUnit.MILLISECONDS))); - assertThat(result.expirationTime(TimeUnit.MILLISECONDS), is(valueHolder.expirationTime(TimeUnit.MILLISECONDS))); + assertThat(result.creationTime(), is(valueHolder.creationTime())); + assertThat(result.lastAccessTime(), is(valueHolder.lastAccessTime())); + assertThat(result.expirationTime(), is(valueHolder.expirationTime())); assertThat(result.get(), is(valueHolder.get())); } } From 049ed3542897edb070cf27d7d3bb5356eabdc6c7 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Sat, 11 Aug 2018 00:21:24 -0400 Subject: [PATCH 039/372] Get rid of the nativeTimeUnit method --- .../ehcache/core/spi/store/AbstractValueHolder.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java b/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java index 6977b07e73..99124b7474 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java +++ b/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java @@ -53,10 +53,6 @@ protected AbstractValueHolder(long id, long creationTime, long expirationTime) { this.lastAccessTime = creationTime; } - protected final TimeUnit nativeTimeUnit() { - return TimeUnit.MILLISECONDS; - } - @Override public long creationTime() { return creationTime; @@ -68,7 +64,7 @@ public void setExpirationTime(long expirationTime, TimeUnit unit) { } else if (expirationTime < 0) { throw new IllegalArgumentException("invalid expiration time: " + expirationTime); } else { - updateExpirationTime(nativeTimeUnit().convert(expirationTime, unit)); + updateExpirationTime(TimeUnit.MILLISECONDS.convert(expirationTime, unit)); } } @@ -85,7 +81,7 @@ private void updateExpirationTime(long update) { } public void accessed(long now, Duration expiration) { - final TimeUnit timeUnit = nativeTimeUnit(); + final TimeUnit timeUnit = TimeUnit.MILLISECONDS; if (expiration != null) { if (isExpiryDurationInfinite(expiration)) { setExpirationTime(Store.ValueHolder.NO_EXPIRE, null); @@ -121,7 +117,7 @@ public long lastAccessTime() { } public void setLastAccessTime(long lastAccessTime, TimeUnit unit) { - long update = unit.convert(lastAccessTime, nativeTimeUnit()); + long update = unit.convert(lastAccessTime, TimeUnit.MILLISECONDS); while (true) { long current = this.lastAccessTime; if (current >= update) { From 44a9e3bdd7b8714d0b4f676758e9b4670ffad40a Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Tue, 14 Aug 2018 10:28:41 -0400 Subject: [PATCH 040/372] Always set time in milliseconds on value holders --- .../core/spi/store/AbstractValueHolder.java | 35 +++++++++++-------- .../spi/store/AbstractValueHolderTest.java | 15 ++++---- .../impl/internal/store/heap/OnHeapStore.java | 6 ++-- .../store/offheap/AbstractOffHeapStore.java | 2 +- .../offheap/BasicOffHeapValueHolder.java | 2 +- .../offheap/BinaryOffHeapValueHolder.java | 2 +- .../store/offheap/LazyOffHeapValueHolder.java | 8 ++--- .../OffHeapValueHolderPortabilityTest.java | 14 +++----- .../TieredStoreFlushWhileShutdownTest.java | 4 +-- .../xa/internal/XAValueHolder.java | 3 +- 10 files changed, 45 insertions(+), 46 deletions(-) diff --git a/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java b/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java index 99124b7474..b7a3b270fe 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java +++ b/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java @@ -58,13 +58,19 @@ public long creationTime() { return creationTime; } - public void setExpirationTime(long expirationTime, TimeUnit unit) { + /** + * Set the new expiration time in milliseconds. Can be {@link #NO_EXPIRE} if the entry + * shouldn't expire. + * + * @param expirationTime new expiration time + */ + public void setExpirationTime(long expirationTime) { if (expirationTime == NO_EXPIRE) { updateExpirationTime(NO_EXPIRE); } else if (expirationTime < 0) { throw new IllegalArgumentException("invalid expiration time: " + expirationTime); } else { - updateExpirationTime(TimeUnit.MILLISECONDS.convert(expirationTime, unit)); + updateExpirationTime(expirationTime); } } @@ -81,25 +87,20 @@ private void updateExpirationTime(long update) { } public void accessed(long now, Duration expiration) { - final TimeUnit timeUnit = TimeUnit.MILLISECONDS; if (expiration != null) { if (isExpiryDurationInfinite(expiration)) { - setExpirationTime(Store.ValueHolder.NO_EXPIRE, null); + setExpirationTime(Store.ValueHolder.NO_EXPIRE); } else { long newExpirationTime = ExpiryUtils.getExpirationMillis(now, expiration); - setExpirationTime(newExpirationTime, timeUnit); + setExpirationTime(newExpirationTime); } } - setLastAccessTime(now, timeUnit); + setLastAccessTime(now); } @Override public long expirationTime() { - long expire = this.expirationTime; - if (expire == NO_EXPIRE) { - return NO_EXPIRE; - } - return expire; + return this.expirationTime; } @Override @@ -116,14 +117,18 @@ public long lastAccessTime() { return lastAccessTime; } - public void setLastAccessTime(long lastAccessTime, TimeUnit unit) { - long update = unit.convert(lastAccessTime, TimeUnit.MILLISECONDS); + /** + * Set the last time this entry was accessed in milliseconds. + * + * @param lastAccessTime last time the entry was accessed + */ + public void setLastAccessTime(long lastAccessTime) { while (true) { long current = this.lastAccessTime; - if (current >= update) { + if (current >= lastAccessTime) { break; } - if (ACCESSTIME_UPDATER.compareAndSet(this, current, update)) { + if (ACCESSTIME_UPDATER.compareAndSet(this, current, lastAccessTime)) { break; } } diff --git a/core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java b/core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java index 18533b22ba..7105a313c4 100644 --- a/core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java +++ b/core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java @@ -51,7 +51,7 @@ public void testLastAccessTime() throws Exception { assertThat(valueHolder.lastAccessTime(), is(1000L)); - valueHolder = newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 0L, 2000L); + valueHolder = newAbstractValueHolder(1000L, 0L, 2000L); assertThat(valueHolder.lastAccessTime(), is(2000L)); } @@ -75,11 +75,11 @@ public void testEquals() throws Exception { assertThat(newAbstractValueHolder(2L, 0L).equals(newAbstractValueHolder(2L, 1L)), is(false)); assertThat(newAbstractValueHolder(2L, 0L).equals(newAbstractValueHolder(3L, 0L)), is(false)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L)), is(true)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1L, 2L, 1L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L)), is(false)); + assertThat(newAbstractValueHolder(0L, 2L, 1L).equals(newAbstractValueHolder(0L, 2L, 1L)), is(true)); + assertThat(newAbstractValueHolder(1L, 2L, 1L).equals(newAbstractValueHolder(0L, 2L, 1L)), is(false)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 3L, 1L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L)), is(false)); - assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 3L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L)), is(false)); + assertThat(newAbstractValueHolder(0L, 3L, 1L).equals(newAbstractValueHolder(0L, 2L, 1L)), is(false)); + assertThat(newAbstractValueHolder(0L, 2L, 3L).equals(newAbstractValueHolder(0L, 2L, 1L)), is(false)); } @Test @@ -142,14 +142,15 @@ public String get() { } }; } - private AbstractValueHolder newAbstractValueHolder(TimeUnit timeUnit, long creationTime, long expirationTime, long lastAccessTime) { + + private AbstractValueHolder newAbstractValueHolder(long creationTime, long expirationTime, long lastAccessTime) { final AbstractValueHolder abstractValueHolder = new AbstractValueHolder(-1, creationTime, expirationTime) { @Override public String get() { throw new UnsupportedOperationException(); } }; - abstractValueHolder.setLastAccessTime(lastAccessTime, timeUnit); + abstractValueHolder.setLastAccessTime(lastAccessTime); return abstractValueHolder; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index f04e4ec77a..b15dbc3ba4 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -1017,7 +1017,7 @@ public long creationTime() { } @Override - public void setExpirationTime(long expirationTime, TimeUnit unit) { + public void setExpirationTime(long expirationTime) { throw new UnsupportedOperationException(); } @@ -1037,7 +1037,7 @@ public long lastAccessTime() { } @Override - public void setLastAccessTime(long lastAccessTime, TimeUnit unit) { + public void setLastAccessTime(long lastAccessTime) { throw new UnsupportedOperationException(); } @@ -1083,7 +1083,7 @@ public ValueHolder getAndCompute(K key, BiFunction { long delta = 0L; - if (mappedValue != null && mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue != null && mappedValue.isExpired(now)) { fireOnExpirationEvent(mappedKey, mappedValue, eventSink); delta -= mappedValue.size(); mappedValue = null; diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java index 044c7a39e3..c8ab308450 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java @@ -533,7 +533,7 @@ public ValueHolder getAndCompute(K key, BiFunction, OffHeapValueHolder> computeFunction = (mappedKey, mappedValue) -> { long now = timeSource.getTimeMillis(); V existingValue = null; - if (mappedValue == null || mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) { + if (mappedValue == null || mappedValue.isExpired(now)) { if (mappedValue != null) { onExpiration(mappedKey, mappedValue, eventSink); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolder.java index 6c2d0752ef..ce755034f0 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolder.java @@ -33,7 +33,7 @@ public BasicOffHeapValueHolder(long id, V value, long creationTime, long expireT public BasicOffHeapValueHolder(long id, V value, long creationTime, long expireTime, long lastAccessTime) { super(id, creationTime, expireTime); - setLastAccessTime(lastAccessTime, TimeUnit.MILLISECONDS); + setLastAccessTime(lastAccessTime); this.value = value; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolder.java index 7e03dde497..18df2eb356 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolder.java @@ -34,7 +34,7 @@ final class BinaryOffHeapValueHolder extends OffHeapValueHolder implements BinaryOffHeapValueHolder(long id, V value, ByteBuffer binaryValue, long creationTime, long expireTime, long lastAccessTime) { super(id, creationTime, expireTime); this.value = value; - setLastAccessTime(lastAccessTime, TimeUnit.MILLISECONDS); + setLastAccessTime(lastAccessTime); this.binaryValue = binaryValue; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java index 301612c2fe..1f1934b616 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java @@ -23,9 +23,7 @@ import org.ehcache.spi.serialization.Serializer; import org.terracotta.offheapstore.storage.portability.WriteContext; -import java.io.IOException; import java.nio.ByteBuffer; -import java.util.concurrent.TimeUnit; /** * OffHeapValueHolder variant that supports lazy deserialization and also serving the binary value if detached. @@ -40,7 +38,7 @@ public final class LazyOffHeapValueHolder extends OffHeapValueHolder imple public LazyOffHeapValueHolder(long id, ByteBuffer binaryValue, Serializer serializer, long creationTime, long expireTime, long lastAccessTime, WriteContext writeContext) { super(id, creationTime, expireTime); - setLastAccessTime(lastAccessTime, TimeUnit.MILLISECONDS); + setLastAccessTime(lastAccessTime); this.binaryValue = binaryValue; this.valueSerializer = serializer; this.writeContext = writeContext; @@ -72,8 +70,8 @@ void updateMetadata(final Store.ValueHolder valueFlushed) { if(getId() != valueFlushed.getId()) { throw new IllegalArgumentException("Wrong id passed in [this.id != id] : " + getId() + " != " + valueFlushed.getId()); } - this.setLastAccessTime(valueFlushed.lastAccessTime(), TimeUnit.MILLISECONDS); - this.setExpirationTime(valueFlushed.expirationTime(), TimeUnit.MILLISECONDS); + this.setLastAccessTime(valueFlushed.lastAccessTime()); + this.setExpirationTime(valueFlushed.expirationTime()); } /** diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolderPortabilityTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolderPortabilityTest.java index e33dcd8cf8..60dd0d79ad 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolderPortabilityTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolderPortabilityTest.java @@ -17,7 +17,6 @@ package org.ehcache.impl.internal.store.offheap; import org.ehcache.impl.internal.store.offheap.portability.OffHeapValueHolderPortability; -import org.ehcache.core.spi.store.AbstractValueHolder; import org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider; import org.ehcache.impl.serialization.StringSerializer; import org.ehcache.spi.serialization.SerializationProvider; @@ -28,13 +27,10 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.nio.ByteBuffer; -import java.nio.MappedByteBuffer; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.concurrent.TimeUnit; import static org.ehcache.impl.internal.spi.TestServiceProvider.providerContaining; import static org.hamcrest.CoreMatchers.equalTo; @@ -104,9 +100,9 @@ public void testDecodingAPreviousVersionWithTheHits() { OffHeapValueHolder decoded = valueHolderPortability.decode(byteBuffer); assertThat(decoded.getId(), equalTo(123L)); - assertThat(decoded.creationTime(OffHeapValueHolder.TIME_UNIT), equalTo(time)); - assertThat(decoded.lastAccessTime(OffHeapValueHolder.TIME_UNIT), equalTo(time + 1)); - assertThat(decoded.expirationTime(OffHeapValueHolder.TIME_UNIT), equalTo(time + 2)); + assertThat(decoded.creationTime(), equalTo(time)); + assertThat(decoded.lastAccessTime(), equalTo(time + 1)); + assertThat(decoded.expirationTime(), equalTo(time + 2)); assertThat(decoded.get(), equalTo("test")); } @@ -116,8 +112,8 @@ public void testWriteBackSupport() throws NoSuchMethodException, InvocationTarge WriteContext writeContext = mock(WriteContext.class); OffHeapValueHolder decoded = valueHolderPortability.decode(encoded, writeContext); - decoded.setExpirationTime(4L, TimeUnit.MILLISECONDS); - decoded.setLastAccessTime(6L, TimeUnit.MILLISECONDS); + decoded.setExpirationTime(4L); + decoded.setLastAccessTime(6L); decoded.writeBack(); verify(writeContext).setLong(OffHeapValueHolderPortability.ACCESS_TIME_OFFSET, 6L); diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java index fe3caffc70..848e30ad6f 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java @@ -137,7 +137,7 @@ public CacheLoaderWriter getCacheLoaderWriter() { // Keep the creation time to make sure we have them at restart long[] creationTimes = new long[20]; for (int i = 0; i < 20; i++) { - creationTimes[i] = tieredStore.get(i).creationTime(TimeUnit.MILLISECONDS); + creationTimes[i] = tieredStore.get(i).creationTime(); } tieredStoreProvider.releaseStore(tieredStore); @@ -155,7 +155,7 @@ public CacheLoaderWriter getCacheLoaderWriter() { tieredStoreProvider.initStore(tieredStore); for(int i = 0; i < 20; i++) { - assertThat(tieredStore.get(i).creationTime(TimeUnit.MILLISECONDS), is(creationTimes[i])); + assertThat(tieredStore.get(i).creationTime(), is(creationTimes[i])); } } diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java index d50d97c5f6..51d60d591a 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java @@ -23,7 +23,6 @@ import java.io.Serializable; import java.nio.ByteBuffer; -import java.util.concurrent.TimeUnit; import static org.ehcache.core.internal.util.TypeUtil.uncheckedCast; @@ -69,7 +68,7 @@ public XAValueHolder(XAValueHolder valueHolder, V value) { private XAValueHolder(long id, long creationTime, long lastAccessTime, long expirationTime, V value, byte[] valueSerialized) { super(id, creationTime, expirationTime); - setLastAccessTime(lastAccessTime, TimeUnit.MILLISECONDS); + setLastAccessTime(lastAccessTime); this.value = value; this.valueSerialized = valueSerialized; } From ceb4878e7d4bcc0be3ab72147833da10e067a803 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Fri, 7 Dec 2018 15:47:34 -0500 Subject: [PATCH 041/372] Fix copyright format --- .../ehcache/impl/internal/store/heap/OnHeapStrategyTest.java | 2 +- .../src/test/java/org/ehcache/docs/Performance.java | 2 +- .../org/ehcache/integration/OnHeapEvictionStrategyTest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java index 41151cbf39..a8fec575a1 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/integration-test/src/test/java/org/ehcache/docs/Performance.java b/integration-test/src/test/java/org/ehcache/docs/Performance.java index 90972788e7..7ff07712b6 100644 --- a/integration-test/src/test/java/org/ehcache/docs/Performance.java +++ b/integration-test/src/test/java/org/ehcache/docs/Performance.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/integration-test/src/test/java/org/ehcache/integration/OnHeapEvictionStrategyTest.java b/integration-test/src/test/java/org/ehcache/integration/OnHeapEvictionStrategyTest.java index 6dd83ab71c..d160090ef9 100644 --- a/integration-test/src/test/java/org/ehcache/integration/OnHeapEvictionStrategyTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/OnHeapEvictionStrategyTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, From f184abd3f1923c7efe781a4a0c2ec370baebdb9a Mon Sep 17 00:00:00 2001 From: Venkata Sairam Madduri Date: Mon, 10 Dec 2018 22:08:19 +0530 Subject: [PATCH 042/372] terracotta version bump --- gradle.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 106d512ea3..b0600ddabe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,10 +9,10 @@ slf4jVersion = 1.7.25 sizeofVersion = 0.3.0 # Terracotta clustered -terracottaPlatformVersion = 5.6.0-pre3 -terracottaApisVersion = 1.6.0-pre1 -terracottaCoreVersion = 5.6.0-pre4 -terracottaPassthroughTestingVersion = 1.6.0-pre1 +terracottaPlatformVersion = 5.6.0-pre4 +terracottaApisVersion = 1.6.0-pre2 +terracottaCoreVersion = 5.6.0-pre5 +terracottaPassthroughTestingVersion = 1.6.0-pre2 # Test lib versions junitVersion = 4.12 From 651a0ecfcbcee9bcc7acdd14a5dfab1efa07e008 Mon Sep 17 00:00:00 2001 From: Venkata Sairam Madduri Date: Tue, 11 Dec 2018 10:20:40 +0530 Subject: [PATCH 043/372] bump platform versions --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index b0600ddabe..10a3644ae6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,9 +9,9 @@ slf4jVersion = 1.7.25 sizeofVersion = 0.3.0 # Terracotta clustered -terracottaPlatformVersion = 5.6.0-pre4 +terracottaPlatformVersion = 5.6.0-pre5 terracottaApisVersion = 1.6.0-pre2 -terracottaCoreVersion = 5.6.0-pre5 +terracottaCoreVersion = 5.6.0-pre6 terracottaPassthroughTestingVersion = 1.6.0-pre2 # Test lib versions From eecff51ae03fea7b779c27545e4e23c241cc6b87 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Mon, 27 Aug 2018 14:21:12 -0400 Subject: [PATCH 044/372] A ValueHolder cannot hold a null value --- .../main/java/org/ehcache/core/spi/store/Store.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/src/main/java/org/ehcache/core/spi/store/Store.java b/core/src/main/java/org/ehcache/core/spi/store/Store.java index 5b9b195d57..2868ffaebb 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/Store.java +++ b/core/src/main/java/org/ehcache/core/spi/store/Store.java @@ -38,6 +38,8 @@ import java.util.function.Function; import java.util.function.Supplier; +import javax.annotation.Nonnull; + /** * The {@code Store} interface represents the backing storage of a {@link Cache}. It abstracts the support for multiple * tiers, eventing, eviction and expiry. @@ -505,6 +507,14 @@ interface ValueHolder extends Supplier { */ long getId(); + /** + * Returns the value held by this value holder. This value can't be {@code null}. + * + * @return the value held + */ + @Nonnull + @Override + V get(); } /** From 0a24ba806672a15c8a59b2cc1a1d8d0d6ea1eeed Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Mon, 27 Aug 2018 14:22:15 -0400 Subject: [PATCH 045/372] Move the specific value holder to a class since they might be useful for others --- .../store/basic/DelegatingValueHolder.java | 66 +++++++++++++++++++ .../store/basic/SimpleValueHolder.java | 66 +++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 impl/src/test/java/org/ehcache/impl/internal/store/basic/DelegatingValueHolder.java create mode 100644 impl/src/test/java/org/ehcache/impl/internal/store/basic/SimpleValueHolder.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/basic/DelegatingValueHolder.java b/impl/src/test/java/org/ehcache/impl/internal/store/basic/DelegatingValueHolder.java new file mode 100644 index 0000000000..7dc3e2d71d --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/internal/store/basic/DelegatingValueHolder.java @@ -0,0 +1,66 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.internal.store.basic; + +import org.ehcache.core.spi.store.Store; + +import java.util.concurrent.TimeUnit; + +import javax.annotation.Nonnull; + +/** + * ValueHolder delegating everything to another ValueHolder. + */ +public class DelegatingValueHolder implements Store.ValueHolder { + + private final Store.ValueHolder valueHolder; + + public DelegatingValueHolder(Store.ValueHolder valueHolder) { + this.valueHolder = valueHolder; + } + + @Override + @Nonnull + public T get() { + return valueHolder.get(); + } + + @Override + public long creationTime() { + return valueHolder.creationTime(); + } + + @Override + public long expirationTime() { + return valueHolder.expirationTime(); + } + + @Override + public boolean isExpired(long expirationTime) { + return valueHolder.isExpired(expirationTime); + } + + @Override + public long lastAccessTime() { + return valueHolder.lastAccessTime(); + } + + @Override + public long getId() { + return valueHolder.getId(); + } +} diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/basic/SimpleValueHolder.java b/impl/src/test/java/org/ehcache/impl/internal/store/basic/SimpleValueHolder.java new file mode 100644 index 0000000000..dbde912285 --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/internal/store/basic/SimpleValueHolder.java @@ -0,0 +1,66 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.internal.store.basic; + +import org.ehcache.core.spi.store.Store; + +import java.util.concurrent.TimeUnit; + +import javax.annotation.Nonnull; + +/** + * A really basic value holder that just holds a value. + */ +public class SimpleValueHolder implements Store.ValueHolder { + + private final T value; + + public SimpleValueHolder(T v) { + this.value = v; + } + + @Override + @Nonnull + public T get() { + return value; + } + + @Override + public long creationTime() { + return 0; + } + + @Override + public long expirationTime() { + return 0; + } + + @Override + public boolean isExpired(long expirationTime) { + return false; + } + + @Override + public long lastAccessTime() { + return 0; + } + + @Override + public long getId() { + return 0; + } +} From 93c573ecd9a0075d62d63dcc41cfcbfceb467bd2 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Fri, 24 Aug 2018 16:27:02 -0400 Subject: [PATCH 046/372] Remove an impossible possibility during a putIfAbsent --- .../java/org/ehcache/core/EhcacheBase.java | 3 - .../ehcache/integration/EhcacheBaseTest.java | 324 ++++++++++++++++++ .../AbstractCacheCalculationTest.java | 13 +- 3 files changed, 332 insertions(+), 8 deletions(-) create mode 100644 integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java diff --git a/core/src/main/java/org/ehcache/core/EhcacheBase.java b/core/src/main/java/org/ehcache/core/EhcacheBase.java index aca14f72c7..7d35caa153 100644 --- a/core/src/main/java/org/ehcache/core/EhcacheBase.java +++ b/core/src/main/java/org/ehcache/core/EhcacheBase.java @@ -297,9 +297,6 @@ public V putIfAbsent(final K key, final V value) { if (put[0]) { putIfAbsentObserver.end(PutIfAbsentOutcome.PUT); return null; - } else if (inCache == null) { - putIfAbsentObserver.end(PutIfAbsentOutcome.HIT); - return null; } else { putIfAbsentObserver.end(PutIfAbsentOutcome.HIT); return inCache.get(); diff --git a/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java b/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java new file mode 100644 index 0000000000..7e154f93ab --- /dev/null +++ b/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java @@ -0,0 +1,324 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.integration; + +import org.ehcache.Cache; +import org.ehcache.CacheManager; +import org.ehcache.config.Configuration; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.config.builders.ConfigurationBuilder; +import org.ehcache.config.builders.ExpiryPolicyBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.core.EhcacheManager; +import org.ehcache.core.spi.service.StatisticsService; +import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; +import org.ehcache.impl.internal.TimeSourceConfiguration; +import org.ehcache.impl.internal.statistics.DefaultStatisticsService; +import org.ehcache.integration.statistics.AbstractCacheCalculationTest; +import org.ehcache.spi.loaderwriter.CacheLoaderWriter; +import org.ehcache.spi.service.Service; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.IOException; +import java.time.Duration; +import java.util.Collection; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNullPointerException; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +/** + * @author Henri Tremblay + */ +@RunWith(Parameterized.class) +public class EhcacheBaseTest extends AbstractCacheCalculationTest { + + private CacheManager cacheManager; + + private Cache cache; + + private final StatisticsService statisticsService = new DefaultStatisticsService(); + + private final TestTimeSource timeSource = new TestTimeSource(); + + public EhcacheBaseTest(ResourcePoolsBuilder poolBuilder) { + super(poolBuilder); + } + + @After + public void after() { + if (cacheManager != null) { + cacheManager.close(); + } + } + + private void createCacheManager(CacheManagerBuilder builder) { + cacheManager = builder + .build(true); + } + + private void createNotAtomicCacheManager() throws IOException { + Configuration config = ConfigurationBuilder.newConfigurationBuilder() + .addService(new TimeSourceConfiguration(timeSource)) + .addService(new DefaultPersistenceConfiguration(diskPath.newFolder())) + .build(); + + Collection services = Collections.singleton(statisticsService); + cacheManager = new EhcacheManager(config, services, false); + cacheManager.init(); + } + + private void createCacheManager() { + createCacheManager(baseCacheManagerConfig()); + } + + private CacheManagerBuilder baseCacheManagerConfig() { + try { + return CacheManagerBuilder.newCacheManagerBuilder() + .using(new DefaultPersistenceConfiguration(diskPath.newFolder())) + .using(statisticsService) + .using(new TimeSourceConfiguration(timeSource)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private Cache createCache() { + return createCache(baseConfig()); + } + + private Cache createCache(CacheConfigurationBuilder config) { + Cache cache = cacheManager.createCache("cache", config); + cacheStatistics = statisticsService.getCacheStatistics("cache"); + return cache; + } + + private CacheConfigurationBuilder baseConfig() { + return CacheConfigurationBuilder.newCacheConfigurationBuilder(Integer.class, String.class, resources); + } + + @Test + public void putIfAbsent_absent() { + createCacheManager(); + + cache = createCache(); + + assertThat(cache.putIfAbsent(1, "a")).isNull(); + + assertThat(cache.get(1)).isEqualTo("a"); + + changesOf(1, 1, 1, 0); + } + + @Test + public void putIfAbsent_present() { + createCacheManager(); + + cache = createCache(); + + cache.put(1, "a"); + + assertThat(cache.putIfAbsent(1, "b")).isEqualTo("a"); + + changesOf(1, 0, 1, 0); + } + + @Test + public void putIfAbsent_presentButExpired() { + createCacheManager(); + + CacheConfigurationBuilder builder = baseConfig() + .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(10))); + cache = createCache(builder); + + cache.put(1, "a"); + + timeSource.advanceTime(15); + + assertThat(cache.putIfAbsent(1, "b")).isNull(); + + assertThat(cache.get(1)).isEqualTo("b"); + + changesOf(1, 1, 2, 0); + } + + @Test + public void putIfAbsent_absentPutNull() { + createCacheManager(); + + cache = createCache(); + + assertThatNullPointerException().isThrownBy(() -> cache.putIfAbsent(1, null)); + + changesOf(0, 0, 0, 0); + } + + @Test + public void putIfAbsentLoaderWriter_absentAndLoaded() throws Exception { + createCacheManager(); + + CacheLoaderWriter loader = mockLoader(); + when(loader.load(1)).thenReturn("a"); + + CacheConfigurationBuilder builder = baseConfig() + .withLoaderWriter(loader); + cache = createCache(builder); + + assertThat(cache.putIfAbsent(1, "b")).isEqualTo("a"); + + assertThat(cache.get(1)).isEqualTo("a"); + + changesOf(2, 0, 0, 0); + } + + @Test + public void putIfAbsentLoaderWriter_absentAndNotLoaded() throws Exception { + createCacheManager(); + + CacheLoaderWriter loader = mockLoader(); + when(loader.load(1)).thenReturn(null); + + CacheConfigurationBuilder builder = baseConfig() + .withLoaderWriter(loader); + cache = createCache(builder); + + assertThat(cache.putIfAbsent(1, "b")).isNull(); + + verify(loader).write(1, "b"); + + assertThat(cache.get(1)).isEqualTo("b"); + + changesOf(1, 1, 1, 0); + } + + @Test + public void putIfAbsentLoaderWriter_present() throws Exception { + createCacheManager(); + + CacheLoaderWriter loader = mockLoader(); + + CacheConfigurationBuilder builder = baseConfig() + .withLoaderWriter(loader); + cache = createCache(builder); + + cache.put(1, "a"); + + assertThat(cache.putIfAbsent(1, "b")).isEqualTo("a"); + + verify(loader).write(1, "a"); + + changesOf(1, 0, 1, 0); + } + + @Test + public void putIfAbsentLoaderWriter_presentButExpiredAndLoaded() throws Exception { + createCacheManager(); + + CacheLoaderWriter loader = mockLoader(); + when(loader.load(1)).thenReturn("c"); + + CacheConfigurationBuilder builder = baseConfig() + .withLoaderWriter(loader) + .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(10))); + cache = createCache(builder); + + cache.put(1, "a"); + + timeSource.advanceTime(15); + + assertThat(cache.putIfAbsent(1, "b")).isEqualTo("c"); + + verify(loader).write(1, "a"); + + changesOf(1, 0, 1, 0); + } + + @Test + public void putIfAbsentLoaderWriter_presentButExpiredAndNotLoaded() throws Exception { + createCacheManager(); + + CacheLoaderWriter loader = mockLoader(); + when(loader.load(1)).thenReturn(null); + + CacheConfigurationBuilder builder = baseConfig() + .withLoaderWriter(loader) + .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(10))); + cache = createCache(builder); + + cache.put(1, "a"); + + timeSource.advanceTime(15); + + assertThat(cache.putIfAbsent(1, "b")).isNull(); + + verify(loader).write(1, "b"); + + changesOf(0, 1, 2, 0); + } + + @Test + public void putIfAbsentLoaderWriterNotAtomic_absent() throws Exception { + createNotAtomicCacheManager(); + + CacheLoaderWriter loader = mockLoader(); + + CacheConfigurationBuilder builder = baseConfig() + .withLoaderWriter(loader); + cache = createCache(builder); + + assertThat(cache.putIfAbsent(1, "a")).isNull(); + + verify(loader).write(1, "a"); + + assertThat(cache.get(1)).isEqualTo("a"); + + changesOf(1, 1, 1, 0); + } + + @Test + public void putIfAbsentLoaderWriterNotAtomic_present() throws Exception { + createNotAtomicCacheManager(); + + CacheLoaderWriter loader = mockLoader(); + + CacheConfigurationBuilder builder = baseConfig() + .withLoaderWriter(loader); + cache = createCache(builder); + + cache.put(1, "a"); + + assertThat(cache.putIfAbsent(1, "b")).isEqualTo("a"); + + verify(loader).write(1, "a"); + verifyNoMoreInteractions(loader); + + changesOf(1, 0, 1, 0); + } + + @SuppressWarnings("unchecked") + private static CacheLoaderWriter mockLoader() { + return mock(CacheLoaderWriter.class); + } +} diff --git a/integration-test/src/test/java/org/ehcache/integration/statistics/AbstractCacheCalculationTest.java b/integration-test/src/test/java/org/ehcache/integration/statistics/AbstractCacheCalculationTest.java index 3bab93e7da..e5cfc61d2b 100644 --- a/integration-test/src/test/java/org/ehcache/integration/statistics/AbstractCacheCalculationTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/statistics/AbstractCacheCalculationTest.java @@ -18,13 +18,13 @@ import java.util.Arrays; import java.util.Collection; +import org.assertj.core.api.SoftAssertions; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.core.statistics.CacheStatistics; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import static org.assertj.core.api.Assertions.assertThat; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.config.units.EntryUnit.ENTRIES; import static org.ehcache.config.units.MemoryUnit.MB; @@ -79,10 +79,13 @@ public static Collection data() { * @param remove how many removes should have happened */ protected void changesOf(long hit, long miss, long put, long remove) { - assertThat(cacheStatistics.getCacheHits() - hitCount).as("Hits").isEqualTo(hit); - assertThat(cacheStatistics.getCacheMisses() - missCount).as("Misses").isEqualTo(miss); - assertThat(cacheStatistics.getCachePuts() - putCount).as("Puts").isEqualTo(put); - assertThat(cacheStatistics.getCacheRemovals() - removalCount).as("Removals").isEqualTo(remove); + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(cacheStatistics.getCacheHits() - hitCount).as("Hits").isEqualTo(hit); + softly.assertThat(cacheStatistics.getCacheMisses() - missCount).as("Misses").isEqualTo(miss); + softly.assertThat(cacheStatistics.getCachePuts() - putCount).as("Puts").isEqualTo(put); + softly.assertThat(cacheStatistics.getCacheRemovals() - removalCount).as("Removals").isEqualTo(remove); + softly.assertAll(); + hitCount += hit; missCount += miss; putCount += put; From 725be1dc7e1b2b96f82a2c7c6596647ca372ecbe Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Tue, 4 Dec 2018 15:03:36 -0500 Subject: [PATCH 047/372] Explain why we need to have a specific consumer knowing is a value was put --- .../internal/store/loaderwriter/LocalLoaderWriterStore.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java index c25aff48b6..1824d6ebf3 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java @@ -120,6 +120,9 @@ public ValueHolder putIfAbsent(K key, V value, Consumer put) throws throw new StorePassThroughException(newCacheWritingException(e)); } + // Here were a returning an actual value instead of null because the mappingFunction is called by a map.compute(). So we + // want the compute to actually set the value to the backend. However, the putIfAbsent should return null since there + // was no previous value. This is why we use put.accept(true). This will tell EhcacheBase: "Hey! A put was done, you should return null" put.accept(true); return value; }; From 2984a7ca4f7cfc83213b8850ed8aa3aeab81d6b7 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Mon, 10 Dec 2018 11:49:29 -0500 Subject: [PATCH 048/372] Badly formatted copyright --- .../impl/internal/store/basic/DelegatingValueHolder.java | 2 +- .../ehcache/impl/internal/store/basic/SimpleValueHolder.java | 2 +- .../src/test/java/org/ehcache/integration/EhcacheBaseTest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/basic/DelegatingValueHolder.java b/impl/src/test/java/org/ehcache/impl/internal/store/basic/DelegatingValueHolder.java index 7dc3e2d71d..ff3af1fc49 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/basic/DelegatingValueHolder.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/basic/DelegatingValueHolder.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/basic/SimpleValueHolder.java b/impl/src/test/java/org/ehcache/impl/internal/store/basic/SimpleValueHolder.java index dbde912285..78442bc9ee 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/basic/SimpleValueHolder.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/basic/SimpleValueHolder.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java b/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java index 7e154f93ab..9110cb6317 100644 --- a/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, From 049a987ff88ca0c1d070b15b65a31292b6625d9a Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Mon, 10 Dec 2018 13:33:39 -0500 Subject: [PATCH 049/372] A ValueHolder can't contain null so this is actually an impossible ValueHolder. --- .../store/basic/EmptyValueHolder.java | 65 ------------------- .../impl/internal/store/basic/NopStore.java | 8 +-- 2 files changed, 4 insertions(+), 69 deletions(-) delete mode 100644 impl/src/main/java/org/ehcache/impl/internal/store/basic/EmptyValueHolder.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/basic/EmptyValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/basic/EmptyValueHolder.java deleted file mode 100644 index 1146ee26bb..0000000000 --- a/impl/src/main/java/org/ehcache/impl/internal/store/basic/EmptyValueHolder.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.ehcache.impl.internal.store.basic; - -import org.ehcache.core.spi.store.Store; - -import java.util.concurrent.TimeUnit; - -/** - * A value holder that always contains null - * - * @author Henri Tremblay - */ -public class EmptyValueHolder implements Store.ValueHolder { - - private static final Store.ValueHolder EMPTY = new EmptyValueHolder<>(); - - @SuppressWarnings("unchecked") - public static Store.ValueHolder empty() { - return (Store.ValueHolder) EMPTY; - } - - @Override - public V get() { - return null; - } - - @Override - public long creationTime() { - return 0; - } - - @Override - public long expirationTime() { - return 0; - } - - @Override - public boolean isExpired(long expirationTime) { - return false; - } - - @Override - public long lastAccessTime() { - return 0; - } - - @Override - public long getId() { - return 0; - } -} diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java index 841a31cf62..f98cb42a6a 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java @@ -83,7 +83,7 @@ public PutStatus put(K key, V value) throws StoreAccessException { @Override public ValueHolder putIfAbsent(K key, V value, Consumer put) throws StoreAccessException { - return EmptyValueHolder.empty(); + return null; } @Override @@ -158,7 +158,7 @@ public Cache.Entry> next() { @Override public ValueHolder getAndCompute(K key, BiFunction mappingFunction) { - return EmptyValueHolder.empty(); + return null; } @Override @@ -180,7 +180,7 @@ public Map> bulkCompute(Set keys, Function> bulkCompute(Set keys, Function>, Iterable>> remappingFunction, Supplier replaceEqual) { Map> map = new HashMap<>(keys.size()); for(K key : keys) { - map.put(key, EmptyValueHolder.empty()); + map.put(key, null); } return map; } @@ -189,7 +189,7 @@ public Map> bulkCompute(Set keys, Function> bulkComputeIfAbsent(Set keys, Function, Iterable>> mappingFunction) { Map> map = new HashMap<>(keys.size()); for(K key : keys) { - map.put(key, EmptyValueHolder.empty()); + map.put(key, null); } return map; } From 3a7a0af5cdb3f0fcec9655e81e632206438b82ef Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Mon, 10 Dec 2018 13:38:40 -0500 Subject: [PATCH 050/372] Add missing imports for the javadoc --- .../java/org/ehcache/core/resilience/DefaultRecoveryStore.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/java/org/ehcache/core/resilience/DefaultRecoveryStore.java b/core/src/main/java/org/ehcache/core/resilience/DefaultRecoveryStore.java index e56b7076b8..0609385882 100644 --- a/core/src/main/java/org/ehcache/core/resilience/DefaultRecoveryStore.java +++ b/core/src/main/java/org/ehcache/core/resilience/DefaultRecoveryStore.java @@ -15,6 +15,8 @@ */ package org.ehcache.core.resilience; +import org.ehcache.core.internal.resilience.RobustLoaderWriterResilienceStrategy; +import org.ehcache.core.internal.resilience.RobustResilienceStrategy; import org.ehcache.core.spi.store.Store; import org.ehcache.spi.resilience.RecoveryStore; import org.ehcache.spi.resilience.StoreAccessException; From d9debcd08344de9662573d912e12458c94db661f Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Mon, 10 Dec 2018 13:49:04 -0500 Subject: [PATCH 051/372] Describe which stat failed because it's useful --- .../providers/statistics/StandardEhcacheStatisticsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java index 74a4d6bac7..68f8eb19d5 100755 --- a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java @@ -151,7 +151,7 @@ public void statTest() throws InterruptedException { private AbstractLongAssert assertStatistic(String statName) { long value = getStatistic(statName); - return assertThat(value); + return assertThat(value).describedAs(statName); } private long getStatistic(String statName) { From 903cb3e0851683dc5a3e98d63f4084e09fc398a2 Mon Sep 17 00:00:00 2001 From: "Sun, Boyu" Date: Wed, 12 Dec 2018 10:44:26 -0800 Subject: [PATCH 052/372] TDB-4221 Enhance log message for ClusteredStatisticsCountTest.countTest --- .../management/AbstractClusteringManagementTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index b320f523ca..7a854f80e5 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -321,6 +321,7 @@ public static void sendManagementCallOnEntityToCollectStats() throws Exception { public static void waitForAllNotifications(String... notificationTypes) throws InterruptedException { List waitingFor = new ArrayList<>(Arrays.asList(notificationTypes)); List missingOnes = new ArrayList<>(); + List existingOnes = new ArrayList<>(); // please keep these sout because it is really hard to troubleshoot blocking tests in the beforeClass method in the case we do not receive all notifs. // System.out.println("waitForAllNotifications: " + waitingFor); @@ -331,6 +332,7 @@ public static void waitForAllNotifications(String... notificationTypes) throws I if (message.getType().equals("NOTIFICATION")) { for (ContextualNotification notification : message.unwrap(ContextualNotification.class)) { if (waitingFor.remove(notification.getType())) { + existingOnes.add(notification); // System.out.println("Remove " + notification.getType()); // System.out.println("Still waiting for: " + waitingFor); } else { @@ -348,7 +350,7 @@ public static void waitForAllNotifications(String... notificationTypes) throws I t.join(30_000); // should be way enough to receive all messages t.interrupt(); // we interrupt the thread that is waiting on the message queue - assertTrue("Still waiting for: " + waitingFor, waitingFor.isEmpty()); - assertTrue("Unexpected notification: " + missingOnes, missingOnes.isEmpty()); + assertTrue("Still waiting for: " + waitingFor + ", only got: " + existingOnes, waitingFor.isEmpty()); + assertTrue("Unexpected notification: " + missingOnes + ", only got: " + existingOnes, missingOnes.isEmpty()); } } From 3b8f8ea8790a37bb512edf0738525214d6671997 Mon Sep 17 00:00:00 2001 From: "Sun, Boyu" Date: Wed, 12 Dec 2018 10:44:26 -0800 Subject: [PATCH 053/372] Enhance log message for ClusteredStatisticsCountTest.countTest --- .../management/AbstractClusteringManagementTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index b320f523ca..7a854f80e5 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -321,6 +321,7 @@ public static void sendManagementCallOnEntityToCollectStats() throws Exception { public static void waitForAllNotifications(String... notificationTypes) throws InterruptedException { List waitingFor = new ArrayList<>(Arrays.asList(notificationTypes)); List missingOnes = new ArrayList<>(); + List existingOnes = new ArrayList<>(); // please keep these sout because it is really hard to troubleshoot blocking tests in the beforeClass method in the case we do not receive all notifs. // System.out.println("waitForAllNotifications: " + waitingFor); @@ -331,6 +332,7 @@ public static void waitForAllNotifications(String... notificationTypes) throws I if (message.getType().equals("NOTIFICATION")) { for (ContextualNotification notification : message.unwrap(ContextualNotification.class)) { if (waitingFor.remove(notification.getType())) { + existingOnes.add(notification); // System.out.println("Remove " + notification.getType()); // System.out.println("Still waiting for: " + waitingFor); } else { @@ -348,7 +350,7 @@ public static void waitForAllNotifications(String... notificationTypes) throws I t.join(30_000); // should be way enough to receive all messages t.interrupt(); // we interrupt the thread that is waiting on the message queue - assertTrue("Still waiting for: " + waitingFor, waitingFor.isEmpty()); - assertTrue("Unexpected notification: " + missingOnes, missingOnes.isEmpty()); + assertTrue("Still waiting for: " + waitingFor + ", only got: " + existingOnes, waitingFor.isEmpty()); + assertTrue("Unexpected notification: " + missingOnes + ", only got: " + existingOnes, missingOnes.isEmpty()); } } From b7c8860cdd465e141997ce33e414ddd47c5442ff Mon Sep 17 00:00:00 2001 From: mobasherul Date: Sun, 2 Dec 2018 22:22:32 -0800 Subject: [PATCH 054/372] Destroy Cache Manager in reconnect path when connection lost during destruction. --- ...ClusterTierManagerClientEntityFactory.java | 17 +- .../internal/service/ConnectionState.java | 25 ++- .../service/DefaultClusteringService.java | 5 + .../service/DefaultClusteringServiceTest.java | 18 ++ .../DestroyInProgressException.java | 5 + ...gerClientEntityFactoryIntegrationTest.java | 4 +- .../clustered/ReconnectDuringDestroyTest.java | 198 ++++++++++++++++++ 7 files changed, 257 insertions(+), 15 deletions(-) create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java index 0ba843cbc3..070c8b8e2c 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java @@ -81,8 +81,8 @@ public boolean acquireLeadership(String entityIdentifier) { } } - public boolean abandonAllHolds(String entityIdentifier) { - return abandonLeadership(entityIdentifier) | abandonFetchHolds(entityIdentifier); + public boolean abandonAllHolds(String entityIdentifier, boolean healthyConnection) { + return abandonLeadership(entityIdentifier, healthyConnection) | abandonFetchHolds(entityIdentifier, healthyConnection); } /** @@ -91,9 +91,9 @@ public boolean abandonAllHolds(String entityIdentifier) { * @param entityIdentifier the master entity identifier * @return true of abandoned false otherwise */ - public boolean abandonLeadership(String entityIdentifier) { + public boolean abandonLeadership(String entityIdentifier, boolean healthyConnection) { Hold hold = maintenanceHolds.remove(entityIdentifier); - return (hold != null) && silentlyUnlock(hold, entityIdentifier); + return (hold != null) && healthyConnection && silentlyUnlock(hold, entityIdentifier); } /** @@ -102,9 +102,9 @@ public boolean abandonLeadership(String entityIdentifier) { * @param entityIdentifier the master entity identifier * @return true of abandoned false otherwise */ - private boolean abandonFetchHolds(String entityIdentifier) { + private boolean abandonFetchHolds(String entityIdentifier, boolean healthyConnection) { Hold hold = fetchHolds.remove(entityIdentifier); - return (hold != null) && silentlyUnlock(hold, entityIdentifier); + return (hold != null) && healthyConnection && silentlyUnlock(hold, entityIdentifier); } /** @@ -342,4 +342,9 @@ public void destroyClusteredStoreEntity(String clusterTierManagerIdentifier, Str private static String entityName(String clusterTierManagerIdentifier, String storeIdentifier) { return clusterTierManagerIdentifier + "$" + storeIdentifier; } + + // For test purposes + public Map getMaintenanceHolds() { + return maintenanceHolds; + } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java index 6f3f8edec8..abf9ad7c5d 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java @@ -158,6 +158,17 @@ public void closeConnection() { } } + private boolean silentDestroyUtil() { + try { + silentDestroy(); + return true; + } catch (ConnectionClosedException | ConnectionShutdownException e) { + LOGGER.info("Disconnected from the server", e); + reconnect(); + return false; + } + } + private void silentDestroy() { LOGGER.debug("Found a broken ClusterTierManager - trying to clean it up"); try { @@ -209,9 +220,9 @@ private void retrieveEntity() { } public void destroyState(boolean healthyConnection) { - if (entityFactory != null && healthyConnection) { + if (entityFactory != null) { // proactively abandon any acquired read or write locks on a healthy connection - entityFactory.abandonAllHolds(entityIdentifier); + entityFactory.abandonAllHolds(entityIdentifier, healthyConnection); } entityFactory = null; @@ -247,9 +258,10 @@ public void destroy(String name) throws CachePersistenceException { throw new CachePersistenceException("Could not connect to the cluster tier manager '" + entityIdentifier + "'; retrieve operation timed out", e); } catch (DestroyInProgressException e) { - silentDestroy(); - // Nothing left to do - break; + if (silentDestroyUtil()) { + // Nothing left to do + break; + } } catch (ConnectionClosedException | ConnectionShutdownException e) { reconnect(); } @@ -288,7 +300,7 @@ private void autoCreateEntity() throws ClusterTierManagerValidationException, Il entity = entityFactory.retrieve(entityIdentifier, serviceConfiguration.getServerConfiguration()); break; } catch (DestroyInProgressException e) { - silentDestroy(); + silentDestroyUtil(); } catch (EntityNotFoundException e) { //ignore - loop and try to create } catch (TimeoutException e) { @@ -307,7 +319,6 @@ private void handleConnectionClosedException() { try { destroyState(false); reconnect(); - retrieveEntity(); connectionRecoveryListener.run(); break; } catch (ConnectionClosedException | ConnectionShutdownException e) { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java index 2892a19998..1d7a71b9b7 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java @@ -340,4 +340,9 @@ private static class ClusteredSpace { } } + // for test purposes + public ConnectionState getConnectionState() { + return connectionState; + } + } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java index fc76c80768..f224f93fe1 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java @@ -22,6 +22,7 @@ import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; +import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntityFactory; import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntityService; import org.ehcache.clustered.client.internal.UnitTestConnectionService; import org.ehcache.clustered.client.internal.UnitTestConnectionService.PassthroughServerBuilder; @@ -2054,6 +2055,23 @@ public void testReleasePersistenceSpaceIdentifierTwice() throws Exception { service.releasePersistenceSpaceIdentifier(cacheIdentifier); } + @Test + public void releaseMaintenanceHoldsWhenConnectionClosedDuringDestruction() { + ClusteringServiceConfiguration configuration = + new ClusteringServiceConfiguration(URI.create(CLUSTER_URI_BASE), true, new ServerSideConfiguration(Collections.emptyMap())); + DefaultClusteringService service = new DefaultClusteringService(configuration); + assertThat(service.isConnected(), is(false)); + service.startForMaintenance(null, MaintainableService.MaintenanceScope.CACHE_MANAGER); + assertThat(service.isConnected(), is(true)); + + ConnectionState connectionState = service.getConnectionState(); + ClusterTierManagerClientEntityFactory clusterTierManagerClientEntityFactory = connectionState.getEntityFactory(); + assertEquals(clusterTierManagerClientEntityFactory.getMaintenanceHolds().size(), 1); + connectionState.destroyState(false); + assertEquals(clusterTierManagerClientEntityFactory.getMaintenanceHolds().size(), 0); + service.stop(); + } + private static Throwable getRootCause(Throwable t) { if (t.getCause() == null || t.getCause() == t) { return t; diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/DestroyInProgressException.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/DestroyInProgressException.java index afe0e5281a..ae6c63c4f4 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/DestroyInProgressException.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/DestroyInProgressException.java @@ -26,4 +26,9 @@ public class DestroyInProgressException extends LifecycleException { public DestroyInProgressException(String message) { super(message); } + + @Override + public DestroyInProgressException withClientStackTrace() { + return new DestroyInProgressException(this.getMessage()); + } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java index 8678e0b8e0..1198e2b217 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java @@ -156,7 +156,7 @@ public void testDestroyWhenNotExisting() throws Exception { @Test public void testAbandonLeadershipWhenNotOwning() throws Exception { ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION); - assertFalse(factory.abandonLeadership("testAbandonLeadershipWhenNotOwning")); + assertFalse(factory.abandonLeadership("testAbandonLeadershipWhenNotOwning", true)); } @Test @@ -180,7 +180,7 @@ public void testAcquireLeadershipWhenTaken() throws Exception { public void testAcquireLeadershipAfterAbandoned() throws Exception { ClusterTierManagerClientEntityFactory factoryA = new ClusterTierManagerClientEntityFactory(CONNECTION); factoryA.acquireLeadership("testAcquireLeadershipAfterAbandoned"); - assertTrue(factoryA.abandonLeadership("testAcquireLeadershipAfterAbandoned")); + assertTrue(factoryA.abandonLeadership("testAcquireLeadershipAfterAbandoned", true)); try (Connection clientB = CLUSTER.newConnection()) { ClusterTierManagerClientEntityFactory factoryB = new ClusterTierManagerClientEntityFactory(clientB); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java new file mode 100644 index 0000000000..5ce3033044 --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -0,0 +1,198 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered; + +import org.ehcache.Cache; +import org.ehcache.PersistentCacheManager; +import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; +import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; +import org.ehcache.clustered.client.config.builders.ServerSideConfigurationBuilder; +import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntity; +import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock; +import org.ehcache.clustered.client.service.EntityBusyException; +import org.ehcache.clustered.common.internal.ClusterTierManagerConfiguration; +import org.ehcache.clustered.reconnect.ThrowingResiliencyStrategy; +import org.ehcache.clustered.util.TCPProxyUtil; +import org.ehcache.config.CacheConfiguration; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.config.units.MemoryUnit; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.terracotta.connection.Connection; +import org.terracotta.connection.entity.EntityRef; +import org.terracotta.exception.EntityNotFoundException; +import org.terracotta.lease.connection.LeasedConnectionFactory; +import org.terracotta.testing.rules.Cluster; + +import com.tc.net.proxy.TCPProxy; + +import java.io.File; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import static org.ehcache.clustered.common.EhcacheEntityVersion.ENTITY_VERSION; +import static org.ehcache.clustered.reconnect.BasicCacheReconnectTest.RESOURCE_CONFIG; +import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; +import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + +/** + * ReconnectDuringDestroyTest + */ +public class ReconnectDuringDestroyTest extends ClusteredTests { + + private static URI connectionURI; + private static List proxies; + PersistentCacheManager cacheManager; + + @ClassRule + public static Cluster CLUSTER = + newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + + @BeforeClass + public static void waitForActive() throws Exception { + CLUSTER.getClusterControl().waitForActive(); + proxies = new ArrayList<>(); + connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.getConnectionURI(), proxies); + } + + @Before + public void initializeCacheManager() { + ServerSideConfigurationBuilder serverSideConfigurationBuilder = + ClusteringServiceConfigurationBuilder.cluster(connectionURI.resolve("/crud-cm")) + .autoCreate() + .defaultServerResource("primary-server-resource"); + + CacheManagerBuilder clusteredCacheManagerBuilder + = CacheManagerBuilder.newCacheManagerBuilder() + .with(serverSideConfigurationBuilder); + cacheManager = clusteredCacheManagerBuilder.build(false); + cacheManager.init(); + } + + /* + This is to test the scenario in which reconnect happens while cache manager + destruction is in progress. This test checks whether the cache manager + gets destructed properly in the reconnect path once the connection is closed + after the prepareForDestroy() call. + */ + @Test + public void reconnectDuringDestroyTest() throws Exception { + cacheManager.close(); + Connection client = null; + try { + client = LeasedConnectionFactory.connect(connectionURI, new Properties()); + VoltronReadWriteLock voltronReadWriteLock = new VoltronReadWriteLock(client, "crud-cm"); + try (VoltronReadWriteLock.Hold localMaintenance = voltronReadWriteLock.tryWriteLock()) { + if (localMaintenance == null) { + throw new EntityBusyException("Unable to obtain maintenance lease for " + "crud-cm"); + } + EntityRef ref = getEntityRef(client); + try { + ClusterTierManagerClientEntity entity = ref.fetchEntity(null); + entity.prepareForDestroy(); + entity.close(); + } catch (EntityNotFoundException e) { + Assert.fail(); + } + } + // For reconnection. + setDelay(6000, proxies); // Connection Lease time is 5 seconds so delaying for more than 5 seconds. + Thread.sleep(6000); + setDelay(0L, proxies); + client = LeasedConnectionFactory.connect(connectionURI, new Properties()); + + // For mimicking the cacheManager.destroy() in the reconnect path. + voltronReadWriteLock = new VoltronReadWriteLock(client, "crud-cm"); + try (VoltronReadWriteLock.Hold localMaintenance = voltronReadWriteLock.tryWriteLock()) { + if (localMaintenance == null) { + throw new EntityBusyException("Unable to obtain maintenance lease for " + "crud-cm"); + } + EntityRef ref = getEntityRef(client); + try { + ClusterTierManagerClientEntity entity = ref.fetchEntity(null); + entity.prepareForDestroy(); + entity.close(); + } catch (EntityNotFoundException e) { + Assert.fail("Unexpected exception " + e.getMessage()); + } + if (!ref.destroy()) { + Assert.fail("Unexpected exception while trying to destroy cache manager"); + } + } + } finally { + client.close(); + } + } + + @Test + public void reconnectAfterDestroyOneOfTheCache() throws Exception { + try { + CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, + ResourcePoolsBuilder.newResourcePoolsBuilder() + .with(ClusteredResourcePoolBuilder. + clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB))) + .withResilienceStrategy(new ThrowingResiliencyStrategy<>()) + .build(); + Cache cache1 = cacheManager.createCache("clustered-cache-1", config); + Cache cache2 = cacheManager.createCache("clustered-cache-2", config); + cache1.put(1L, "The one"); + cache1.put(2L, "The two"); + cache2.put(1L, "The one"); + cache2.put(2L, "The two"); + cacheManager.destroyCache("clustered-cache-1"); + + // For reconnection. + setDelay(6000, proxies); // Connection Lease time is 5 seconds so delaying for more than 5 seconds. + Thread.sleep(6000); + setDelay(0L, proxies); + + cache2 = cacheManager.getCache("clustered-cache-2", Long.class, String.class); + int count = 0; + while (count < 5) { + Thread.sleep(2000); + count++; + try { + cache2.get(1L); + break; + } catch (Exception e) { + // Can happen during reconnect + } + } + if (count == 5) { + Assert.fail("Unexpected reconnection exception"); + } + assertThat(cache2.get(1L), equalTo("The one")); + assertThat(cache2.get(2L), equalTo("The two")); + cache2.put(3L, "The three"); + assertThat(cache2.get(3L), equalTo("The three")); + } finally { + cacheManager.close(); + } + } + + private EntityRef getEntityRef(Connection client) throws org.terracotta.exception.EntityNotProvidedException { + return client.getEntityRef(ClusterTierManagerClientEntity.class, ENTITY_VERSION, "crud-cm"); + } +} From 12173f914ec6ba719ce87fb508e8ffa449c71b8a Mon Sep 17 00:00:00 2001 From: Albin Suresh Date: Thu, 20 Dec 2018 16:48:24 +0530 Subject: [PATCH 055/372] Extensible ClusterTierActiveEntity --- .../clustered/server/store/ClusterTierActiveEntity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java b/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java index 8b1db23bc3..d62d74df62 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java @@ -835,11 +835,11 @@ public void destroy() { management.close(); } - Set getConnectedClients() { + protected Set getConnectedClients() { return connectedClients.keySet(); } - Set getValidatedClients() { + protected Set getValidatedClients() { return connectedClients.entrySet().stream().filter(Map.Entry::getValue).map(Map.Entry::getKey).collect(toSet()); } From e2be0c582f49f7b8566f3357d30deda1c6e1c1fa Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 20 Sep 2018 13:55:40 -0400 Subject: [PATCH 056/372] Move ServiceLocator to an exported package --- CONTRIBUTING.adoc | 2 +- .../ClusteredLoaderWriterStoreProviderTest.java | 4 ++-- .../ClusteredWriteBehindStoreProviderTest.java | 4 ++-- .../internal/store/ClusteredStoreProviderTest.java | 4 ++-- core/build.gradle | 1 - .../src/main/java/org/ehcache/core/EhcacheManager.java | 6 +++--- .../org/ehcache/core/internal/store/StoreSupport.java | 2 +- .../core/{internal/service => spi}/ServiceLocator.java | 2 +- .../ehcache/core/internal/store/StoreSupportTest.java | 4 ++-- .../service => spi}/ServiceLocatorPluralTest.java | 6 ++---- .../{internal/service => spi}/ServiceLocatorTest.java | 10 +++++----- .../config/builders/UserManagedCacheBuilder.java | 4 ++-- .../config/builders/UserManagedCacheBuilderTest.java | 2 +- .../java/org/ehcache/core/spi/ServiceProviderTest.java | 3 +-- .../impl/internal/DefaultTimeSourceServiceTest.java | 6 ++---- .../store/disk/OffHeapDiskStoreProviderTest.java | 4 ++-- .../internal/store/disk/OffHeapDiskStoreSPITest.java | 4 ++-- .../impl/internal/store/disk/OffHeapDiskStoreTest.java | 4 ++-- .../store/heap/ByteSizedOnHeapStoreByRefSPITest.java | 4 ++-- .../store/heap/ByteSizedOnHeapStoreByValueSPITest.java | 4 ++-- .../internal/store/heap/OnHeapStoreByRefSPITest.java | 4 ++-- .../internal/store/heap/OnHeapStoreByValueSPITest.java | 4 ++-- .../store/heap/OnHeapStoreCachingTierByRefSPITest.java | 2 +- .../heap/OnHeapStoreCachingTierByValueSPITest.java | 2 +- .../bytesized/OnHeapStoreCachingTierByRefSPITest.java | 2 +- .../OnHeapStoreCachingTierByValueSPITest.java | 2 +- .../internal/store/offheap/OffHeapStoreSPITest.java | 4 ++-- .../store/tiering/CompoundCachingTierSPITest.java | 2 +- .../tiering/TieredStoreFlushWhileShutdownTest.java | 4 ++-- .../internal/store/tiering/TieredStoreSPITest.java | 4 ++-- .../impl/internal/store/tiering/TieredStoreTest.java | 4 ++-- .../store/tiering/TieredStoreWith3TiersSPITest.java | 4 ++-- .../ehcache/integration/EhcacheBulkMethodsITest.java | 4 ++-- .../ehcache/transactions/xa/internal/XAStoreTest.java | 7 ++----- 34 files changed, 60 insertions(+), 69 deletions(-) rename core/src/main/java/org/ehcache/core/{internal/service => spi}/ServiceLocator.java (99%) rename core/src/test/java/org/ehcache/core/{internal/service => spi}/ServiceLocatorPluralTest.java (98%) rename core/src/test/java/org/ehcache/core/{internal/service => spi}/ServiceLocatorTest.java (98%) diff --git a/CONTRIBUTING.adoc b/CONTRIBUTING.adoc index 8dab9e13a5..a8701cacac 100644 --- a/CONTRIBUTING.adoc +++ b/CONTRIBUTING.adoc @@ -54,7 +54,7 @@ An example of `Service` being the `org.ehcache.core.spi.store.Store.Provider`, i `Service` instances are created using Java's https://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html[`java.util.ServiceLoader` service-provider loading facility]. It is used to locate all `org.ehcache.core.spi.service.ServiceFactory` implementations on the classpath. -These are in turn used to create `Service` instances. Each `CacheManager` uses its own `org.ehcache.core.internal.service.ServiceLocator` facility to locate `Service` instances, which it then in turn life cycles. +These are in turn used to create `Service` instances. Each `CacheManager` uses its own `org.ehcache.core.spi.ServiceLocator` facility to locate `Service` instances, which it then in turn life cycles. `Service` instances are configured by their own respective `ServiceConfiguration` at `Service.start()` invocation time. `CacheManager` and its `Service` instances can then use these services. diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java index 681ccb0a97..b8bf723321 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java @@ -18,7 +18,7 @@ import org.ehcache.clustered.client.config.ClusteredResourceType; import org.ehcache.clustered.client.internal.store.ClusteredStoreProviderTest; import org.ehcache.clustered.client.service.ClusteringService; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.impl.internal.store.disk.OffHeapDiskStore; import org.ehcache.impl.internal.store.heap.OnHeapStore; @@ -30,7 +30,7 @@ import java.util.Collections; import java.util.HashSet; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java index 332d008fc3..489c772f0b 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java @@ -18,7 +18,7 @@ import org.ehcache.clustered.client.config.ClusteredResourceType; import org.ehcache.clustered.client.internal.store.ClusteredStoreProviderTest; import org.ehcache.clustered.client.service.ClusteringService; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.impl.internal.store.disk.OffHeapDiskStore; import org.ehcache.impl.internal.store.heap.OnHeapStore; @@ -32,7 +32,7 @@ import java.util.Collections; import java.util.HashSet; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java index e0c76ef807..1b922b6337 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java @@ -28,7 +28,7 @@ import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.config.ResourcePoolsImpl; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.store.Store; import org.ehcache.expiry.ExpiryPolicy; @@ -49,7 +49,7 @@ import java.util.List; import java.util.Map; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.*; diff --git a/core/build.gradle b/core/build.gradle index f5b9904422..6998b42651 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -30,7 +30,6 @@ jar { instruction 'Export-Package', 'org.ehcache.core.internal.events', 'org.ehcache.core.internal.resilience', - 'org.ehcache.core.internal.service', 'org.ehcache.core.internal.store', 'org.ehcache.core.internal.util', '!org.ehcache.core.internal.*', 'org.ehcache.core.*' diff --git a/core/src/main/java/org/ehcache/core/EhcacheManager.java b/core/src/main/java/org/ehcache/core/EhcacheManager.java index 6ee54d9973..6679ce1584 100644 --- a/core/src/main/java/org/ehcache/core/EhcacheManager.java +++ b/core/src/main/java/org/ehcache/core/EhcacheManager.java @@ -34,10 +34,10 @@ import org.ehcache.core.events.CacheEventListenerConfiguration; import org.ehcache.core.events.CacheEventListenerProvider; import org.ehcache.core.events.CacheManagerListener; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.internal.util.ClassLoading; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.core.internal.store.StoreSupport; -import org.ehcache.core.internal.util.ClassLoading; import org.ehcache.core.resilience.DefaultRecoveryStore; import org.ehcache.core.spi.LifeCycled; import org.ehcache.core.spi.LifeCycledAdapter; @@ -79,7 +79,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicReference; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.ehcache.core.spi.service.ServiceUtils.findOptionalAmongst; import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; diff --git a/core/src/main/java/org/ehcache/core/internal/store/StoreSupport.java b/core/src/main/java/org/ehcache/core/internal/store/StoreSupport.java index 8da0d2320d..225507f756 100644 --- a/core/src/main/java/org/ehcache/core/internal/store/StoreSupport.java +++ b/core/src/main/java/org/ehcache/core/internal/store/StoreSupport.java @@ -17,7 +17,7 @@ package org.ehcache.core.internal.store; import org.ehcache.config.ResourceType; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.WrapperStore; import org.ehcache.spi.service.ServiceProvider; diff --git a/core/src/main/java/org/ehcache/core/internal/service/ServiceLocator.java b/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java similarity index 99% rename from core/src/main/java/org/ehcache/core/internal/service/ServiceLocator.java rename to core/src/main/java/org/ehcache/core/spi/ServiceLocator.java index 5b2110229e..92b43c93e2 100644 --- a/core/src/main/java/org/ehcache/core/internal/service/ServiceLocator.java +++ b/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.internal.service; +package org.ehcache.core.spi; import org.ehcache.config.Builder; import org.ehcache.spi.service.OptionalServiceDependencies; diff --git a/core/src/test/java/org/ehcache/core/internal/store/StoreSupportTest.java b/core/src/test/java/org/ehcache/core/internal/store/StoreSupportTest.java index ae223eac4e..59cb5ce8db 100644 --- a/core/src/test/java/org/ehcache/core/internal/store/StoreSupportTest.java +++ b/core/src/test/java/org/ehcache/core/internal/store/StoreSupportTest.java @@ -18,7 +18,7 @@ import org.ehcache.config.ResourcePool; import org.ehcache.config.ResourceType; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.store.Store; import org.ehcache.spi.service.ServiceProvider; import org.ehcache.spi.service.Service; @@ -32,7 +32,7 @@ import java.util.concurrent.atomic.AtomicInteger; import static java.util.Arrays.asList; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; diff --git a/core/src/test/java/org/ehcache/core/internal/service/ServiceLocatorPluralTest.java b/core/src/test/java/org/ehcache/core/spi/ServiceLocatorPluralTest.java similarity index 98% rename from core/src/test/java/org/ehcache/core/internal/service/ServiceLocatorPluralTest.java rename to core/src/test/java/org/ehcache/core/spi/ServiceLocatorPluralTest.java index 6a739d1776..d6e4c0f937 100644 --- a/core/src/test/java/org/ehcache/core/internal/service/ServiceLocatorPluralTest.java +++ b/core/src/test/java/org/ehcache/core/spi/ServiceLocatorPluralTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.internal.service; +package org.ehcache.core.spi; import org.ehcache.spi.service.ServiceProvider; import org.ehcache.spi.service.PluralService; @@ -23,16 +23,14 @@ import org.hamcrest.Matchers; import org.junit.Test; -import java.util.Collection; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.everyItem; import static org.hamcrest.Matchers.isOneOf; -import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; diff --git a/core/src/test/java/org/ehcache/core/internal/service/ServiceLocatorTest.java b/core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java similarity index 98% rename from core/src/test/java/org/ehcache/core/internal/service/ServiceLocatorTest.java rename to core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java index ed1b545237..c2082de08d 100644 --- a/core/src/test/java/org/ehcache/core/internal/service/ServiceLocatorTest.java +++ b/core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.internal.service; +package org.ehcache.core.spi; import java.io.IOException; import java.net.URL; @@ -43,7 +43,7 @@ import org.hamcrest.CoreMatchers; import org.junit.Test; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -463,8 +463,8 @@ public void testRankedServiceBecomesMandatory() { @ServiceDependencies(TestService.class) @OptionalServiceDependencies({ - "org.ehcache.core.internal.service.OptService1", - "org.ehcache.core.internal.service.OptService2"}) + "org.ehcache.core.spi.OptService1", + "org.ehcache.core.spi.OptService2"}) class ServiceWithOptionalDeps implements Service { @Override @@ -481,7 +481,7 @@ public void stop() { @ServiceDependencies(TestService.class) @OptionalServiceDependencies({ "org.ehcache.core.internal.service.ServiceThatDoesNotExist", - "org.ehcache.core.internal.service.OptService2"}) + "org.ehcache.core.spi.OptService2"}) class ServiceWithOptionalNonExistentDeps implements Service { @Override diff --git a/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java b/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java index 4ca9ca234c..bf80f5afa7 100644 --- a/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java @@ -34,7 +34,7 @@ import org.ehcache.core.events.CacheEventDispatcher; import org.ehcache.core.events.CacheEventListenerConfiguration; import org.ehcache.core.events.CacheEventListenerProvider; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.core.internal.store.StoreSupport; import org.ehcache.core.internal.util.ClassLoading; @@ -83,7 +83,7 @@ import static org.ehcache.config.ResourceType.Core.DISK; import static org.ehcache.config.ResourceType.Core.OFFHEAP; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; import static org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration.DEFAULT_MAX_OBJECT_SIZE; import static org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration.DEFAULT_OBJECT_GRAPH_SIZE; diff --git a/impl/src/test/java/org/ehcache/config/builders/UserManagedCacheBuilderTest.java b/impl/src/test/java/org/ehcache/config/builders/UserManagedCacheBuilderTest.java index 2d0a12014b..b84c23242b 100644 --- a/impl/src/test/java/org/ehcache/config/builders/UserManagedCacheBuilderTest.java +++ b/impl/src/test/java/org/ehcache/config/builders/UserManagedCacheBuilderTest.java @@ -22,7 +22,7 @@ import org.ehcache.config.CacheRuntimeConfiguration; import org.ehcache.event.EventType; import org.ehcache.spi.loaderwriter.BulkCacheWritingException; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.impl.internal.spi.event.DefaultCacheEventListenerProviderTest; import org.junit.Test; diff --git a/impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java b/impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java index 339dce04f6..03be2c5d0a 100644 --- a/impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java +++ b/impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java @@ -16,7 +16,6 @@ package org.ehcache.core.spi; -import org.ehcache.core.internal.service.ServiceLocator; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.impl.internal.store.disk.OffHeapDiskStore; import org.ehcache.impl.internal.store.heap.OnHeapStore; @@ -27,7 +26,7 @@ import org.hamcrest.core.IsSame; import org.junit.Test; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; diff --git a/impl/src/test/java/org/ehcache/impl/internal/DefaultTimeSourceServiceTest.java b/impl/src/test/java/org/ehcache/impl/internal/DefaultTimeSourceServiceTest.java index 7a3d6d7a49..d6a1d2f579 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/DefaultTimeSourceServiceTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/DefaultTimeSourceServiceTest.java @@ -19,12 +19,10 @@ import org.ehcache.core.spi.time.SystemTimeSource; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.core.spi.time.TimeSourceService; -import org.ehcache.core.internal.service.ServiceLocator; -import org.ehcache.spi.service.Service; -import org.ehcache.spi.service.ServiceDependencies; +import org.ehcache.core.spi.ServiceLocator; import org.junit.Test; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.hamcrest.CoreMatchers.sameInstance; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java index 106e4f705a..10f4c84cba 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java @@ -25,7 +25,7 @@ import org.ehcache.config.SizedResourcePool; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.store.Store; import org.ehcache.expiry.ExpiryPolicy; @@ -46,7 +46,7 @@ import java.util.Set; import static java.util.Collections.singleton; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.Matchers.empty; import static org.junit.Assert.assertThat; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java index 08bd778335..f6840b5363 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java @@ -37,7 +37,7 @@ import org.ehcache.internal.store.StoreFactory; import org.ehcache.internal.tier.AuthoritativeTierFactory; import org.ehcache.internal.tier.AuthoritativeTierSPITest; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; import org.ehcache.spi.serialization.Serializer; @@ -55,7 +55,7 @@ import static org.ehcache.config.ResourceType.Core.DISK; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration.DEFAULT_DISK_SEGMENTS; import static org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration.DEFAULT_WRITER_CONCURRENCY; import static org.ehcache.test.MockitoUtil.mock; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java index bb05437557..2475051efd 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java @@ -39,7 +39,7 @@ import org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider; import org.ehcache.core.spi.time.SystemTimeSource; import org.ehcache.core.spi.time.TimeSource; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.store.Store; import org.ehcache.impl.internal.util.UnmatchedResourceType; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; @@ -78,7 +78,7 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.config.units.MemoryUnit.MB; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration.DEFAULT_DISK_SEGMENTS; import static org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration.DEFAULT_WRITER_CONCURRENCY; import static org.ehcache.impl.internal.spi.TestServiceProvider.providerContaining; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java index 4070c9a0e8..9571656646 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java @@ -30,13 +30,13 @@ import org.ehcache.core.spi.time.TimeSource; import org.ehcache.internal.store.StoreFactory; import org.ehcache.internal.store.StoreSPITest; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.store.Store; import org.ehcache.spi.service.ServiceConfiguration; import org.junit.Before; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; public class ByteSizedOnHeapStoreByRefSPITest extends StoreSPITest { diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java index 60d60b1fc5..c24301182b 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java @@ -31,7 +31,7 @@ import org.ehcache.impl.serialization.JavaSerializer; import org.ehcache.internal.store.StoreFactory; import org.ehcache.internal.store.StoreSPITest; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.store.Store; import org.ehcache.spi.copy.Copier; import org.ehcache.spi.serialization.Serializer; @@ -40,7 +40,7 @@ import static java.lang.ClassLoader.getSystemClassLoader; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; public class ByteSizedOnHeapStoreByValueSPITest extends StoreSPITest { diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java index a8fe6c36a4..c1620bac17 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java @@ -30,13 +30,13 @@ import org.ehcache.core.spi.time.TimeSource; import org.ehcache.internal.store.StoreFactory; import org.ehcache.internal.store.StoreSPITest; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.store.Store; import org.ehcache.spi.service.ServiceConfiguration; import org.junit.Before; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; /** * Test the {@link org.ehcache.internal.store.heap.OnHeapStore} compliance to the diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java index 6e558ed30e..3bcb8a9f67 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java @@ -31,7 +31,7 @@ import org.ehcache.impl.serialization.JavaSerializer; import org.ehcache.internal.store.StoreFactory; import org.ehcache.internal.store.StoreSPITest; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.store.Store; import org.ehcache.spi.copy.Copier; import org.ehcache.spi.serialization.Serializer; @@ -40,7 +40,7 @@ import static java.lang.ClassLoader.getSystemClassLoader; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; /** * Test the {@link OnHeapStore} compliance to the diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java index ffac6f1dea..d9989fd90f 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java @@ -35,7 +35,7 @@ import org.junit.Before; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; /** * This factory instantiates a CachingTier diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java index f9539cb1f5..76fe3ef9b8 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java @@ -39,7 +39,7 @@ import static java.lang.ClassLoader.getSystemClassLoader; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; /** * This factory instantiates a CachingTier diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java index aa202e7c93..e24d67f1ae 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java @@ -38,7 +38,7 @@ import java.util.Arrays; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; public class OnHeapStoreCachingTierByRefSPITest extends CachingTierSPITest { diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java index aee64743f5..9f89556aa8 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java @@ -42,7 +42,7 @@ import static java.lang.ClassLoader.getSystemClassLoader; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; public class OnHeapStoreCachingTierByValueSPITest extends CachingTierSPITest { diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java index 5c93ac6fe9..dc87e2a901 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java @@ -31,7 +31,7 @@ import org.ehcache.internal.store.StoreFactory; import org.ehcache.internal.tier.AuthoritativeTierFactory; import org.ehcache.internal.tier.AuthoritativeTierSPITest; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; import org.ehcache.spi.serialization.Serializer; @@ -41,7 +41,7 @@ import java.util.Arrays; import static org.ehcache.config.ResourceType.Core.OFFHEAP; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; /** * OffHeapStoreSPITest diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java index 1be86824b6..2c29306be9 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java @@ -44,7 +44,7 @@ import static java.lang.ClassLoader.getSystemClassLoader; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; /** * This factory instantiates a CachingTier diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java index 848e30ad6f..e2a42c16f9 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java @@ -28,7 +28,7 @@ import org.ehcache.impl.persistence.DefaultDiskResourceService; import org.ehcache.impl.internal.store.disk.OffHeapDiskStore; import org.ehcache.impl.internal.store.heap.OnHeapStore; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.store.Store; import org.ehcache.impl.persistence.DefaultLocalPersistenceService; import org.ehcache.impl.serialization.JavaSerializer; @@ -43,7 +43,7 @@ import java.util.concurrent.TimeUnit; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.ehcache.test.MockitoUtil.mock; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java index a860c2968a..0e8a549373 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java @@ -44,7 +44,7 @@ import org.ehcache.impl.serialization.JavaSerializer; import org.ehcache.internal.store.StoreFactory; import org.ehcache.internal.store.StoreSPITest; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.spi.service.ServiceProvider; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; @@ -69,7 +69,7 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.config.units.MemoryUnit.MB; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration.DEFAULT_DISK_SEGMENTS; import static org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration.DEFAULT_WRITER_CONCURRENCY; import static org.ehcache.test.MockitoUtil.mock; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java index 4760526da8..cea579a1bc 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java @@ -20,7 +20,7 @@ import org.ehcache.config.ResourceType; import org.ehcache.config.SizedResourcePool; import org.ehcache.core.exceptions.StorePassThroughException; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.Store.RemoveStatus; @@ -59,7 +59,7 @@ import java.util.function.Function; import java.util.function.Supplier; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.Is.is; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java index f959636901..26f719e13c 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java @@ -47,7 +47,7 @@ import org.ehcache.impl.serialization.JavaSerializer; import org.ehcache.internal.store.StoreFactory; import org.ehcache.internal.store.StoreSPITest; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.spi.service.ServiceProvider; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; @@ -71,7 +71,7 @@ import java.util.concurrent.atomic.AtomicInteger; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration.DEFAULT_DISK_SEGMENTS; import static org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration.DEFAULT_WRITER_CONCURRENCY; import static org.ehcache.test.MockitoUtil.mock; diff --git a/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java b/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java index 0c094e5bb2..fcb7ca1645 100644 --- a/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java +++ b/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java @@ -29,7 +29,7 @@ import org.ehcache.impl.internal.sizeof.NoopSizeOfEngine; import org.ehcache.impl.internal.store.heap.OnHeapStore; import org.ehcache.core.spi.time.SystemTimeSource; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.spi.service.ServiceProvider; import org.ehcache.core.spi.store.Store; import org.ehcache.spi.copy.Copier; @@ -51,7 +51,7 @@ import java.util.function.Function; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsCollectionContaining.hasItems; diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java index 6218e7147e..1d3bde2bfd 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java @@ -18,15 +18,13 @@ import org.ehcache.Cache; import org.ehcache.config.EvictionAdvisor; -import org.ehcache.config.ResourcePool; -import org.ehcache.config.ResourceType; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.core.events.StoreEventDispatcher; -import org.ehcache.core.internal.service.ServiceLocator; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.store.Store; import org.ehcache.expiry.ExpiryPolicy; @@ -91,12 +89,11 @@ import static java.time.Duration.ofSeconds; import static java.util.Collections.emptySet; import static org.ehcache.config.builders.ExpiryPolicyBuilder.timeToLiveExpiration; -import static org.ehcache.core.internal.service.ServiceLocator.dependencySet; +import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; From 9318732dc918105f10e8aefda1b9ed2c6f234d3d Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 20 Sep 2018 14:19:49 -0400 Subject: [PATCH 057/372] Move resilience implementations to the impl module --- core/build.gradle | 2 -- .../ehcache/core/EhcacheBasicGetAllTest.java | 28 ++++++++++--------- .../core/EhcacheBasicIteratorTest.java | 22 ++++++--------- .../core/EhcacheBasicPutIfAbsentTest.java | 7 ++--- .../org/ehcache/core/EhcacheBasicPutTest.java | 6 +--- .../ehcache/core/EhcacheBasicRemoveTest.java | 7 +---- .../builders/UserManagedCacheBuilder.java | 4 +-- ...silienceStrategyProviderConfiguration.java | 5 ++-- .../AbstractResilienceStrategy.java | 4 +-- .../RobustLoaderWriterResilienceStrategy.java | 2 +- .../resilience/RobustResilienceStrategy.java | 9 ++---- .../DefaultResilienceStrategyProvider.java | 1 - .../ehcache/impl}/internal/util/Pacer.java | 2 +- .../CacheConfigurationBuilderTest.java | 2 +- ...ltResilienceStrategyConfigurationTest.java | 2 +- ...ustLoaderWriterResilienceStrategyTest.java | 28 +++++++++++-------- .../RobustResilienceStrategyTest.java | 10 ++++--- ...DefaultResilienceStrategyProviderTest.java | 2 +- .../impl}/internal/util/PacerTest.java | 2 +- 19 files changed, 67 insertions(+), 78 deletions(-) rename {core/src/main/java/org/ehcache/core => impl/src/main/java/org/ehcache/impl}/internal/resilience/AbstractResilienceStrategy.java (98%) rename {core/src/main/java/org/ehcache/core => impl/src/main/java/org/ehcache/impl}/internal/resilience/RobustLoaderWriterResilienceStrategy.java (99%) rename {core/src/main/java/org/ehcache/core => impl/src/main/java/org/ehcache/impl}/internal/resilience/RobustResilienceStrategy.java (93%) rename {core/src/main/java/org/ehcache/core => impl/src/main/java/org/ehcache/impl}/internal/util/Pacer.java (97%) rename {core/src/test/java/org/ehcache/core => impl/src/test/java/org/ehcache/impl}/internal/resilience/RobustLoaderWriterResilienceStrategyTest.java (94%) rename {core/src/test/java/org/ehcache/core => impl/src/test/java/org/ehcache/impl}/internal/resilience/RobustResilienceStrategyTest.java (92%) rename {core/src/test/java/org/ehcache/core => impl/src/test/java/org/ehcache/impl}/internal/util/PacerTest.java (97%) diff --git a/core/build.gradle b/core/build.gradle index 6998b42651..7c7ba1278c 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -29,10 +29,8 @@ jar { instruction 'Bundle-Activator', 'org.ehcache.core.osgi.EhcacheActivator' instruction 'Export-Package', 'org.ehcache.core.internal.events', - 'org.ehcache.core.internal.resilience', 'org.ehcache.core.internal.store', 'org.ehcache.core.internal.util', '!org.ehcache.core.internal.*', 'org.ehcache.core.*' - instruction 'Import-Package', '*' } } diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java index 31e686a994..6c163147ad 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java @@ -17,24 +17,31 @@ package org.ehcache.core; import org.ehcache.Status; -import org.ehcache.core.internal.resilience.RobustResilienceStrategy; +import org.ehcache.core.internal.util.CollectionUtil; import org.ehcache.core.resilience.DefaultRecoveryStore; import org.ehcache.core.spi.store.Store; import org.ehcache.core.statistics.CacheOperationOutcomes; import org.ehcache.core.statistics.BulkOps; +import org.ehcache.spi.resilience.ResilienceStrategy; import org.ehcache.spi.resilience.StoreAccessException; import org.hamcrest.Matchers; import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.EnumSet; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.LongAdder; import java.util.function.Function; +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.toMap; +import static java.util.stream.StreamSupport.stream; import static org.ehcache.core.EhcacheBasicBulkUtil.KEY_SET_A; import static org.ehcache.core.EhcacheBasicBulkUtil.KEY_SET_B; import static org.ehcache.core.EhcacheBasicBulkUtil.KEY_SET_C; @@ -50,10 +57,12 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; /** * Provides testing of basic GET_ALL operations on an {@code Ehcache}. @@ -163,9 +172,7 @@ public void testGetAllStoreAllMatchStoreAccessExceptionBeforeNoLoader() throws E final Ehcache ehcache = this.getEhcache(); final Set fetchKeys = fanIn(KEY_SET_A, KEY_SET_B); - final Map actual = ehcache.getAll(fetchKeys); - - assertThat(actual, equalTo(getNullEntryMap(fetchKeys))); + ehcache.getAll(fetchKeys); verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction()); // ResilienceStrategy invoked: no assertion for Store content @@ -223,13 +230,11 @@ public void testGetAllStoreNoMatchStoreAccessExceptionBeforeNoLoader() throws Ex final Ehcache ehcache = this.getEhcache(); - final Map actual = ehcache.getAll(KEY_SET_A); - assertThat(actual, equalTo(getNullEntryMap(KEY_SET_A))); + ehcache.getAll(KEY_SET_A); verify(this.store).bulkComputeIfAbsent(eq(KEY_SET_A), getAnyIterableFunction()); // ResilienceStrategy invoked: no assertion for Store content - verify(this.resilienceStrategy) - .getAllFailure(eq(KEY_SET_A), any(StoreAccessException.class)); + verify(this.resilienceStrategy).getAllFailure(eq(KEY_SET_A), any(StoreAccessException.class)); validateStatsNoneof(ehcache); validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE)); @@ -285,9 +290,7 @@ public void testGetAllStoreSomeMatchStoreAccessExceptionBeforeNoLoader() throws final Ehcache ehcache = this.getEhcache(); final Set fetchKeys = fanIn(KEY_SET_A, KEY_SET_C); - final Map actual = ehcache.getAll(fetchKeys); - - assertThat(actual, equalTo(getNullEntryMap(fetchKeys))); + ehcache.getAll(fetchKeys); verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction()); // ResilienceStrategy invoked: no assertion for Store content @@ -307,8 +310,8 @@ private void validateStatsNoneof(Ehcache cache) { * * @return a new {@code Ehcache} instance */ + @SuppressWarnings("unchecked") private Ehcache getEhcache() { - this.resilienceStrategy = spy(new RobustResilienceStrategy<>(new DefaultRecoveryStore<>(this.store))); final Ehcache ehcache = new Ehcache<>(CACHE_CONFIGURATION, this.store, resilienceStrategy, cacheEventDispatcher, LoggerFactory .getLogger(Ehcache.class + "-" + "EhcacheBasicGetAllTest")); ehcache.init(); @@ -344,5 +347,4 @@ static Set getAnyStringSet() { static Function, Iterable>> getAnyIterableFunction() { return any(Function.class); // unchecked } - } diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicIteratorTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicIteratorTest.java index 056df6e28d..627864f345 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicIteratorTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicIteratorTest.java @@ -18,9 +18,6 @@ import org.ehcache.Cache; import org.ehcache.Status; -import org.ehcache.CacheIterationException; -import org.ehcache.core.internal.resilience.RobustResilienceStrategy; -import org.ehcache.core.resilience.DefaultRecoveryStore; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.Store.RemoveStatus; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; @@ -44,7 +41,10 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; /** * Provides testing of basic ITERATOR operations on an {@code Ehcache}. @@ -228,20 +228,16 @@ public void testIteratorStoreAccessException() throws Exception { final Iterator> iterator = ehcache.iterator(); assertThat(iterator, is(notNullValue())); assertThat(iterator.hasNext(), is(true)); - doThrow(new StoreAccessException("")).when(storeIterator).next(); + StoreAccessException exception = new StoreAccessException(""); + doThrow(exception).when(storeIterator).next(); Cache.Entry entry = iterator.next(); assertThat(entry.getKey(), is("foo")); assertThat(entry.getValue(), is("bar")); - doThrow(new StoreAccessException("")).when(storeIterator).next(); doReturn(RemoveStatus.REMOVED).when(this.store).remove(anyString(), anyString()); - try { - iterator.next(); - fail(); - } catch (CacheIterationException e) { - // Expected - } + iterator.next(); + verify(resilienceStrategy).iteratorFailure(exception); assertThat(iterator.hasNext(), is(false)); @@ -281,8 +277,8 @@ protected Map getTestStoreEntries() { * * @return a new {@code Ehcache} instance */ + @SuppressWarnings("unchecked") protected InternalCache getEhcache() throws Exception { - this.resilienceStrategy = spy(new RobustResilienceStrategy<>(new DefaultRecoveryStore<>(this.store))); final Ehcache ehcache = new Ehcache<>(CACHE_CONFIGURATION, this.store, resilienceStrategy, cacheEventDispatcher, LoggerFactory .getLogger(Ehcache.class + "-" + "EhcacheBasicIteratorTest")); ehcache.init(); diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java index 338ec5d166..c1f4d97bb7 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java @@ -36,7 +36,6 @@ import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -141,8 +140,7 @@ public void testPutIfAbsentNoStoreEntryStoreAccessException() throws Exception { ehcache.putIfAbsent("key", "value"); verify(this.store).putIfAbsent(eq("key"), eq("value"), any()); - verify(this.resilienceStrategy) - .putIfAbsentFailure(eq("key"), eq("value"), any(StoreAccessException.class)); + verify(this.resilienceStrategy).putIfAbsentFailure(eq("key"), eq("value"), any(StoreAccessException.class)); validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.PutIfAbsentOutcome.FAILURE)); } @@ -163,8 +161,7 @@ public void testPutIfAbsentHasStoreEntryStoreAccessException() throws Exception ehcache.putIfAbsent("key", "value"); verify(this.store).putIfAbsent(eq("key"), eq("value"), any()); - verify(this.resilienceStrategy) - .putIfAbsentFailure(eq("key"), eq("value"), any(StoreAccessException.class)); + verify(this.resilienceStrategy).putIfAbsentFailure(eq("key"), eq("value"), any(StoreAccessException.class)); validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.PutIfAbsentOutcome.FAILURE)); } diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicPutTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicPutTest.java index bdbb49a4fc..24142a3fdd 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicPutTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicPutTest.java @@ -20,8 +20,6 @@ import org.ehcache.Status; import org.ehcache.config.CacheConfiguration; -import org.ehcache.core.internal.resilience.RobustResilienceStrategy; -import org.ehcache.core.resilience.DefaultRecoveryStore; import org.ehcache.core.statistics.CacheOperationOutcomes; import org.ehcache.spi.resilience.StoreAccessException; import org.hamcrest.CoreMatchers; @@ -29,7 +27,6 @@ import org.slf4j.LoggerFactory; import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; @@ -161,7 +158,6 @@ public void testPutHasStoreEntryStoreAccessException() throws Exception { ehcache.put("key", "value"); verify(this.store).put(eq("key"), eq("value")); verify(this.resilienceStrategy).putFailure(eq("key"), eq("value"), any(StoreAccessException.class)); - assertThat(fakeStore.getEntryMap().containsKey("key"), is(false)); validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.PutOutcome.FAILURE)); } @@ -205,8 +201,8 @@ private Ehcache getEhcache() { return getEhcache(CACHE_CONFIGURATION); } + @SuppressWarnings("unchecked") private Ehcache getEhcache(CacheConfiguration config) { - this.resilienceStrategy = spy(new RobustResilienceStrategy<>(new DefaultRecoveryStore<>(this.store))); final Ehcache ehcache = new Ehcache<>(config, this.store, resilienceStrategy, cacheEventDispatcher, LoggerFactory.getLogger(Ehcache.class + "-" + "EhcacheBasicPutTest")); ehcache.init(); assertThat("cache not initialized", ehcache.getStatus(), CoreMatchers.is(Status.AVAILABLE)); diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveTest.java index 5f37f8b950..a7fb480665 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveTest.java @@ -19,8 +19,6 @@ import java.util.EnumSet; import org.ehcache.Status; -import org.ehcache.core.internal.resilience.RobustResilienceStrategy; -import org.ehcache.core.resilience.DefaultRecoveryStore; import org.ehcache.core.statistics.CacheOperationOutcomes; import org.ehcache.spi.resilience.StoreAccessException; import org.hamcrest.CoreMatchers; @@ -35,7 +33,6 @@ import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verifyZeroInteractions; /** @@ -92,7 +89,6 @@ public void testRemoveNoStoreEntryStoreAccessException() throws Exception { final Ehcache ehcache = this.getEhcache(); ehcache.remove("key"); - verify(this.store, times(2)).remove(eq("key")); verify(this.resilienceStrategy).removeFailure(eq("key"), any(StoreAccessException.class)); validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.RemoveOutcome.FAILURE)); } @@ -134,7 +130,6 @@ public void testRemoveHasStoreEntryStoreAccessException() throws Exception { final Ehcache ehcache = this.getEhcache(); ehcache.remove("key"); - verify(this.store, times(2)).remove(eq("key")); verify(this.resilienceStrategy).removeFailure(eq("key"), any(StoreAccessException.class)); validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.RemoveOutcome.FAILURE)); } @@ -144,8 +139,8 @@ public void testRemoveHasStoreEntryStoreAccessException() throws Exception { * * @return a new {@code Ehcache} instance */ + @SuppressWarnings("unchecked") private Ehcache getEhcache() { - this.resilienceStrategy = spy(new RobustResilienceStrategy<>(new DefaultRecoveryStore<>(this.store))); final Ehcache ehcache = new Ehcache<>(CACHE_CONFIGURATION, this.store, resilienceStrategy, cacheEventDispatcher, LoggerFactory .getLogger(Ehcache.class + "-" + "EhcacheBasicRemoveTest")); ehcache.init(); diff --git a/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java b/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java index bf80f5afa7..7fe975c2d1 100644 --- a/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java @@ -39,8 +39,6 @@ import org.ehcache.core.internal.store.StoreSupport; import org.ehcache.core.internal.util.ClassLoading; import org.ehcache.core.resilience.DefaultRecoveryStore; -import org.ehcache.core.internal.resilience.RobustLoaderWriterResilienceStrategy; -import org.ehcache.core.internal.resilience.RobustResilienceStrategy; import org.ehcache.core.spi.LifeCycled; import org.ehcache.core.spi.LifeCycledAdapter; import org.ehcache.core.spi.service.DiskResourceService; @@ -56,6 +54,8 @@ import org.ehcache.impl.copy.SerializingCopier; import org.ehcache.impl.events.CacheEventDispatcherImpl; import org.ehcache.impl.internal.events.DisabledCacheEventNotificationService; +import org.ehcache.impl.internal.resilience.RobustLoaderWriterResilienceStrategy; +import org.ehcache.impl.internal.resilience.RobustResilienceStrategy; import org.ehcache.impl.internal.spi.event.DefaultCacheEventListenerProvider; import org.ehcache.spi.copy.Copier; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; diff --git a/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java index 11188620db..2055759d8a 100644 --- a/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java @@ -15,9 +15,10 @@ */ package org.ehcache.impl.config.resilience; -import org.ehcache.core.internal.resilience.RobustLoaderWriterResilienceStrategy; -import org.ehcache.core.internal.resilience.RobustResilienceStrategy; import org.ehcache.impl.internal.classes.ClassInstanceProviderConfiguration; +import org.ehcache.impl.internal.resilience.RobustLoaderWriterResilienceStrategy; +import org.ehcache.impl.internal.resilience.RobustResilienceStrategy; +import org.ehcache.impl.internal.spi.resilience.DefaultResilienceStrategyProvider; import org.ehcache.spi.resilience.ResilienceStrategy; import org.ehcache.spi.resilience.ResilienceStrategyProvider; import org.ehcache.spi.service.ServiceCreationConfiguration; diff --git a/core/src/main/java/org/ehcache/core/internal/resilience/AbstractResilienceStrategy.java b/impl/src/main/java/org/ehcache/impl/internal/resilience/AbstractResilienceStrategy.java similarity index 98% rename from core/src/main/java/org/ehcache/core/internal/resilience/AbstractResilienceStrategy.java rename to impl/src/main/java/org/ehcache/impl/internal/resilience/AbstractResilienceStrategy.java index 60ac37f9cc..614e98fe71 100644 --- a/core/src/main/java/org/ehcache/core/internal/resilience/AbstractResilienceStrategy.java +++ b/impl/src/main/java/org/ehcache/impl/internal/resilience/AbstractResilienceStrategy.java @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.internal.resilience; +package org.ehcache.impl.internal.resilience; import org.ehcache.Cache; import org.ehcache.CacheIterationException; -import org.ehcache.core.internal.util.Pacer; +import org.ehcache.impl.internal.util.Pacer; import org.ehcache.core.spi.time.SystemTimeSource; import org.ehcache.spi.resilience.RecoveryStore; import org.ehcache.spi.resilience.ResilienceStrategy; diff --git a/core/src/main/java/org/ehcache/core/internal/resilience/RobustLoaderWriterResilienceStrategy.java b/impl/src/main/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategy.java similarity index 99% rename from core/src/main/java/org/ehcache/core/internal/resilience/RobustLoaderWriterResilienceStrategy.java rename to impl/src/main/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategy.java index 114149fb32..7f018f7d82 100644 --- a/core/src/main/java/org/ehcache/core/internal/resilience/RobustLoaderWriterResilienceStrategy.java +++ b/impl/src/main/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategy.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.internal.resilience; +package org.ehcache.impl.internal.resilience; import org.ehcache.core.exceptions.ExceptionFactory; import org.ehcache.spi.loaderwriter.BulkCacheLoadingException; diff --git a/core/src/main/java/org/ehcache/core/internal/resilience/RobustResilienceStrategy.java b/impl/src/main/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategy.java similarity index 93% rename from core/src/main/java/org/ehcache/core/internal/resilience/RobustResilienceStrategy.java rename to impl/src/main/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategy.java index 553864999d..3ec5cb8bbb 100644 --- a/core/src/main/java/org/ehcache/core/internal/resilience/RobustResilienceStrategy.java +++ b/impl/src/main/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategy.java @@ -13,16 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.internal.resilience; +package org.ehcache.impl.internal.resilience; -import org.ehcache.core.internal.util.CollectionUtil; -import org.ehcache.core.spi.store.Store; import org.ehcache.spi.resilience.RecoveryStore; import org.ehcache.spi.resilience.StoreAccessException; +import java.util.Collection; import java.util.HashMap; import java.util.Map; -import java.util.Objects; /** * Default resilience strategy used by a {@link org.ehcache.Cache} without {@link org.ehcache.spi.loaderwriter.CacheLoaderWriter}. @@ -173,8 +171,7 @@ public boolean replaceFailure(K key, V value, V newValue, StoreAccessException e public Map getAllFailure(Iterable keys, StoreAccessException e) { cleanup(keys, e); - int size = CollectionUtil.findBestCollectionSize(keys, 16); // 16 is the HashMap default - HashMap result = new HashMap<>(size); + HashMap result = keys instanceof Collection ? new HashMap<>(((Collection) keys).size()) : new HashMap<>(); for (K key : keys) { result.put(key, null); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProvider.java b/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProvider.java index 956a99b755..00c9697634 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProvider.java @@ -18,7 +18,6 @@ import org.ehcache.config.CacheConfiguration; import org.ehcache.impl.config.resilience.DefaultResilienceStrategyConfiguration; import org.ehcache.impl.config.resilience.DefaultResilienceStrategyProviderConfiguration; -import org.ehcache.impl.internal.classes.ClassInstanceConfiguration; import org.ehcache.impl.internal.classes.ClassInstanceProvider; import org.ehcache.impl.internal.classes.ClassInstanceProviderConfiguration; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; diff --git a/core/src/main/java/org/ehcache/core/internal/util/Pacer.java b/impl/src/main/java/org/ehcache/impl/internal/util/Pacer.java similarity index 97% rename from core/src/main/java/org/ehcache/core/internal/util/Pacer.java rename to impl/src/main/java/org/ehcache/impl/internal/util/Pacer.java index 36f91686a1..5f49bf05ae 100644 --- a/core/src/main/java/org/ehcache/core/internal/util/Pacer.java +++ b/impl/src/main/java/org/ehcache/impl/internal/util/Pacer.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.internal.util; +package org.ehcache.impl.internal.util; import org.ehcache.core.spi.time.TimeSource; diff --git a/impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java b/impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java index 149020b7b1..866f64d017 100644 --- a/impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java +++ b/impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java @@ -19,7 +19,6 @@ import org.ehcache.config.*; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.internal.resilience.RobustResilienceStrategy; import org.ehcache.core.spi.service.ServiceUtils; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.config.copy.DefaultCopierConfiguration; @@ -28,6 +27,7 @@ import org.ehcache.impl.config.serializer.DefaultSerializerConfiguration; import org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration; import org.ehcache.impl.internal.classes.ClassInstanceConfiguration; +import org.ehcache.impl.internal.resilience.RobustResilienceStrategy; import org.ehcache.spi.copy.Copier; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.loaderwriter.CacheLoaderWriterConfiguration; diff --git a/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java index 0e8cccb7ef..142b7b5116 100644 --- a/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java @@ -15,7 +15,7 @@ */ package org.ehcache.impl.config.resilience; -import org.ehcache.core.internal.resilience.RobustResilienceStrategy; +import org.ehcache.impl.internal.resilience.RobustResilienceStrategy; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.resilience.RecoveryStore; import org.ehcache.spi.resilience.ResilienceStrategy; diff --git a/core/src/test/java/org/ehcache/core/internal/resilience/RobustLoaderWriterResilienceStrategyTest.java b/impl/src/test/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategyTest.java similarity index 94% rename from core/src/test/java/org/ehcache/core/internal/resilience/RobustLoaderWriterResilienceStrategyTest.java rename to impl/src/test/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategyTest.java index 8561840778..e9505f007a 100644 --- a/core/src/test/java/org/ehcache/core/internal/resilience/RobustLoaderWriterResilienceStrategyTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategyTest.java @@ -13,11 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.internal.resilience; +package org.ehcache.impl.internal.resilience; import org.assertj.core.data.MapEntry; -import org.ehcache.core.internal.util.CollectionUtil; -import org.ehcache.core.spi.store.Store; import org.ehcache.spi.loaderwriter.BulkCacheLoadingException; import org.ehcache.spi.loaderwriter.BulkCacheWritingException; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; @@ -37,9 +35,15 @@ import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collector; +import static java.util.Collections.singletonMap; +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.toMap; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.doNothing; @@ -68,10 +72,10 @@ public class RobustLoaderWriterResilienceStrategyTest { private final Exception exception = new Exception("failed"); private final BulkCacheLoadingException bulkLoadingException = new BulkCacheLoadingException( - CollectionUtil.map(1, exception), CollectionUtil.map(2, 2L)); + singletonMap(1, exception), singletonMap(2, 2L)); private final BulkCacheWritingException bulkWritingException = new BulkCacheWritingException( - CollectionUtil.map(1, exception), Collections.singleton(2)); + singletonMap(1, exception), Collections.singleton(2)); @After public void noMoreInteractions() { @@ -360,7 +364,8 @@ public void replaceFailure1_writeFails() throws Exception { @Test public void getAllFailure_nothingFound() throws Exception { List keys = Arrays.asList(1, 2); - Map entries = CollectionUtil.map(1, null, 2, null); + Map entries = new HashMap<>(); + keys.forEach(k -> entries.put(k, null)); when(loaderWriter.loadAll(keys)).thenReturn(entries); @@ -376,7 +381,7 @@ public void getAllFailure_nothingFound() throws Exception { @Test public void getAllFailure_allFound() throws Exception { List keys = Arrays.asList(1, 2); - Map entries = CollectionUtil.map(1, 1L, 2, 2L); + Map entries = keys.stream().collect(toMap(identity(), k -> (long) k)); when(loaderWriter.loadAll(keys)).thenReturn(entries); @@ -392,7 +397,8 @@ public void getAllFailure_allFound() throws Exception { @Test public void getAllFailure_partialFound() throws Exception { List keys = Arrays.asList(1, 2); - Map entries = CollectionUtil.map(1, 1L, 2, null); + Map entries = new HashMap<>(); + keys.forEach(k -> entries.put(k, k == 2 ? null : (long) k)); when(loaderWriter.loadAll(keys)).thenReturn(entries); @@ -441,7 +447,7 @@ public void getAllFailure_loadFailsWithBulkException() throws Exception { @Test public void putAllFailure() throws Exception { List> entryList = Arrays.asList(entry(1, 1L), entry(2, 2L)); - Map entryMap = CollectionUtil.map(1, 1L, 2, 2L); + Map entryMap = entryList.stream().collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); doNothing().when(loaderWriter).writeAll(argThat(containsAllMatcher(entryList))); @@ -457,7 +463,7 @@ public void putAllFailure() throws Exception { @Test public void putAllFailure_writeAllFailsWithException() throws Exception { List> entryList = Arrays.asList(entry(1, 1L), entry(2, 2L)); - Map entryMap = CollectionUtil.map(1, 1L, 2, 2L); + Map entryMap = entryList.stream().collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); doThrow(exception).when(loaderWriter).writeAll(argThat(containsAllMatcher(entryList))); @@ -475,7 +481,7 @@ public void putAllFailure_writeAllFailsWithException() throws Exception { @Test public void putAllFailure_writeAllFailsWithBulkException() throws Exception { List> entryList = Arrays.asList(entry(1, 1L), entry(2, 2L)); - Map entryMap = CollectionUtil.map(1, 1L, 2, 2L); + Map entryMap = entryList.stream().collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); doThrow(bulkWritingException).when(loaderWriter).writeAll(argThat(containsAllMatcher(entryList))); diff --git a/core/src/test/java/org/ehcache/core/internal/resilience/RobustResilienceStrategyTest.java b/impl/src/test/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategyTest.java similarity index 92% rename from core/src/test/java/org/ehcache/core/internal/resilience/RobustResilienceStrategyTest.java rename to impl/src/test/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategyTest.java index 06d43fcc87..8c76a68850 100644 --- a/core/src/test/java/org/ehcache/core/internal/resilience/RobustResilienceStrategyTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategyTest.java @@ -13,10 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.internal.resilience; +package org.ehcache.impl.internal.resilience; -import org.ehcache.core.internal.util.CollectionUtil; -import org.ehcache.core.spi.store.Store; import org.ehcache.spi.resilience.RecoveryStore; import org.ehcache.spi.resilience.StoreAccessException; import org.junit.After; @@ -31,6 +29,10 @@ import java.util.Arrays; import static java.util.Arrays.asList; +import static java.util.Arrays.stream; +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.toMap; +import static java.util.stream.Stream.of; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -118,7 +120,7 @@ public void getAllFailure() throws StoreAccessException { @Test public void putAllFailure() throws StoreAccessException { - strategy.putAllFailure(CollectionUtil.map(1, 2L, 2, 2L), accessException); + strategy.putAllFailure(of(1, 2).collect(toMap(identity(), k -> (long) k)), accessException); @SuppressWarnings("unchecked") ArgumentCaptor> captor = ArgumentCaptor.forClass(Iterable.class); verify(store).obliterate(captor.capture()); diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderTest.java index ecd3a7eef7..4c27ba13ea 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderTest.java @@ -16,9 +16,9 @@ package org.ehcache.impl.internal.spi.resilience; import org.ehcache.config.CacheConfiguration; -import org.ehcache.core.internal.resilience.RobustResilienceStrategy; import org.ehcache.impl.config.resilience.DefaultResilienceStrategyConfiguration; import org.ehcache.impl.config.resilience.DefaultResilienceStrategyProviderConfiguration; +import org.ehcache.impl.internal.resilience.RobustResilienceStrategy; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.resilience.RecoveryStore; import org.ehcache.spi.resilience.ResilienceStrategy; diff --git a/core/src/test/java/org/ehcache/core/internal/util/PacerTest.java b/impl/src/test/java/org/ehcache/impl/internal/util/PacerTest.java similarity index 97% rename from core/src/test/java/org/ehcache/core/internal/util/PacerTest.java rename to impl/src/test/java/org/ehcache/impl/internal/util/PacerTest.java index f026db6bd0..9ee33cd86e 100644 --- a/core/src/test/java/org/ehcache/core/internal/util/PacerTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/util/PacerTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.internal.util; +package org.ehcache.impl.internal.util; import org.ehcache.core.spi.time.TimeSource; import org.junit.Before; From aa7d0668f0157133d45b1d1b163ed50042cccbf8 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 20 Sep 2018 14:57:29 -0400 Subject: [PATCH 058/372] Move ClassLoading to an exported package --- .../java/org/ehcache/jsr107/EhcacheCachingProvider.java | 2 +- .../ehcache/clustered/client/NonClusteredCacheTest.java | 2 +- ...steringCacheManagerServiceConfigurationParserTest.java | 2 +- .../internal/service/ClusteringServiceFactoryTest.java | 2 +- core/src/main/java/org/ehcache/core/EhcacheManager.java | 2 +- .../org/ehcache/core/config/DefaultConfiguration.java | 2 +- .../main/java/org/ehcache/core/spi/ServiceLocator.java | 8 ++++---- .../ehcache/core/{internal => }/util/ClassLoading.java | 2 +- .../test/java/org/ehcache/core/EhcacheManagerTest.java | 2 +- .../core/{internal => }/util/ClassLoadingTest.java | 2 +- .../ehcache/config/builders/UserManagedCacheBuilder.java | 2 +- .../ehcache/management/providers/ExposedCacheBinding.java | 2 +- .../xml/TxCacheManagerServiceConfigurationParser.java | 2 +- .../java/org/ehcache/transactions/NonXACacheTest.java | 2 +- .../main/java/org/ehcache/xml/ConfigurationParser.java | 4 ++-- xml/src/main/java/org/ehcache/xml/XmlConfiguration.java | 2 +- .../test/java/org/ehcache/xml/XmlConfigurationTest.java | 2 +- .../service/DefaultSerializerConfigurationParserTest.java | 2 +- 18 files changed, 22 insertions(+), 22 deletions(-) rename core/src/main/java/org/ehcache/core/{internal => }/util/ClassLoading.java (98%) rename core/src/test/java/org/ehcache/core/{internal => }/util/ClassLoadingTest.java (99%) diff --git a/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java b/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java index 5795b7f143..59e7a27bb0 100644 --- a/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java +++ b/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java @@ -18,8 +18,8 @@ import org.ehcache.config.Configuration; import org.ehcache.core.EhcacheManager; import org.ehcache.core.config.DefaultConfiguration; -import org.ehcache.core.internal.util.ClassLoading; import org.ehcache.core.spi.service.ServiceUtils; +import org.ehcache.core.util.ClassLoading; import org.ehcache.impl.config.serializer.DefaultSerializationProviderConfiguration; import org.ehcache.jsr107.config.Jsr107Configuration; import org.ehcache.jsr107.internal.DefaultJsr107Service; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java index e72b29449c..4f7df21b3c 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java @@ -25,8 +25,8 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.internal.util.ClassLoading; import org.ehcache.core.spi.service.ServiceFactory; +import org.ehcache.core.util.ClassLoading; import org.junit.Test; import java.util.stream.Collectors; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java index 337056d3e5..4a786e4995 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java @@ -22,8 +22,8 @@ import org.ehcache.clustered.client.internal.ConnectionSource; import org.ehcache.config.Configuration; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.internal.util.ClassLoading; import org.ehcache.core.spi.service.ServiceUtils; +import org.ehcache.core.util.ClassLoading; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.xml.CacheManagerServiceConfigurationParser; import org.ehcache.xml.XmlConfiguration; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java index 443b48f127..0f6f5a2dc7 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java @@ -17,7 +17,7 @@ package org.ehcache.clustered.client.internal.service; import org.ehcache.core.spi.service.ServiceFactory; -import org.ehcache.core.internal.util.ClassLoading; +import org.ehcache.core.util.ClassLoading; import org.junit.Test; import java.util.stream.Collectors; diff --git a/core/src/main/java/org/ehcache/core/EhcacheManager.java b/core/src/main/java/org/ehcache/core/EhcacheManager.java index 6679ce1584..8c5a8c8898 100644 --- a/core/src/main/java/org/ehcache/core/EhcacheManager.java +++ b/core/src/main/java/org/ehcache/core/EhcacheManager.java @@ -34,7 +34,6 @@ import org.ehcache.core.events.CacheEventListenerConfiguration; import org.ehcache.core.events.CacheEventListenerProvider; import org.ehcache.core.events.CacheManagerListener; -import org.ehcache.core.internal.util.ClassLoading; import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.core.internal.store.StoreSupport; @@ -45,6 +44,7 @@ import org.ehcache.core.spi.service.ServiceUtils; import org.ehcache.core.spi.store.InternalCacheManager; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.util.ClassLoading; import org.ehcache.event.CacheEventListener; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.loaderwriter.CacheLoaderWriterConfiguration; diff --git a/core/src/main/java/org/ehcache/core/config/DefaultConfiguration.java b/core/src/main/java/org/ehcache/core/config/DefaultConfiguration.java index 408637fc57..fe7d4821d8 100644 --- a/core/src/main/java/org/ehcache/core/config/DefaultConfiguration.java +++ b/core/src/main/java/org/ehcache/core/config/DefaultConfiguration.java @@ -27,7 +27,7 @@ import org.ehcache.config.CacheRuntimeConfiguration; import org.ehcache.config.Configuration; import org.ehcache.core.HumanReadable; -import org.ehcache.core.internal.util.ClassLoading; +import org.ehcache.core.util.ClassLoading; import org.ehcache.spi.service.ServiceCreationConfiguration; import static java.util.Collections.unmodifiableCollection; diff --git a/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java b/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java index 92b43c93e2..875340fa41 100644 --- a/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java +++ b/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java @@ -25,7 +25,6 @@ import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.core.spi.service.ServiceFactory; -import org.ehcache.core.internal.util.ClassLoading; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,8 +55,9 @@ import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toList; import static java.util.stream.StreamSupport.stream; -import static org.ehcache.core.internal.util.ClassLoading.delegationChain; -import static org.ehcache.core.internal.util.ClassLoading.getDefaultClassLoader; +import static org.ehcache.core.util.ClassLoading.delegationChain; +import static org.ehcache.core.util.ClassLoading.getDefaultClassLoader; +import static org.ehcache.core.util.ClassLoading.servicesOfType; /** * Provides discovery and tracking services for {@link Service} implementations. @@ -231,7 +231,7 @@ private boolean hasRunningDependents(Service service, Iterable running) public static class DependencySet implements Builder { @SuppressWarnings({"rawtypes", "unchecked"}) - private final Iterable> serviceFactories = (Iterable) ClassLoading.servicesOfType(ServiceFactory.class); + private final Iterable> serviceFactories = (Iterable) servicesOfType(ServiceFactory.class); private final ServiceMap provided = new ServiceMap(); private final Set> requested = new HashSet<>(); diff --git a/core/src/main/java/org/ehcache/core/internal/util/ClassLoading.java b/core/src/main/java/org/ehcache/core/util/ClassLoading.java similarity index 98% rename from core/src/main/java/org/ehcache/core/internal/util/ClassLoading.java rename to core/src/main/java/org/ehcache/core/util/ClassLoading.java index 144aef780a..a17a34d901 100644 --- a/core/src/main/java/org/ehcache/core/internal/util/ClassLoading.java +++ b/core/src/main/java/org/ehcache/core/util/ClassLoading.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.internal.util; +package org.ehcache.core.util; import org.ehcache.core.osgi.SafeOsgi; import org.ehcache.core.osgi.OsgiServiceLoader; diff --git a/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java b/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java index 1ab41843ac..bbc0abfb67 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java @@ -34,9 +34,9 @@ import org.ehcache.core.events.CacheEventDispatcherFactory; import org.ehcache.core.events.CacheEventListenerProvider; import org.ehcache.core.events.CacheManagerListener; -import org.ehcache.core.internal.util.ClassLoading; import org.ehcache.core.spi.service.LocalPersistenceService; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.util.ClassLoading; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.loaderwriter.CacheLoaderWriterProvider; import org.ehcache.spi.loaderwriter.WriteBehindProvider; diff --git a/core/src/test/java/org/ehcache/core/internal/util/ClassLoadingTest.java b/core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java similarity index 99% rename from core/src/test/java/org/ehcache/core/internal/util/ClassLoadingTest.java rename to core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java index c482135de9..94370a415d 100644 --- a/core/src/test/java/org/ehcache/core/internal/util/ClassLoadingTest.java +++ b/core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.internal.util; +package org.ehcache.core.util; import static java.util.Collections.list; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; diff --git a/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java b/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java index 7fe975c2d1..b5f612ed04 100644 --- a/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java @@ -37,7 +37,6 @@ import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.core.internal.store.StoreSupport; -import org.ehcache.core.internal.util.ClassLoading; import org.ehcache.core.resilience.DefaultRecoveryStore; import org.ehcache.core.spi.LifeCycled; import org.ehcache.core.spi.LifeCycledAdapter; @@ -45,6 +44,7 @@ import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.heap.SizeOfEngine; import org.ehcache.core.spi.store.heap.SizeOfEngineProvider; +import org.ehcache.core.util.ClassLoading; import org.ehcache.event.CacheEventListener; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.config.copy.DefaultCopierConfiguration; diff --git a/management/src/main/java/org/ehcache/management/providers/ExposedCacheBinding.java b/management/src/main/java/org/ehcache/management/providers/ExposedCacheBinding.java index 1ab7966668..e43cdcdce5 100644 --- a/management/src/main/java/org/ehcache/management/providers/ExposedCacheBinding.java +++ b/management/src/main/java/org/ehcache/management/providers/ExposedCacheBinding.java @@ -15,7 +15,7 @@ */ package org.ehcache.management.providers; -import org.ehcache.core.internal.util.ClassLoading; +import org.ehcache.core.util.ClassLoading; import org.ehcache.management.ManagementRegistryServiceConfiguration; import org.terracotta.management.model.capabilities.descriptors.Descriptor; import org.terracotta.management.model.context.Context; diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java index 28f8133eaa..ea23eefe81 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java @@ -34,8 +34,8 @@ import java.net.URI; import java.net.URL; -import static org.ehcache.core.internal.util.ClassLoading.delegationChain; import static org.ehcache.core.internal.util.TypeUtil.uncheckedCast; +import static org.ehcache.core.util.ClassLoading.delegationChain; /** * @author Ludovic Orban diff --git a/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java b/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java index e7cc9f62a4..2c07e5f62d 100644 --- a/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java @@ -23,8 +23,8 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.internal.util.ClassLoading; import org.ehcache.core.spi.service.ServiceFactory; +import org.ehcache.core.util.ClassLoading; import org.ehcache.transactions.xa.internal.XAStore; import org.ehcache.transactions.xa.txmgr.provider.TransactionManagerProvider; import org.junit.Test; diff --git a/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java index d2bad1584f..c68f1eb6e3 100644 --- a/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java @@ -21,6 +21,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.ConfigurationBuilder; +import org.ehcache.core.util.ClassLoading; import org.ehcache.xml.exceptions.XmlConfigurationException; import org.ehcache.xml.model.BaseCacheType; import org.ehcache.xml.model.CacheDefinition; @@ -29,7 +30,6 @@ import org.ehcache.xml.model.CacheTemplateType; import org.ehcache.xml.model.CacheType; import org.ehcache.xml.model.ConfigType; -import org.ehcache.core.internal.util.ClassLoading; import org.ehcache.xml.model.ObjectFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -92,7 +92,7 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ConfigurationBuilder.newConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.util.ClassLoading.servicesOfType; +import static org.ehcache.core.util.ClassLoading.servicesOfType; import static org.ehcache.xml.XmlConfiguration.CORE_SCHEMA_URL; import static org.ehcache.xml.XmlConfiguration.getClassForName; diff --git a/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java b/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java index 3a35552477..ac99366163 100644 --- a/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java +++ b/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java @@ -21,7 +21,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.Builder; import org.ehcache.config.builders.CacheConfigurationBuilder; -import org.ehcache.core.internal.util.ClassLoading; +import org.ehcache.core.util.ClassLoading; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.xml.exceptions.XmlConfigurationException; import org.w3c.dom.Document; diff --git a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java index 5a64851b52..1cfba1940f 100644 --- a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java @@ -23,7 +23,7 @@ import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.internal.util.ClassLoading; +import org.ehcache.core.util.ClassLoading; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.config.copy.DefaultCopierConfiguration; import org.ehcache.impl.config.copy.DefaultCopyProviderConfiguration; diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultSerializerConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/service/DefaultSerializerConfigurationParserTest.java index 96263cf315..f72c030db9 100644 --- a/xml/src/test/java/org/ehcache/xml/service/DefaultSerializerConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/service/DefaultSerializerConfigurationParserTest.java @@ -17,7 +17,7 @@ package org.ehcache.xml.service; import org.ehcache.config.CacheConfiguration; -import org.ehcache.core.internal.util.ClassLoading; +import org.ehcache.core.util.ClassLoading; import org.ehcache.impl.config.serializer.DefaultSerializerConfiguration; import org.ehcache.xml.XmlConfiguration; import org.ehcache.xml.exceptions.XmlConfigurationException; From a71a020bac4dcf57122be24d254114323a3fc69a Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 20 Sep 2018 15:51:39 -0400 Subject: [PATCH 059/372] Remove unused methods from CollectionUtil --- .../main/java/org/ehcache/core/Ehcache.java | 3 +- .../core/internal/util/CollectionUtil.java | 67 ------------------- .../internal/util/CollectionUtilTest.java | 53 --------------- 3 files changed, 2 insertions(+), 121 deletions(-) diff --git a/core/src/main/java/org/ehcache/core/Ehcache.java b/core/src/main/java/org/ehcache/core/Ehcache.java index 06a56408fc..104ef58279 100644 --- a/core/src/main/java/org/ehcache/core/Ehcache.java +++ b/core/src/main/java/org/ehcache/core/Ehcache.java @@ -16,6 +16,7 @@ package org.ehcache.core; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; @@ -350,7 +351,7 @@ public static class GetAllFunction implements Function> computeResult = new ArrayList<>(size); for (K key : keys) { - computeResult.add(CollectionUtil.entry(key, null)); + computeResult.add(new AbstractMap.SimpleImmutableEntry<>(key, null)); } return computeResult; diff --git a/core/src/main/java/org/ehcache/core/internal/util/CollectionUtil.java b/core/src/main/java/org/ehcache/core/internal/util/CollectionUtil.java index 85dfb0b3a3..4e41c1624f 100644 --- a/core/src/main/java/org/ehcache/core/internal/util/CollectionUtil.java +++ b/core/src/main/java/org/ehcache/core/internal/util/CollectionUtil.java @@ -15,9 +15,7 @@ */ package org.ehcache.core.internal.util; -import java.util.AbstractMap; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -40,19 +38,6 @@ public static int findBestCollectionSize(Iterable iterable, int bestBet) { return (iterable instanceof Collection ? ((Collection) iterable).size() : bestBet); } - /** - * Return a map entry for the key and value provided. - * - * @param key the key of the entry - * @param value the value of the entry - * @param type of the key - * @param type of the value - * @return the map entry for the key and value - */ - public static Map.Entry entry(K key, V value) { - return new AbstractMap.SimpleImmutableEntry<>(key, value); - } - /** * Copy each map entry to a new map but check that each key and value isn't null. Throw * a {@code NullPointerException} if it's the case. @@ -74,56 +59,4 @@ public static Map copyMapButFailOnNull(Map key type - * @param value type - * @return map with one entry - */ - public static Map map(K key0, V value0) { - return Collections.singletonMap(key0, value0); - } - - /** - * Create a map with two key/value pairs. - * - * @param key0 first key - * @param value0 first value - * @param key1 second key - * @param value1 second value - * @param key type - * @param value type - * @return map with two entries - */ - public static Map map(K key0, V value0, K key1, V value1) { - Map map = new HashMap<>(2); - map.put(key0, value0); - map.put(key1, value1); - return map; - } - - /** - * Create a map with three key/value pairs. - * - * @param key0 first key - * @param value0 first value - * @param key1 second key - * @param value1 second value - * @param key2 third key - * @param value2 third value - * @param key type - * @param value type - * @return map with three entries - */ - public static Map map(K key0, V value0, K key1, V value1, K key2, V value2) { - Map map = new HashMap<>(2); - map.put(key0, value0); - map.put(key1, value1); - map.put(key2, value2); - return map; - } } diff --git a/core/src/test/java/org/ehcache/core/internal/util/CollectionUtilTest.java b/core/src/test/java/org/ehcache/core/internal/util/CollectionUtilTest.java index 4f5c3e9c57..9e4dd06906 100644 --- a/core/src/test/java/org/ehcache/core/internal/util/CollectionUtilTest.java +++ b/core/src/test/java/org/ehcache/core/internal/util/CollectionUtilTest.java @@ -19,7 +19,6 @@ import java.util.Arrays; import java.util.Collections; -import java.util.Map; import static org.assertj.core.api.Assertions.*; @@ -48,56 +47,4 @@ public void findBestCollectionSize_notSizeable() { int size = CollectionUtil.findBestCollectionSize(() -> null, 100); assertThat(size).isEqualTo(100); } - - @Test - public void entry_value() { - Map.Entry entry = CollectionUtil.entry(1, "a"); - assertThat(entry.getKey()).isEqualTo(1); - assertThat(entry.getValue()).isEqualTo("a"); - } - - @Test - public void entry_nullAccepted() { - Map.Entry entry = CollectionUtil.entry(null, null); - assertThat(entry.getKey()).isNull(); - assertThat(entry.getValue()).isNull(); - } - - @Test - public void copyMapButFailOnNull_nullKey() { - Map map = CollectionUtil.map(1, 1, null, 2, 3, 3); - assertThatExceptionOfType(NullPointerException.class) - .isThrownBy(() -> CollectionUtil.copyMapButFailOnNull(map)); - } - - @Test - public void copyMapButFailOnNull_nullValue() { - Map map = CollectionUtil.map(1, 1, 2, null, 3, 3); - assertThatExceptionOfType(NullPointerException.class) - .isThrownBy(() -> CollectionUtil.copyMapButFailOnNull(Collections.singletonMap(1, null))); - } - - @Test - public void copyMapButFailOnNull_copy() { - Map map = CollectionUtil.map(1, 1L, 2, 2L, 3, 3L); - assertThat(map).containsExactly(entry(1, 1L), entry(2, 2L), entry(3, 3L)); - } - - @Test - public void map1() { - Map map = CollectionUtil.map(1, 1L); - assertThat(map).containsExactly(entry(1, 1L)); - } - - @Test - public void map2() { - Map map = CollectionUtil.map(1, 1L, 2, 2L); - assertThat(map).containsExactly(entry(1, 1L), entry(2, 2L)); - } - - @Test - public void map3() { - Map map = CollectionUtil.map(1, 1L, 2, 2L, 3, 3L); - assertThat(map).containsExactly(entry(1, 1L), entry(2, 2L), entry(3, 3L)); - } } From 892537a86f0f49c459341328e22af02843a54693 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 20 Sep 2018 16:10:54 -0400 Subject: [PATCH 060/372] Move TypeUtil to transactions where it is used --- core/build.gradle | 1 - core/src/main/java/org/ehcache/core/Ehcache.java | 2 +- .../core/{internal => }/util/CollectionUtil.java | 2 +- .../java/org/ehcache/core/EhcacheBasicGetAllTest.java | 11 ----------- .../core/internal/util/CollectionUtilTest.java | 1 + dist/build.gradle | 1 - .../store/loaderwriter/LocalLoaderWriterStore.java | 2 +- .../transactions/xa/internal/SoftLockSerializer.java | 2 +- .../ehcache/transactions/xa/internal}/TypeUtil.java | 2 +- .../org/ehcache/transactions/xa/internal/XAStore.java | 2 +- .../transactions/xa/internal/XAValueHolder.java | 2 +- .../xa/internal/journal/PersistentJournal.java | 2 +- .../xml/TxCacheManagerServiceConfigurationParser.java | 2 +- ...LookupTransactionManagerProviderConfiguration.java | 2 +- 14 files changed, 11 insertions(+), 23 deletions(-) rename core/src/main/java/org/ehcache/core/{internal => }/util/CollectionUtil.java (98%) rename {core/src/main/java/org/ehcache/core/internal/util => transactions/src/main/java/org/ehcache/transactions/xa/internal}/TypeUtil.java (95%) diff --git a/core/build.gradle b/core/build.gradle index 7c7ba1278c..f2f5e9aea6 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -30,7 +30,6 @@ jar { instruction 'Export-Package', 'org.ehcache.core.internal.events', 'org.ehcache.core.internal.store', - 'org.ehcache.core.internal.util', '!org.ehcache.core.internal.*', 'org.ehcache.core.*' } } diff --git a/core/src/main/java/org/ehcache/core/Ehcache.java b/core/src/main/java/org/ehcache/core/Ehcache.java index 104ef58279..f292378291 100644 --- a/core/src/main/java/org/ehcache/core/Ehcache.java +++ b/core/src/main/java/org/ehcache/core/Ehcache.java @@ -32,7 +32,7 @@ import org.ehcache.Cache; import org.ehcache.config.CacheConfiguration; import org.ehcache.core.events.CacheEventDispatcher; -import org.ehcache.core.internal.util.CollectionUtil; +import org.ehcache.core.util.CollectionUtil; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.Store.ValueHolder; import org.ehcache.spi.resilience.ResilienceStrategy; diff --git a/core/src/main/java/org/ehcache/core/internal/util/CollectionUtil.java b/core/src/main/java/org/ehcache/core/util/CollectionUtil.java similarity index 98% rename from core/src/main/java/org/ehcache/core/internal/util/CollectionUtil.java rename to core/src/main/java/org/ehcache/core/util/CollectionUtil.java index 4e41c1624f..9acc986ac5 100644 --- a/core/src/main/java/org/ehcache/core/internal/util/CollectionUtil.java +++ b/core/src/main/java/org/ehcache/core/util/CollectionUtil.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.internal.util; +package org.ehcache.core.util; import java.util.Collection; import java.util.HashMap; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java index 6c163147ad..aabc45a006 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java @@ -17,31 +17,22 @@ package org.ehcache.core; import org.ehcache.Status; -import org.ehcache.core.internal.util.CollectionUtil; -import org.ehcache.core.resilience.DefaultRecoveryStore; import org.ehcache.core.spi.store.Store; import org.ehcache.core.statistics.CacheOperationOutcomes; import org.ehcache.core.statistics.BulkOps; -import org.ehcache.spi.resilience.ResilienceStrategy; import org.ehcache.spi.resilience.StoreAccessException; import org.hamcrest.Matchers; import org.junit.Test; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.EnumSet; -import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.LongAdder; import java.util.function.Function; -import static java.util.function.Function.identity; -import static java.util.stream.Collectors.toMap; -import static java.util.stream.StreamSupport.stream; import static org.ehcache.core.EhcacheBasicBulkUtil.KEY_SET_A; import static org.ehcache.core.EhcacheBasicBulkUtil.KEY_SET_B; import static org.ehcache.core.EhcacheBasicBulkUtil.KEY_SET_C; @@ -57,12 +48,10 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; /** * Provides testing of basic GET_ALL operations on an {@code Ehcache}. diff --git a/core/src/test/java/org/ehcache/core/internal/util/CollectionUtilTest.java b/core/src/test/java/org/ehcache/core/internal/util/CollectionUtilTest.java index 9e4dd06906..af5f56349e 100644 --- a/core/src/test/java/org/ehcache/core/internal/util/CollectionUtilTest.java +++ b/core/src/test/java/org/ehcache/core/internal/util/CollectionUtilTest.java @@ -15,6 +15,7 @@ */ package org.ehcache.core.internal.util; +import org.ehcache.core.util.CollectionUtil; import org.junit.Test; import java.util.Arrays; diff --git a/dist/build.gradle b/dist/build.gradle index 396335af5b..080330c761 100644 --- a/dist/build.gradle +++ b/dist/build.gradle @@ -42,7 +42,6 @@ jar { '!org.ehcache.jsr107.tck', '!org.ehcache.*.internal.*', 'org.ehcache.*', 'org.terracotta.statistics.*', 'org.terracotta.context', 'org.ehcache.core.internal.store', - 'org.ehcache.core.internal.util', 'org.ehcache.impl.internal.concurrent', 'org.ehcache.impl.internal.events', 'org.ehcache.impl.internal.store.basic', diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java index 1824d6ebf3..ae439cc414 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java @@ -19,7 +19,7 @@ import org.ehcache.core.CacheConfigurationChangeListener; import org.ehcache.core.Ehcache; import org.ehcache.core.exceptions.StorePassThroughException; -import org.ehcache.core.internal.util.CollectionUtil; +import org.ehcache.core.util.CollectionUtil; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.WrapperStore; import org.ehcache.core.spi.store.events.StoreEventSource; diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java index 9e77a44146..8881b7e7fe 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java @@ -31,7 +31,7 @@ import java.util.HashMap; import java.util.Map; -import static org.ehcache.core.internal.util.TypeUtil.uncheckedCast; +import static org.ehcache.transactions.xa.internal.TypeUtil.uncheckedCast; /** * The stateless {@link Serializer} used to serialize {@link SoftLock}s. diff --git a/core/src/main/java/org/ehcache/core/internal/util/TypeUtil.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/TypeUtil.java similarity index 95% rename from core/src/main/java/org/ehcache/core/internal/util/TypeUtil.java rename to transactions/src/main/java/org/ehcache/transactions/xa/internal/TypeUtil.java index b9f2133996..92c635d904 100644 --- a/core/src/main/java/org/ehcache/core/internal/util/TypeUtil.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/TypeUtil.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.internal.util; +package org.ehcache.transactions.xa.internal; /** * Holder for static helper methods related to types and casting. diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java index 97dfe789da..818466a4a3 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java @@ -80,9 +80,9 @@ import javax.transaction.SystemException; import javax.transaction.Transaction; -import static org.ehcache.core.internal.util.TypeUtil.uncheckedCast; import static org.ehcache.core.spi.service.ServiceUtils.findAmongst; import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; +import static org.ehcache.transactions.xa.internal.TypeUtil.uncheckedCast; /** * A {@link Store} implementation wrapping another {@link Store} driven by a JTA diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java index 51d60d591a..db1f629b87 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java @@ -24,7 +24,7 @@ import java.io.Serializable; import java.nio.ByteBuffer; -import static org.ehcache.core.internal.util.TypeUtil.uncheckedCast; +import static org.ehcache.transactions.xa.internal.TypeUtil.uncheckedCast; /** * The {@link XAStore} {@link Store.ValueHolder} implementation. diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/PersistentJournal.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/PersistentJournal.java index e47e574213..76c82b8f51 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/PersistentJournal.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/PersistentJournal.java @@ -34,7 +34,7 @@ import java.util.HashMap; import java.util.Map; -import static org.ehcache.core.internal.util.TypeUtil.uncheckedCast; +import static org.ehcache.transactions.xa.internal.TypeUtil.uncheckedCast; /** * A persistent, but not durable {@link Journal} implementation. diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java index ea23eefe81..5f282685e6 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java @@ -34,8 +34,8 @@ import java.net.URI; import java.net.URL; -import static org.ehcache.core.internal.util.TypeUtil.uncheckedCast; import static org.ehcache.core.util.ClassLoading.delegationChain; +import static org.ehcache.transactions.xa.internal.TypeUtil.uncheckedCast; /** * @author Ludovic Orban diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfiguration.java b/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfiguration.java index c138922816..78bb33f3cc 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfiguration.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfiguration.java @@ -18,7 +18,7 @@ import org.ehcache.spi.service.ServiceCreationConfiguration; -import static org.ehcache.core.internal.util.TypeUtil.uncheckedCast; +import static org.ehcache.transactions.xa.internal.TypeUtil.uncheckedCast; /** * Specialized {@link ServiceCreationConfiguration} for the {@link LookupTransactionManagerProvider}. From 53e27be55c37d2ad27a747268b1918b9886ccfe5 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 20 Sep 2018 16:30:58 -0400 Subject: [PATCH 061/372] Move store support classes to exported package --- .../loaderwriter/DelegatingLoaderWriterStoreProvider.java | 2 +- .../service/ClusterStateRepositoryReplicationTest.java | 2 +- .../ClusterTierManagerClientEntityExceptionTest.java | 2 +- .../internal/service/DefaultClusteringServiceTest.java | 2 +- .../internal/service/StateRepositoryWhitelistingTest.java | 2 +- .../client/replication/ActivePassiveClientIdTest.java | 2 +- core/build.gradle | 1 - core/src/main/java/org/ehcache/core/EhcacheManager.java | 4 ++-- .../core/config/store/StoreEventSourceConfiguration.java | 1 - .../org/ehcache/core/resilience/DefaultRecoveryStore.java | 7 +++---- .../core/{internal => }/store/StoreConfigurationImpl.java | 2 +- .../ehcache/core/{internal => }/store/StoreSupport.java | 2 +- .../core/{internal => }/store/StoreSupportTest.java | 2 +- dist/build.gradle | 1 - .../ehcache/config/builders/UserManagedCacheBuilder.java | 4 ++-- .../store/loaderwriter/LoaderWriterStoreProvider.java | 2 +- .../impl/internal/store/disk/OffHeapDiskStoreSPITest.java | 2 +- .../impl/internal/store/disk/OffHeapDiskStoreTest.java | 2 +- .../store/heap/ByteSizedOnHeapStoreByRefSPITest.java | 2 +- .../store/heap/ByteSizedOnHeapStoreByValueSPITest.java | 2 +- .../impl/internal/store/heap/OnHeapStoreByRefSPITest.java | 2 +- .../internal/store/heap/OnHeapStoreByValueSPITest.java | 2 +- .../store/heap/OnHeapStoreCachingTierByRefSPITest.java | 2 +- .../store/heap/OnHeapStoreCachingTierByValueSPITest.java | 2 +- .../impl/internal/store/heap/OnHeapStoreEvictionTest.java | 2 +- .../heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java | 2 +- .../bytesized/OnHeapStoreCachingTierByValueSPITest.java | 2 +- .../impl/internal/store/offheap/OffHeapStoreSPITest.java | 2 +- .../impl/internal/store/offheap/OffHeapStoreTest.java | 2 +- .../internal/store/tiering/CompoundCachingTierSPITest.java | 2 +- .../internal/store/tiering/TieredStoreMutatorTest.java | 2 +- .../impl/internal/store/tiering/TieredStoreSPITest.java | 2 +- .../store/tiering/TieredStoreWith3TiersSPITest.java | 2 +- .../java/org/ehcache/transactions/xa/internal/XAStore.java | 4 ++-- .../org/ehcache/transactions/xa/internal/XAStoreTest.java | 2 +- 35 files changed, 37 insertions(+), 41 deletions(-) rename core/src/main/java/org/ehcache/core/{internal => }/store/StoreConfigurationImpl.java (99%) rename core/src/main/java/org/ehcache/core/{internal => }/store/StoreSupport.java (99%) rename core/src/test/java/org/ehcache/core/{internal => }/store/StoreSupportTest.java (99%) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java index d0e72a93e2..5055ce22cf 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java @@ -18,9 +18,9 @@ import org.ehcache.clustered.client.service.ClusteringService; import org.ehcache.clustered.client.service.ClusteringService.ClusteredCacheIdentifier; import org.ehcache.config.ResourceType; -import org.ehcache.core.internal.store.StoreSupport; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.WrapperStore; +import org.ehcache.core.store.StoreSupport; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.ehcache.impl.internal.store.loaderwriter.LoaderWriterStoreProvider.StoreRef; import org.ehcache.spi.loaderwriter.CacheLoaderWriterConfiguration; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java index 19469217ef..c9c4d57905 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java @@ -31,7 +31,7 @@ import org.ehcache.clustered.server.ClusterTierManagerServerEntityService; import org.ehcache.clustered.server.store.ClusterTierServerEntityService; import org.ehcache.core.config.BaseCacheConfiguration; -import org.ehcache.core.internal.store.StoreConfigurationImpl; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.spi.persistence.StateHolder; import org.junit.After; import org.junit.Before; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java index 9d9e6986f3..9e1c959b42 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java @@ -30,8 +30,8 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.config.store.StoreEventSourceConfiguration; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider; import org.junit.After; import org.junit.Before; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java index f224f93fe1..997df9e5cd 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java @@ -49,8 +49,8 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.config.store.StoreEventSourceConfiguration; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider; import org.ehcache.spi.persistence.PersistableResourceService; import org.ehcache.spi.persistence.StateRepository; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java index e6d5cc2e21..c3b29980e4 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java @@ -30,7 +30,7 @@ import org.ehcache.clustered.server.ClusterTierManagerServerEntityService; import org.ehcache.clustered.server.store.ClusterTierServerEntityService; import org.ehcache.core.config.BaseCacheConfiguration; -import org.ehcache.core.internal.store.StoreConfigurationImpl; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.spi.persistence.StateHolder; import org.junit.After; import org.junit.Before; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java index 20b4d1249d..27ceb521cc 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java @@ -35,7 +35,7 @@ import org.ehcache.clustered.server.store.ObservableClusterTierServerEntityService; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; +import org.ehcache.core.store.StoreConfigurationImpl; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/core/build.gradle b/core/build.gradle index f2f5e9aea6..79f3b37575 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -29,7 +29,6 @@ jar { instruction 'Bundle-Activator', 'org.ehcache.core.osgi.EhcacheActivator' instruction 'Export-Package', 'org.ehcache.core.internal.events', - 'org.ehcache.core.internal.store', '!org.ehcache.core.internal.*', 'org.ehcache.core.*' } } diff --git a/core/src/main/java/org/ehcache/core/EhcacheManager.java b/core/src/main/java/org/ehcache/core/EhcacheManager.java index 8c5a8c8898..367bb2ff44 100644 --- a/core/src/main/java/org/ehcache/core/EhcacheManager.java +++ b/core/src/main/java/org/ehcache/core/EhcacheManager.java @@ -35,8 +35,6 @@ import org.ehcache.core.events.CacheEventListenerProvider; import org.ehcache.core.events.CacheManagerListener; import org.ehcache.core.spi.ServiceLocator; -import org.ehcache.core.internal.store.StoreConfigurationImpl; -import org.ehcache.core.internal.store.StoreSupport; import org.ehcache.core.resilience.DefaultRecoveryStore; import org.ehcache.core.spi.LifeCycled; import org.ehcache.core.spi.LifeCycledAdapter; @@ -44,6 +42,8 @@ import org.ehcache.core.spi.service.ServiceUtils; import org.ehcache.core.spi.store.InternalCacheManager; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.store.StoreConfigurationImpl; +import org.ehcache.core.store.StoreSupport; import org.ehcache.core.util.ClassLoading; import org.ehcache.event.CacheEventListener; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; diff --git a/core/src/main/java/org/ehcache/core/config/store/StoreEventSourceConfiguration.java b/core/src/main/java/org/ehcache/core/config/store/StoreEventSourceConfiguration.java index 6625eaab5d..52e2bf81a4 100644 --- a/core/src/main/java/org/ehcache/core/config/store/StoreEventSourceConfiguration.java +++ b/core/src/main/java/org/ehcache/core/config/store/StoreEventSourceConfiguration.java @@ -16,7 +16,6 @@ package org.ehcache.core.config.store; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.core.spi.store.Store; import org.ehcache.spi.service.ServiceConfiguration; diff --git a/core/src/main/java/org/ehcache/core/resilience/DefaultRecoveryStore.java b/core/src/main/java/org/ehcache/core/resilience/DefaultRecoveryStore.java index 0609385882..c7276d3c94 100644 --- a/core/src/main/java/org/ehcache/core/resilience/DefaultRecoveryStore.java +++ b/core/src/main/java/org/ehcache/core/resilience/DefaultRecoveryStore.java @@ -15,15 +15,14 @@ */ package org.ehcache.core.resilience; -import org.ehcache.core.internal.resilience.RobustLoaderWriterResilienceStrategy; -import org.ehcache.core.internal.resilience.RobustResilienceStrategy; import org.ehcache.core.spi.store.Store; import org.ehcache.spi.resilience.RecoveryStore; import org.ehcache.spi.resilience.StoreAccessException; /** - * Default implementation of the {@link RecoveryStore} as used by the {@link RobustResilienceStrategy} and - * {@link RobustLoaderWriterResilienceStrategy}. It simply remove the required keys from the store. + * Default implementation of the {@link RecoveryStore}. + * + * It maps each obliterate operation to the equivalent remove operation. */ public class DefaultRecoveryStore implements RecoveryStore { diff --git a/core/src/main/java/org/ehcache/core/internal/store/StoreConfigurationImpl.java b/core/src/main/java/org/ehcache/core/store/StoreConfigurationImpl.java similarity index 99% rename from core/src/main/java/org/ehcache/core/internal/store/StoreConfigurationImpl.java rename to core/src/main/java/org/ehcache/core/store/StoreConfigurationImpl.java index 0aafe86d47..30fe9c2d49 100644 --- a/core/src/main/java/org/ehcache/core/internal/store/StoreConfigurationImpl.java +++ b/core/src/main/java/org/ehcache/core/store/StoreConfigurationImpl.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.internal.store; +package org.ehcache.core.store; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.EvictionAdvisor; diff --git a/core/src/main/java/org/ehcache/core/internal/store/StoreSupport.java b/core/src/main/java/org/ehcache/core/store/StoreSupport.java similarity index 99% rename from core/src/main/java/org/ehcache/core/internal/store/StoreSupport.java rename to core/src/main/java/org/ehcache/core/store/StoreSupport.java index 225507f756..e8baca30bd 100644 --- a/core/src/main/java/org/ehcache/core/internal/store/StoreSupport.java +++ b/core/src/main/java/org/ehcache/core/store/StoreSupport.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.internal.store; +package org.ehcache.core.store; import org.ehcache.config.ResourceType; import org.ehcache.core.spi.ServiceLocator; diff --git a/core/src/test/java/org/ehcache/core/internal/store/StoreSupportTest.java b/core/src/test/java/org/ehcache/core/store/StoreSupportTest.java similarity index 99% rename from core/src/test/java/org/ehcache/core/internal/store/StoreSupportTest.java rename to core/src/test/java/org/ehcache/core/store/StoreSupportTest.java index 59cb5ce8db..744d5e0797 100644 --- a/core/src/test/java/org/ehcache/core/internal/store/StoreSupportTest.java +++ b/core/src/test/java/org/ehcache/core/store/StoreSupportTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.internal.store; +package org.ehcache.core.store; import org.ehcache.config.ResourcePool; import org.ehcache.config.ResourceType; diff --git a/dist/build.gradle b/dist/build.gradle index 080330c761..4bbaa7f418 100644 --- a/dist/build.gradle +++ b/dist/build.gradle @@ -41,7 +41,6 @@ jar { instruction 'Export-Package', '!org.ehcache.jsr107.tck', '!org.ehcache.*.internal.*', 'org.ehcache.*', 'org.terracotta.statistics.*', 'org.terracotta.context', - 'org.ehcache.core.internal.store', 'org.ehcache.impl.internal.concurrent', 'org.ehcache.impl.internal.events', 'org.ehcache.impl.internal.store.basic', diff --git a/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java b/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java index b5f612ed04..b9503178d8 100644 --- a/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java @@ -35,8 +35,6 @@ import org.ehcache.core.events.CacheEventListenerConfiguration; import org.ehcache.core.events.CacheEventListenerProvider; import org.ehcache.core.spi.ServiceLocator; -import org.ehcache.core.internal.store.StoreConfigurationImpl; -import org.ehcache.core.internal.store.StoreSupport; import org.ehcache.core.resilience.DefaultRecoveryStore; import org.ehcache.core.spi.LifeCycled; import org.ehcache.core.spi.LifeCycledAdapter; @@ -44,6 +42,8 @@ import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.heap.SizeOfEngine; import org.ehcache.core.spi.store.heap.SizeOfEngineProvider; +import org.ehcache.core.store.StoreConfigurationImpl; +import org.ehcache.core.store.StoreSupport; import org.ehcache.core.util.ClassLoading; import org.ehcache.event.CacheEventListener; import org.ehcache.expiry.ExpiryPolicy; diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java index 76c71b165d..e592819a7a 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java @@ -16,11 +16,11 @@ package org.ehcache.impl.internal.store.loaderwriter; import org.ehcache.config.ResourceType; -import org.ehcache.core.internal.store.StoreSupport; import org.ehcache.core.spi.LifeCycledAdapter; import org.ehcache.core.spi.service.ServiceUtils; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.WrapperStore; +import org.ehcache.core.store.StoreSupport; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.loaderwriter.CacheLoaderWriterConfiguration; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java index f6840b5363..55e58396b1 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java @@ -20,10 +20,10 @@ import org.ehcache.config.EvictionAdvisor; import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.SizedResourcePool; import org.ehcache.config.units.MemoryUnit; import org.ehcache.CachePersistenceException; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.ehcache.impl.internal.events.TestStoreEventDispatcher; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java index 2475051efd..1fadbf84dc 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java @@ -23,9 +23,9 @@ import org.ehcache.config.ResourcePool; import org.ehcache.config.ResourceType; import org.ehcache.config.builders.CacheConfigurationBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.statistics.LowerCachingTierOperationsOutcome; import org.ehcache.CachePersistenceException; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java index 9571656646..e9f0662e80 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java @@ -19,8 +19,8 @@ import org.ehcache.config.EvictionAdvisor; import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.impl.internal.events.TestStoreEventDispatcher; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java index c24301182b..d97df7852e 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java @@ -19,8 +19,8 @@ import org.ehcache.config.EvictionAdvisor; import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.SerializingCopier; import org.ehcache.impl.internal.events.TestStoreEventDispatcher; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java index c1620bac17..e0924ccd5a 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java @@ -19,8 +19,8 @@ import org.ehcache.config.EvictionAdvisor; import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.units.EntryUnit; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.impl.internal.events.TestStoreEventDispatcher; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java index 3bcb8a9f67..4b0edc7b27 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java @@ -19,8 +19,8 @@ import org.ehcache.config.EvictionAdvisor; import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.units.EntryUnit; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.SerializingCopier; import org.ehcache.impl.internal.events.TestStoreEventDispatcher; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java index d9989fd90f..2210573f6e 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java @@ -18,8 +18,8 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.units.EntryUnit; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.core.events.NullStoreEventDispatcher; import org.ehcache.impl.internal.sizeof.NoopSizeOfEngine; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java index 76fe3ef9b8..6145137524 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java @@ -18,8 +18,8 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.units.EntryUnit; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.SerializingCopier; import org.ehcache.core.events.NullStoreEventDispatcher; import org.ehcache.impl.internal.sizeof.NoopSizeOfEngine; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java index 548031f33c..60c530f358 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java @@ -19,8 +19,8 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.event.EventType; import org.ehcache.expiry.ExpiryPolicy; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java index e24d67f1ae..81cec2d405 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java @@ -18,8 +18,8 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.core.events.NullStoreEventDispatcher; import org.ehcache.impl.internal.sizeof.DefaultSizeOfEngine; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java index 9f89556aa8..506c20e2da 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java @@ -18,8 +18,8 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.SerializingCopier; import org.ehcache.core.events.NullStoreEventDispatcher; import org.ehcache.impl.internal.sizeof.DefaultSizeOfEngine; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java index dc87e2a901..fb2dd5ed0c 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java @@ -19,10 +19,10 @@ import org.ehcache.config.EvictionAdvisor; import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.SizedResourcePool; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.events.TestStoreEventDispatcher; import org.ehcache.core.spi.time.SystemTimeSource; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java index 6c2e7e7b0a..5fb729f92b 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java @@ -18,9 +18,9 @@ import org.ehcache.config.EvictionAdvisor; import org.ehcache.config.ResourceType; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.events.TestStoreEventDispatcher; import org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java index 2c29306be9..53a26eea87 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java @@ -18,10 +18,10 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.events.StoreEventDispatcher; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.core.events.NullStoreEventDispatcher; import org.ehcache.impl.internal.sizeof.NoopSizeOfEngine; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java index 62a345095b..b583861545 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java @@ -19,8 +19,8 @@ import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; import org.ehcache.core.spi.store.tiering.CachingTier; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java index 0e8a549373..ab75b2da78 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java @@ -21,12 +21,12 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.ResourceType; import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.SizedResourcePool; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.CachePersistenceException; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.ehcache.impl.copy.IdentityCopier; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java index 26f719e13c..13248fb2ea 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java @@ -21,13 +21,13 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.ResourceType; import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.config.SizedResourcePool; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.CachePersistenceException; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.ehcache.impl.copy.IdentityCopier; diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java index 818466a4a3..adda2dd991 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java @@ -20,10 +20,10 @@ import org.ehcache.config.ResourceType; import org.ehcache.core.CacheConfigurationChangeListener; import org.ehcache.config.EvictionAdvisor; -import org.ehcache.core.internal.store.StoreConfigurationImpl; -import org.ehcache.core.internal.store.StoreSupport; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.store.WrapperStore; +import org.ehcache.core.store.StoreConfigurationImpl; +import org.ehcache.core.store.StoreSupport; import org.ehcache.impl.internal.util.CheckerUtil; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.expiry.ExpiryPolicy; diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java index 1d3bde2bfd..3a00afd0ca 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java @@ -22,11 +22,11 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.internal.store.StoreConfigurationImpl; import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.config.copy.DefaultCopyProviderConfiguration; import org.ehcache.core.events.NullStoreEventDispatcher; From ad7a51e1e22b6b1fd57cf54e44964e323a1f2051 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 20 Sep 2018 17:10:56 -0400 Subject: [PATCH 062/372] Move EventListenerWrapper to an exported package --- core/build.gradle | 4 +--- .../java/org/ehcache/core/EhcacheRuntimeConfiguration.java | 2 +- .../core/{internal => }/events/EventListenerWrapper.java | 2 +- .../org/ehcache/impl/events/CacheEventDispatcherImpl.java | 2 +- .../main/java/org/ehcache/impl/events/EventDispatchTask.java | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) rename core/src/main/java/org/ehcache/core/{internal => }/events/EventListenerWrapper.java (98%) diff --git a/core/build.gradle b/core/build.gradle index 79f3b37575..1cdb5fe99d 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -27,8 +27,6 @@ dependencies { jar { manifest { instruction 'Bundle-Activator', 'org.ehcache.core.osgi.EhcacheActivator' - instruction 'Export-Package', - 'org.ehcache.core.internal.events', - '!org.ehcache.core.internal.*', 'org.ehcache.core.*' + instruction 'Export-Package', '!org.ehcache.core.internal.*', 'org.ehcache.core.*' } } diff --git a/core/src/main/java/org/ehcache/core/EhcacheRuntimeConfiguration.java b/core/src/main/java/org/ehcache/core/EhcacheRuntimeConfiguration.java index 8417844d90..32f79f36ea 100644 --- a/core/src/main/java/org/ehcache/core/EhcacheRuntimeConfiguration.java +++ b/core/src/main/java/org/ehcache/core/EhcacheRuntimeConfiguration.java @@ -21,7 +21,7 @@ import org.ehcache.config.EvictionAdvisor; import org.ehcache.config.ResourcePools; import org.ehcache.core.config.ExpiryUtils; -import org.ehcache.core.internal.events.EventListenerWrapper; +import org.ehcache.core.events.EventListenerWrapper; import org.ehcache.event.CacheEventListener; import org.ehcache.event.EventFiring; import org.ehcache.event.EventOrdering; diff --git a/core/src/main/java/org/ehcache/core/internal/events/EventListenerWrapper.java b/core/src/main/java/org/ehcache/core/events/EventListenerWrapper.java similarity index 98% rename from core/src/main/java/org/ehcache/core/internal/events/EventListenerWrapper.java rename to core/src/main/java/org/ehcache/core/events/EventListenerWrapper.java index f91477ca1a..2076b68d81 100644 --- a/core/src/main/java/org/ehcache/core/internal/events/EventListenerWrapper.java +++ b/core/src/main/java/org/ehcache/core/events/EventListenerWrapper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.internal.events; +package org.ehcache.core.events; import org.ehcache.event.CacheEvent; import org.ehcache.event.CacheEventListener; diff --git a/impl/src/main/java/org/ehcache/impl/events/CacheEventDispatcherImpl.java b/impl/src/main/java/org/ehcache/impl/events/CacheEventDispatcherImpl.java index 655201f5e7..0eaf85435f 100644 --- a/impl/src/main/java/org/ehcache/impl/events/CacheEventDispatcherImpl.java +++ b/impl/src/main/java/org/ehcache/impl/events/CacheEventDispatcherImpl.java @@ -21,7 +21,7 @@ import org.ehcache.core.CacheConfigurationProperty; import org.ehcache.core.events.CacheEventDispatcher; import org.ehcache.core.events.CacheEvents; -import org.ehcache.core.internal.events.EventListenerWrapper; +import org.ehcache.core.events.EventListenerWrapper; import org.ehcache.event.CacheEvent; import org.ehcache.event.CacheEventListener; import org.ehcache.event.EventFiring; diff --git a/impl/src/main/java/org/ehcache/impl/events/EventDispatchTask.java b/impl/src/main/java/org/ehcache/impl/events/EventDispatchTask.java index 79897ca453..fbdcbdf88d 100644 --- a/impl/src/main/java/org/ehcache/impl/events/EventDispatchTask.java +++ b/impl/src/main/java/org/ehcache/impl/events/EventDispatchTask.java @@ -16,7 +16,7 @@ package org.ehcache.impl.events; -import org.ehcache.core.internal.events.EventListenerWrapper; +import org.ehcache.core.events.EventListenerWrapper; import org.ehcache.event.CacheEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; From f72c96a974016358f6977f5493b6b3bc6a5327e5 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 21 Sep 2018 09:06:12 -0400 Subject: [PATCH 063/372] Move BaseStore to exported package --- .../ehcache/clustered/client/internal/store/ClusteredStore.java | 2 +- dist/build.gradle | 1 - impl/build.gradle | 1 - .../java/org/ehcache/impl/internal/store/heap/OnHeapStore.java | 2 +- .../impl/internal/store/offheap/AbstractOffHeapStore.java | 2 +- .../ehcache/impl/{internal/store/basic => store}/BaseStore.java | 2 +- 6 files changed, 4 insertions(+), 6 deletions(-) rename impl/src/main/java/org/ehcache/impl/{internal/store/basic => store}/BaseStore.java (99%) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index 9808015103..42b02d9042 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -47,7 +47,7 @@ import org.ehcache.core.spi.service.ExecutionService; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.events.StoreEventSource; -import org.ehcache.impl.internal.store.basic.BaseStore; +import org.ehcache.impl.store.BaseStore; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; import org.ehcache.core.spi.time.TimeSource; diff --git a/dist/build.gradle b/dist/build.gradle index 4bbaa7f418..eb889ee2f6 100644 --- a/dist/build.gradle +++ b/dist/build.gradle @@ -43,7 +43,6 @@ jar { 'org.terracotta.statistics.*', 'org.terracotta.context', 'org.ehcache.impl.internal.concurrent', 'org.ehcache.impl.internal.events', - 'org.ehcache.impl.internal.store.basic', 'org.ehcache.impl.internal.store.loaderwriter', 'org.ehcache.impl.internal.util' instruction 'Import-Package', 'javax.cache.*;resolution:=optional', '!org.ehcache', '!sun.misc.*', '!com.sun.jmx.mbeanserver.*', '*' diff --git a/impl/build.gradle b/impl/build.gradle index 0da519e47d..46e48571e9 100644 --- a/impl/build.gradle +++ b/impl/build.gradle @@ -40,7 +40,6 @@ jar { 'org.ehcache.impl.internal.events', 'org.ehcache.impl.internal.spi.loaderwriter', 'org.ehcache.impl.internal.spi.serialization', - 'org.ehcache.impl.internal.store.basic', 'org.ehcache.impl.internal.store.loaderwriter', 'org.ehcache.impl.internal.util', diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index b15dbc3ba4..03aeab0f09 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -30,7 +30,7 @@ import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.core.events.StoreEventSink; import org.ehcache.impl.internal.concurrent.EvictingConcurrentMap; -import org.ehcache.impl.internal.store.basic.BaseStore; +import org.ehcache.impl.store.BaseStore; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.store.heap.LimitExceededException; import org.ehcache.expiry.ExpiryPolicy; diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java index c8ab308450..7fb2efefa6 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java @@ -36,7 +36,7 @@ import org.ehcache.core.config.ExpiryUtils; import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.core.events.StoreEventSink; -import org.ehcache.impl.internal.store.basic.BaseStore; +import org.ehcache.impl.store.BaseStore; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.expiry.ExpiryPolicy; diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/basic/BaseStore.java b/impl/src/main/java/org/ehcache/impl/store/BaseStore.java similarity index 99% rename from impl/src/main/java/org/ehcache/impl/internal/store/basic/BaseStore.java rename to impl/src/main/java/org/ehcache/impl/store/BaseStore.java index 0f39f9ebec..e1131301fa 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/basic/BaseStore.java +++ b/impl/src/main/java/org/ehcache/impl/store/BaseStore.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.impl.internal.store.basic; +package org.ehcache.impl.store; import org.ehcache.config.ResourceType; import org.ehcache.core.config.store.StoreStatisticsConfiguration; From 8810080aa669dfc98e7f6dadfde4a3afa385937d Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 21 Sep 2018 09:09:59 -0400 Subject: [PATCH 064/372] Improve generics in ClassInstanceProvider --- .../ehcache/jsr107/ConfigurationMerger.java | 8 ++-- impl/build.gradle | 1 - .../DefaultCopyProviderConfiguration.java | 7 +-- ...acheLoaderWriterProviderConfiguration.java | 2 +- ...silienceStrategyProviderConfiguration.java | 3 +- .../classes/ClassInstanceProvider.java | 31 ++++++------- .../ClassInstanceProviderConfiguration.java | 6 +-- .../spi/copy/DefaultCopyProvider.java | 5 +-- .../DefaultCacheEventListenerProvider.java | 4 +- .../DefaultCacheLoaderWriterProvider.java | 2 +- .../DefaultResilienceStrategyProvider.java | 9 ++-- ...lassInstanceProviderConfigurationTest.java | 2 +- .../classes/ClassInstanceProviderTest.java | 44 +++++++++---------- ...CacheEventListenerConfigurationParser.java | 24 +++++----- ...tCacheLoaderWriterConfigurationParser.java | 8 +++- .../DefaultCopierConfigurationParser.java | 13 +++--- ...ResilienceStrategyConfigurationParser.java | 8 +++- .../DefaultSerializerConfigurationParser.java | 13 +++--- .../SimpleCoreServiceConfigurationParser.java | 8 ---- ...ltCopyProviderConfigurationParserTest.java | 5 +-- 20 files changed, 99 insertions(+), 104 deletions(-) diff --git a/107/src/main/java/org/ehcache/jsr107/ConfigurationMerger.java b/107/src/main/java/org/ehcache/jsr107/ConfigurationMerger.java index 5c6a8f4a75..9d312ee038 100644 --- a/107/src/main/java/org/ehcache/jsr107/ConfigurationMerger.java +++ b/107/src/main/java/org/ehcache/jsr107/ConfigurationMerger.java @@ -23,12 +23,10 @@ import org.ehcache.impl.config.copy.DefaultCopierConfiguration; import org.ehcache.impl.config.copy.DefaultCopyProviderConfiguration; import org.ehcache.impl.config.loaderwriter.DefaultCacheLoaderWriterConfiguration; -import org.ehcache.impl.internal.classes.ClassInstanceConfiguration; import org.ehcache.impl.copy.SerializingCopier; import org.ehcache.jsr107.config.ConfigurationElementState; import org.ehcache.jsr107.config.Jsr107CacheConfiguration; import org.ehcache.jsr107.internal.Jsr107CacheLoaderWriter; -import org.ehcache.spi.copy.Copier; import org.ehcache.spi.loaderwriter.CacheLoaderWriterConfiguration; import org.ehcache.xml.XmlConfiguration; import org.slf4j.Logger; @@ -153,7 +151,7 @@ private CacheConfigurationBuilder handleStoreByValue(Eh107CompleteC DefaultCopyProviderConfiguration defaultCopyProviderConfiguration = findSingletonAmongst(DefaultCopyProviderConfiguration.class, xmlConfiguration.getServiceCreationConfigurations()); if (defaultCopyProviderConfiguration != null) { - Map, ClassInstanceConfiguration>> defaults = defaultCopyProviderConfiguration.getDefaults(); + Map, DefaultCopierConfiguration> defaults = defaultCopyProviderConfiguration.getDefaults(); handleCopierDefaultsforImmutableTypes(defaults); boolean matchingDefault = false; if (defaults.containsKey(jsr107Configuration.getKeyType())) { @@ -204,7 +202,7 @@ private static CacheConfigurationBuilder addDefaultCopiers(CacheCon return builder; } - private static void handleCopierDefaultsforImmutableTypes(Map, ClassInstanceConfiguration>> defaults) { + private static void handleCopierDefaultsforImmutableTypes(Map, DefaultCopierConfiguration> defaults) { addIdentityCopierIfNoneRegistered(defaults, Long.class); addIdentityCopierIfNoneRegistered(defaults, Integer.class); addIdentityCopierIfNoneRegistered(defaults, String.class); @@ -214,7 +212,7 @@ private static void handleCopierDefaultsforImmutableTypes(Map, ClassIns } @SuppressWarnings({"rawtypes", "unchecked"}) - private static void addIdentityCopierIfNoneRegistered(Map, ClassInstanceConfiguration>> defaults, Class clazz) { + private static void addIdentityCopierIfNoneRegistered(Map, DefaultCopierConfiguration> defaults, Class clazz) { if (!defaults.containsKey(clazz)) { defaults.put(clazz, new DefaultCopierConfiguration(Eh107IdentityCopier.class, DefaultCopierConfiguration.Type.VALUE)); } diff --git a/impl/build.gradle b/impl/build.gradle index 46e48571e9..5df859a839 100644 --- a/impl/build.gradle +++ b/impl/build.gradle @@ -35,7 +35,6 @@ jar { from "$rootDir/NOTICE" manifest { instruction 'Export-Package', - 'org.ehcache.impl.internal.classes', 'org.ehcache.impl.internal.concurrent', 'org.ehcache.impl.internal.events', 'org.ehcache.impl.internal.spi.loaderwriter', diff --git a/impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfiguration.java index 350fcf0665..9542fb7703 100644 --- a/impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfiguration.java @@ -16,7 +16,6 @@ package org.ehcache.impl.config.copy; -import org.ehcache.impl.internal.classes.ClassInstanceConfiguration; import org.ehcache.impl.internal.classes.ClassInstanceProviderConfiguration; import org.ehcache.spi.copy.Copier; import org.ehcache.spi.copy.CopyProvider; @@ -28,7 +27,7 @@ * Enables configuring {@link Class} - {@link Copier} pairs that will be selected unless cache level configurations * are provided. */ -public class DefaultCopyProviderConfiguration extends ClassInstanceProviderConfiguration, Copier> implements ServiceCreationConfiguration { +public class DefaultCopyProviderConfiguration extends ClassInstanceProviderConfiguration, DefaultCopierConfiguration> implements ServiceCreationConfiguration { /** * Default constructor. @@ -93,9 +92,7 @@ public DefaultCopyProviderConfiguration addCopierFor(Class clazz, Class> configuration = (ClassInstanceConfiguration) new DefaultCopierConfiguration<>(copierClass); - getDefaults().put(clazz, configuration); + getDefaults().put(clazz, new DefaultCopierConfiguration<>(copierClass)); return this; } } diff --git a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfiguration.java index 4ff724373d..6bdbb156ec 100644 --- a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfiguration.java @@ -24,7 +24,7 @@ /** * {@link ServiceCreationConfiguration} for the default {@link CacheLoaderWriterProvider}. */ -public class DefaultCacheLoaderWriterProviderConfiguration extends ClassInstanceProviderConfiguration> implements ServiceCreationConfiguration { +public class DefaultCacheLoaderWriterProviderConfiguration extends ClassInstanceProviderConfiguration implements ServiceCreationConfiguration { /** * {@inheritDoc} diff --git a/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java index 2055759d8a..6b38ff73b6 100644 --- a/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java @@ -18,7 +18,6 @@ import org.ehcache.impl.internal.classes.ClassInstanceProviderConfiguration; import org.ehcache.impl.internal.resilience.RobustLoaderWriterResilienceStrategy; import org.ehcache.impl.internal.resilience.RobustResilienceStrategy; -import org.ehcache.impl.internal.spi.resilience.DefaultResilienceStrategyProvider; import org.ehcache.spi.resilience.ResilienceStrategy; import org.ehcache.spi.resilience.ResilienceStrategyProvider; import org.ehcache.spi.service.ServiceCreationConfiguration; @@ -26,7 +25,7 @@ /** * {@link ServiceCreationConfiguration} for the default {@link ResilienceStrategyProvider}. */ -public class DefaultResilienceStrategyProviderConfiguration extends ClassInstanceProviderConfiguration> implements ServiceCreationConfiguration { +public class DefaultResilienceStrategyProviderConfiguration extends ClassInstanceProviderConfiguration implements ServiceCreationConfiguration { @SuppressWarnings("rawtypes") private static final Class DEFAULT_RESILIENCE = RobustResilienceStrategy.class; diff --git a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java b/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java index c2c5cf5c4c..1778d208b7 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java @@ -17,7 +17,6 @@ package org.ehcache.impl.internal.classes; import org.ehcache.config.CacheConfiguration; -import org.ehcache.impl.config.resilience.DefaultResilienceStrategyConfiguration; import org.ehcache.spi.service.ServiceProvider; import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceConfiguration; @@ -40,12 +39,12 @@ /** * @author Alex Snaps */ -public class ClassInstanceProvider { +public class ClassInstanceProvider, T> { /** * The order in which entries are put in is kept. */ - protected final Map> preconfigured = Collections.synchronizedMap(new LinkedHashMap>()); + protected final Map preconfigured = Collections.synchronizedMap(new LinkedHashMap()); /** * Instances provided by this provider vs their counts. @@ -53,17 +52,16 @@ public class ClassInstanceProvider { protected final ConcurrentWeakIdentityHashMap providedVsCount = new ConcurrentWeakIdentityHashMap<>(); protected final Set instantiated = Collections.newSetFromMap(new ConcurrentWeakIdentityHashMap()); - private final Class> cacheLevelConfig; + private final Class cacheLevelConfig; private final boolean uniqueClassLevelConfig; - protected ClassInstanceProvider(ClassInstanceProviderConfiguration factoryConfig, - Class> cacheLevelConfig) { + protected ClassInstanceProvider(ClassInstanceProviderConfiguration factoryConfig, + Class cacheLevelConfig) { this(factoryConfig, cacheLevelConfig, false); } - protected ClassInstanceProvider(ClassInstanceProviderConfiguration factoryConfig, - Class> cacheLevelConfig, - boolean uniqueClassLevelConfig) { + protected ClassInstanceProvider(ClassInstanceProviderConfiguration factoryConfig, + Class cacheLevelConfig, boolean uniqueClassLevelConfig) { this.uniqueClassLevelConfig = uniqueClassLevelConfig; if (factoryConfig != null) { preconfigured.putAll(factoryConfig.getDefaults()); @@ -71,16 +69,16 @@ protected ClassInstanceProvider(ClassInstanceProviderConfiguration factory this.cacheLevelConfig = cacheLevelConfig; } - protected ClassInstanceConfiguration getPreconfigured(K alias) { + protected C getPreconfigured(K alias) { return preconfigured.get(alias); } protected T newInstance(K alias, CacheConfiguration cacheConfiguration) { - ClassInstanceConfiguration config = null; + C config = null; if (uniqueClassLevelConfig) { config = findSingletonAmongst(cacheLevelConfig, cacheConfiguration.getServiceConfigurations()); } else { - Iterator> iterator = + Iterator iterator = findAmongst(cacheLevelConfig, cacheConfiguration.getServiceConfigurations()).iterator(); if (iterator.hasNext()) { config = iterator.next(); @@ -90,9 +88,8 @@ protected T newInstance(K alias, CacheConfiguration cacheConfiguration) { } protected T newInstance(K alias, ServiceConfiguration... serviceConfigurations) { - ClassInstanceConfiguration config = null; - Iterator> iterator = - findAmongst(cacheLevelConfig, (Object[]) serviceConfigurations).iterator(); + C config = null; + Iterator iterator = findAmongst(cacheLevelConfig, (Object[]) serviceConfigurations).iterator(); if (iterator.hasNext()) { config = iterator.next(); } @@ -100,14 +97,14 @@ protected T newInstance(K alias, ServiceConfiguration... serviceConfiguration } protected T newInstance(K alias, ServiceConfiguration serviceConfiguration) { - ClassInstanceConfiguration config = null; + C config = null; if (serviceConfiguration != null && cacheLevelConfig.isAssignableFrom(serviceConfiguration.getClass())) { config = cacheLevelConfig.cast(serviceConfiguration); } return newInstance(alias, config); } - private T newInstance(K alias, ClassInstanceConfiguration config) { + private T newInstance(K alias, ClassInstanceConfiguration config) { if (config == null) { config = getPreconfigured(alias); if (config == null) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfiguration.java b/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfiguration.java index 5a2330618c..fc53901160 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfiguration.java @@ -27,11 +27,11 @@ * * @author Alex Snaps */ -public class ClassInstanceProviderConfiguration { +public class ClassInstanceProviderConfiguration> { - private final Map> defaults = new LinkedHashMap<>(); + private final Map defaults = new LinkedHashMap<>(); - public Map> getDefaults() { + public Map getDefaults() { return defaults; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProvider.java b/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProvider.java index 1ca546b355..a0e9e75a1e 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProvider.java @@ -20,7 +20,6 @@ import org.ehcache.impl.config.copy.DefaultCopierConfiguration; import org.ehcache.impl.config.copy.DefaultCopierConfiguration.Type; import org.ehcache.impl.config.copy.DefaultCopyProviderConfiguration; -import org.ehcache.impl.internal.classes.ClassInstanceConfiguration; import org.ehcache.impl.internal.classes.ClassInstanceProvider; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.impl.copy.SerializingCopier; @@ -36,7 +35,7 @@ /** * @author Albin Suresh */ -public class DefaultCopyProvider extends ClassInstanceProvider, Copier> implements CopyProvider { +public class DefaultCopyProvider extends ClassInstanceProvider, DefaultCopierConfiguration, Copier> implements CopyProvider { private static final Logger LOG = LoggerFactory.getLogger(DefaultCopyProvider.class); @@ -67,7 +66,7 @@ private Copier createCopier(Type type, Class clazz, Serializer serializer, ServiceConfiguration... configs) { DefaultCopierConfiguration conf = find(type, configs); Copier copier; - final ClassInstanceConfiguration> preConfigured = preconfigured.get(clazz); + final DefaultCopierConfiguration preConfigured = preconfigured.get(clazz); if (conf != null && conf.getClazz().isAssignableFrom(SerializingCopier.class)) { if (serializer == null) { throw new IllegalStateException("No Serializer configured for type '" + clazz.getName() diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProvider.java b/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProvider.java index 63c550731c..e9c7d620b1 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProvider.java @@ -25,7 +25,7 @@ /** * @author rism */ -public class DefaultCacheEventListenerProvider extends ClassInstanceProvider> implements CacheEventListenerProvider { +public class DefaultCacheEventListenerProvider extends ClassInstanceProvider> implements CacheEventListenerProvider { public DefaultCacheEventListenerProvider() { super(null, DefaultCacheEventListenerConfiguration.class); @@ -41,4 +41,4 @@ public CacheEventListener createEventListener(String alias, Service public void releaseEventListener(CacheEventListener cacheEventListener) throws Exception { releaseInstance(cacheEventListener); } -} \ No newline at end of file +} diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProvider.java b/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProvider.java index 80871b9435..d7613234e3 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProvider.java @@ -30,7 +30,7 @@ /** * @author Alex Snaps */ -public class DefaultCacheLoaderWriterProvider extends ClassInstanceProvider> implements CacheLoaderWriterProvider { +public class DefaultCacheLoaderWriterProvider extends ClassInstanceProvider> implements CacheLoaderWriterProvider { private final Set cachesWithJsrRegisteredLoaders = new HashSet<>(); diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProvider.java b/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProvider.java index 00c9697634..0807f32cad 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProvider.java @@ -19,7 +19,6 @@ import org.ehcache.impl.config.resilience.DefaultResilienceStrategyConfiguration; import org.ehcache.impl.config.resilience.DefaultResilienceStrategyProviderConfiguration; import org.ehcache.impl.internal.classes.ClassInstanceProvider; -import org.ehcache.impl.internal.classes.ClassInstanceProviderConfiguration; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.resilience.RecoveryStore; import org.ehcache.spi.resilience.ResilienceStrategy; @@ -81,11 +80,11 @@ public void stop() { } } - static class ComponentProvider extends ClassInstanceProvider> { + static class ComponentProvider extends ClassInstanceProvider> { private DefaultResilienceStrategyConfiguration defaultConfiguration; - protected ComponentProvider(DefaultResilienceStrategyConfiguration dflt, ClassInstanceProviderConfiguration> factoryConfig) { + protected ComponentProvider(DefaultResilienceStrategyConfiguration dflt, DefaultResilienceStrategyProviderConfiguration factoryConfig) { super(factoryConfig, DefaultResilienceStrategyConfiguration.class); this.defaultConfiguration = dflt; } @@ -94,7 +93,7 @@ protected ComponentProvider(DefaultResilienceStrategyConfiguration dflt, ClassIn public ResilienceStrategy create(String alias, DefaultResilienceStrategyConfiguration config, RecoveryStore recoveryStore, CacheLoaderWriter loaderWriter) { if (config == null) { - DefaultResilienceStrategyConfiguration preconfigured = (DefaultResilienceStrategyConfiguration) getPreconfigured(alias); + DefaultResilienceStrategyConfiguration preconfigured = getPreconfigured(alias); if (preconfigured == null) { return (ResilienceStrategy) newInstance(alias, defaultConfiguration.bind(recoveryStore, loaderWriter)); } else { @@ -108,7 +107,7 @@ public ResilienceStrategy create(String alias, DefaultResilienceStr @SuppressWarnings("unchecked") public ResilienceStrategy create(String alias, DefaultResilienceStrategyConfiguration config, RecoveryStore recoveryStore) { if (config == null) { - DefaultResilienceStrategyConfiguration preconfigured = (DefaultResilienceStrategyConfiguration) getPreconfigured(alias); + DefaultResilienceStrategyConfiguration preconfigured = getPreconfigured(alias); if (preconfigured == null) { return (ResilienceStrategy) newInstance(alias, defaultConfiguration.bind(recoveryStore)); } else { diff --git a/impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfigurationTest.java index 7983b50c60..001e4154f9 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfigurationTest.java @@ -30,7 +30,7 @@ public class ClassInstanceProviderConfigurationTest { @Test public void testOrdering() throws Exception { - ClassInstanceProviderConfiguration classInstanceProviderFactoryConfig = new ClassInstanceProviderConfiguration<>(); + ClassInstanceProviderConfiguration> classInstanceProviderFactoryConfig = new ClassInstanceProviderConfiguration<>(); for (int i = 0; i < 100; i++) { classInstanceProviderFactoryConfig.getDefaults().put("" + i, new ClassInstanceConfiguration(String.class)); diff --git a/impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderTest.java index f529cedf61..520e313652 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderTest.java @@ -44,7 +44,7 @@ public class ClassInstanceProviderTest { @Test public void testNewInstanceUsingAliasAndNoArgs() throws Exception { - ClassInstanceProvider classInstanceProvider = new ClassInstanceProvider<>(null, configClass); + ClassInstanceProvider, TestService> classInstanceProvider = new ClassInstanceProvider<>(null, configClass); classInstanceProvider.preconfigured.put("test stuff", new ClassInstanceConfiguration(TestService.class)); TestService obj = classInstanceProvider.newInstance("test stuff", (ServiceConfiguration) null); @@ -54,7 +54,7 @@ public void testNewInstanceUsingAliasAndNoArgs() throws Exception { @Test public void testNewInstanceUsingAliasAndArg() throws Exception { - ClassInstanceProvider classInstanceProvider = new ClassInstanceProvider<>(null, configClass); + ClassInstanceProvider, TestService> classInstanceProvider = new ClassInstanceProvider<>(null, configClass); classInstanceProvider.preconfigured.put("test stuff", new ClassInstanceConfiguration<>(TestService.class, "test string")); TestService obj = classInstanceProvider.newInstance("test stuff", (ServiceConfiguration) null); @@ -64,7 +64,7 @@ public void testNewInstanceUsingAliasAndArg() throws Exception { @Test public void testNewInstanceUsingServiceConfig() throws Exception { - ClassInstanceProvider classInstanceProvider = new ClassInstanceProvider<>(null, configClass); + ClassInstanceProvider, TestService> classInstanceProvider = new ClassInstanceProvider<>(null, configClass); TestServiceConfiguration config = new TestServiceConfiguration(); TestService obj = classInstanceProvider.newInstance("test stuff", config); @@ -77,7 +77,7 @@ public void testNewInstanceUsingServiceConfigFactory() throws Exception { TestServiceProviderConfiguration factoryConfig = new TestServiceProviderConfiguration(); factoryConfig.getDefaults().put("test stuff", new ClassInstanceConfiguration(TestService.class)); - ClassInstanceProvider classInstanceProvider = new ClassInstanceProvider<>(factoryConfig, configClass); + ClassInstanceProvider, TestService> classInstanceProvider = new ClassInstanceProvider<>(factoryConfig, configClass); classInstanceProvider.start(null); TestService obj = classInstanceProvider.newInstance("test stuff", (ServiceConfiguration) null); @@ -86,14 +86,14 @@ public void testNewInstanceUsingServiceConfigFactory() throws Exception { @Test(expected = IllegalArgumentException.class) public void testReleaseInstanceByAnotherProvider() throws Exception { - ClassInstanceProvider classInstanceProvider = new ClassInstanceProvider<>(null, null); + ClassInstanceProvider, String> classInstanceProvider = new ClassInstanceProvider<>(null, null); classInstanceProvider.releaseInstance("foo"); } @Test(expected = IllegalArgumentException.class) public void testReleaseSameInstanceMultipleTimesThrows() throws Exception { - ClassInstanceProvider classInstanceProvider = new ClassInstanceProvider<>(null, null); + ClassInstanceProvider, String> classInstanceProvider = new ClassInstanceProvider<>(null, null); classInstanceProvider.providedVsCount.put("foo", new AtomicInteger(1)); classInstanceProvider.releaseInstance("foo"); @@ -102,7 +102,7 @@ public void testReleaseSameInstanceMultipleTimesThrows() throws Exception { @Test public void testReleaseCloseableInstance() throws Exception { - ClassInstanceProvider classInstanceProvider = new ClassInstanceProvider<>(null, null); + ClassInstanceProvider, Closeable> classInstanceProvider = new ClassInstanceProvider<>(null, null); Closeable closeable = mock(Closeable.class); classInstanceProvider.providedVsCount.put(closeable, new AtomicInteger(1)); classInstanceProvider.instantiated.add(closeable); @@ -113,7 +113,7 @@ public void testReleaseCloseableInstance() throws Exception { @Test(expected = IOException.class) public void testReleaseCloseableInstanceThrows() throws Exception { - ClassInstanceProvider classInstanceProvider = new ClassInstanceProvider<>(null, null); + ClassInstanceProvider, Closeable> classInstanceProvider = new ClassInstanceProvider<>(null, null); Closeable closeable = mock(Closeable.class); doThrow(IOException.class).when(closeable).close(); classInstanceProvider.providedVsCount.put(closeable, new AtomicInteger(1)); @@ -124,7 +124,7 @@ public void testReleaseCloseableInstanceThrows() throws Exception { @Test public void testNewInstanceWithActualInstanceInServiceConfig() throws Exception { - ClassInstanceProvider classInstanceProvider = new ClassInstanceProvider<>(null, configClass); + ClassInstanceProvider, TestService> classInstanceProvider = new ClassInstanceProvider<>(null, configClass); TestService service = new TestService(); TestServiceConfiguration config = new TestServiceConfiguration(service); @@ -136,7 +136,7 @@ public void testNewInstanceWithActualInstanceInServiceConfig() throws Exception @Test public void testSameInstanceRetrievedMultipleTimesUpdatesTheProvidedCount() throws Exception { - ClassInstanceProvider classInstanceProvider = new ClassInstanceProvider<>(null, configClass); + ClassInstanceProvider, TestService> classInstanceProvider = new ClassInstanceProvider<>(null, configClass); TestService service = new TestService(); TestServiceConfiguration config = new TestServiceConfiguration(service); @@ -152,13 +152,13 @@ public void testSameInstanceRetrievedMultipleTimesUpdatesTheProvidedCount() thro @Test public void testInstancesNotCreatedByProviderDoesNotClose() throws IOException { @SuppressWarnings("unchecked") - Class> configClass = (Class) ClassInstanceConfiguration.class; - ClassInstanceProvider classInstanceProvider = new ClassInstanceProvider<>(null, configClass); + Class> configClass = (Class) ClassInstanceConfiguration.class; + ClassInstanceProvider, TestCloseableService> classInstanceProvider = new ClassInstanceProvider<>(null, configClass); - TestCloaseableService service = mock(TestCloaseableService.class); + TestCloseableService service = mock(TestCloseableService.class); TestCloaseableServiceConfig config = new TestCloaseableServiceConfig(service); - TestCloaseableService newService = classInstanceProvider.newInstance("testClose", config); + TestCloseableService newService = classInstanceProvider.newInstance("testClose", config); assertThat(newService, sameInstance(service)); classInstanceProvider.releaseInstance(newService); verify(service, times(0)).close(); @@ -166,23 +166,23 @@ public void testInstancesNotCreatedByProviderDoesNotClose() throws IOException { } - public static abstract class TestCloaseableService implements Service, Closeable { + public static abstract class TestCloseableService implements Service, Closeable { } - public static class TestCloaseableServiceConfig extends ClassInstanceConfiguration implements ServiceConfiguration { + public static class TestCloaseableServiceConfig extends ClassInstanceConfiguration implements ServiceConfiguration { public TestCloaseableServiceConfig() { - super(TestCloaseableService.class); + super(TestCloseableService.class); } - public TestCloaseableServiceConfig(TestCloaseableService testCloaseableService) { - super(testCloaseableService); + public TestCloaseableServiceConfig(TestCloseableService testCloseableService) { + super(testCloseableService); } @Override - public Class getServiceType() { - return TestCloaseableService.class; + public Class getServiceType() { + return TestCloseableService.class; } } @@ -221,7 +221,7 @@ public Class getServiceType() { } } - public static class TestServiceProviderConfiguration extends ClassInstanceProviderConfiguration implements ServiceConfiguration { + public static class TestServiceProviderConfiguration extends ClassInstanceProviderConfiguration> implements ServiceConfiguration { @Override public Class getServiceType() { return TestService.class; diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParser.java index 72840bbe9a..6456db5330 100644 --- a/xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParser.java @@ -24,6 +24,7 @@ import org.ehcache.event.EventOrdering; import org.ehcache.impl.config.event.DefaultCacheEventListenerConfiguration; import org.ehcache.xml.CoreServiceConfigurationParser; +import org.ehcache.xml.exceptions.XmlConfigurationException; import org.ehcache.xml.model.CacheTemplate; import org.ehcache.xml.model.CacheType; import org.ehcache.xml.model.EventFiringType; @@ -33,14 +34,11 @@ import org.ehcache.xml.model.ListenersType; import java.util.Collection; -import java.util.List; import java.util.Set; -import java.util.stream.Collectors; import static java.util.stream.Collectors.toSet; import static org.ehcache.core.spi.service.ServiceUtils.findAmongst; import static org.ehcache.xml.XmlConfiguration.getClassForName; -import static org.ehcache.xml.service.SimpleCoreServiceConfigurationParser.checkNoConcreteInstance; public class DefaultCacheEventListenerConfigurationParser implements CoreServiceConfigurationParser { @@ -79,14 +77,18 @@ public CacheType unparseServiceConfiguration(CacheConfiguration cacheConfi Set listeners = serviceConfigs.stream().map(serviceConfig -> { ListenersType.Listener listener = new ListenersType.Listener(); - checkNoConcreteInstance(serviceConfig); - return listener.withClazz(serviceConfig.getClazz().getName()) - .withEventFiringMode(EventFiringType.fromValue(serviceConfig.firingMode().name())) - .withEventOrderingMode(EventOrderingType.fromValue(serviceConfig.orderingMode().name())) - .withEventsToFireOn(serviceConfig.fireOn() - .stream() - .map(eventType -> EventType.fromValue(eventType.name())) - .collect(toSet())); + if(serviceConfig.getInstance() == null) { + return listener.withClazz(serviceConfig.getClazz().getName()) + .withEventFiringMode(EventFiringType.fromValue(serviceConfig.firingMode().name())) + .withEventOrderingMode(EventOrderingType.fromValue(serviceConfig.orderingMode().name())) + .withEventsToFireOn(serviceConfig.fireOn() + .stream() + .map(eventType -> EventType.fromValue(eventType.name())) + .collect(toSet())); + } else { + throw new XmlConfigurationException("XML translation for instance based initialization for DefaultCacheEventListenerConfiguration is not supported"); + + } }).collect(toSet()); cacheType.withListeners(listenersType.withListener(listeners)); diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParser.java index bfff87a8a9..7144111c85 100644 --- a/xml/src/main/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParser.java @@ -18,6 +18,7 @@ import org.ehcache.impl.config.loaderwriter.DefaultCacheLoaderWriterConfiguration; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; +import org.ehcache.xml.exceptions.XmlConfigurationException; import org.ehcache.xml.model.CacheLoaderWriterType; import org.ehcache.xml.model.CacheTemplate; import org.ehcache.xml.model.CacheType; @@ -34,8 +35,11 @@ public DefaultCacheLoaderWriterConfigurationParser() { (config, loader) -> new DefaultCacheLoaderWriterConfiguration((Class>) getClassForName(config, loader)), CacheType::getLoaderWriter, CacheType::setLoaderWriter, config -> { - checkNoConcreteInstance(config); - return new CacheLoaderWriterType().withClazz(config.getClazz().getName()); + if(config.getInstance() == null) { + return new CacheLoaderWriterType().withClazz(config.getClazz().getName()); + } else { + throw new XmlConfigurationException("XML translation for instance based initialization for DefaultCacheLoaderWriterConfiguration is not supported"); + } }); } } diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultCopierConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/service/DefaultCopierConfigurationParser.java index ae5bc94b89..2891906096 100644 --- a/xml/src/main/java/org/ehcache/xml/service/DefaultCopierConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/service/DefaultCopierConfigurationParser.java @@ -20,6 +20,7 @@ import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.impl.config.copy.DefaultCopierConfiguration; import org.ehcache.xml.CoreServiceConfigurationParser; +import org.ehcache.xml.exceptions.XmlConfigurationException; import org.ehcache.xml.model.CacheTemplate; import org.ehcache.xml.model.CacheType; @@ -27,7 +28,6 @@ import static org.ehcache.core.spi.service.ServiceUtils.findAmongst; import static org.ehcache.xml.XmlConfiguration.getClassForName; -import static org.ehcache.xml.service.SimpleCoreServiceConfigurationParser.checkNoConcreteInstance; public class DefaultCopierConfigurationParser implements CoreServiceConfigurationParser { @@ -53,11 +53,14 @@ public CacheType unparseServiceConfiguration(CacheConfiguration cacheConfi Collection copierConfigs = findAmongst(DefaultCopierConfiguration.class, cacheConfiguration.getServiceConfigurations()); for (DefaultCopierConfiguration copierConfig : copierConfigs) { - checkNoConcreteInstance(copierConfig); - if (copierConfig.getType() == DefaultCopierConfiguration.Type.KEY) { - cacheType.getKeyType().setCopier(copierConfig.getClazz().getName()); + if(copierConfig.getInstance() == null) { + if (copierConfig.getType() == DefaultCopierConfiguration.Type.KEY) { + cacheType.getKeyType().setCopier(copierConfig.getClazz().getName()); + } else { + cacheType.getValueType().setCopier(copierConfig.getClazz().getName()); + } } else { - cacheType.getValueType().setCopier(copierConfig.getClazz().getName()); + throw new XmlConfigurationException("XML translation for instance based initialization for DefaultCopierConfiguration is not supported"); } } return cacheType; diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParser.java index 6874ed1f91..6aa97a81fc 100644 --- a/xml/src/main/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParser.java @@ -18,6 +18,7 @@ import org.ehcache.impl.config.resilience.DefaultResilienceStrategyConfiguration; import org.ehcache.spi.resilience.ResilienceStrategy; +import org.ehcache.xml.exceptions.XmlConfigurationException; import org.ehcache.xml.model.CacheTemplate; import org.ehcache.xml.model.CacheType; @@ -32,8 +33,11 @@ public DefaultResilienceStrategyConfigurationParser() { CacheTemplate::resilienceStrategy, (config, loader) -> new DefaultResilienceStrategyConfiguration((Class) getClassForName(config, loader)), CacheType::getResilience, CacheType::setResilience, config -> { - checkNoConcreteInstance(config); - return config.getClazz().getName(); + if(config.getInstance() == null) { + return config.getClazz().getName(); + } else { + throw new XmlConfigurationException("XML translation for instance based initialization for DefaultResilienceStrategyConfiguration is not supported"); + } }); } } diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultSerializerConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/service/DefaultSerializerConfigurationParser.java index 42537a6c43..244a58f3a0 100644 --- a/xml/src/main/java/org/ehcache/xml/service/DefaultSerializerConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/service/DefaultSerializerConfigurationParser.java @@ -20,6 +20,7 @@ import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.impl.config.serializer.DefaultSerializerConfiguration; import org.ehcache.xml.CoreServiceConfigurationParser; +import org.ehcache.xml.exceptions.XmlConfigurationException; import org.ehcache.xml.model.CacheTemplate; import org.ehcache.xml.model.CacheType; @@ -27,7 +28,6 @@ import static org.ehcache.core.spi.service.ServiceUtils.findAmongst; import static org.ehcache.xml.XmlConfiguration.getClassForName; -import static org.ehcache.xml.service.SimpleCoreServiceConfigurationParser.checkNoConcreteInstance; public class DefaultSerializerConfigurationParser implements CoreServiceConfigurationParser { @@ -52,11 +52,14 @@ public CacheType unparseServiceConfiguration(CacheConfiguration cacheConfi Collection serializerConfigs = findAmongst(DefaultSerializerConfiguration.class, cacheConfiguration.getServiceConfigurations()); for (DefaultSerializerConfiguration serializerConfig : serializerConfigs) { - checkNoConcreteInstance(serializerConfig); - if (serializerConfig.getType() == DefaultSerializerConfiguration.Type.KEY) { - cacheType.getKeyType().setSerializer(serializerConfig.getClazz().getName()); + if(serializerConfig.getInstance() == null) { + if (serializerConfig.getType() == DefaultSerializerConfiguration.Type.KEY) { + cacheType.getKeyType().setSerializer(serializerConfig.getClazz().getName()); + } else { + cacheType.getValueType().setSerializer(serializerConfig.getClazz().getName()); + } } else { - cacheType.getValueType().setSerializer(serializerConfig.getClazz().getName()); + throw new XmlConfigurationException("XML translation for instance based initialization for DefaultSerializerConfiguration is not supported"); } } return cacheType; diff --git a/xml/src/main/java/org/ehcache/xml/service/SimpleCoreServiceConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/service/SimpleCoreServiceConfigurationParser.java index f2be91e5a6..8ee09376ec 100644 --- a/xml/src/main/java/org/ehcache/xml/service/SimpleCoreServiceConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/service/SimpleCoreServiceConfigurationParser.java @@ -19,10 +19,8 @@ import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.core.spi.service.ServiceUtils; -import org.ehcache.impl.internal.classes.ClassInstanceConfiguration; import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.xml.CoreServiceConfigurationParser; -import org.ehcache.xml.exceptions.XmlConfigurationException; import org.ehcache.xml.model.CacheTemplate; import org.ehcache.xml.model.CacheType; @@ -42,12 +40,6 @@ class SimpleCoreServiceConfigurationParser unparser; private final BinaryOperator merger; - public static void checkNoConcreteInstance(ClassInstanceConfiguration classInstanceConfiguration) { - if(classInstanceConfiguration.getInstance() != null) { - throw new XmlConfigurationException("XML translation for instance based initialization for " + classInstanceConfiguration.getClass().getSimpleName() + - " is not supported"); - } - } SimpleCoreServiceConfigurationParser(Class configType, Function extractor, Function parser, Function getter, BiConsumer setter, Function unparser) { diff --git a/xml/src/test/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParserTest.java index 66ce75719d..10e7dadc79 100644 --- a/xml/src/test/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParserTest.java @@ -18,9 +18,8 @@ import org.ehcache.config.Configuration; import org.ehcache.config.builders.ConfigurationBuilder; +import org.ehcache.impl.config.copy.DefaultCopierConfiguration; import org.ehcache.impl.config.copy.DefaultCopyProviderConfiguration; -import org.ehcache.impl.internal.classes.ClassInstanceConfiguration; -import org.ehcache.spi.copy.Copier; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.xml.XmlConfiguration; import org.ehcache.xml.model.ConfigType; @@ -55,7 +54,7 @@ public void parseServiceCreationConfiguration() throws SAXException, JAXBExcepti assertThat(configuration).isExactlyInstanceOf(DefaultCopyProviderConfiguration.class); DefaultCopyProviderConfiguration factoryConfiguration = (DefaultCopyProviderConfiguration) configuration; - Map, ClassInstanceConfiguration>> defaults = factoryConfiguration.getDefaults(); + Map, DefaultCopierConfiguration> defaults = factoryConfiguration.getDefaults(); assertThat(defaults).hasSize(2); assertThat(defaults.get(Description.class).getClazz()).isEqualTo(DescriptionCopier.class); assertThat(defaults.get(Person.class).getClazz()).isEqualTo((PersonCopier.class)); From ab6b51a254a4ae069ce1c0e84a15fbd18301276e Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 21 Sep 2018 11:27:17 -0400 Subject: [PATCH 065/372] Remove impl serialization dependencies from 107 module --- .../DefaultJsr107SerializationProvider.java | 32 ------------------- .../jsr107/EhcacheCachingProvider.java | 26 ++++++++------- .../java/org/ehcache/core/EhcacheManager.java | 15 ++++++--- 3 files changed, 25 insertions(+), 48 deletions(-) delete mode 100644 107/src/main/java/org/ehcache/jsr107/DefaultJsr107SerializationProvider.java diff --git a/107/src/main/java/org/ehcache/jsr107/DefaultJsr107SerializationProvider.java b/107/src/main/java/org/ehcache/jsr107/DefaultJsr107SerializationProvider.java deleted file mode 100644 index 5267f646c9..0000000000 --- a/107/src/main/java/org/ehcache/jsr107/DefaultJsr107SerializationProvider.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.ehcache.jsr107; - -import org.ehcache.impl.config.serializer.DefaultSerializationProviderConfiguration; -import org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider; -import org.ehcache.impl.serialization.PlainJavaSerializer; - -/** - * @author Ludovic Orban - */ -class DefaultJsr107SerializationProvider extends DefaultSerializationProvider { - - @SuppressWarnings("unchecked") - DefaultJsr107SerializationProvider() { - super(new DefaultSerializationProviderConfiguration() - .addSerializerFor(Object.class, (Class) PlainJavaSerializer.class)); - } -} diff --git a/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java b/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java index 59e7a27bb0..fd0b415ba0 100644 --- a/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java +++ b/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java @@ -18,25 +18,26 @@ import org.ehcache.config.Configuration; import org.ehcache.core.EhcacheManager; import org.ehcache.core.config.DefaultConfiguration; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.service.ServiceUtils; import org.ehcache.core.util.ClassLoading; import org.ehcache.impl.config.serializer.DefaultSerializationProviderConfiguration; +import org.ehcache.impl.serialization.PlainJavaSerializer; import org.ehcache.jsr107.config.Jsr107Configuration; import org.ehcache.jsr107.internal.DefaultJsr107Service; -import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.xml.XmlConfiguration; import org.osgi.service.component.annotations.Component; import java.net.URI; import java.net.URISyntaxException; -import java.util.ArrayList; import java.util.Collection; import java.util.Map; import java.util.Properties; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.function.UnaryOperator; import javax.cache.CacheException; import javax.cache.CacheManager; @@ -139,21 +140,22 @@ Eh107CacheManager getCacheManager(ConfigSupplier configSupplier, Properties prop } private Eh107CacheManager createCacheManager(URI uri, Configuration config, Properties properties) { - Eh107CacheLoaderWriterProvider cacheLoaderWriterFactory = new Eh107CacheLoaderWriterProvider(); - Collection> serviceCreationConfigurations = config.getServiceCreationConfigurations(); Jsr107Service jsr107Service = new DefaultJsr107Service(ServiceUtils.findSingletonAmongst(Jsr107Configuration.class, serviceCreationConfigurations)); + Eh107CacheLoaderWriterProvider cacheLoaderWriterFactory = new Eh107CacheLoaderWriterProvider(); + @SuppressWarnings("unchecked") + DefaultSerializationProviderConfiguration serializerConfiguration = new DefaultSerializationProviderConfiguration().addSerializerFor(Object.class, (Class) PlainJavaSerializer.class); - Collection services = new ArrayList<>(4); - services.add(cacheLoaderWriterFactory); - services.add(jsr107Service); - - if (ServiceUtils.findSingletonAmongst(DefaultSerializationProviderConfiguration.class, serviceCreationConfigurations) == null) { - services.add(new DefaultJsr107SerializationProvider()); - } + UnaryOperator customization = dependencies -> { + ServiceLocator.DependencySet d = dependencies.with(jsr107Service).with(cacheLoaderWriterFactory); + if (ServiceUtils.findSingletonAmongst(DefaultSerializationProviderConfiguration.class, serviceCreationConfigurations) == null) { + d = d.with(serializerConfiguration); + } + return d; + }; - org.ehcache.CacheManager ehcacheManager = new EhcacheManager(config, services, !jsr107Service.jsr107CompliantAtomics()); + org.ehcache.CacheManager ehcacheManager = new EhcacheManager(config, customization, !jsr107Service.jsr107CompliantAtomics()); ehcacheManager.init(); return new Eh107CacheManager(this, ehcacheManager, jsr107Service, properties, config.getClassLoader(), uri, diff --git a/core/src/main/java/org/ehcache/core/EhcacheManager.java b/core/src/main/java/org/ehcache/core/EhcacheManager.java index 367bb2ff44..7664143e79 100644 --- a/core/src/main/java/org/ehcache/core/EhcacheManager.java +++ b/core/src/main/java/org/ehcache/core/EhcacheManager.java @@ -78,6 +78,7 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.UnaryOperator; import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.ehcache.core.spi.service.ServiceUtils.findOptionalAmongst; @@ -113,13 +114,17 @@ public EhcacheManager(Configuration config, Collection services) { } public EhcacheManager(Configuration config, Collection services, boolean useLoaderInAtomics) { + this(config, dependencies -> dependencies.with(services), useLoaderInAtomics); + } + + public EhcacheManager(Configuration config, UnaryOperator customization, boolean useLoaderInAtomics) { final String simpleName = this.getClass().getSimpleName(); this.simpleName = (simpleName.isEmpty() ? this.getClass().getName() : simpleName); this.configuration = new DefaultConfiguration(config); this.cacheManagerClassLoader = config.getClassLoader() != null ? config.getClassLoader() : ClassLoading.getDefaultClassLoader(); this.useLoaderInAtomics = useLoaderInAtomics; validateServicesConfigs(); - this.serviceLocator = resolveServices(services); + this.serviceLocator = resolveServices(customization); } private void validateServicesConfigs() { @@ -131,15 +136,17 @@ private void validateServicesConfigs() { } } - private ServiceLocator resolveServices(Collection services) { + private ServiceLocator resolveServices(UnaryOperator customization) { ServiceLocator.DependencySet builder = dependencySet() .with(Store.Provider.class) .with(CacheLoaderWriterProvider.class) .with(WriteBehindProvider.class) .with(CacheEventDispatcherFactory.class) .with(CacheEventListenerProvider.class) - .with(ResilienceStrategyProvider.class) - .with(services); + .with(ResilienceStrategyProvider.class); + + builder = customization.apply(builder); + if (!builder.contains(CacheManagerProviderService.class)) { builder = builder.with(new DefaultCacheManagerProviderService(this)); } From febaa079e1309292f0ab5d41dbd5b8f08a90a307 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 21 Sep 2018 11:42:11 -0400 Subject: [PATCH 066/372] Remove internal event code usage from transactions --- .../xa/internal/StoreEventSourceWrapper.java | 62 ++++++++++++------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/StoreEventSourceWrapper.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/StoreEventSourceWrapper.java index 575c453a77..adaccc5c78 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/StoreEventSourceWrapper.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/StoreEventSourceWrapper.java @@ -16,18 +16,15 @@ package org.ehcache.transactions.xa.internal; -import org.ehcache.impl.internal.events.StoreEventImpl; import org.ehcache.core.spi.store.events.StoreEvent; import org.ehcache.core.spi.store.events.StoreEventFilter; import org.ehcache.core.spi.store.events.StoreEventListener; import org.ehcache.core.spi.store.events.StoreEventSource; +import org.ehcache.event.EventType; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import static org.ehcache.impl.internal.events.StoreEvents.createEvent; -import static org.ehcache.impl.internal.events.StoreEvents.updateEvent; - /** * StoreEventSourceWrapper */ @@ -104,23 +101,7 @@ private StoreEventListenerWrapper(StoreEventListener wrappedOne) { @Override public void onEvent(StoreEvent> event) { - StoreEvent eventToPropagate = null; - switch (event.getType()) { - case CREATED: - eventToPropagate = createEvent(event.getKey(), event.getNewValue().getOldValue()); - break; - case UPDATED: - eventToPropagate = updateEvent(event.getKey(), event.getOldValue().getOldValue(), event.getNewValue() - .getOldValue()); - break; - case REMOVED: - case EXPIRED: - case EVICTED: - eventToPropagate = new StoreEventImpl<>(event.getType(), event.getKey(), event.getOldValue() - .getOldValue(), null); - break; - } - wrappedOne.onEvent(eventToPropagate); + wrappedOne.onEvent(new XaEvent<>(event)); } @Override @@ -139,4 +120,43 @@ public int hashCode() { return wrappedOne.hashCode(); } } + + static class XaEvent implements StoreEvent { + + private final StoreEvent> delegate; + + XaEvent(StoreEvent> delegate) { + this.delegate = delegate; + } + + @Override + public EventType getType() { + return delegate.getType(); + } + + @Override + public K getKey() { + return delegate.getKey(); + } + + @Override + public V getNewValue() { + SoftLock newValue = delegate.getNewValue(); + if (newValue == null) { + return null; + } else { + return newValue.getOldValue(); + } + } + + @Override + public V getOldValue() { + SoftLock oldValue = delegate.getOldValue(); + if (oldValue == null) { + return null; + } else { + return oldValue.getOldValue(); + } + } + } } From 342e5ec70ec36da52962c6453fb3d6e78a0ee35f Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 21 Sep 2018 12:03:55 -0400 Subject: [PATCH 067/372] Use BaseStore as base for XAStore --- .../impl/internal/util/CheckerUtil.java | 39 ----------- .../org/ehcache/impl/store/BaseStore.java | 21 ++++-- .../impl/internal/util/CheckerUtilTest.java | 64 ------------------- .../transactions/xa/internal/XAStore.java | 22 +++---- 4 files changed, 23 insertions(+), 123 deletions(-) delete mode 100644 impl/src/main/java/org/ehcache/impl/internal/util/CheckerUtil.java delete mode 100644 impl/src/test/java/org/ehcache/impl/internal/util/CheckerUtilTest.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/util/CheckerUtil.java b/impl/src/main/java/org/ehcache/impl/internal/util/CheckerUtil.java deleted file mode 100644 index 7dfdb4178a..0000000000 --- a/impl/src/main/java/org/ehcache/impl/internal/util/CheckerUtil.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.ehcache.impl.internal.util; - -import java.util.Objects; - -/** - * @author Henri Tremblay - */ -public final class CheckerUtil { - - public static void checkKey(Class keyType, Object keyObject) { - if (!keyType.isInstance(Objects.requireNonNull(keyObject))) { - throw new ClassCastException("Invalid key type, expected : " + keyType.getName() + " but was : " + keyObject.getClass().getName()); - } - } - - public static void checkValue(Class valueType, Object valueObject) { - if (!valueType.isInstance(Objects.requireNonNull(valueObject))) { - throw new ClassCastException("Invalid value type, expected : " + valueType.getName() + " but was : " + valueObject.getClass().getName()); - } - } - - private CheckerUtil() {} -} diff --git a/impl/src/main/java/org/ehcache/impl/store/BaseStore.java b/impl/src/main/java/org/ehcache/impl/store/BaseStore.java index e1131301fa..4acb762ff8 100644 --- a/impl/src/main/java/org/ehcache/impl/store/BaseStore.java +++ b/impl/src/main/java/org/ehcache/impl/store/BaseStore.java @@ -20,16 +20,17 @@ import org.ehcache.core.config.store.StoreStatisticsConfiguration; import org.ehcache.core.spi.store.Store; import org.ehcache.impl.internal.statistics.StatsUtils; -import org.ehcache.impl.internal.util.CheckerUtil; import org.terracotta.statistics.MappedOperationStatistic; import org.terracotta.statistics.OperationStatistic; import org.terracotta.statistics.StatisticType; import org.terracotta.statistics.StatisticsManager; import org.terracotta.statistics.ZeroOperationStatistic; import org.terracotta.statistics.observer.OperationObserver; +import sun.security.krb5.Config; import java.io.Serializable; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.function.Supplier; @@ -49,17 +50,25 @@ public abstract class BaseStore implements Store { protected final boolean operationStatisticsEnabled; public BaseStore(Configuration config) { - this.keyType = config.getKeyType(); - this.valueType = config.getValueType(); - this.operationStatisticsEnabled = config.isOperationStatisticsEnabled(); + this(config.getKeyType(), config.getValueType(), config.isOperationStatisticsEnabled()); + } + + public BaseStore(Class keyType, Class valueType, boolean operationStatisticsEnabled) { + this.keyType = keyType; + this.valueType = valueType; + this.operationStatisticsEnabled = operationStatisticsEnabled; } protected void checkKey(K keyObject) { - CheckerUtil.checkKey(keyType, keyObject); + if (!keyType.isInstance(Objects.requireNonNull((Object) keyObject))) { + throw new ClassCastException("Invalid key type, expected : " + keyType.getName() + " but was : " + keyObject.getClass().getName()); + } } protected void checkValue(V valueObject) { - CheckerUtil.checkValue(valueType, valueObject); + if (!valueType.isInstance(Objects.requireNonNull((Object) valueObject))) { + throw new ClassCastException("Invalid value type, expected : " + valueType.getName() + " but was : " + valueObject.getClass().getName()); + } } /** diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/CheckerUtilTest.java b/impl/src/test/java/org/ehcache/impl/internal/util/CheckerUtilTest.java deleted file mode 100644 index 50da07c920..0000000000 --- a/impl/src/test/java/org/ehcache/impl/internal/util/CheckerUtilTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.ehcache.impl.internal.util; - -import org.ehcache.spi.loaderwriter.CacheLoadingException; -import org.junit.Test; - -import static org.assertj.core.api.Assertions.*; - -/** - * @author Henri Tremblay - */ -public class CheckerUtilTest { - - @Test - public void checkKey_null() { - assertThatThrownBy(() -> CheckerUtil.checkKey(getClass(), null)) - .isExactlyInstanceOf(NullPointerException.class); - } - - @Test - public void checkKey_invalid() { - assertThatThrownBy(() -> CheckerUtil.checkKey(getClass(), "test")) - .isExactlyInstanceOf(ClassCastException.class) - .hasMessage("Invalid key type, expected : " + getClass().getName() + " but was : " + String.class.getName()); - } - - @Test - public void checkKey_valid() { - CheckerUtil.checkKey(Object.class, "test"); - } - - @Test - public void checkValue() { - assertThatThrownBy(() -> CheckerUtil.checkValue(getClass(), null)) - .isExactlyInstanceOf(NullPointerException.class); - } - - @Test - public void checkValue_invalid() { - assertThatThrownBy(() -> CheckerUtil.checkValue(getClass(), "test")) - .isExactlyInstanceOf(ClassCastException.class) - .hasMessage("Invalid value type, expected : " + getClass().getName() + " but was : " + String.class.getName()); - } - - @Test - public void checkValue_valid() { - CheckerUtil.checkValue(Object.class, "test"); - } -} diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java index adda2dd991..30c43a22ab 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java @@ -24,7 +24,7 @@ import org.ehcache.core.spi.store.WrapperStore; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.core.store.StoreSupport; -import org.ehcache.impl.internal.util.CheckerUtil; +import org.ehcache.impl.store.BaseStore; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.config.copy.DefaultCopierConfiguration; @@ -88,14 +88,12 @@ * A {@link Store} implementation wrapping another {@link Store} driven by a JTA * {@link javax.transaction.TransactionManager} using the XA 2-phase commit protocol. */ -public class XAStore implements WrapperStore { +public class XAStore extends BaseStore implements WrapperStore { private static final Logger LOGGER = LoggerFactory.getLogger(XAStore.class); private static final Supplier REPLACE_EQUALS_TRUE = () -> Boolean.TRUE; - private final Class keyType; - private final Class valueType; private final Store> underlyingStore; private final TransactionManagerWrapper transactionManagerWrapper; private final Map> xaResources = new ConcurrentHashMap<>(); @@ -108,8 +106,7 @@ public class XAStore implements WrapperStore { public XAStore(Class keyType, Class valueType, Store> underlyingStore, TransactionManagerWrapper transactionManagerWrapper, TimeSource timeSource, Journal journal, String uniqueXAResourceId) { - this.keyType = keyType; - this.valueType = valueType; + super(keyType, valueType, true); this.underlyingStore = underlyingStore; this.transactionManagerWrapper = transactionManagerWrapper; this.timeSource = timeSource; @@ -167,14 +164,6 @@ public void afterCompletion(int status) { } } - private void checkKey(K keyObject) { - CheckerUtil.checkKey(keyType, keyObject); - } - - private void checkValue(V valueObject) { - CheckerUtil.checkValue(valueType, valueObject); - } - @Override public ValueHolder get(K key) throws StoreAccessException { checkKey(key); @@ -420,6 +409,11 @@ public Iterator>> iterator() { return new XAIterator(valueHolderMap, underlyingStore.iterator(), currentContext.getTransactionId()); } + @Override + protected String getStatisticsTag() { + return "XaStore"; + } + class XAIterator implements Iterator>> { private final java.util.Iterator>> iterator; From 7ae79cbdb298ddee653bcbd1f4d1b8385e094fcd Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 21 Sep 2018 12:05:22 -0400 Subject: [PATCH 068/372] Move ByteBufferInputStream to be a core util class --- .../main/java/org/ehcache/core}/util/ByteBufferInputStream.java | 2 +- .../org/ehcache/impl/serialization/CompactJavaSerializer.java | 2 +- .../org/ehcache/impl/serialization/PlainJavaSerializer.java | 2 +- .../ehcache/impl/internal/util/ByteBufferInputStreamTest.java | 2 ++ .../java/org/ehcache/impl/serialization/JavaSerializer.java | 2 +- .../ehcache/transactions/xa/internal/SoftLockSerializer.java | 2 +- .../java/org/ehcache/transactions/xa/utils/JavaSerializer.java | 2 +- 7 files changed, 8 insertions(+), 6 deletions(-) rename {impl/src/main/java/org/ehcache/impl/internal => core/src/main/java/org/ehcache/core}/util/ByteBufferInputStream.java (97%) diff --git a/impl/src/main/java/org/ehcache/impl/internal/util/ByteBufferInputStream.java b/core/src/main/java/org/ehcache/core/util/ByteBufferInputStream.java similarity index 97% rename from impl/src/main/java/org/ehcache/impl/internal/util/ByteBufferInputStream.java rename to core/src/main/java/org/ehcache/core/util/ByteBufferInputStream.java index d9af55b39b..e43ca5370f 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/util/ByteBufferInputStream.java +++ b/core/src/main/java/org/ehcache/core/util/ByteBufferInputStream.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.impl.internal.util; +package org.ehcache.core.util; import java.io.IOException; import java.io.InputStream; diff --git a/impl/src/main/java/org/ehcache/impl/serialization/CompactJavaSerializer.java b/impl/src/main/java/org/ehcache/impl/serialization/CompactJavaSerializer.java index 64d850cffa..fe40894987 100644 --- a/impl/src/main/java/org/ehcache/impl/serialization/CompactJavaSerializer.java +++ b/impl/src/main/java/org/ehcache/impl/serialization/CompactJavaSerializer.java @@ -37,7 +37,7 @@ import org.ehcache.spi.persistence.StateHolder; import org.ehcache.spi.persistence.StateRepository; import org.ehcache.spi.serialization.SerializerException; -import org.ehcache.impl.internal.util.ByteBufferInputStream; +import org.ehcache.core.util.ByteBufferInputStream; import org.ehcache.spi.serialization.Serializer; import org.ehcache.spi.serialization.StatefulSerializer; diff --git a/impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java b/impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java index a5c8cb420d..a48c066453 100644 --- a/impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java +++ b/impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java @@ -16,7 +16,7 @@ package org.ehcache.impl.serialization; -import org.ehcache.impl.internal.util.ByteBufferInputStream; +import org.ehcache.core.util.ByteBufferInputStream; import org.ehcache.spi.serialization.Serializer; import org.ehcache.spi.serialization.SerializerException; diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/ByteBufferInputStreamTest.java b/impl/src/test/java/org/ehcache/impl/internal/util/ByteBufferInputStreamTest.java index 6cb6f8eb5b..ba522cec81 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/util/ByteBufferInputStreamTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/util/ByteBufferInputStreamTest.java @@ -18,6 +18,8 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.Random; + +import org.ehcache.core.util.ByteBufferInputStream; import org.junit.Assert; import org.junit.Test; diff --git a/impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java b/impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java index 070bfe2627..ebff194cdb 100644 --- a/impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java +++ b/impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java @@ -16,7 +16,7 @@ package org.ehcache.impl.serialization; import org.ehcache.spi.serialization.SerializerException; -import org.ehcache.impl.internal.util.ByteBufferInputStream; +import org.ehcache.core.util.ByteBufferInputStream; import org.ehcache.spi.serialization.Serializer; import java.io.ByteArrayOutputStream; diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java index 8881b7e7fe..3064b950a2 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java @@ -17,7 +17,7 @@ package org.ehcache.transactions.xa.internal; import org.ehcache.spi.serialization.SerializerException; -import org.ehcache.impl.internal.util.ByteBufferInputStream; +import org.ehcache.core.util.ByteBufferInputStream; import org.ehcache.spi.serialization.Serializer; import java.io.ByteArrayOutputStream; diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java b/transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java index b5d6fdb5ea..a2f80d75f3 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java @@ -16,7 +16,7 @@ package org.ehcache.transactions.xa.utils; import org.ehcache.spi.serialization.SerializerException; -import org.ehcache.impl.internal.util.ByteBufferInputStream; +import org.ehcache.core.util.ByteBufferInputStream; import org.ehcache.spi.serialization.Serializer; import java.io.ByteArrayOutputStream; From 718a7c675f3b2412b3476f6faa44eee229722f28 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 29 Oct 2018 17:57:32 -0400 Subject: [PATCH 069/372] Introduce abstract store wrapper provider to avoid exposing StoreRef --- .../DelegatingLoaderWriterStoreProvider.java | 49 +-------- .../internal/store/lock/LockManagerImpl.java | 2 +- .../lock/LockRetentionDuringFailoverTest.java | 2 +- .../loaderWriter/TestCacheLoaderWriter.java | 2 +- .../ObservableEhcacheServerEntityService.java | 2 +- .../store/AbstractWrapperStoreProvider.java | 97 +++++++++++++++++ .../LoaderWriterStoreProvider.java | 100 ++++-------------- .../loaderwriter/LocalLoaderWriterStore.java | 3 + .../LocalWriteBehindLoaderWriterStore.java | 34 ++++++ 9 files changed, 163 insertions(+), 128 deletions(-) create mode 100644 core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java create mode 100644 impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalWriteBehindLoaderWriterStore.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java index 5055ce22cf..0f356a4da8 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java @@ -18,54 +18,23 @@ import org.ehcache.clustered.client.service.ClusteringService; import org.ehcache.clustered.client.service.ClusteringService.ClusteredCacheIdentifier; import org.ehcache.config.ResourceType; +import org.ehcache.core.spi.store.AbstractWrapperStoreProvider; import org.ehcache.core.spi.store.Store; -import org.ehcache.core.spi.store.WrapperStore; -import org.ehcache.core.store.StoreSupport; -import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; -import org.ehcache.impl.internal.store.loaderwriter.LoaderWriterStoreProvider.StoreRef; import org.ehcache.spi.loaderwriter.CacheLoaderWriterConfiguration; import org.ehcache.spi.loaderwriter.CacheLoaderWriterProvider; -import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.spi.service.ServiceDependencies; -import org.ehcache.spi.service.ServiceProvider; - -import java.util.Arrays; import java.util.Collection; -import java.util.Map; import java.util.Set; import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; @ServiceDependencies({CacheLoaderWriterProvider.class, ClusteringService.class}) -public class DelegatingLoaderWriterStoreProvider implements WrapperStore.Provider { - private volatile ServiceProvider serviceProvider; - - private final Map, StoreRef> createdStores = new ConcurrentHashMap<>(); - - @Override - public Store createStore(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { - - Store.Provider underlyingStoreProvider = StoreSupport - .selectStoreProvider(serviceProvider, storeConfig.getResourcePools().getResourceTypeSet(), - Arrays.asList(serviceConfigs)); - - Store store = underlyingStoreProvider.createStore(storeConfig, serviceConfigs); - DelegatingLoaderWriterStore loaderWriterStore = new DelegatingLoaderWriterStore<>(store); - createdStores.put(loaderWriterStore, new StoreRef<>(store, underlyingStoreProvider)); - return loaderWriterStore; - } - - @Override - public void releaseStore(Store resource) { - StoreRef storeRef = createdStores.remove(resource); - storeRef.getUnderlyingStoreProvider().releaseStore(storeRef.getUnderlyingStore()); - } +public class DelegatingLoaderWriterStoreProvider extends AbstractWrapperStoreProvider { @Override - public void initStore(Store resource) { - StoreRef storeRef = createdStores.get(resource); - storeRef.getUnderlyingStoreProvider().initStore(storeRef.getUnderlyingStore()); + protected Store wrap(Store store, Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + return new DelegatingLoaderWriterStore<>(store); } @Override @@ -73,16 +42,6 @@ public int rank(Set> resourceTypes, Collection serviceProvider) { - this.serviceProvider = serviceProvider; - } - - @Override - public void stop() { - this.serviceProvider = null; - } - @Override public int wrapperStoreRank(Collection> serviceConfigs) { CacheLoaderWriterConfiguration loaderWriterConfiguration = findSingletonAmongst(CacheLoaderWriterConfiguration.class, serviceConfigs); diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImpl.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImpl.java index 397f2fb703..9306765a72 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImpl.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImpl.java @@ -23,10 +23,10 @@ import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.LockMessage; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.UnlockMessage; import org.ehcache.clustered.common.internal.store.Chain; -import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import java.util.Collections; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeoutException; import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.LOCK_FAILURE; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java index 3f26f4d520..be452bb883 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java @@ -27,7 +27,6 @@ import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; -import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.junit.After; import org.junit.Before; @@ -38,6 +37,7 @@ import org.terracotta.passthrough.PassthroughTestHelpers; import java.net.URI; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/TestCacheLoaderWriter.java b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/TestCacheLoaderWriter.java index 4dd229b209..36d1f10d7a 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/TestCacheLoaderWriter.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/TestCacheLoaderWriter.java @@ -16,10 +16,10 @@ package org.ehcache.clustered.loaderWriter; -import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class TestCacheLoaderWriter implements CacheLoaderWriter { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/server/ObservableEhcacheServerEntityService.java b/clustered/client/src/test/java/org/ehcache/clustered/server/ObservableEhcacheServerEntityService.java index 2dba617610..ea6957ebcf 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/server/ObservableEhcacheServerEntityService.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/server/ObservableEhcacheServerEntityService.java @@ -18,7 +18,6 @@ import org.ehcache.clustered.common.internal.messages.EhcacheEntityMessage; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse; -import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.terracotta.entity.ActiveInvokeContext; import org.terracotta.entity.ClientDescriptor; import org.terracotta.entity.ClientSourceId; @@ -33,6 +32,7 @@ import java.util.Collections; import java.util.List; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; /** * Provides an alternative to {@link ClusterTierManagerServerEntityService} for unit tests to enable observing diff --git a/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java b/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java new file mode 100644 index 0000000000..65277d90e9 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java @@ -0,0 +1,97 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.spi.store; + +import org.ehcache.core.collections.ConcurrentWeakIdentityHashMap; +import org.ehcache.spi.service.Service; +import org.ehcache.spi.service.ServiceConfiguration; +import org.ehcache.spi.service.ServiceProvider; + +import java.util.Arrays; +import java.util.IdentityHashMap; +import java.util.Map; + +import static java.util.Collections.synchronizedMap; +import static org.ehcache.core.store.StoreSupport.selectStoreProvider; + +public abstract class AbstractWrapperStoreProvider implements WrapperStore.Provider { + + private volatile ServiceProvider serviceProvider; + + private final Map, StoreReference> createdStores = new ConcurrentWeakIdentityHashMap<>(); + + + @Override + public Store createStore(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + + Store.Provider underlyingStoreProvider = selectStoreProvider(serviceProvider, storeConfig.getResourcePools().getResourceTypeSet(), + Arrays.asList(serviceConfigs)); + Store store = underlyingStoreProvider.createStore(storeConfig, serviceConfigs); + + Store wrappedStore = wrap(store, storeConfig, serviceConfigs); + createdStores.put(wrappedStore, new StoreReference<>(store, underlyingStoreProvider)); + return wrappedStore; + } + + protected abstract Store wrap(Store store, Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs); + + @Override + public void releaseStore(Store resource) { + StoreReference storeRef = createdStores.remove(resource); + if (storeRef != null) { + storeRef.release(); + } + } + + @Override + public void initStore(Store resource) { + StoreReference storeRef = createdStores.get(resource); + if (storeRef != null) { + storeRef.init(); + } + } + + @Override + public void start(ServiceProvider serviceProvider) { + this.serviceProvider = serviceProvider; + } + + @Override + public void stop() { + this.createdStores.clear(); + this.serviceProvider = null; + } + + + private static class StoreReference { + + private final Store store; + private final Store.Provider provider; + + public StoreReference(Store store, Store.Provider provider) { + this.store = store; + this.provider = provider; + } + + public void release() { + provider.releaseStore(store); + } + + public void init() { + provider.initStore(store); + } + } +} diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java index e592819a7a..46f5688d76 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java @@ -16,12 +16,8 @@ package org.ehcache.impl.internal.store.loaderwriter; import org.ehcache.config.ResourceType; -import org.ehcache.core.spi.LifeCycledAdapter; -import org.ehcache.core.spi.service.ServiceUtils; +import org.ehcache.core.spi.store.AbstractWrapperStoreProvider; import org.ehcache.core.spi.store.Store; -import org.ehcache.core.spi.store.WrapperStore; -import org.ehcache.core.store.StoreSupport; -import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.loaderwriter.CacheLoaderWriterConfiguration; import org.ehcache.spi.loaderwriter.CacheLoaderWriterProvider; @@ -32,87 +28,53 @@ import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.spi.service.ServiceProvider; -import java.util.Arrays; import java.util.Collection; -import java.util.Map; import java.util.Set; import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; @ServiceDependencies({CacheLoaderWriterProvider.class, WriteBehindProvider.class}) -public class LoaderWriterStoreProvider implements WrapperStore.Provider { +public class LoaderWriterStoreProvider extends AbstractWrapperStoreProvider { - private volatile ServiceProvider serviceProvider; - - private final Map, StoreRef> createdStores = new ConcurrentHashMap<>(); - - private volatile LifeCycledAdapter writeBehindLifecycleAdapter; + private volatile WriteBehindProvider writeBehindProvider; @Override - public Store createStore(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { - Store.Provider underlyingStoreProvider = StoreSupport.selectStoreProvider(serviceProvider, - storeConfig.getResourcePools().getResourceTypeSet(), Arrays.asList(serviceConfigs)); - Store store = underlyingStoreProvider.createStore(storeConfig, serviceConfigs); - - CacheLoaderWriter cacheLoaderWriter = storeConfig.getCacheLoaderWriter(); - CacheLoaderWriter decorator; - - WriteBehindConfiguration writeBehindConfiguration = - ServiceUtils.findSingletonAmongst(WriteBehindConfiguration.class, (Object[]) serviceConfigs); + protected Store wrap(Store store, Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + WriteBehindConfiguration writeBehindConfiguration = findSingletonAmongst(WriteBehindConfiguration.class, (Object[]) serviceConfigs); if(writeBehindConfiguration == null) { - decorator = cacheLoaderWriter; + return new LocalLoaderWriterStore<>(store, storeConfig.getCacheLoaderWriter(), storeConfig.useLoaderInAtomics(), storeConfig.getExpiry()); } else { - WriteBehindProvider factory = serviceProvider.getService(WriteBehindProvider.class); - decorator = factory.createWriteBehindLoaderWriter(cacheLoaderWriter, writeBehindConfiguration); - if(decorator != null) { - writeBehindLifecycleAdapter = new LifeCycledAdapter() { - @Override - public void close() { - factory.releaseWriteBehindLoaderWriter(decorator); - } - }; - } + CacheLoaderWriter writeBehindLoaderWriter = writeBehindProvider.createWriteBehindLoaderWriter(storeConfig.getCacheLoaderWriter(), writeBehindConfiguration); + return new LocalWriteBehindLoaderWriterStore<>(store, writeBehindLoaderWriter, storeConfig.useLoaderInAtomics(), storeConfig.getExpiry()); } - - LocalLoaderWriterStore loaderWriterStore = new LocalLoaderWriterStore<>(store, decorator, - storeConfig.useLoaderInAtomics(), storeConfig.getExpiry()); - createdStores.put(loaderWriterStore, new StoreRef<>(store, underlyingStoreProvider)); - return loaderWriterStore; } @Override public void releaseStore(Store resource) { - StoreRef storeRef = createdStores.remove(resource); - storeRef.getUnderlyingStoreProvider().releaseStore(storeRef.getUnderlyingStore()); - if (writeBehindLifecycleAdapter != null) { - try { - writeBehindLifecycleAdapter.close(); - } catch (Exception e) { - throw new RuntimeException(e); + try { + if (resource instanceof LocalWriteBehindLoaderWriterStore) { + writeBehindProvider.releaseWriteBehindLoaderWriter(((LocalWriteBehindLoaderWriterStore) resource).getCacheLoaderWriter()); } + } finally { + super.releaseStore(resource); } } @Override - public void initStore(Store resource) { - StoreRef storeRef = createdStores.get(resource); - storeRef.getUnderlyingStoreProvider().initStore(storeRef.getUnderlyingStore()); - } - - @Override - public int rank(Set> resourceTypes, Collection> serviceConfigs) { - throw new UnsupportedOperationException("Its a Wrapper store provider, does not support regular ranking"); + public void start(ServiceProvider serviceProvider) { + super.start(serviceProvider); + this.writeBehindProvider = serviceProvider.getService(WriteBehindProvider.class); } @Override - public void start(ServiceProvider serviceProvider) { - this.serviceProvider = serviceProvider; + public void stop() { + this.writeBehindProvider = null; + super.stop(); } @Override - public void stop() { - this.serviceProvider = null; - this.createdStores.clear(); + public int rank(Set> resourceTypes, Collection> serviceConfigs) { + throw new UnsupportedOperationException("Its a Wrapper store provider, does not support regular ranking"); } @Override @@ -123,24 +85,4 @@ public int wrapperStoreRank(Collection> serviceConfigs) } return 2; } - - public static class StoreRef { - private final Store underlyingStore; - private final Store.Provider underlyingStoreProvider; - - public StoreRef(Store underlyingStore, Store.Provider underlyingStoreProvider) { - this.underlyingStore = underlyingStore; - this.underlyingStoreProvider = underlyingStoreProvider; - } - - public Store.Provider getUnderlyingStoreProvider() { - return underlyingStoreProvider; - } - - public Store getUnderlyingStore() { - return underlyingStore; - } - - } - } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java index ae439cc414..3673f38047 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java @@ -27,7 +27,9 @@ import org.ehcache.spi.loaderwriter.BulkCacheLoadingException; import org.ehcache.spi.loaderwriter.BulkCacheWritingException; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; +import org.ehcache.spi.loaderwriter.WriteBehindConfiguration; import org.ehcache.spi.resilience.StoreAccessException; +import org.ehcache.spi.service.ServiceConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.terracotta.context.ContextManager; @@ -48,6 +50,7 @@ import static org.ehcache.core.exceptions.ExceptionFactory.newCacheLoadingException; import static org.ehcache.core.exceptions.ExceptionFactory.newCacheWritingException; +import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; public class LocalLoaderWriterStore implements WrapperStore { diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalWriteBehindLoaderWriterStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalWriteBehindLoaderWriterStore.java new file mode 100644 index 0000000000..bfbcf6e936 --- /dev/null +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalWriteBehindLoaderWriterStore.java @@ -0,0 +1,34 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.impl.internal.store.loaderwriter; + +import org.ehcache.core.spi.store.Store; +import org.ehcache.expiry.ExpiryPolicy; +import org.ehcache.spi.loaderwriter.CacheLoaderWriter; + +public class LocalWriteBehindLoaderWriterStore extends LocalLoaderWriterStore { + + private final CacheLoaderWriter cacheLoaderWriter; + + public LocalWriteBehindLoaderWriterStore(Store delegate, CacheLoaderWriter cacheLoaderWriter, boolean useLoaderInAtomics, ExpiryPolicy expiry) { + super(delegate, cacheLoaderWriter, useLoaderInAtomics, expiry); + this.cacheLoaderWriter = cacheLoaderWriter; + } + + public CacheLoaderWriter getCacheLoaderWriter() { + return cacheLoaderWriter; + } +} From d9cbd5a74f7bc323102fbc1f9eec172034beb9ed Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 21 Sep 2018 10:19:19 -0400 Subject: [PATCH 070/372] OSGi Manifest Cleanup --- 107/build.gradle | 2 +- clustered/clustered-dist/build.gradle | 4 ++-- clustered/common/gradle.properties | 3 --- dist/build.gradle | 10 ++-------- impl/build.gradle | 12 ++---------- transactions/build.gradle | 2 +- xml/build.gradle | 3 +-- 7 files changed, 9 insertions(+), 27 deletions(-) diff --git a/107/build.gradle b/107/build.gradle index 2ef65c4405..ff0914e8d6 100644 --- a/107/build.gradle +++ b/107/build.gradle @@ -55,7 +55,7 @@ javadoc { jar { manifest { instruction 'Export-Package', '!org.ehcache.jsr107.tck', '!org.ehcache.jsr107.internal.*', 'org.ehcache.jsr107.*' - instruction 'Import-Package', 'javax.cache.*;resolution:=optional', '!sun.misc.*', '!com.sun.jmx.mbeanserver.*', '*' + instruction 'Import-Package', 'javax.cache.*;resolution:=optional', '*' instruction 'Service-Component', 'OSGI-INF/*.xml' } } diff --git a/clustered/clustered-dist/build.gradle b/clustered/clustered-dist/build.gradle index cd6041d578..84dde04b37 100644 --- a/clustered/clustered-dist/build.gradle +++ b/clustered/clustered-dist/build.gradle @@ -75,8 +75,8 @@ task copyDocs(type: Copy) { jar { manifest { - instruction 'Export-Package', '!com.tc.*', '!com.terracotta.*', '!org.terracotta.*', '!org.ehcache.clustered.client.internal.*', '!sun.misc', 'org.ehcache.clustered.client.*' - instruction 'Import-Package', '!sun.misc.*', '*' + instruction 'Export-Package', '!com.tc.*', '!com.terracotta.*', '!org.terracotta.*', '!org.ehcache.*.internal.*', '!sun.misc', 'org.ehcache.clustered.client.*' + instruction 'Import-Package', '!sun.misc.*', 'org.ehcache.xml.*;resolution:=optional', '*' } } diff --git a/clustered/common/gradle.properties b/clustered/common/gradle.properties index e3f551d033..6dda235a04 100644 --- a/clustered/common/gradle.properties +++ b/clustered/common/gradle.properties @@ -16,6 +16,3 @@ subPomName = Ehcache 3 Common Clustering module subPomDesc = The Common Clustering module of Ehcache 3 - -osgi = {"Export-Package" : ["!org.ehcache.clustered.common.internal.*"],\ - "Import-Package" : ["!org.ehcache.clustered.common.*"]} diff --git a/dist/build.gradle b/dist/build.gradle index eb889ee2f6..c4c636d865 100644 --- a/dist/build.gradle +++ b/dist/build.gradle @@ -38,13 +38,7 @@ jar { instructionReplace 'Bundle-Description', 'Ehcache is an open-source caching library, compliant with the JSR-107 standard.' instruction 'Bundle-Activator', 'org.ehcache.core.osgi.EhcacheActivator' - instruction 'Export-Package', - '!org.ehcache.jsr107.tck', '!org.ehcache.*.internal.*', 'org.ehcache.*', - 'org.terracotta.statistics.*', 'org.terracotta.context', - 'org.ehcache.impl.internal.concurrent', - 'org.ehcache.impl.internal.events', - 'org.ehcache.impl.internal.store.loaderwriter', - 'org.ehcache.impl.internal.util' - instruction 'Import-Package', 'javax.cache.*;resolution:=optional', '!org.ehcache', '!sun.misc.*', '!com.sun.jmx.mbeanserver.*', '*' + instruction 'Export-Package', '!org.ehcache.jsr107.tck', '!org.ehcache.*.internal.*', 'org.ehcache.*', 'org.terracotta.statistics.*', 'org.terracotta.context' + instruction 'Import-Package', 'javax.cache.*;resolution:=optional', '!sun.misc', '*' } } diff --git a/impl/build.gradle b/impl/build.gradle index 5df859a839..6752b6bebd 100644 --- a/impl/build.gradle +++ b/impl/build.gradle @@ -34,16 +34,8 @@ dependencies { jar { from "$rootDir/NOTICE" manifest { - instruction 'Export-Package', - 'org.ehcache.impl.internal.concurrent', - 'org.ehcache.impl.internal.events', - 'org.ehcache.impl.internal.spi.loaderwriter', - 'org.ehcache.impl.internal.spi.serialization', - 'org.ehcache.impl.internal.store.loaderwriter', - 'org.ehcache.impl.internal.util', - - '!org.ehcache.impl.internal.*', - 'org.ehcache.impl.*', 'org.ehcache.config.builders' + instruction 'Export-Package', '!org.ehcache.impl.internal.*', 'org.ehcache.impl.*', 'org.ehcache.config.builders', + 'org.ehcache.impl.internal.spi.loaderwriter' //ugly 107 induced internal export wart instruction 'Import-Package', '!sun.misc', '*' instruction 'Service-Component', 'OSGI-INF/*.xml' } diff --git a/transactions/build.gradle b/transactions/build.gradle index 361b4523ce..6357b5f0d9 100644 --- a/transactions/build.gradle +++ b/transactions/build.gradle @@ -49,7 +49,7 @@ test { jar { manifest { instruction 'Export-Package', 'org.ehcache.transactions.xa.*' - instruction 'Import-Package', 'bitronix.tm.*;resolution:=optional', 'javax.transaction.*;resolution:=optional', '*' + instruction 'Import-Package', 'bitronix.tm.*;resolution:=optional', 'javax.transaction.*;resolution:=optional', 'org.ehcache.xml.*;resolution:=optional', '*' instruction 'Service-Component', 'OSGI-INF/*.xml' } } diff --git a/xml/build.gradle b/xml/build.gradle index a2cf8ce0ca..36ce752054 100644 --- a/xml/build.gradle +++ b/xml/build.gradle @@ -40,8 +40,7 @@ test { jar { manifest { - instruction 'Export-Package', 'org.ehcache.xml.*' - instruction 'Import-Package', '!sun.misc.*', '*' + instruction 'Export-Package', 'org.ehcache.xml', 'org.ehcache.xml.exceptions', 'org.ehcache.xml.model' } } From 43f6403f0030052c432460064f842396a538fa56 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 27 Sep 2018 17:37:33 -0400 Subject: [PATCH 071/372] Protect OSGi service loading with a system property --- .../ehcache/core/osgi/EhcacheActivator.java | 20 ++++++++- .../ehcache/integration/OsgiSafetyTest.java | 42 +++++++++++++++++++ .../org/ehcache/osgi/OffHeapOsgiTest.java | 15 ++++++- .../java/org/ehcache/osgi/SimpleOsgiTest.java | 15 ++++++- .../ehcache/osgi/TransactionalOsgiTest.java | 2 + 5 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 integration-test/src/test/java/org/ehcache/integration/OsgiSafetyTest.java diff --git a/core/src/main/java/org/ehcache/core/osgi/EhcacheActivator.java b/core/src/main/java/org/ehcache/core/osgi/EhcacheActivator.java index 4960afd954..485af41100 100644 --- a/core/src/main/java/org/ehcache/core/osgi/EhcacheActivator.java +++ b/core/src/main/java/org/ehcache/core/osgi/EhcacheActivator.java @@ -16,6 +16,8 @@ package org.ehcache.core.osgi; +import org.ehcache.core.spi.service.ServiceFactory; +import org.ehcache.core.util.ClassLoading; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.slf4j.Logger; @@ -23,8 +25,14 @@ import java.util.concurrent.atomic.AtomicReference; +import static java.util.Spliterators.spliterator; +import static java.util.stream.Collectors.joining; +import static java.util.stream.StreamSupport.stream; + public class EhcacheActivator implements BundleActivator { + public static final String OSGI_LOADING = "org.ehcache.core.osgi"; + private static final Logger LOGGER = LoggerFactory.getLogger(EhcacheActivator.class); private static final AtomicReference CORE_BUNDLE = new AtomicReference<>(); @@ -33,8 +41,16 @@ public class EhcacheActivator implements BundleActivator { public void start(BundleContext context) throws Exception { BundleContext currentContext = CORE_BUNDLE.getAndUpdate(current -> current == null ? context : current); if (currentContext == null) { - SafeOsgi.enableOSGiServiceLoading(); - LOGGER.info("Detected OSGi Environment (core is in bundle: " + context.getBundle() + "): OSGi Based Service Loading Enabled Via System/Framework Property"); + String greeting = "Detected OSGi Environment (core is in bundle: " + context.getBundle() + ")"; + if ("false".equalsIgnoreCase(context.getProperty(OSGI_LOADING))) { + SafeOsgi.disableOSGiServiceLoading(); + LOGGER.info(greeting + ": OSGi Based Service Loading Disabled Via System/Framework Property - Extensions Outside This Bundle Will Not Be Detected"); + LOGGER.debug("JDK Service Loading Sees:\n\t" + stream(spliterator(ClassLoading.servicesOfType(ServiceFactory.class).iterator(), Long.MAX_VALUE, 0), false) + .map(sf -> sf.getServiceType().getName()).collect(joining("\n\t"))); + } else { + SafeOsgi.enableOSGiServiceLoading(); + LOGGER.info(greeting + ": Using OSGi Based Service Loading"); + } } else { throw new IllegalStateException("Multiple bundle instances running against the same core classes: existing bundle: " + currentContext.getBundle() + " new bundle: " + context.getBundle()); } diff --git a/integration-test/src/test/java/org/ehcache/integration/OsgiSafetyTest.java b/integration-test/src/test/java/org/ehcache/integration/OsgiSafetyTest.java new file mode 100644 index 0000000000..3380fcbc44 --- /dev/null +++ b/integration-test/src/test/java/org/ehcache/integration/OsgiSafetyTest.java @@ -0,0 +1,42 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.integration; + +import org.ehcache.core.osgi.SafeOsgi; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +public class OsgiSafetyTest { + + @Test + public void testOsgiIsNotHere() { + try { + Class.forName("org.osgi.framework.Bundle"); + fail("Expected ClassNotFoundException"); + } catch (ClassNotFoundException e) { + //expected + } + } + + @Test + public void testSafeOsgiIsSafe() { + assertThat(SafeOsgi.useOSGiServiceLoading(), is(false)); + } +} diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java index f6ab3c64ce..a7ecbe48b5 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java @@ -33,11 +33,13 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.ehcache.core.osgi.EhcacheActivator.OSGI_LOADING; import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.ops4j.pax.exam.CoreOptions.frameworkProperty; import static org.ops4j.pax.exam.CoreOptions.options; @RunWith(PaxExam.class) @@ -60,7 +62,7 @@ public Option[] individualModules() { } @Configuration - public Option[] uberJar() { + public Option[] uberJarWithOsgiServiceLoading() { return options( gradleBundle("org.ehcache:dist"), @@ -68,6 +70,17 @@ public Option[] uberJar() { ); } + @Configuration + public Option[] uberJarWithJdkServiceLoading() { + return options( + frameworkProperty(OSGI_LOADING).value("false"), + + gradleBundle("org.ehcache:dist"), + + baseConfiguration() + ); + } + @Test public void testOffHeapInOsgi() { TestMethods.testOffHeapInOsgi(); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java index 8c859ca17f..f240116c78 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java @@ -44,6 +44,7 @@ import static java.util.stream.StreamSupport.stream; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.ehcache.core.osgi.EhcacheActivator.OSGI_LOADING; import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; @@ -51,6 +52,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.ops4j.pax.exam.CoreOptions.frameworkProperty; import static org.ops4j.pax.exam.CoreOptions.options; @RunWith(PaxExam.class) @@ -74,7 +76,7 @@ public Option[] individualModules() { } @Configuration - public Option[] uberJar() { + public Option[] uberJarWithOsgiServiceLoading() { return options( gradleBundle("org.ehcache:dist"), @@ -82,6 +84,17 @@ public Option[] uberJar() { ); } + @Configuration + public Option[] uberJarWithJdkServiceLoading() { + return options( + frameworkProperty(OSGI_LOADING).value("false"), + + gradleBundle("org.ehcache:dist"), + + baseConfiguration() + ); + } + @Test public void testEhcache3AsBundle() { TestMethods.testEhcache3AsBundle(); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java index 96550a8a04..aff82795cf 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java @@ -39,10 +39,12 @@ import static bitronix.tm.TransactionManagerServices.getTransactionManager; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManager; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.ehcache.core.osgi.EhcacheActivator.OSGI_LOADING; import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.ops4j.pax.exam.CoreOptions.cleanCaches; +import static org.ops4j.pax.exam.CoreOptions.frameworkProperty; import static org.ops4j.pax.exam.CoreOptions.options; @RunWith(PaxExam.class) From b215f3b88227bbb26a1af949abfe8eca985b89ee Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 1 Oct 2018 14:15:01 -0400 Subject: [PATCH 072/372] Document OSGi Deployment Options --- docs/src/docs/asciidoc/user/index.adoc | 1 + docs/src/docs/asciidoc/user/osgi.adoc | 97 ++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 docs/src/docs/asciidoc/user/osgi.adoc diff --git a/docs/src/docs/asciidoc/user/index.adoc b/docs/src/docs/asciidoc/user/index.adoc index 5b7b55d3be..5d86bd231e 100644 --- a/docs/src/docs/asciidoc/user/index.adoc +++ b/docs/src/docs/asciidoc/user/index.adoc @@ -56,5 +56,6 @@ Each topic below corresponds to a menu item at the left. |link:cache-event-listeners{outfilesuffix}[Cache Event Listeners]|Getting notified about events within the cache |link:eviction-advisor{outfilesuffix}[Eviction Advisor]|Affecting the way entries are chosen for eviction |link:class-loading{outfilesuffix}[Class loading]|Ehcache and `ClassLoader` interactions +|link:osgi{outfilesuffix}[OSGi Deployment]|How to use Ehcache in an OSGi Environment |link:performance{outfilesuffix}[Performance Tuning]|Ehcache Performance Tuning |=== diff --git a/docs/src/docs/asciidoc/user/osgi.adoc b/docs/src/docs/asciidoc/user/osgi.adoc new file mode 100644 index 0000000000..2bb9849e45 --- /dev/null +++ b/docs/src/docs/asciidoc/user/osgi.adoc @@ -0,0 +1,97 @@ +--- +--- += OSGi Deployment +ifndef::sourcedir36[] +include::common.adoc[] +endif::sourcedir36[] + +ifdef::notBuildingForSite[] +include::menu.adoc[] +endif::notBuildingForSite[] + +== OSGi Compatible Bundles + +The following Ehcache artifacts are also valid OSGi bundles: + +* `org.ehcache:ehcache` ++ +includes: `api`, `core`, `impl`, `xml`, `107` + +* `org.ehcache:ehcache-clustered` +* `org.ehcache:ehcache-transactions` +* `org.ehcache.modules:ehcache-api` +* `org.ehcache.modules:ehcache-core` +* `org.ehcache.modules:ehcache-impl` +* `org.ehcache.modules:ehcache-xml` +* `org.ehcache.modules:ehcache-107` + +== Ehcache Service Lookup & OSGi + +To allow for the extension of its feature set and to support the internal modularity of the source code, Ehcache uses +a `java.util.ServiceLoader` based lookup system to discover the set of available functionalities at runtime. When +deployed as bundles in an OSGi environment this lookup mechanism is replaced by a lookup mechanism based on OSGi +components. Activation of the bundle containing the Ehcache core code will result in the following logging +[source,log] +---- +org.ehcache[org.ehcache.core.osgi.EhcacheActivator] : Detected OSGi Environment (core is in bundle: org.ehcache [13]): Using OSGi Based Service Loading +---- +In this mode, to enable transactional and/or clustered caching it is sufficient to just provision the +`org.ehcache:ehcache-transactions` and/or `org.ehcache:ehcache-clustered` bundles alongside the `org.ehcache:ehcache` +main bundle + +When in this mode of operation it is also possible to provision the Ehcache modules as independent bundles. A minimal +Ehcache configuration will need: + +* `org.ehcache.modules:ehcache-api` +* `org.ehcache.modules:ehcache-core` +* `org.ehcache.modules:ehcache-impl` + +Additional features can then be added by including one or more of: + +* `org.ehcache.modules:ehcache-xml` +* `org.ehcache.modules:ehcache-107` +* `org.ehcache:ehcache-clustered` +* `org.ehcache:ehcache-transactions` + +=== Reverting to JDK Service Lookup + +If the `org.ehcache.core.osgi` property is set to `"false"` as either a framework or system property then Ehcache will +fall back to the JDK based service lookup mechanism. This will result in the following log line: +[source,log] +---- +org.ehcache[org.ehcache.core.osgi.EhcacheActivator] : Detected OSGi Environment (core is in bundle: org.ehcache [13]): OSGi Based Service Loading Disabled Via System/Framework Property - Extensions Outside This Bundle Will Not Be Detected +---- +Enabling debug logging will show the detected set of services: +[source,log] +---- +org.ehcache[org.ehcache.core.osgi.EhcacheActivator] : JDK Service Loading Sees: + org.ehcache.impl.internal.store.heap.OnHeapStore$Provider + org.ehcache.impl.internal.store.offheap.OffHeapStore$Provider + org.ehcache.impl.internal.store.disk.OffHeapDiskStore$Provider + org.ehcache.impl.internal.store.tiering.TieredStore$Provider + org.ehcache.impl.internal.store.tiering.CompoundCachingTier$Provider + org.ehcache.core.spi.time.TimeSourceService + org.ehcache.spi.serialization.SerializationProvider + org.ehcache.spi.loaderwriter.CacheLoaderWriterProvider + org.ehcache.core.events.CacheEventListenerProvider + org.ehcache.core.spi.service.ExecutionService + org.ehcache.core.spi.service.LocalPersistenceService + org.ehcache.impl.persistence.DefaultDiskResourceService + org.ehcache.spi.loaderwriter.WriteBehindProvider + org.ehcache.impl.internal.events.CacheEventDispatcherFactoryImpl + org.ehcache.spi.copy.CopyProvider + org.ehcache.core.spi.store.heap.SizeOfEngineProvider + org.ehcache.core.spi.service.StatisticsService + org.ehcache.spi.resilience.ResilienceStrategyProvider +---- + +In this configuration only features in the bundle with the Ehcache core classes are available. Using this service lookup +mechanism only the `org.ehcache:ehcache` (bundle symbolic name: `org.ehcache`) bundle can be succesfully deployed. Use +of this bundle provides for most of the regular Ehcache features, but *does not support transactional or clustered +caching*. + +In order to use transactional or clustered caches in this environment the user must create their own bundle by merging +the `org.ehcache:ehcache` bundle with the `org.ehcache:ehcache-clustered` and/or `org.ehcache:ehcache-transactions` +bundles. Care must be taken when creating the custom bundle that all of the `META-INF/services` files are correctly +merged to allow for correct service discovery. + From 712534abf3a46591fff7e404cffb0cd172755a27 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 13 Sep 2018 11:01:57 -0400 Subject: [PATCH 073/372] Use OSGi service lookup when inside an OSGi environment --- 107/build.gradle | 12 ++ 107/gradle.properties | 2 - .../jsr107/EhcacheCachingProvider.java | 2 + .../Jsr107CacheConfigurationParser.java | 4 +- .../Jsr107ServiceConfigurationParser.java | 4 +- api/build.gradle | 8 + build.gradle | 16 ++ buildSrc/src/main/groovy/EhDistribute.groovy | 20 +- buildSrc/src/main/groovy/EhOsgi.groovy | 95 ---------- clustered/client/build.gradle | 3 + clustered/client/gradle.properties | 2 - .../ClusteredResourceConfigurationParser.java | 2 + ...acheManagerServiceConfigurationParser.java | 5 +- ...teringCacheServiceConfigurationParser.java | 4 +- ...teredLoaderWriterStoreProviderFactory.java | 2 + ...atingLoaderWriterStoreProviderFactory.java | 2 + ...steredWriteBehindStoreProviderFactory.java | 3 +- .../service/ClusteringServiceFactory.java | 3 +- .../store/ClusteredStoreProviderFactory.java | 2 + .../client/NonClusteredCacheTest.java | 21 +- ...ManagerServiceConfigurationParserTest.java | 19 +- .../service/ClusteringServiceFactoryTest.java | 21 +- clustered/clustered-dist/build.gradle | 8 + clustered/clustered-dist/gradle.properties | 3 - clustered/osgi-test/build.gradle | 92 +++++++++ .../config/checkstyle-suppressions.xml | 9 + .../org/ehcache/osgi/ClusteredOsgiTest.java | 179 ++++++++++++++++++ .../java/org/ehcache/osgi/OsgiTestUtils.java | 171 +++++++++++++++++ .../test/java/org/ehcache/osgi/Person.java | 34 ++++ .../ehcache/osgi/ehcache-clustered-osgi.xml | 41 ++++ core/build.gradle | 16 ++ core/gradle.properties | 1 - .../core/internal/service/ServiceLocator.java | 33 ++-- .../core/internal/util/ClassLoading.java | 93 ++++++--- .../ehcache/core/osgi/EhcacheActivator.java | 52 +++++ .../ehcache/core/osgi/OsgiServiceLoader.java | 53 ++++++ .../java/org/ehcache/core/osgi/SafeOsgi.java | 63 ++++++ .../core/internal/util/ClassLoadingTest.java | 34 +--- dist/build.gradle | 21 ++ dist/gradle.properties | 1 - impl/build.gradle | 19 ++ impl/gradle.properties | 2 - .../internal/TimeSourceServiceFactory.java | 4 +- ...icationListenerServiceProviderFactory.java | 2 + .../DefaultExecutionServiceFactory.java | 4 +- .../WriteBehindProviderFactory.java | 8 +- .../DefaultDiskResourceServiceFactory.java | 2 + ...DefaultLocalPersistenceServiceFactory.java | 6 +- .../DefaultSizeOfEngineProviderFactory.java | 7 +- .../spi/copy/DefaultCopyProviderFactory.java | 5 +- ...aultCacheEventListenerProviderFactory.java | 6 +- ...faultCacheLoaderWriterProviderFactory.java | 5 +- ...aultResilienceStrategyProviderFactory.java | 2 + .../DefaultSerializationProviderFactory.java | 5 +- .../DefaultStatisticsServiceFactory.java | 2 + .../disk/OffHeapDiskStoreProviderFactory.java | 4 +- .../heap/OnHeapStoreProviderFactory.java | 4 +- .../LoaderWriterStoreProviderFactory.java | 2 + .../offheap/OffHeapStoreProviderFactory.java | 4 +- .../CompoundCachingTierProviderFactory.java | 4 +- .../tiering/TieredStoreProviderFactory.java | 4 +- ...entRegistryServiceConfigurationParser.java | 2 +- osgi-test/build.gradle | 61 ++++-- .../ehcache/osgi/ByteSizedOnHeapOsgiTest.java | 52 +++-- .../java/org/ehcache/osgi/Jsr107OsgiTest.java | 87 +++++++-- .../org/ehcache/osgi/OffHeapOsgiTest.java | 113 ++++++----- .../java/org/ehcache/osgi/OsgiTestUtils.java | 64 +++++++ .../java/org/ehcache/osgi/SimpleOsgiTest.java | 160 +++++++++++----- .../ehcache/osgi/TransactionalOsgiTest.java | 155 +++++++++++++++ .../java/org/ehcache/osgi/VersionUtil.java | 64 ------- .../org/ehcache/osgi/ehcache-xa-osgi.xml | 32 ++++ settings.gradle | 2 +- transactions/build.gradle | 12 +- transactions/gradle.properties | 3 - .../configuration/XAStoreProviderFactory.java | 2 + .../DefaultJournalProviderFactory.java | 2 + ...aultTransactionManagerProviderFactory.java | 2 + ...acheManagerServiceConfigurationParser.java | 13 +- .../TxCacheServiceConfigurationParser.java | 4 +- .../ehcache/transactions/NonXACacheTest.java | 22 +-- xml/build.gradle | 8 + xml/gradle.properties | 2 - ...acheManagerServiceConfigurationParser.java | 2 +- .../xml/CacheServiceConfigurationParser.java | 2 +- .../org/ehcache/xml/ConfigurationParser.java | 25 ++- .../xml/ServiceConfigurationParser.java | 2 +- .../ServiceCreationConfigurationParser.java | 2 +- .../test/java/org/ehcache/xml/BarParser.java | 2 +- .../java/org/ehcache/xml/FancyParser.java | 2 +- .../test/java/org/ehcache/xml/FooParser.java | 2 +- 90 files changed, 1637 insertions(+), 521 deletions(-) delete mode 100644 buildSrc/src/main/groovy/EhOsgi.groovy create mode 100644 clustered/osgi-test/build.gradle create mode 100644 clustered/osgi-test/config/checkstyle-suppressions.xml create mode 100644 clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java create mode 100644 clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java create mode 100644 clustered/osgi-test/src/test/java/org/ehcache/osgi/Person.java create mode 100644 clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml create mode 100644 core/src/main/java/org/ehcache/core/osgi/EhcacheActivator.java create mode 100644 core/src/main/java/org/ehcache/core/osgi/OsgiServiceLoader.java create mode 100644 core/src/main/java/org/ehcache/core/osgi/SafeOsgi.java create mode 100644 osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java create mode 100644 osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java delete mode 100644 osgi-test/src/test/java/org/ehcache/osgi/VersionUtil.java create mode 100644 osgi-test/src/test/resources/org/ehcache/osgi/ehcache-xa-osgi.xml diff --git a/107/build.gradle b/107/build.gradle index 8a205f3f09..2ef65c4405 100644 --- a/107/build.gradle +++ b/107/build.gradle @@ -15,6 +15,8 @@ */ apply plugin: EhDeploy +apply plugin: 'osgi' +apply plugin: 'osgi-ds' configurations { tckTestClasses @@ -37,6 +39,8 @@ dependencies { implementation project(':xml') implementation "org.terracotta:statistics:$parent.statisticVersion" + compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' + tckTestRuntime "javax.cache:cache-tests:$jcacheTckVersion" tckTestClasses("javax.cache:cache-tests:$jcacheTckVersion:tests") { transitive = false @@ -48,6 +52,14 @@ javadoc { exclude '**/tck/**' } +jar { + manifest { + instruction 'Export-Package', '!org.ehcache.jsr107.tck', '!org.ehcache.jsr107.internal.*', 'org.ehcache.jsr107.*' + instruction 'Import-Package', 'javax.cache.*;resolution:=optional', '!sun.misc.*', '!com.sun.jmx.mbeanserver.*', '*' + instruction 'Service-Component', 'OSGI-INF/*.xml' + } +} + test { if (testJava.javaVersion.isJava9Compatible()) { jvmArgs += ['--add-modules', 'java.xml.bind'] diff --git a/107/gradle.properties b/107/gradle.properties index 2be5b29d91..afb38dd5de 100644 --- a/107/gradle.properties +++ b/107/gradle.properties @@ -1,4 +1,2 @@ subPomName = Ehcache 3 JSR-107 module subPomDesc = The JSR-107 compatibility module of Ehcache 3 -osgi = {"Export-Package" : ["!org.ehcache.jsr107.tck", "!org.ehcache.jsr107.internal*"],\ - "Import-Package" : ["javax.cache.*;resolution:=optional", "!sun.misc.*", "!sun.security.action.*", "!com.sun.jmx.mbeanserver.*"]} diff --git a/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java b/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java index 46f353d777..5795b7f143 100644 --- a/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java +++ b/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java @@ -26,6 +26,7 @@ import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.xml.XmlConfiguration; +import org.osgi.service.component.annotations.Component; import java.net.URI; import java.net.URISyntaxException; @@ -47,6 +48,7 @@ /** * {@link CachingProvider} implementation for Ehcache. */ +@Component public class EhcacheCachingProvider implements CachingProvider { private static final String DEFAULT_URI_STRING = "urn:X-ehcache:jsr107-default-config"; diff --git a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java b/107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java index fd01b7b146..149acb6375 100644 --- a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java +++ b/107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java @@ -23,6 +23,7 @@ import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.xml.CacheServiceConfigurationParser; import org.ehcache.xml.exceptions.XmlConfigurationException; +import org.osgi.service.component.annotations.Component; import org.w3c.dom.Element; import java.io.IOException; @@ -35,6 +36,7 @@ /** * Jsr107CacheConfigurationParser */ +@Component public class Jsr107CacheConfigurationParser implements CacheServiceConfigurationParser { private static final URI NAMESPACE = URI.create("http://www.ehcache.org/v3/jsr107"); @@ -53,7 +55,7 @@ public URI getNamespace() { } @Override - public ServiceConfiguration parseServiceConfiguration(Element fragment) { + public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { String localName = fragment.getLocalName(); if ("mbeans".equals(localName)) { ConfigurationElementState managementEnabled = ConfigurationElementState.UNSPECIFIED; diff --git a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java b/107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java index d465058dd6..325be8163f 100644 --- a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java +++ b/107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java @@ -22,6 +22,7 @@ import org.ehcache.jsr107.Jsr107Service; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.xml.exceptions.XmlConfigurationException; +import org.osgi.service.component.annotations.Component; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -39,6 +40,7 @@ /** * @author Alex Snaps */ +@Component public class Jsr107ServiceConfigurationParser implements CacheManagerServiceConfigurationParser { private static final URI NAMESPACE = URI.create("http://www.ehcache.org/v3/jsr107"); @@ -61,7 +63,7 @@ public URI getNamespace() { } @Override - public ServiceCreationConfiguration parseServiceCreationConfiguration(final Element fragment) { + public ServiceCreationConfiguration parseServiceCreationConfiguration(final Element fragment, ClassLoader classLoader) { boolean jsr107CompliantAtomics = true; ConfigurationElementState enableManagementAll = ConfigurationElementState.UNSPECIFIED; ConfigurationElementState enableStatisticsAll = ConfigurationElementState.UNSPECIFIED; diff --git a/api/build.gradle b/api/build.gradle index 540fd89a80..ca291e48b1 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -15,7 +15,15 @@ */ apply plugin: EhDeploy +apply plugin: 'osgi' checkstyle { configFile = file("$projectDir/config/checkstyle.xml") } + +jar { + manifest { + instruction 'Export-Package', 'org.ehcache.*' + instruction 'Import-Package', '*' + } +} diff --git a/build.gradle b/build.gradle index eeb52c5238..e798721546 100644 --- a/build.gradle +++ b/build.gradle @@ -25,6 +25,8 @@ plugins { id "com.dorongold.task-tree" version "1.3.1" // Declare spotbugs at the top id 'com.github.spotbugs' version '1.6.5' apply false + // Declare osgi-ds at the top + id 'org.jayware.osgi-ds' version '0.5.5' apply false } wrapper { @@ -219,6 +221,20 @@ subprojects { // force 'org.terracotta:statistics:2.0-SNAPSHOT' } } + + if (plugins.hasPlugin('osgi')) { + jar { + manifest { + instruction 'Bundle-Name', project.properties.subPomName + instruction 'Bundle-Description', project.properties.subPomDesc + instruction 'Bundle-SymbolicName', "org.ehcache.$project.archivesBaseName" + instruction 'Bundle-DocURL', 'http://ehcache.org' + instruction 'Bundle-License', 'LICENSE' + instruction 'Bundle-Vendor', 'Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.' + instruction 'Bundle-RequiredExecutionEnvironment', 'JavaSE-1.8' + } + } + } } allprojects { diff --git a/buildSrc/src/main/groovy/EhDistribute.groovy b/buildSrc/src/main/groovy/EhDistribute.groovy index c3f2e59319..2d388cb495 100644 --- a/buildSrc/src/main/groovy/EhDistribute.groovy +++ b/buildSrc/src/main/groovy/EhDistribute.groovy @@ -1,6 +1,7 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.ProjectDependency +import org.gradle.api.plugins.osgi.OsgiPluginConvention import scripts.Utils /* @@ -33,13 +34,10 @@ class EhDistribute implements Plugin { project.plugins.apply 'maven' project.plugins.apply 'signing' project.plugins.apply 'com.github.johnrengelman.shadow' - project.plugins.apply EhOsgi project.plugins.apply EhPomMangle project.plugins.apply EhDocs project.plugins.apply EhPomGenerate - def OSGI_OVERRIDE_KEYS = ['Import-Package', 'Export-Package', 'Private-Package', 'Tool', 'Bnd-LastModified', 'Created-By', 'Require-Capability'] - project.configurations { shadowCompile shadowProvided @@ -63,6 +61,21 @@ class EhDistribute implements Plugin { // LICENSE is included in root gradle build from "$project.rootDir/NOTICE" duplicatesStrategy = 'exclude' + + def osgiConvention = new OsgiPluginConvention(project) + manifest = osgiConvention.osgiManifest { + classesDir = project.shadowJar.archivePath + classpath = project.files(project.configurations.shadowCompile, project.configurations.shadowProvided) + + // Metadata + instruction 'Bundle-DocURL', 'http://ehcache.org' + instruction 'Bundle-License', 'LICENSE' + instruction 'Bundle-Vendor', 'Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.' + instruction 'Bundle-RequiredExecutionEnvironment', 'JavaSE-1.8' + instruction 'Service-Component', 'OSGI-INF/*.xml' + } + + utils.fillManifest(manifest, project.archivesBaseName) } @@ -72,7 +85,6 @@ class EhDistribute implements Plugin { } } - project.signing { required { project.isReleaseVersion && project.gradle.taskGraph.hasTask("uploadArchives") } sign project.configurations.getByName('archives') diff --git a/buildSrc/src/main/groovy/EhOsgi.groovy b/buildSrc/src/main/groovy/EhOsgi.groovy deleted file mode 100644 index dda5ea0c88..0000000000 --- a/buildSrc/src/main/groovy/EhOsgi.groovy +++ /dev/null @@ -1,95 +0,0 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.DefaultInheritManifest -import groovy.json.JsonSlurper -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.artifacts.ProjectDependency -import org.gradle.api.internal.file.FileResolver -import org.gradle.api.plugins.osgi.OsgiPluginConvention -import scripts.Utils - -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * EhOsgi - * OSGI additions to the manifest controlled by osgi key in gradle.properties - * This plugin supports shadowJar if available - */ -class EhOsgi implements Plugin { - - @Override - void apply(Project project) { - def utils = new Utils(project.baseVersion, project.logger) - def hashsetOfProjects = project.configurations.compile.dependencies.withType(ProjectDependency).dependencyProject + - project.configurations.compileOnly.dependencies.withType(ProjectDependency).dependencyProject - hashsetOfProjects += project //self also, in case the invoking project defines osgi properties - - project.plugins.apply 'java-library' - project.plugins.apply 'maven' - project.plugins.apply 'signing' - - def OSGI_OVERRIDE_KEYS = ['Import-Package', 'Export-Package', 'Private-Package', 'Tool', 'Bnd-LastModified', 'Created-By', 'Require-Capability'] - - project.jar.doFirst { - manifest = new DefaultInheritManifest(getServices().get(FileResolver.class)) - if (project.hasProperty('shadowJar')) { - manifest.inheritFrom "$project.buildDir/tmp/shadowJar/MANIFEST.MF" - } - utils.fillManifest(manifest, project.archivesBaseName) - - def osgiConvention = new OsgiPluginConvention(project) - def osgiManifest = osgiConvention.osgiManifest { - - if (project.hasProperty('shadowJar')) { - classesDir = project.shadowJar.archivePath - classpath = project.files(project.configurations.shadowCompile, project.configurations.shadowProvided) - } else { - classesDir = project.sourceSets.main.java.outputDir - classpath = project.sourceSets.main.compileClasspath - } - - // Metadata - instructionReplace 'Bundle-Name', "$project.archivesBaseName 3" - instructionReplace 'Bundle-SymbolicName', "org.ehcache.$project.archivesBaseName" - instruction 'Bundle-Description', 'Ehcache is an open-source caching library, compliant with the JSR-107 standard.' - instruction 'Bundle-DocURL', 'http://ehcache.org' - instruction 'Bundle-License', 'LICENSE' - instruction 'Bundle-Vendor', 'Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.' - instruction 'Bundle-RequiredExecutionEnvironment', 'JavaSE-1.8' - - hashsetOfProjects.findAll({ p -> p.ext.properties.osgi}).each{ prop -> - new JsonSlurper().parseText(prop.ext.properties.osgi).each { - project.logger.info "OSGI: ${it.key}: ${it.value}" - instruction(it.key, *it.value) - } - } - - instruction 'Export-Package', '*' - instruction 'Import-Package', '*' - } - manifest.inheritFrom(osgiManifest) { - eachEntry { - if (it.getKey().startsWith('Bundle') || OSGI_OVERRIDE_KEYS.contains(it.getKey())) { - it.setValue(it.getMergeValue()) - } else { - it.setValue(it.getBaseValue()) - } - } - } - } - - } -} diff --git a/clustered/client/build.gradle b/clustered/client/build.gradle index 2198ebd21c..087c922191 100644 --- a/clustered/client/build.gradle +++ b/clustered/client/build.gradle @@ -15,6 +15,8 @@ */ apply plugin: EhDeploy +apply plugin: 'osgi' +apply plugin: 'osgi-ds' dependencies { compileOnly project(':impl') @@ -25,6 +27,7 @@ dependencies { providedImplementation "org.terracotta:runnel:$terracottaPlatformVersion" providedImplementation "org.terracotta:lease-api:$terracottaPlatformVersion" providedImplementation "org.terracotta:connection-api:$terracottaApisVersion" + compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':api') testImplementation project(':impl') diff --git a/clustered/client/gradle.properties b/clustered/client/gradle.properties index 56c6dfbf5d..8531fcc395 100644 --- a/clustered/client/gradle.properties +++ b/clustered/client/gradle.properties @@ -16,5 +16,3 @@ subPomName = Ehcache 3 Client Side Clustering module subPomDesc = The Client Side Clustering module of Ehcache 3 -osgi = {"Export-Package" : ["!org.ehcache.clustered.client.internal.*", "!sun.misc"],\ - "Import-Package" : ["!org.ehcache.clustered.client*", "!sun.misc*"]} diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java index f2858511f3..4478a5fbcd 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java @@ -24,6 +24,7 @@ import org.ehcache.xml.BaseConfigParser; import org.ehcache.xml.CacheResourceConfigurationParser; import org.ehcache.xml.exceptions.XmlConfigurationException; +import org.osgi.service.component.annotations.Component; import org.w3c.dom.Attr; import org.w3c.dom.DOMException; import org.w3c.dom.Document; @@ -46,6 +47,7 @@ /** * Provides a parser for the {@code /config/cache/resources} extension elements. */ +@Component public class ClusteredResourceConfigurationParser extends BaseConfigParser implements CacheResourceConfigurationParser { private static final String CLUSTERED_ELEMENT_NAME = "clustered"; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java index 975989101e..a883f63757 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java @@ -27,6 +27,7 @@ import org.ehcache.xml.CacheManagerServiceConfigurationParser; import org.ehcache.xml.exceptions.XmlConfigurationException; import org.ehcache.xml.model.TimeType; +import org.osgi.service.component.annotations.Component; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -63,6 +64,7 @@ * * @see ClusteredCacheConstants#XSD */ +@Component public class ClusteringCacheManagerServiceConfigurationParser extends BaseConfigParser implements CacheManagerServiceConfigurationParser { public static final String CLUSTER_ELEMENT_NAME = "cluster"; @@ -106,10 +108,11 @@ public URI getNamespace() { * This method presumes the element presented is valid according to the XSD. * * @param fragment the XML fragment to process + * @param classLoader * @return a {@link org.ehcache.clustered.client.config.ClusteringServiceConfiguration ClusteringServiceConfiguration} */ @Override - public ServiceCreationConfiguration parseServiceCreationConfiguration(final Element fragment) { + public ServiceCreationConfiguration parseServiceCreationConfiguration(final Element fragment, ClassLoader classLoader) { if ("cluster".equals(fragment.getLocalName())) { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java index f85cd0aa5b..fb3fa2c357 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java @@ -22,6 +22,7 @@ import org.ehcache.xml.BaseConfigParser; import org.ehcache.xml.CacheServiceConfigurationParser; import org.ehcache.xml.exceptions.XmlConfigurationException; +import org.osgi.service.component.annotations.Component; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -40,6 +41,7 @@ * * @see ClusteredCacheConstants#XSD */ +@Component public class ClusteringCacheServiceConfigurationParser extends BaseConfigParser implements CacheServiceConfigurationParser { public static final String CLUSTERED_STORE_ELEMENT_NAME = "clustered-store"; @@ -60,7 +62,7 @@ public URI getNamespace() { } @Override - public ServiceConfiguration parseServiceConfiguration(Element fragment) { + public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { if (CLUSTERED_STORE_ELEMENT_NAME.equals(fragment.getLocalName())) { if (fragment.hasAttribute(CONSISTENCY_ATTRIBUTE_NAME)) { return new ClusteredStoreConfiguration(Consistency.valueOf(fragment.getAttribute("consistency").toUpperCase())); diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderFactory.java index 7d68a59ce4..529c2bf1f6 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderFactory.java @@ -17,7 +17,9 @@ import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; +@Component public class ClusteredLoaderWriterStoreProviderFactory implements ServiceFactory { @Override diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProviderFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProviderFactory.java index 95828fd554..2b1d811ffd 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProviderFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProviderFactory.java @@ -17,7 +17,9 @@ import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; +@Component public class DelegatingLoaderWriterStoreProviderFactory implements ServiceFactory { @Override diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderFactory.java index a1bec31337..662c4720ab 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderFactory.java @@ -15,10 +15,11 @@ */ package org.ehcache.clustered.client.internal.loaderwriter.writebehind; -import org.ehcache.clustered.client.internal.loaderwriter.ClusteredLoaderWriterStore; import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; +@Component public class ClusteredWriteBehindStoreProviderFactory implements ServiceFactory { @Override diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java index d835ae6407..61b81ea307 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java @@ -17,16 +17,17 @@ package org.ehcache.clustered.client.internal.service; import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; -import org.ehcache.clustered.client.internal.service.DefaultClusteringService; import org.ehcache.clustered.client.service.ClusteringService; import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; /** * A factory for creating a {@link ClusteringService} instance. * * @author Clifford W. Johnson */ +@Component @ServiceFactory.RequiresConfiguration public class ClusteringServiceFactory implements ServiceFactory { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java index 2f7733ae4d..03d9a209de 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java @@ -18,10 +18,12 @@ import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; /** * Factory to create instances of {@link ClusteredStore.Provider}. */ +@Component public class ClusteredStoreProviderFactory implements ServiceFactory { @Override public ClusteredStore.Provider create(final ServiceCreationConfiguration configuration) { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java index 38ab3b9b77..e72b29449c 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java @@ -27,13 +27,13 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.internal.util.ClassLoading; import org.ehcache.core.spi.service.ServiceFactory; -import org.hamcrest.Matchers; import org.junit.Test; -import java.util.HashSet; -import java.util.Set; +import java.util.stream.Collectors; -import static org.hamcrest.core.Is.is; +import static java.util.Spliterators.spliterator; +import static java.util.stream.StreamSupport.stream; +import static org.hamcrest.core.IsCollectionContaining.hasItems; import static org.junit.Assert.assertThat; /** @@ -48,17 +48,8 @@ public void testNonClustered() throws Exception { /* * Ensure the cluster provider classes are loadable through the ServiceLoader mechanism. */ - Set> targetProviders = new HashSet<>(); - targetProviders.add(ClusteredStore.Provider.class); - targetProviders.add(ClusteringService.class); - for (ServiceFactory factory : ClassLoading.libraryServiceLoaderFor(ServiceFactory.class)) { - if (targetProviders.remove(factory.getServiceType())) { - if (targetProviders.isEmpty()) { - break; - } - } - } - assertThat(targetProviders, is(Matchers.empty())); + assertThat(stream(spliterator(ClassLoading.servicesOfType(ServiceFactory.class).iterator(), Long.MAX_VALUE, 0), false).map(f -> f.getServiceType()).collect(Collectors.toList()), + hasItems(ClusteredStore.Provider.class, ClusteringService.class)); CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder( String.class, diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java index 1bc0247e7f..337056d3e5 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java @@ -24,7 +24,6 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.internal.util.ClassLoading; import org.ehcache.core.spi.service.ServiceUtils; -import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.xml.CacheManagerServiceConfigurationParser; import org.ehcache.xml.XmlConfiguration; @@ -52,13 +51,15 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; -import java.util.ServiceLoader; +import java.util.stream.Collectors; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.stream.StreamSource; import static java.time.temporal.ChronoUnit.MINUTES; +import static java.util.Spliterators.spliterator; +import static java.util.stream.StreamSupport.stream; import static org.ehcache.xml.ConfigurationParserTestHelper.assertElement; import static org.ehcache.xml.XmlModel.convertToJavaTimeUnit; import static org.hamcrest.Matchers.containsString; @@ -67,6 +68,7 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.core.IsCollectionContaining.hasItem; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; @@ -84,17 +86,8 @@ public class ClusteringCacheManagerServiceConfigurationParserTest { */ @Test public void testServiceLocator() throws Exception { - String expectedParser = ClusteringCacheManagerServiceConfigurationParser.class.getName(); - @SuppressWarnings({"unchecked", "rawtypes"}) - ServiceLoader> parsers = (ServiceLoader) - ClassLoading.libraryServiceLoaderFor(CacheManagerServiceConfigurationParser.class); - - for (CacheManagerServiceConfigurationParser parser : parsers) { - if (parser.getClass().getName().equals(expectedParser)) { - return; - } - } - fail("Expected parser not found"); + assertThat(stream(spliterator(ClassLoading.servicesOfType(CacheManagerServiceConfigurationParser.class).iterator(), Long.MAX_VALUE, 0), false).map(Object::getClass).collect(Collectors.toList()), + hasItem(ClusteringCacheManagerServiceConfigurationParser.class)); } /** diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java index c25cf95aff..443b48f127 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java @@ -20,9 +20,12 @@ import org.ehcache.core.internal.util.ClassLoading; import org.junit.Test; -import java.util.ServiceLoader; +import java.util.stream.Collectors; -import static org.junit.Assert.fail; +import static java.util.Spliterators.spliterator; +import static java.util.stream.StreamSupport.stream; +import static org.hamcrest.core.IsCollectionContaining.hasItem; +import static org.junit.Assert.assertThat; /** * @author Clifford W. Johnson @@ -31,17 +34,7 @@ public class ClusteringServiceFactoryTest { @Test public void testServiceLocator() throws Exception { - String expectedFactory = ClusteringServiceFactory.class.getName(); - @SuppressWarnings({"unchecked", "rawtypes"}) - ServiceLoader> factories = (ServiceLoader) ClassLoading.libraryServiceLoaderFor(ServiceFactory.class); - - for (ServiceFactory factory : factories) { - if (factory.getClass().getName().equals(expectedFactory)) { - return; - } - } - - fail("Expected factory not found"); + assertThat(stream(spliterator(ClassLoading.servicesOfType(ServiceFactory.class).iterator(), Long.MAX_VALUE, 0), false).map(Object::getClass).collect(Collectors.toList()), + hasItem(ClusteringServiceFactory.class)); } - } diff --git a/clustered/clustered-dist/build.gradle b/clustered/clustered-dist/build.gradle index 3edc1af40d..cd6041d578 100644 --- a/clustered/clustered-dist/build.gradle +++ b/clustered/clustered-dist/build.gradle @@ -31,6 +31,7 @@ ext { dependencies { compileOnly(project(':clustered:client')) { exclude group: 'org.ehcache.modules', module: 'api' + exclude group: 'org.terracotta', module: 'statistics' } // Needed because declared as provided in the different projects compileOnly "org.terracotta:runnel:$parent.terracottaPlatformVersion" @@ -72,6 +73,13 @@ task copyDocs(type: Copy) { into docsFolder } +jar { + manifest { + instruction 'Export-Package', '!com.tc.*', '!com.terracotta.*', '!org.terracotta.*', '!org.ehcache.clustered.client.internal.*', '!sun.misc', 'org.ehcache.clustered.client.*' + instruction 'Import-Package', '!sun.misc.*', '*' + } +} + distributions { main { baseName = archivesBaseName diff --git a/clustered/clustered-dist/gradle.properties b/clustered/clustered-dist/gradle.properties index 048caca19b..4d52981583 100644 --- a/clustered/clustered-dist/gradle.properties +++ b/clustered/clustered-dist/gradle.properties @@ -20,6 +20,3 @@ javadocExclude = **/core/**, **/impl/**, **/xml/**, **/jsr107/**, **/transaction # Set to anything to disable SPI doc and jar generation spiJavadocDisable = true - -osgi = {"Export-Package" : ["!com.tc*", "!com.terracotta*", "!org.terracotta*"],\ - "Import-Package" : ["!com.tc*", "!com.terracotta*", "!org.terracotta*"]} diff --git a/clustered/osgi-test/build.gradle b/clustered/osgi-test/build.gradle new file mode 100644 index 0000000000..f16d5fffa1 --- /dev/null +++ b/clustered/osgi-test/build.gradle @@ -0,0 +1,92 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +configurations { + osgiModule + testCompileOnly.extendsFrom osgiModule +} + +dependencies { + osgiModule project(':api') + osgiModule project(':core') + osgiModule project(':impl') + osgiModule project(':xml') + + osgiModule project(':dist') + osgiModule project(':clustered:clustered-dist') + osgiModule "javax.cache:cache-api:$parent.jcacheVersion" + osgiModule "org.slf4j:slf4j-simple:$parent.slf4jVersion" + osgiModule 'org.apache.felix:org.apache.felix.scr:2.1.6' + + //IDEs cannot handle the :dist or :clustered:clustered-dist dependencies + testCompileOnly project(':clustered:client') + testCompileOnly project(':clustered:common') + + testImplementation 'org.apache.felix:org.apache.felix.framework:6.0.1' + testImplementation ('org.ops4j.pax.exam:pax-exam-junit4:4.12.0') { + exclude group:'org.slf4j', module:'slf4j-api' + } + + testRuntimeOnly ('org.ops4j.pax.exam:pax-exam-container-native:4.12.0') { + exclude group:'org.slf4j', module:'slf4j-api' + } + testRuntimeOnly ('org.ops4j.pax.exam:pax-exam-link-mvn:4.12.0') { + exclude group:'org.slf4j', module:'slf4j-api' + } + testRuntimeOnly ("org.ops4j.pax.url:pax-url-wrap:2.4.5") { + exclude group:'org.slf4j', module:'slf4j-api' + } + +} + +configurations.all { + resolutionStrategy { + force 'org.ops4j.base:ops4j-base-lang:1.5.0' + force 'org.ops4j.base:ops4j-base-net:1.5.0' + force 'org.ops4j.base:ops4j-base-util-property:1.5.0' + } +} + +sourceSets { + test { + // Needed for PaxExam which makes the dynamic bundle load content of a single dir + // matching the package of the test class + output.resourcesDir = java.outputDir + } +} + +configurations.osgiModule.dependencies.withType(ProjectDependency).forEach { + test.dependsOn it.dependencyProject.tasks.jar +} + +task unzipKit(type: Copy) { + dependsOn project(':clustered:clustered-dist').distZip + from zipTree(project(':clustered:clustered-dist').distZip.archivePath) + into 'build/ehcache-kit' +} + +test { + dependsOn unzipKit + + if (testJava.javaVersion.isJava9Compatible()) throw new StopExecutionException("OSGi Tests Not Working in Java 9") + + environment 'JAVA_HOME', testJava.javaHome + systemProperty 'kitInstallationPath', "$unzipKit.destinationDir/${project(':clustered:clustered-dist').archivesBaseName}-$project.version-kit" +}.doFirst { + configurations.osgiModule.resolvedConfiguration.resolvedArtifacts.forEach({ + systemProperty "$it.moduleVersion.id.module:osgi-path", it.file + }) +} diff --git a/clustered/osgi-test/config/checkstyle-suppressions.xml b/clustered/osgi-test/config/checkstyle-suppressions.xml new file mode 100644 index 0000000000..cb41d0baf7 --- /dev/null +++ b/clustered/osgi-test/config/checkstyle-suppressions.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java new file mode 100644 index 0000000000..3dcf98e8e2 --- /dev/null +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java @@ -0,0 +1,179 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.osgi; + +import org.ehcache.Cache; +import org.ehcache.PersistentCacheManager; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.osgi.EhcacheActivator; +import org.ehcache.core.osgi.OsgiServiceLoader; +import org.ehcache.core.spi.service.ServiceFactory; +import org.ehcache.xml.XmlConfiguration; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerMethod; +import org.osgi.framework.wiring.BundleWiring; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathFactory; + +import java.io.File; +import java.util.ServiceLoader; +import java.util.Set; + +import static java.util.Spliterators.spliterator; +import static java.util.stream.Collectors.toSet; +import static java.util.stream.Stream.of; +import static java.util.stream.StreamSupport.stream; +import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; +import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; +import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; +import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; +import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; +import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; +import static org.ehcache.osgi.OsgiTestUtils.startServer; +import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsCollectionContaining.hasItems; +import static org.junit.Assert.assertThat; +import static org.ops4j.pax.exam.CoreOptions.options; + +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerMethod.class) +public class ClusteredOsgiTest { + + @Rule + public TemporaryFolder serverLocation = new TemporaryFolder(); + + @Configuration + public Option[] individualModules() { + return options( + gradleBundle("org.ehcache.modules:api"), + gradleBundle("org.ehcache.modules:core"), + gradleBundle("org.ehcache.modules:impl"), + gradleBundle("org.ehcache.modules:xml"), + gradleBundle("org.ehcache:clustered-dist"), + + wrappedGradleBundle("org.terracotta:statistics"), + wrappedGradleBundle("org.ehcache:sizeof"), + wrappedGradleBundle("org.terracotta:offheap-store"), + + baseConfiguration() + ); + } + + @Configuration + public Option[] uberJar() { + return options( + gradleBundle("org.ehcache:dist"), + gradleBundle("org.ehcache:clustered-dist"), + + baseConfiguration() + ); + } + + @Test + public void testProgrammaticClusteredCache() throws Throwable { + try (OsgiTestUtils.Cluster cluster = startServer(serverLocation.newFolder().toPath())) { + TestMethods.testProgrammaticClusteredCache(cluster); + } + } + + @Test + public void testXmlClusteredCache() throws Throwable { + try (OsgiTestUtils.Cluster cluster = startServer(serverLocation.newFolder().toPath())) { + TestMethods.testXmlClusteredCache(cluster); + } + } + + @Test + public void testAllServicesAreAvailable() { + TestMethods.testAllServicesAreAvailable(); + } + + private static class TestMethods { + + public static void testProgrammaticClusteredCache(OsgiTestUtils.Cluster cluster) throws Throwable { + try (PersistentCacheManager cacheManager = newCacheManagerBuilder() + .with(cluster(cluster.getConnectionUri()).autoCreate()) + .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, + newResourcePoolsBuilder().with(clusteredDedicated("main", 2, MemoryUnit.MB)))) + .build(true)) { + + final Cache cache = cacheManager.getCache("clustered-cache", Long.class, String.class); + + cache.put(1L, "value"); + assertThat(cache.get(1L), is("value")); + } + } + + public static void testXmlClusteredCache(OsgiTestUtils.Cluster cluster) throws Exception { + File config = cluster.getWorkingArea().resolve("ehcache.xml").toFile(); + + Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(TestMethods.class.getResourceAsStream("ehcache-clustered-osgi.xml")); + XPath xpath = XPathFactory.newInstance().newXPath(); + Node clusterUriAttribute = (Node) xpath.evaluate("//config/service/cluster/connection/@url", doc, XPathConstants.NODE); + clusterUriAttribute.setTextContent(cluster.getConnectionUri().toString() + "/cache-manager"); + Transformer xformer = TransformerFactory.newInstance().newTransformer(); + xformer.transform(new DOMSource(doc), new StreamResult(config)); + + + try (PersistentCacheManager cacheManager = (PersistentCacheManager) CacheManagerBuilder.newCacheManager( + new XmlConfiguration(config.toURI().toURL(), TestMethods.class.getClassLoader()) + )) { + cacheManager.init(); + + final Cache cache = cacheManager.getCache("clustered-cache", Long.class, Person.class); + + cache.put(1L, new Person("Brian")); + assertThat(cache.get(1L).name, is("Brian")); + } + } + + public static void testAllServicesAreAvailable() { + Set osgiAvailableClasses = + stream(spliterator(OsgiServiceLoader.load(ServiceFactory.class).iterator(), Long.MAX_VALUE, 0), false) + .map(f -> f.getClass().getName()) + .collect(toSet()); + + Set jdkAvailableClasses = of(EhcacheActivator.getCoreBundle().getBundles()) + .map(b -> b.adapt(BundleWiring.class).getClassLoader()) + .flatMap(cl -> + stream(spliterator(ServiceLoader.load(ServiceFactory.class, cl).iterator(), Long.MAX_VALUE, 0), false) + .map(f -> f.getClass().getName())) + .collect(toSet()); + + assertThat(osgiAvailableClasses, hasItems(jdkAvailableClasses.toArray(new String[0]))); + } + } +} diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java new file mode 100644 index 0000000000..3f6e6dfd2e --- /dev/null +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -0,0 +1,171 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.osgi; + +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.options.UrlProvisionOption; +import org.ops4j.pax.exam.options.WrappedUrlProvisionOption; + +import java.io.Closeable; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.InetSocketAddress; +import java.net.URI; +import java.nio.channels.ServerSocketChannel; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +import static java.nio.file.Files.find; +import static java.nio.file.Files.isRegularFile; +import static java.util.Objects.requireNonNull; +import static java.util.stream.Collectors.joining; +import static org.ops4j.pax.exam.CoreOptions.bundle; +import static org.ops4j.pax.exam.CoreOptions.composite; +import static org.ops4j.pax.exam.CoreOptions.junitBundles; +import static org.ops4j.pax.exam.CoreOptions.systemProperty; +import static org.ops4j.pax.exam.CoreOptions.wrappedBundle; + +public class OsgiTestUtils { + + public static Option baseConfiguration() { + return composite( + gradleBundle("org.slf4j:slf4j-api"), + gradleBundle("org.slf4j:slf4j-simple").noStart(), + gradleBundle("org.apache.felix:org.apache.felix.scr"), + systemProperty("pax.exam.osgi.unresolved.fail").value("true"), + junitBundles() + ); + } + + public static UrlProvisionOption gradleBundle(String module) { + return bundle(artifact(module).toUri().toString()); + } + + public static WrappedUrlProvisionOption wrappedGradleBundle(String module) { + return wrappedBundle(artifact(module).toUri().toString()); + } + + private static Path artifact(String module) { + Path path = Paths.get(requireNonNull(System.getProperty(module + ":osgi-path"), module + " not available")); + if (isRegularFile(path)) { + return path; + } else { + throw new IllegalArgumentException("Module '" + module + "' not found at " + path); + } + } + + public static Cluster startServer(Path serverDirectory) throws IOException { + Path kitLocation = Paths.get(System.getProperty("kitInstallationPath")); + + Path configFile = serverDirectory.resolve("tc-config.xml"); + int tsaPort = selectAvailableEphemeralPort(); + int tsaGroupPort = selectAvailableEphemeralPort(); + + try (PrintWriter writer = new PrintWriter(new FileWriter(configFile.toFile()))) { + writer.println(""); + writer.println(""); + writer.println(""); + writer.println(""); + writer.println(""); + writer.println("32"); + writer.println(""); + writer.println(""); + writer.println(""); + writer.println(""); + writer.println(""); + writer.println("" + serverDirectory.toString() + ""); + writer.println("" + tsaPort + ""); + writer.println("" + tsaGroupPort + ""); + writer.println(""); + writer.println("120"); + writer.println(""); + writer.println(""); + writer.println(""); + } + + + Path serverDir = kitLocation.resolve("server"); + + String pluginClasspath = Stream.of( + serverDir.resolve("plugins").resolve("lib"), + serverDir.resolve("plugins").resolve("api") + ).flatMap(dir -> { + try { + return find(dir, 10, (p, a) -> a.isRegularFile() && p.getFileName().toString().endsWith(".jar")); + } catch (IOException e) { + return Stream.empty(); + } + }).map(p -> p.toString()).collect(joining(File.pathSeparator)); + + ProcessBuilder serverProcess = new ProcessBuilder() + .directory(serverDirectory.toFile()) + .command(Paths.get(System.getProperty("java.home")).resolve("bin") + .resolve(System.getProperty("os.name").contains("Windows") ? "java.exe" : "java").toString(), + "-Dtc.install-root=" + serverDir, + "-cp", serverDir.resolve("lib").resolve("tc.jar") + File.pathSeparator + pluginClasspath, + "com.tc.server.TCServerMain", + "-f", configFile.toString()) + .inheritIO(); + + return new Cluster(serverProcess.start(), URI.create("terracotta://localhost:" + tsaPort), serverDirectory); + } + + private static int selectAvailableEphemeralPort() throws IOException { + try (ServerSocketChannel channel = ServerSocketChannel.open().bind(new InetSocketAddress(0))) { + return channel.socket().getLocalPort(); + } + } + + static class Cluster implements Closeable { + + private final Process serverProcess; + private final URI connectionUri; + private final Path workingPath; + + Cluster(Process serverProcess, URI connectionUri, Path workingPath) { + this.serverProcess = serverProcess; + this.connectionUri = connectionUri; + this.workingPath = workingPath; + } + + public URI getConnectionUri() { + return connectionUri; + } + + @Override + public void close() throws IOException { + try { + serverProcess.destroyForcibly(); + } finally { + try { + serverProcess.waitFor(60, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new AssertionError(e); + } + } + } + + public Path getWorkingArea() { + return workingPath; + } + } +} + diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/Person.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/Person.java new file mode 100644 index 0000000000..568a9b4be5 --- /dev/null +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/Person.java @@ -0,0 +1,34 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.osgi; + +import java.io.Serializable; + +/** + * Person + */ +public class Person implements Serializable { + + private static final long serialVersionUID = 1L; + + final String name; + + Person(String name) { + this.name = name; + } + +} diff --git a/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml b/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml new file mode 100644 index 0000000000..053ae5fc5e --- /dev/null +++ b/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + java.lang.Long + org.ehcache.osgi.Person + + 100 + 1 + + + diff --git a/core/build.gradle b/core/build.gradle index ec8eea368d..f5b9904422 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -15,9 +15,25 @@ */ apply plugin: EhDeploy +apply plugin: 'osgi' dependencies { api project(':api') api "org.terracotta:statistics:$parent.statisticVersion" + compileOnly 'org.osgi:osgi.core:6.0.0' testImplementation project(':spi-tester') } + +jar { + manifest { + instruction 'Bundle-Activator', 'org.ehcache.core.osgi.EhcacheActivator' + instruction 'Export-Package', + 'org.ehcache.core.internal.events', + 'org.ehcache.core.internal.resilience', + 'org.ehcache.core.internal.service', + 'org.ehcache.core.internal.store', + 'org.ehcache.core.internal.util', + '!org.ehcache.core.internal.*', 'org.ehcache.core.*' + instruction 'Import-Package', '*' + } +} diff --git a/core/gradle.properties b/core/gradle.properties index 33ccc9d13a..d33b3d08d9 100644 --- a/core/gradle.properties +++ b/core/gradle.properties @@ -1,3 +1,2 @@ subPomName = Ehcache 3 Core module subPomDesc = The Core module of Ehcache 3 -osgi = {"Export-Package" : ["!org.ehcache.core.internal.*"]} diff --git a/core/src/main/java/org/ehcache/core/internal/service/ServiceLocator.java b/core/src/main/java/org/ehcache/core/internal/service/ServiceLocator.java index 2150a4bfbe..5b2110229e 100644 --- a/core/src/main/java/org/ehcache/core/internal/service/ServiceLocator.java +++ b/core/src/main/java/org/ehcache/core/internal/service/ServiceLocator.java @@ -42,7 +42,6 @@ import java.util.List; import java.util.Map; import java.util.OptionalInt; -import java.util.ServiceLoader; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; @@ -56,6 +55,9 @@ import static java.util.Collections.unmodifiableSet; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toList; +import static java.util.stream.StreamSupport.stream; +import static org.ehcache.core.internal.util.ClassLoading.delegationChain; +import static org.ehcache.core.internal.util.ClassLoading.getDefaultClassLoader; /** * Provides discovery and tracking services for {@link Service} implementations. @@ -228,8 +230,8 @@ private boolean hasRunningDependents(Service service, Iterable running) public static class DependencySet implements Builder { - @SuppressWarnings("rawtypes") - private final ServiceLoader serviceLoader = ClassLoading.libraryServiceLoaderFor(ServiceFactory.class); + @SuppressWarnings({"rawtypes", "unchecked"}) + private final Iterable> serviceFactories = (Iterable) ClassLoading.servicesOfType(ServiceFactory.class); private final ServiceMap provided = new ServiceMap(); private final Set> requested = new HashSet<>(); @@ -256,14 +258,14 @@ public DependencySet with(ServiceCreationConfiguration co } @SuppressWarnings("unchecked") - Collection> serviceFactories = getServiceFactories(serviceLoader).stream() + Collection> typedServiceFactories = stream(serviceFactories.spliterator(), false) .filter(f -> serviceType.isAssignableFrom(f.getServiceType())).map(f -> (ServiceFactory) f) .collect(toList()); - OptionalInt highestRank = serviceFactories.stream().mapToInt(ServiceFactory::rank).max(); + OptionalInt highestRank = typedServiceFactories.stream().mapToInt(ServiceFactory::rank).max(); if (highestRank.isPresent()) { - serviceFactories.stream().filter(f -> highestRank.getAsInt() == f.rank()).forEach(f -> with(f.create(config))); + typedServiceFactories.stream().filter(f -> highestRank.getAsInt() == f.rank()).forEach(f -> with(f.create(config))); return this; } else { throw new IllegalStateException("No factories exist for " + serviceType); @@ -329,7 +331,7 @@ public ServiceLocator build() { } if (includeMandatoryServices) { - for (List> factories : getServiceFactories(serviceLoader).stream().collect(groupingBy(ServiceFactory::getServiceType)).values()) { + for (List> factories : stream(serviceFactories.spliterator(), false).collect(groupingBy(ServiceFactory::getServiceType)).values()) { OptionalInt highestRank = factories.stream().mapToInt(ServiceFactory::rank).max(); if (highestRank.isPresent()) { @@ -415,17 +417,17 @@ private ServiceMap lookupService(ServiceMap resolved, Class< */ private Collection> discoverServices(ServiceMap resolved, Class serviceClass) { @SuppressWarnings("unchecked") - Collection> serviceFactories = getServiceFactories(serviceLoader).stream() + Collection> typedServiceFactories = stream(serviceFactories.spliterator(), false) .filter(f -> serviceClass.isAssignableFrom(f.getServiceType())).map(f -> (ServiceFactory) f) .filter(f -> !f.getClass().isAnnotationPresent(ServiceFactory.RequiresConfiguration.class)) .filter(f -> !provided.contains(f.getServiceType())) .filter(f -> !resolved.contains(f.getServiceType())) .collect(toList()); - OptionalInt highestRank = serviceFactories.stream().mapToInt(ServiceFactory::rank).max(); + OptionalInt highestRank = typedServiceFactories.stream().mapToInt(ServiceFactory::rank).max(); if (highestRank.isPresent()) { - return serviceFactories.stream().filter(f -> highestRank.getAsInt() == f.rank()).collect(toList()); + return typedServiceFactories.stream().filter(f -> highestRank.getAsInt() == f.rank()).collect(toList()); } else { return emptyList(); } @@ -466,7 +468,7 @@ private static Set> identifyImmediateDependenciesOf(fin if (optionalAnnotation != null) { for (String className : optionalAnnotation.value()) { try { - Class dependencyClass = ClassLoading.getDefaultClassLoader().loadClass(className); + Class dependencyClass = delegationChain(getDefaultClassLoader(), clazz.getClassLoader()).loadClass(className); if (Service.class.isAssignableFrom(dependencyClass)) { @SuppressWarnings("unchecked") Class serviceDependency = (Class) dependencyClass; @@ -515,15 +517,6 @@ private static Set> identifyTransitiveDependenciesOf(fi return transitive; } - @SuppressWarnings("unchecked") - private static Collection> getServiceFactories(@SuppressWarnings("rawtypes") ServiceLoader serviceFactory) { - List> list = new ArrayList<>(); - for (ServiceFactory factory : serviceFactory) { - list.add((ServiceFactory)factory); - } - return list; - } - private static class DependencyException extends Exception { private static final long serialVersionUID = -5269926129639323941L; diff --git a/core/src/main/java/org/ehcache/core/internal/util/ClassLoading.java b/core/src/main/java/org/ehcache/core/internal/util/ClassLoading.java index aec4cd8128..144aef780a 100644 --- a/core/src/main/java/org/ehcache/core/internal/util/ClassLoading.java +++ b/core/src/main/java/org/ehcache/core/internal/util/ClassLoading.java @@ -16,73 +16,104 @@ package org.ehcache.core.internal.util; +import org.ehcache.core.osgi.SafeOsgi; +import org.ehcache.core.osgi.OsgiServiceLoader; + import java.io.IOException; import java.net.URL; -import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Collection; import java.util.Enumeration; +import java.util.List; import java.util.ServiceLoader; +import java.util.function.Supplier; + +import static java.security.AccessController.doPrivileged; +import static java.util.Collections.enumeration; +import static java.util.Collections.list; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Stream.concat; +import static java.util.stream.Stream.of; public class ClassLoading { private static final ClassLoader DEFAULT_CLASSLOADER; static { - DEFAULT_CLASSLOADER = AccessController.doPrivileged((PrivilegedAction) DefaultClassLoader::new); + DEFAULT_CLASSLOADER = delegationChain(() -> Thread.currentThread().getContextClassLoader(), ChainedClassLoader.class.getClassLoader()); } public static ClassLoader getDefaultClassLoader() { return DEFAULT_CLASSLOADER; } - public static ServiceLoader libraryServiceLoaderFor(Class serviceType) { - return ServiceLoader.load(serviceType, ClassLoading.class.getClassLoader()); + public static Iterable servicesOfType(Class serviceType) { + if (SafeOsgi.useOSGiServiceLoading()) { + return OsgiServiceLoader.load(serviceType); + } else { + return ServiceLoader.load(serviceType, ClassLoading.class.getClassLoader()); + } + } + + @SuppressWarnings("unchecked") + public static ClassLoader delegationChain(Supplier loader, ClassLoader ... loaders) { + return doPrivileged((PrivilegedAction) () -> new ChainedClassLoader(concat(of(loader), of(loaders).map(l -> () -> l)).collect(toList()))); + } + + @SuppressWarnings("unchecked") + public static ClassLoader delegationChain(ClassLoader ... loaders) { + return doPrivileged((PrivilegedAction) () -> new ChainedClassLoader(of(loaders).>map(l -> () -> l).collect(toList()))); } - private static class DefaultClassLoader extends ClassLoader { - private static final ClassLoader THIS_LOADER = DefaultClassLoader.class.getClassLoader(); + private static class ChainedClassLoader extends ClassLoader { + + private final List> loaders; + + public ChainedClassLoader(List> loaders) { + this.loaders = loaders; + } @Override public Class loadClass(String name) throws ClassNotFoundException { - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - - if (loader != null) { - try { - return loader.loadClass(name); - } catch (ClassNotFoundException cnfe) { - // + ClassNotFoundException lastFailure = new ClassNotFoundException(name); + for (Supplier loader : loaders) { + ClassLoader classLoader = loader.get(); + if (classLoader != null) { + try { + return classLoader.loadClass(name); + } catch (ClassNotFoundException cnfe) { + lastFailure = cnfe; + } } } - - return THIS_LOADER.loadClass(name); + throw lastFailure; } @Override public URL getResource(String name) { - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - - if (loader != null) { - URL res = loader.getResource(name); - if (res != null) { - return res; + for (Supplier loader : loaders) { + ClassLoader classLoader = loader.get(); + if (classLoader != null) { + URL resource = classLoader.getResource(name); + if (resource != null) { + return resource; + } } } - - return THIS_LOADER.getResource(name); + return null; } @Override public Enumeration getResources(String name) throws IOException { - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - - if (loader != null) { - Enumeration resources = loader.getResources(name); - if (resources != null && resources.hasMoreElements()) { - return resources; + Collection aggregate = new ArrayList<>(); + for (Supplier loader : loaders) { + ClassLoader classLoader = loader.get(); + if (classLoader != null) { + aggregate.addAll(list(classLoader.getResources(name))); } } - - return THIS_LOADER.getResources(name); + return enumeration(aggregate); } } } diff --git a/core/src/main/java/org/ehcache/core/osgi/EhcacheActivator.java b/core/src/main/java/org/ehcache/core/osgi/EhcacheActivator.java new file mode 100644 index 0000000000..4960afd954 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/osgi/EhcacheActivator.java @@ -0,0 +1,52 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.core.osgi; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.atomic.AtomicReference; + +public class EhcacheActivator implements BundleActivator { + + private static final Logger LOGGER = LoggerFactory.getLogger(EhcacheActivator.class); + + private static final AtomicReference CORE_BUNDLE = new AtomicReference<>(); + + @Override + public void start(BundleContext context) throws Exception { + BundleContext currentContext = CORE_BUNDLE.getAndUpdate(current -> current == null ? context : current); + if (currentContext == null) { + SafeOsgi.enableOSGiServiceLoading(); + LOGGER.info("Detected OSGi Environment (core is in bundle: " + context.getBundle() + "): OSGi Based Service Loading Enabled Via System/Framework Property"); + } else { + throw new IllegalStateException("Multiple bundle instances running against the same core classes: existing bundle: " + currentContext.getBundle() + " new bundle: " + context.getBundle()); + } + } + + @Override + public void stop(BundleContext context) throws Exception { + SafeOsgi.disableOSGiServiceLoading(); + CORE_BUNDLE.set(null); + } + + public static BundleContext getCoreBundle() { + return CORE_BUNDLE.get(); + } +} diff --git a/core/src/main/java/org/ehcache/core/osgi/OsgiServiceLoader.java b/core/src/main/java/org/ehcache/core/osgi/OsgiServiceLoader.java new file mode 100644 index 0000000000..9dac70dd91 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/osgi/OsgiServiceLoader.java @@ -0,0 +1,53 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.core.osgi; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.toList; + +/** + * An OSGi service based equivalent to {@link java.util.ServiceLoader}. + *

+ * This class is used by the {@link org.ehcache.core.spi.ServiceLocator ServiceLocator} (via + * {@link org.ehcache.core.util.ClassLoading#servicesOfType(Class) ClassLoading.servicesOfType(Class)}) to discover services when running inside an OSGi + * environment. This is needed when the required Ehcache services are split across multiple OSGi bundles. + */ +public class OsgiServiceLoader { + + /** + * Locate all services of type {@code T}. + * + * @param serviceType concrete service class + * @param service type + * @return an iterable of {@code T} services + */ + public static Iterable load(Class serviceType) { + try { + BundleContext coreBundle = EhcacheActivator.getCoreBundle(); + return coreBundle.getServiceReferences(serviceType, null).stream().map(coreBundle::getService).collect(toList()); + } catch (InvalidSyntaxException e) { + throw new AssertionError(e); + } + } +} diff --git a/core/src/main/java/org/ehcache/core/osgi/SafeOsgi.java b/core/src/main/java/org/ehcache/core/osgi/SafeOsgi.java new file mode 100644 index 0000000000..f36e3a32ad --- /dev/null +++ b/core/src/main/java/org/ehcache/core/osgi/SafeOsgi.java @@ -0,0 +1,63 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.core.osgi; + +/** + * A classpath-safe decoupler for the OSGi service loading status. + *

+ * This class provides an OSGi class-decoupled way of checking whether OSGi service loading should be used. It is safe + * to load and call methods on this class when OSGi classes are not present. + */ +public final class SafeOsgi { + + private static volatile boolean OSGI_SERVICE_LOADING; + + /** + * Returns {@code true} if OSGi based service loading should be used. + *

+ * A {@code true} return indicates that Ehcache is running in an OSGi environment and that the user has enabled OSGi + * based service loading. + * + * @return {@code true} if OSGi service loading is enabled. + */ + public static boolean useOSGiServiceLoading() { + return OSGI_SERVICE_LOADING; + } + + /** + * Marks OSGi service loading as enabled. + *

+ * This is called by the {@link EhcacheActivator} when the user has enabled OSGi service loading. + */ + static void enableOSGiServiceLoading() { + OSGI_SERVICE_LOADING = true; + } + + /** + * Marks OSGi service loading as enabled. + *

+ * This is called by the {@link EhcacheActivator} when the user has not enabled OSGi service loading, and also when + * the Ehcache core bundle is stopped. + */ + static void disableOSGiServiceLoading() { + OSGI_SERVICE_LOADING = false; + } + + private SafeOsgi() { + //static holder + } +} diff --git a/core/src/test/java/org/ehcache/core/internal/util/ClassLoadingTest.java b/core/src/test/java/org/ehcache/core/internal/util/ClassLoadingTest.java index 90d7495d2b..c482135de9 100644 --- a/core/src/test/java/org/ehcache/core/internal/util/ClassLoadingTest.java +++ b/core/src/test/java/org/ehcache/core/internal/util/ClassLoadingTest.java @@ -16,6 +16,9 @@ package org.ehcache.core.internal.util; +import static java.util.Collections.list; +import static org.hamcrest.collection.IsIterableContainingInOrder.contains; +import static org.hamcrest.core.Is.is; import static org.junit.Assert.*; import java.io.ByteArrayOutputStream; @@ -25,7 +28,6 @@ import java.util.Enumeration; import java.util.Vector; -import org.ehcache.core.internal.util.ClassLoading; import org.junit.Test; public class ClassLoadingTest { @@ -39,12 +41,12 @@ public void testDefaultClassLoader() throws Exception { Thread.currentThread().setContextClassLoader(null); assertSame(thisLoader.loadClass(getClass().getName()), defaultClassLoader.loadClass(getClass().getName())); assertEquals(thisLoader.getResource(resource), defaultClassLoader.getResource(resource)); - assertEqualEnumeration(thisLoader.getResources(resource), defaultClassLoader.getResources(resource)); + assertThat(list(defaultClassLoader.getResources(resource)), is(list(thisLoader.getResources(resource)))); Thread.currentThread().setContextClassLoader(new FindNothingLoader()); assertSame(thisLoader.loadClass(getClass().getName()), defaultClassLoader.loadClass(getClass().getName())); assertEquals(thisLoader.getResource(resource), defaultClassLoader.getResource(resource)); - assertEqualEnumeration(thisLoader.getResources(resource), defaultClassLoader.getResources(resource)); + assertThat(list(defaultClassLoader.getResources(resource)), is(list(thisLoader.getResources(resource)))); URL url = new URL("file:///tmp"); ClassLoader tc = new TestClassLoader(url); @@ -53,7 +55,7 @@ public void testDefaultClassLoader() throws Exception { assertNotSame(getClass(), c); assertSame(tc, c.getClassLoader()); assertEquals(url, defaultClassLoader.getResource(resource)); - assertEqualEnumeration(enumerationOf(url), defaultClassLoader.getResources(resource)); + assertThat(list(defaultClassLoader.getResources(resource)), contains(url, thisLoader.getResource(resource))); } @SafeVarargs @@ -120,28 +122,4 @@ public Enumeration getResources(String name) throws IOException { return new Vector().elements(); } } - - private void assertEqualEnumeration(Enumeration e1, Enumeration e2) { - while (e1.hasMoreElements()) { - if (!e2.hasMoreElements()) { - throw new AssertionError(); - } - - Object o1 = e1.nextElement(); - Object o2 = e2.nextElement(); - - if (o1 == null || o2 == null) { - throw new AssertionError(); - } - - if ((!o1.equals(o2)) || (!o2.equals(o1))) { - throw new AssertionError(); - } - } - - if (e2.hasMoreElements()) { - throw new AssertionError(); - } - } - } diff --git a/dist/build.gradle b/dist/build.gradle index fec683687b..396335af5b 100644 --- a/dist/build.gradle +++ b/dist/build.gradle @@ -30,3 +30,24 @@ apply plugin: EhDistribute dependencies { shadowCompile "org.slf4j:slf4j-api:$parent.slf4jVersion" } + +jar { + manifest { + instructionReplace 'Bundle-Name', "Ehcache 3" + instructionReplace 'Bundle-SymbolicName', "org.ehcache" + instructionReplace 'Bundle-Description', 'Ehcache is an open-source caching library, compliant with the JSR-107 standard.' + + instruction 'Bundle-Activator', 'org.ehcache.core.osgi.EhcacheActivator' + instruction 'Export-Package', + '!org.ehcache.jsr107.tck', '!org.ehcache.*.internal.*', 'org.ehcache.*', + 'org.terracotta.statistics.*', 'org.terracotta.context', + 'org.ehcache.core.internal.store', + 'org.ehcache.core.internal.util', + 'org.ehcache.impl.internal.concurrent', + 'org.ehcache.impl.internal.events', + 'org.ehcache.impl.internal.store.basic', + 'org.ehcache.impl.internal.store.loaderwriter', + 'org.ehcache.impl.internal.util' + instruction 'Import-Package', 'javax.cache.*;resolution:=optional', '!org.ehcache', '!sun.misc.*', '!com.sun.jmx.mbeanserver.*', '*' + } +} diff --git a/dist/gradle.properties b/dist/gradle.properties index 0c433da83d..944561ba5a 100644 --- a/dist/gradle.properties +++ b/dist/gradle.properties @@ -17,4 +17,3 @@ subPomName = Ehcache subPomDesc = End-user ehcache3 jar artifact javadocExclude = **/core/**, **/impl/**, **/xml/**, **/jsr107/**, **/transactions/**, **/management/**, **/tck/** -osgi = {"Import-Package" : ["!org.ehcache.*", "!org.terracotta.*"]} diff --git a/impl/build.gradle b/impl/build.gradle index 7d56bd2513..0da519e47d 100644 --- a/impl/build.gradle +++ b/impl/build.gradle @@ -15,6 +15,8 @@ */ apply plugin: EhDeploy +apply plugin: 'osgi' +apply plugin: 'osgi-ds' dependencies { api project(':core') @@ -23,6 +25,7 @@ dependencies { exclude group:'org.slf4j', module:'slf4j-api' } implementation ("org.terracotta:statistics:$parent.statisticVersion") + compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':core-spi-test') testImplementation 'org.ow2.asm:asm:6.2' testImplementation 'org.ow2.asm:asm-commons:6.2' @@ -30,6 +33,22 @@ dependencies { jar { from "$rootDir/NOTICE" + manifest { + instruction 'Export-Package', + 'org.ehcache.impl.internal.classes', + 'org.ehcache.impl.internal.concurrent', + 'org.ehcache.impl.internal.events', + 'org.ehcache.impl.internal.spi.loaderwriter', + 'org.ehcache.impl.internal.spi.serialization', + 'org.ehcache.impl.internal.store.basic', + 'org.ehcache.impl.internal.store.loaderwriter', + 'org.ehcache.impl.internal.util', + + '!org.ehcache.impl.internal.*', + 'org.ehcache.impl.*', 'org.ehcache.config.builders' + instruction 'Import-Package', '!sun.misc', '*' + instruction 'Service-Component', 'OSGI-INF/*.xml' + } } compileJava { diff --git a/impl/gradle.properties b/impl/gradle.properties index a89604d2bc..1c43b6bdd0 100644 --- a/impl/gradle.properties +++ b/impl/gradle.properties @@ -1,4 +1,2 @@ subPomName = Ehcache 3 Implementation module subPomDesc = The implementation module of Ehcache 3 -osgi = {"Export-Package" : ["!org.terracotta.offheapstore.*", "!org.ehcache.impl.internal.*"],\ - "Import-Package" : ["!sun.misc.*", "!sun.security.action.*"]} diff --git a/impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java b/impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java index ab7577b741..1efd9becf4 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java @@ -16,13 +16,15 @@ package org.ehcache.impl.internal; +import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.core.spi.time.TimeSourceService; import org.ehcache.spi.service.ServiceCreationConfiguration; -import org.ehcache.core.spi.service.ServiceFactory; +import org.osgi.service.component.annotations.Component; /** * TimeSourceServiceFactory */ +@Component public class TimeSourceServiceFactory implements ServiceFactory { @Override public TimeSourceService create(ServiceCreationConfiguration configuration) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/CacheEventNotificationListenerServiceProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/events/CacheEventNotificationListenerServiceProviderFactory.java index acb05eae07..9b3c58db51 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/events/CacheEventNotificationListenerServiceProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/events/CacheEventNotificationListenerServiceProviderFactory.java @@ -19,7 +19,9 @@ import org.ehcache.core.events.CacheEventDispatcherFactory; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.core.spi.service.ServiceFactory; +import org.osgi.service.component.annotations.Component; +@Component public class CacheEventNotificationListenerServiceProviderFactory implements ServiceFactory { @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java b/impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java index c1423cd0a3..f3fb706a92 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java @@ -15,15 +15,17 @@ */ package org.ehcache.impl.internal.executor; +import org.ehcache.core.spi.service.ExecutionService; import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.impl.config.executor.PooledExecutionServiceConfiguration; -import org.ehcache.core.spi.service.ExecutionService; import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; /** * * @author cdennis */ +@Component public class DefaultExecutionServiceFactory implements ServiceFactory { @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java index 1328dd60b2..f4cfd3f303 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java @@ -15,21 +15,23 @@ */ package org.ehcache.impl.internal.loaderwriter.writebehind; +import org.ehcache.core.spi.service.ExecutionService; +import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.impl.config.loaderwriter.writebehind.WriteBehindProviderConfiguration; -import org.ehcache.spi.service.ServiceProvider; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.loaderwriter.WriteBehindConfiguration; import org.ehcache.spi.loaderwriter.WriteBehindProvider; -import org.ehcache.core.spi.service.ExecutionService; import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.spi.service.ServiceDependencies; -import org.ehcache.core.spi.service.ServiceFactory; +import org.ehcache.spi.service.ServiceProvider; +import org.osgi.service.component.annotations.Component; /** * @author Abhilash * */ +@Component public class WriteBehindProviderFactory implements ServiceFactory { @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java b/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java index 3680ed45cd..7630656387 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java @@ -19,7 +19,9 @@ import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.impl.persistence.DefaultDiskResourceService; import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; +@Component public class DefaultDiskResourceServiceFactory implements ServiceFactory { @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java b/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java index 55ae580bc2..5bcf93a490 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java @@ -16,15 +16,17 @@ package org.ehcache.impl.internal.persistence; -import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; import org.ehcache.core.spi.service.LocalPersistenceService; +import org.ehcache.core.spi.service.ServiceFactory; +import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; import org.ehcache.impl.persistence.DefaultLocalPersistenceService; import org.ehcache.spi.service.ServiceCreationConfiguration; -import org.ehcache.core.spi.service.ServiceFactory; +import org.osgi.service.component.annotations.Component; /** * @author Alex Snaps */ +@Component @ServiceFactory.RequiresConfiguration public class DefaultLocalPersistenceServiceFactory implements ServiceFactory { diff --git a/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java index 3cbd00c945..b1a1043d11 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java @@ -16,17 +16,18 @@ package org.ehcache.impl.internal.sizeof; +import org.ehcache.core.spi.service.ServiceFactory; +import org.ehcache.core.spi.store.heap.SizeOfEngineProvider; import org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration; import org.ehcache.impl.config.store.heap.DefaultSizeOfEngineProviderConfiguration; import org.ehcache.spi.service.ServiceCreationConfiguration; -import org.ehcache.core.spi.service.ServiceFactory; -import org.ehcache.core.spi.store.heap.SizeOfEngineProvider; +import org.osgi.service.component.annotations.Component; /** * @author Abhilash * */ - +@Component public class DefaultSizeOfEngineProviderFactory implements ServiceFactory { @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java index e6c2b83ec6..a1efec10e4 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java @@ -16,15 +16,16 @@ package org.ehcache.impl.internal.spi.copy; +import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.impl.config.copy.DefaultCopyProviderConfiguration; -import org.ehcache.impl.internal.spi.copy.DefaultCopyProvider; import org.ehcache.spi.copy.CopyProvider; import org.ehcache.spi.service.ServiceCreationConfiguration; -import org.ehcache.core.spi.service.ServiceFactory; +import org.osgi.service.component.annotations.Component; /** * @author Albin Suresh */ +@Component public class DefaultCopyProviderFactory implements ServiceFactory { @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java index 5a419fe4c9..e16d07e6c1 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java @@ -17,12 +17,14 @@ package org.ehcache.impl.internal.spi.event; import org.ehcache.core.events.CacheEventListenerProvider; -import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.core.spi.service.ServiceFactory; +import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; /** * @author rism */ +@Component public class DefaultCacheEventListenerProviderFactory implements ServiceFactory { @Override @@ -34,4 +36,4 @@ public DefaultCacheEventListenerProvider create(ServiceCreationConfiguration getServiceType() { return CacheEventListenerProvider.class; } -} \ No newline at end of file +} diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java index e99a445507..8c5591ad6f 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java @@ -16,15 +16,16 @@ package org.ehcache.impl.internal.spi.loaderwriter; +import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.impl.config.loaderwriter.DefaultCacheLoaderWriterProviderConfiguration; -import org.ehcache.impl.internal.spi.loaderwriter.DefaultCacheLoaderWriterProvider; import org.ehcache.spi.loaderwriter.CacheLoaderWriterProvider; import org.ehcache.spi.service.ServiceCreationConfiguration; -import org.ehcache.core.spi.service.ServiceFactory; +import org.osgi.service.component.annotations.Component; /** * @author Alex Snaps */ +@Component public class DefaultCacheLoaderWriterProviderFactory implements ServiceFactory { @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java index f09c0d1352..5248a34014 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java @@ -19,7 +19,9 @@ import org.ehcache.impl.config.resilience.DefaultResilienceStrategyProviderConfiguration; import org.ehcache.spi.resilience.ResilienceStrategyProvider; import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; +@Component public class DefaultResilienceStrategyProviderFactory implements ServiceFactory { @Override public ResilienceStrategyProvider create(ServiceCreationConfiguration configuration) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java index a738fee32a..b1f75c8280 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java @@ -16,15 +16,16 @@ package org.ehcache.impl.internal.spi.serialization; +import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.impl.config.serializer.DefaultSerializationProviderConfiguration; -import org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider; import org.ehcache.spi.serialization.SerializationProvider; import org.ehcache.spi.service.ServiceCreationConfiguration; -import org.ehcache.core.spi.service.ServiceFactory; +import org.osgi.service.component.annotations.Component; /** * @author Ludovic Orban */ +@Component public class DefaultSerializationProviderFactory implements ServiceFactory { @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceFactory.java b/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceFactory.java index 2e8aaf561d..182fed5666 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceFactory.java @@ -19,7 +19,9 @@ import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; +@Component public class DefaultStatisticsServiceFactory implements ServiceFactory { @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java index b259debf1a..6a81d69be9 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java @@ -16,13 +16,15 @@ package org.ehcache.impl.internal.store.disk; +import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.impl.config.store.disk.OffHeapDiskStoreProviderConfiguration; import org.ehcache.spi.service.ServiceCreationConfiguration; -import org.ehcache.core.spi.service.ServiceFactory; +import org.osgi.service.component.annotations.Component; /** * @author Chris Dennis */ +@Component public class OffHeapDiskStoreProviderFactory implements ServiceFactory { @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java index 13f97b8df6..d0b4ff9edd 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java @@ -16,12 +16,14 @@ package org.ehcache.impl.internal.store.heap; -import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.core.spi.service.ServiceFactory; +import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; /** * @author Alex Snaps */ +@Component public class OnHeapStoreProviderFactory implements ServiceFactory { @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProviderFactory.java index 7d3f831266..7330837d0a 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProviderFactory.java @@ -17,7 +17,9 @@ import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; +@Component public class LoaderWriterStoreProviderFactory implements ServiceFactory { @Override public LoaderWriterStoreProvider create(ServiceCreationConfiguration configuration) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java index 4d3865d91e..a7df475f21 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java @@ -16,12 +16,14 @@ package org.ehcache.impl.internal.store.offheap; -import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.core.spi.service.ServiceFactory; +import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; /** * OffHeapStoreProviderFactory */ +@Component public class OffHeapStoreProviderFactory implements ServiceFactory { @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java index 4fd20e68f4..55ef0ec1a1 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java @@ -15,12 +15,14 @@ */ package org.ehcache.impl.internal.store.tiering; -import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.core.spi.service.ServiceFactory; +import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; /** * @author Ludovic Orban */ +@Component public class CompoundCachingTierProviderFactory implements ServiceFactory { @Override public CompoundCachingTier.Provider create(ServiceCreationConfiguration serviceConfiguration) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java index 0a215b71b1..85ffcf22b4 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java @@ -16,12 +16,14 @@ package org.ehcache.impl.internal.store.tiering; -import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.core.spi.service.ServiceFactory; +import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.osgi.service.component.annotations.Component; /** * @author Ludovic Orban */ +@Component public class TieredStoreProviderFactory implements ServiceFactory { @Override diff --git a/management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java b/management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java index c3a9e809b4..336c63f178 100644 --- a/management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java +++ b/management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java @@ -53,7 +53,7 @@ public URI getNamespace() { } @Override - public ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment) { + public ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment, ClassLoader classLoader) { if ("management".equals(fragment.getLocalName())) { DefaultManagementRegistryConfiguration registryConfiguration = new DefaultManagementRegistryConfiguration(); diff --git a/osgi-test/build.gradle b/osgi-test/build.gradle index bd096c3548..eca61490de 100644 --- a/osgi-test/build.gradle +++ b/osgi-test/build.gradle @@ -14,26 +14,43 @@ * limitations under the License. */ +configurations { + osgiModule + testCompileOnly.extendsFrom osgiModule +} + dependencies { - ext { - paxExamVersion = '4.11.0' - felixVersion = '5.6.10' + osgiModule project(':api') + osgiModule project(':core') + osgiModule project(':impl') + osgiModule project(':xml') + osgiModule project(':107') + osgiModule project(':transactions') + + osgiModule "javax.cache:cache-api:$parent.jcacheVersion" + osgiModule ('org.codehaus.btm:btm:2.1.4') { + exclude group:'org.slf4j', module:'slf4j-api' } - testImplementation project(':impl') - testImplementation project(':xml') - testImplementation project(':107') - testImplementation "javax.cache:cache-api:$parent.jcacheVersion" - testImplementation "org.apache.felix:org.apache.felix.framework:$felixVersion" - testImplementation ("org.ops4j.pax.exam:pax-exam-junit4:$paxExamVersion") { + osgiModule project(':dist') + + osgiModule "org.slf4j:slf4j-simple:$parent.slf4jVersion" + osgiModule 'org.apache.felix:org.apache.felix.scr:2.1.6' + + + + testImplementation 'org.apache.felix:org.apache.felix.framework:6.0.1' + testImplementation ('org.ops4j.pax.exam:pax-exam-junit4:4.12.0') { exclude group:'org.slf4j', module:'slf4j-api' } - testRuntimeOnly "org.slf4j:slf4j-simple:$parent.slf4jVersion", - testRuntimeOnly ("org.ops4j.pax.exam:pax-exam-container-native:$paxExamVersion") { + testRuntimeOnly ('org.ops4j.pax.exam:pax-exam-container-native:4.12.0') { + exclude group:'org.slf4j', module:'slf4j-api' + } + testRuntimeOnly ('org.ops4j.pax.exam:pax-exam-link-mvn:4.12.0') { exclude group:'org.slf4j', module:'slf4j-api' } - testRuntimeOnly ("org.ops4j.pax.exam:pax-exam-link-mvn:$paxExamVersion") { + testRuntimeOnly ("org.ops4j.pax.url:pax-url-wrap:2.4.5") { exclude group:'org.slf4j', module:'slf4j-api' } } @@ -41,24 +58,26 @@ dependencies { configurations.all { resolutionStrategy { force 'org.ops4j.base:ops4j-base-lang:1.5.0' + force 'org.ops4j.base:ops4j-base-net:1.5.0' force 'org.ops4j.base:ops4j-base-util-property:1.5.0' } } sourceSets { test { - // Needed for PaxExam which makes the dynamic bundle load content of a single dir - // matching the package of the test class + // Needed to allow PaxExam to see the test resources output.resourcesDir = java.outputDir } } -test { - systemProperty 'ehcache.osgi.jar', project(':dist').jar.archivePath.getPath() - systemProperty 'ehcache.osgi.jcache.version', parent.jcacheVersion - systemProperty 'ehcache.osgi.slf4j.version', parent.slf4jVersion -}.doFirst { - if (testJava.javaVersion.isJava9Compatible()) throw new StopExecutionException("OSGi Tests Not Working in Java 9") +configurations.osgiModule.dependencies.withType(ProjectDependency).forEach { + test.dependsOn it.dependencyProject.tasks.jar } -test.dependsOn ':dist:jar' +test.doFirst { + if (testJava.javaVersion.isJava9Compatible()) throw new StopExecutionException("OSGi Tests Not Working in Java 9") + + configurations.osgiModule.resolvedConfiguration.resolvedArtifacts.forEach({ + systemProperty "$it.moduleVersion.id.module:osgi-path", it.file + }) +} diff --git a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java index 52976e5883..e14b7dda7a 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java @@ -18,9 +18,10 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ops4j.pax.exam.CoreOptions.bundle; +import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; +import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; +import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.ops4j.pax.exam.CoreOptions.junitBundles; -import static org.ops4j.pax.exam.CoreOptions.mavenBundle; import static org.ops4j.pax.exam.CoreOptions.options; import org.ehcache.Cache; @@ -35,36 +36,53 @@ import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerMethod; -/** - * - */ @RunWith(PaxExam.class) @ExamReactorStrategy(PerMethod.class) public class ByteSizedOnHeapOsgiTest { @Configuration - public Option[] config() { - String slf4jVersion = VersionUtil.version("ehcache.osgi.slf4j.version", "slf4jVersion"); + public Option[] individualModules() { + return options( + gradleBundle("org.ehcache.modules:impl"), + gradleBundle("org.ehcache.modules:core"), + gradleBundle("org.ehcache.modules:api"), + + wrappedGradleBundle("org.terracotta:statistics"), + wrappedGradleBundle("org.ehcache:sizeof"), + wrappedGradleBundle("org.terracotta:offheap-store"), + + baseConfiguration(), + + junitBundles() + ); + } + + @Configuration + public Option[] uberJar() { return options( - mavenBundle("org.slf4j", "slf4j-api", slf4jVersion), - mavenBundle("org.slf4j", "slf4j-simple", slf4jVersion).noStart(), - bundle("file:" + VersionUtil.ehcacheOsgiJar()), - junitBundles() + gradleBundle("org.ehcache:dist"), + + baseConfiguration() ); } @Test public void testByteSizedOnHeapInOsgi() { - CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() + TestMethods.testByteSizedOnHeapInOsgi(); + } + + private static class TestMethods { + public static void testByteSizedOnHeapInOsgi() { + CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .withCache("myCache", newCacheConfigurationBuilder(Long.class, String.class, newResourcePoolsBuilder().heap(10, MemoryUnit.KB)) - .build()) + .build()) .build(true); - Cache cache = cacheManager.getCache("myCache", Long.class, String.class); + Cache cache = cacheManager.getCache("myCache", Long.class, String.class); - cache.put(42L, "I am out of heap!!"); + cache.put(42L, "I am out of heap!!"); - cache.get(42L); + cache.get(42L); + } } - } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java index 50260b0dfa..472c49be5b 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java @@ -16,7 +16,9 @@ package org.ehcache.osgi; -import org.junit.Ignore; +import org.ehcache.core.osgi.EhcacheActivator; +import org.ehcache.core.osgi.OsgiServiceLoader; +import org.ehcache.core.spi.service.ServiceFactory; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Configuration; @@ -24,16 +26,26 @@ import org.ops4j.pax.exam.junit.PaxExam; import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerMethod; +import org.osgi.framework.wiring.BundleWiring; import javax.cache.Cache; import javax.cache.CacheManager; import javax.cache.Caching; import javax.cache.spi.CachingProvider; +import java.util.ServiceLoader; +import java.util.Set; + +import static java.util.Spliterators.spliterator; +import static java.util.stream.Collectors.toSet; +import static java.util.stream.Stream.of; +import static java.util.stream.StreamSupport.stream; +import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; +import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; +import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; +import static org.hamcrest.core.IsCollectionContaining.hasItems; import static org.junit.Assert.assertEquals; -import static org.ops4j.pax.exam.CoreOptions.bundle; -import static org.ops4j.pax.exam.CoreOptions.junitBundles; -import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.junit.Assert.assertThat; import static org.ops4j.pax.exam.CoreOptions.options; /** @@ -44,25 +56,66 @@ public class Jsr107OsgiTest { @Configuration - public Option[] config() { - String slf4jVersion = VersionUtil.version("ehcache.osgi.slf4j.version", "slf4jVersion"); + public Option[] individualModules() { + return options( + gradleBundle("org.ehcache.modules:impl"), + gradleBundle("org.ehcache.modules:xml"), + gradleBundle("org.ehcache.modules:107"), + gradleBundle("org.ehcache.modules:core"), + gradleBundle("org.ehcache.modules:api"), + gradleBundle("javax.cache:cache-api"), + + wrappedGradleBundle("org.terracotta:statistics"), + wrappedGradleBundle("org.ehcache:sizeof"), + wrappedGradleBundle("org.terracotta:offheap-store"), + + baseConfiguration() + ); + } + + @Configuration + public Option[] uberJar() { return options( - mavenBundle("org.slf4j", "slf4j-api", slf4jVersion), - mavenBundle("org.slf4j", "slf4j-simple", slf4jVersion).noStart(), - bundle("file:" + VersionUtil.ehcacheOsgiJar()), - mavenBundle("javax.cache", "cache-api", VersionUtil.version("ehcache.osgi.jcache.version", "jcacheVersion")), - junitBundles() + gradleBundle("org.ehcache:dist"), + gradleBundle("javax.cache:cache-api"), + + baseConfiguration() ); } @Test - @Ignore("Needs https://github.com/jsr107/jsr107spec/issues/326 to be fixed and so will wait on javax.cache:cache-api:1.0.1 only") - @SuppressWarnings("unchecked") public void testJsr107EhcacheOsgi() throws Exception { - CachingProvider cachingProvider = Caching.getCachingProvider("org.ehcache.jsr107.EhcacheCachingProvider", getClass().getClassLoader()); - CacheManager cacheManager = cachingProvider.getCacheManager(getClass().getResource("/org/ehcache/osgi/ehcache-107-osgi.xml").toURI(), getClass().getClassLoader()); - Cache personCache = cacheManager.getCache("personCache", Long.class, Person.class); - assertEquals(Person.class, personCache.getConfiguration(javax.cache.configuration.Configuration.class).getValueType()); + TestMethods.testJsr107EhcacheOsgi(); + } + + @Test + public void testAllServicesAreAvailable() { + TestMethods.testAllServicesAreAvailable(); } + private static class TestMethods { + @SuppressWarnings("unchecked") + public static void testJsr107EhcacheOsgi() throws Exception { + CachingProvider cachingProvider = Caching.getCachingProvider("org.ehcache.jsr107.EhcacheCachingProvider", TestMethods.class.getClassLoader()); + CacheManager cacheManager = cachingProvider.getCacheManager(TestMethods.class.getResource("/org/ehcache/osgi/ehcache-107-osgi.xml").toURI(), TestMethods.class.getClassLoader()); + Cache personCache = cacheManager.getCache("personCache", Long.class, Person.class); + assertEquals(Person.class, personCache.getConfiguration(javax.cache.configuration.Configuration.class).getValueType()); + } + + public static void testAllServicesAreAvailable() { + Set osgiAvailableClasses = + stream(spliterator(OsgiServiceLoader.load(ServiceFactory.class).iterator(), Long.MAX_VALUE, 0), false) + .map(f -> f.getClass().getName()) + .collect(toSet()); + + Set jdkAvailableClasses = of(EhcacheActivator.getCoreBundle().getBundles()) + .map(b -> b.adapt(BundleWiring.class).getClassLoader()) + .flatMap(cl -> + stream(spliterator(ServiceLoader.load(ServiceFactory.class, cl).iterator(), Long.MAX_VALUE, 0), false) + .map(f -> f.getClass().getName())) + .collect(toSet()); + + assertThat(osgiAvailableClasses, hasItems(jdkAvailableClasses.toArray(new String[0]))); + } + } } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java index 35ea3f9c36..f6ab3c64ce 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java @@ -33,86 +33,109 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; +import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; +import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.ops4j.pax.exam.CoreOptions.bundle; -import static org.ops4j.pax.exam.CoreOptions.junitBundles; -import static org.ops4j.pax.exam.CoreOptions.mavenBundle; import static org.ops4j.pax.exam.CoreOptions.options; -/** - * OffHeapOsgiTest - */ @RunWith(PaxExam.class) @ExamReactorStrategy(PerMethod.class) public class OffHeapOsgiTest { @Configuration - public Option[] config() { - String slf4jVersion = VersionUtil.version("ehcache.osgi.slf4j.version", "slf4jVersion"); + public Option[] individualModules() { + return options( + gradleBundle("org.ehcache.modules:api"), + gradleBundle("org.ehcache.modules:core"), + gradleBundle("org.ehcache.modules:impl"), + + wrappedGradleBundle("org.terracotta:statistics"), + wrappedGradleBundle("org.ehcache:sizeof"), + wrappedGradleBundle("org.terracotta:offheap-store"), + + baseConfiguration() + ); + } + + @Configuration + public Option[] uberJar() { return options( - mavenBundle("org.slf4j", "slf4j-api", slf4jVersion), - mavenBundle("org.slf4j", "slf4j-simple", slf4jVersion).noStart(), - bundle("file:" + VersionUtil.ehcacheOsgiJar()), - junitBundles() + gradleBundle("org.ehcache:dist"), + + baseConfiguration() ); } @Test public void testOffHeapInOsgi() { - CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() + TestMethods.testOffHeapInOsgi(); + } + + @Test + public void testOffHeapClientClass() { + TestMethods.testOffHeapClientClass(); + } + + private static class TestMethods { + + public static void testOffHeapInOsgi() { + CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .withCache("myCache", newCacheConfigurationBuilder(Long.class, String.class, newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).offheap(10, MemoryUnit.MB)) - .build()) + .build()) .build(true); - Cache cache = cacheManager.getCache("myCache", Long.class, String.class); + Cache cache = cacheManager.getCache("myCache", Long.class, String.class); - cache.put(42L, "I am out of heap!!"); + cache.put(42L, "I am out of heap!!"); - cache.get(42L); - } + cache.get(42L); + } - @Test - public void testOffHeapClientClass() { - CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() - .withClassLoader(getClass().getClassLoader()) + public static void testOffHeapClientClass() { + CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() + .withClassLoader(TestMethods.class.getClassLoader()) .withCache("myCache", newCacheConfigurationBuilder(Long.class, Order.class, newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).offheap(2, MemoryUnit.MB)) - .build()) + .build()) .build(true); - Cache cache = cacheManager.getCache("myCache", Long.class, Order.class); + Cache cache = cacheManager.getCache("myCache", Long.class, Order.class); - Order order = new Order(42L); - cache.put(42L, order); + Order order = new Order(42L); + cache.put(42L, order); - assertTrue(cache.get(42L) instanceof Order); + assertTrue(cache.get(42L) instanceof Order); - cache.replace(42L, order, new Order(-1L)); + cache.replace(42L, order, new Order(-1L)); - assertEquals(-1L, cache.get(42L).id); - } + assertEquals(-1L, cache.get(42L).id); + } - private static class Order implements Serializable { + private static class Order implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - final long id; + final long id; - Order(long id) { - this.id = id; - } + Order(long id) { + this.id = id; + } - @Override - public int hashCode() { - return (int) id; - } + @Override + public int hashCode() { + return (int) id; + } - @Override - public boolean equals(Object obj) { - if (obj instanceof Order) { - return ((Order) obj).id == this.id; + @Override + public boolean equals(Object obj) { + if (obj instanceof Order) { + return ((Order) obj).id == this.id; + } + return false; } - return false; } + + } } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java new file mode 100644 index 0000000000..2196e83700 --- /dev/null +++ b/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -0,0 +1,64 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.osgi; + +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.options.UrlProvisionOption; +import org.ops4j.pax.exam.options.WrappedUrlProvisionOption; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import static java.nio.file.Files.isRegularFile; +import static java.util.Objects.requireNonNull; +import static org.ops4j.pax.exam.CoreOptions.bundle; +import static org.ops4j.pax.exam.CoreOptions.cleanCaches; +import static org.ops4j.pax.exam.CoreOptions.composite; +import static org.ops4j.pax.exam.CoreOptions.junitBundles; +import static org.ops4j.pax.exam.CoreOptions.systemProperty; +import static org.ops4j.pax.exam.CoreOptions.wrappedBundle; + +public class OsgiTestUtils { + + public static Option baseConfiguration() { + return composite( + gradleBundle("org.slf4j:slf4j-api"), + gradleBundle("org.slf4j:slf4j-simple").noStart(), + gradleBundle("org.apache.felix:org.apache.felix.scr"), + systemProperty("pax.exam.osgi.unresolved.fail").value("true"), + junitBundles() + ); + } + + public static UrlProvisionOption gradleBundle(String module) { + return bundle(artifact(module).toUri().toString()); + } + + public static WrappedUrlProvisionOption wrappedGradleBundle(String module) { + return wrappedBundle(artifact(module).toUri().toString()); + } + + private static Path artifact(String module) { + Path path = Paths.get(requireNonNull(System.getProperty(module + ":osgi-path"), module + " not available")); + if (isRegularFile(path)) { + return path; + } else { + throw new IllegalArgumentException("Module '" + module + "' not found at " + path); + } + } +} + diff --git a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java index 74460dfce7..8c859ca17f 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java @@ -19,6 +19,9 @@ import org.ehcache.Cache; import org.ehcache.CacheManager; import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.core.osgi.EhcacheActivator; +import org.ehcache.core.osgi.OsgiServiceLoader; +import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.impl.config.copy.DefaultCopierConfiguration; import org.ehcache.impl.copy.ReadWriteCopier; import org.ehcache.impl.copy.SerializingCopier; @@ -30,90 +33,151 @@ import org.ops4j.pax.exam.junit.PaxExam; import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerMethod; +import org.osgi.framework.wiring.BundleWiring; +import java.util.ServiceLoader; +import java.util.Set; + +import static java.util.Spliterators.spliterator; +import static java.util.stream.Collectors.toSet; +import static java.util.stream.Stream.of; +import static java.util.stream.StreamSupport.stream; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; +import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; +import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; +import static org.hamcrest.core.IsCollectionContaining.hasItems; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; -import static org.ops4j.pax.exam.CoreOptions.bundle; -import static org.ops4j.pax.exam.CoreOptions.junitBundles; -import static org.ops4j.pax.exam.CoreOptions.mavenBundle; import static org.ops4j.pax.exam.CoreOptions.options; -/** - * SimpleOsgiTest - */ @RunWith(PaxExam.class) @ExamReactorStrategy(PerMethod.class) public class SimpleOsgiTest { @Configuration - public Option[] config() { - String slf4jVersion = VersionUtil.version("ehcache.osgi.slf4j.version", "slf4jVersion"); + public Option[] individualModules() { + return options( + gradleBundle("org.ehcache.modules:api"), + gradleBundle("org.ehcache.modules:core"), + gradleBundle("org.ehcache.modules:impl"), + gradleBundle("org.ehcache.modules:xml"), + + wrappedGradleBundle("org.terracotta:statistics"), + wrappedGradleBundle("org.ehcache:sizeof"), + wrappedGradleBundle("org.terracotta:offheap-store"), + + baseConfiguration() + ); + } + + @Configuration + public Option[] uberJar() { return options( - mavenBundle("org.slf4j", "slf4j-api", slf4jVersion), - mavenBundle("org.slf4j", "slf4j-simple", slf4jVersion).noStart(), - bundle("file:" + VersionUtil.ehcacheOsgiJar()), - junitBundles() + gradleBundle("org.ehcache:dist"), + + baseConfiguration() ); } @Test public void testEhcache3AsBundle() { - CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() - .withCache("myCache", newCacheConfigurationBuilder(Long.class, String.class, heap(10)) - .build()) - .build(true); + TestMethods.testEhcache3AsBundle(); + } + + @Test + public void testEhcache3WithSerializationAndClientClass() { + TestMethods.testEhcache3WithSerializationAndClientClass(); + } - Cache myCache = cacheManager.getCache("myCache", Long.class, String.class); + @Test + public void testCustomCopier() { + TestMethods.testCustomCopier(); + } - myCache.put(42L, "DaAnswer!"); - assertEquals("DaAnswer!", myCache.get(42L)); + @Test + public void testEhcacheXMLConfig() throws Exception { + TestMethods.testEhcacheXMLConfig(); } @Test - public void testEhcache3WithSerializationAndClientClass() { - CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() + public void testAllServicesAreAvailable() { + TestMethods.testAllServicesAreAvailable(); + } + + private static class TestMethods { + + public static void testEhcache3AsBundle() { + CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() + .withCache("myCache", newCacheConfigurationBuilder(Long.class, String.class, heap(10)) + .build()) + .build(true); + + Cache myCache = cacheManager.getCache("myCache", Long.class, String.class); + + myCache.put(42L, "DaAnswer!"); + assertEquals("DaAnswer!", myCache.get(42L)); + } + + public static void testEhcache3WithSerializationAndClientClass() { + CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .withCache("myCache", newCacheConfigurationBuilder(Long.class, Person.class, heap(10)) - .add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)) - .withClassLoader(getClass().getClassLoader()) - .build()) + .add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)) + .withClassLoader(TestMethods.class.getClassLoader()) + .build()) .build(true); - Cache myCache = cacheManager.getCache("myCache", Long.class, Person.class); + Cache myCache = cacheManager.getCache("myCache", Long.class, Person.class); - myCache.put(42L, new Person("Arthur")); - assertTrue(myCache.get(42L) instanceof Person); - } + myCache.put(42L, new Person("Arthur")); + assertTrue(myCache.get(42L) instanceof Person); + } - @Test - public void testCustomCopier() { - CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() + public static void testCustomCopier() { + CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .withCache("myCache", newCacheConfigurationBuilder(Long.class, String.class, heap(10)) - .add(new DefaultCopierConfiguration<>(StringCopier.class, DefaultCopierConfiguration.Type.VALUE)) - .withClassLoader(getClass().getClassLoader()) - .build()) + .add(new DefaultCopierConfiguration<>(StringCopier.class, DefaultCopierConfiguration.Type.VALUE)) + .withClassLoader(TestMethods.class.getClassLoader()) + .build()) .build(true); - Cache cache = cacheManager.getCache("myCache", Long.class, String.class); + Cache cache = cacheManager.getCache("myCache", Long.class, String.class); - cache.put(42L, "What's the question again?"); - cache.get(42L); - } + cache.put(42L, "What's the question again?"); + cache.get(42L); + } - @Test - public void testEhcacheXMLConfig() throws Exception { - XmlConfiguration configuration = new XmlConfiguration(getClass().getResource("/org/ehcache/osgi/ehcache-osgi.xml").toURI().toURL(), getClass().getClassLoader()); + public static void testEhcacheXMLConfig() throws Exception { + XmlConfiguration configuration = new XmlConfiguration(TestMethods.class.getResource("/org/ehcache/osgi/ehcache-osgi.xml").toURI().toURL(), TestMethods.class.getClassLoader()); - assertEquals(Person.class, configuration.getCacheConfigurations().get("bar").getValueType()); - } + assertEquals(Person.class, configuration.getCacheConfigurations().get("bar").getValueType()); + } - public static class StringCopier extends ReadWriteCopier { + public static void testAllServicesAreAvailable() { + Set osgiAvailableClasses = + stream(spliterator(OsgiServiceLoader.load(ServiceFactory.class).iterator(), Long.MAX_VALUE, 0), false) + .map(f -> f.getClass().getName()) + .collect(toSet()); - @Override - public String copy(String obj) { - return new String(obj); + Set jdkAvailableClasses = of(EhcacheActivator.getCoreBundle().getBundles()) + .map(b -> b.adapt(BundleWiring.class).getClassLoader()) + .flatMap(cl -> + stream(spliterator(ServiceLoader.load(ServiceFactory.class, cl).iterator(), Long.MAX_VALUE, 0), false) + .map(f -> f.getClass().getName())) + .collect(toSet()); + + assertThat(osgiAvailableClasses, hasItems(jdkAvailableClasses.toArray(new String[0]))); } - } + public static class StringCopier extends ReadWriteCopier { + + @Override + public String copy(String obj) { + return new String(obj); + } + } + + } } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java new file mode 100644 index 0000000000..96550a8a04 --- /dev/null +++ b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java @@ -0,0 +1,155 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.osgi; + +import bitronix.tm.BitronixTransactionManager; +import bitronix.tm.TransactionManagerServices; +import org.ehcache.Cache; +import org.ehcache.CacheManager; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.transactions.xa.configuration.XAStoreConfiguration; +import org.ehcache.transactions.xa.txmgr.btm.BitronixTransactionManagerLookup; +import org.ehcache.transactions.xa.txmgr.provider.LookupTransactionManagerProviderConfiguration; +import org.ehcache.xml.XmlConfiguration; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerMethod; + +import static bitronix.tm.TransactionManagerServices.getTransactionManager; +import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManager; +import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; +import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; +import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; +import static org.ops4j.pax.exam.CoreOptions.cleanCaches; +import static org.ops4j.pax.exam.CoreOptions.options; + +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerMethod.class) +public class TransactionalOsgiTest { + + @Configuration + public Option[] individualModules() { + return options( + gradleBundle("org.ehcache.modules:api"), + gradleBundle("org.ehcache.modules:core"), + gradleBundle("org.ehcache.modules:impl"), + gradleBundle("org.ehcache.modules:xml"), + gradleBundle("org.ehcache:transactions"), + + wrappedGradleBundle("org.terracotta:statistics"), + wrappedGradleBundle("org.ehcache:sizeof"), + wrappedGradleBundle("org.terracotta:offheap-store"), + + wrappedGradleBundle("javax.transaction:jta") + .instructions("Fragment-Host=org.apache.felix.framework"), + wrappedGradleBundle("org.codehaus.btm:btm"), + + baseConfiguration() + ); + } + + @Configuration + public Option[] uberJar() { + return options( + gradleBundle("org.ehcache:dist"), + gradleBundle("org.ehcache:transactions"), + + wrappedGradleBundle("javax.transaction:jta") + .instructions("Fragment-Host=org.apache.felix.framework"), + wrappedGradleBundle("org.codehaus.btm:btm"), + + cleanCaches(true), + baseConfiguration() + ); + } + + @Before + public void setUp() throws Exception { + TransactionManagerServices.getConfiguration().setJournal("null").setServerId(getClass().getSimpleName()); + } + + @After + public void tearDown() throws Exception { + if (TransactionManagerServices.isTransactionManagerRunning()) { + TransactionManagerServices.getTransactionManager().shutdown(); + } + } + + @Test + public void testProgrammaticConfiguration() throws Exception { + TestMethods.testProgrammaticConfiguration(); + } + + @Test + public void testXmlConfiguration() throws Exception { + TestMethods.testXmlConfiguration(); + } + + private static class TestMethods { + + public static void testProgrammaticConfiguration() throws Exception { + BitronixTransactionManager transactionManager = getTransactionManager(); + + try (CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() + .withClassLoader(TestMethods.class.getClassLoader()) + .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) + .withCache("xaCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, heap(10)) + .add(new XAStoreConfiguration("xaCache")).build()).build(true)) { + + Cache xaCache = cacheManager.getCache("xaCache", Long.class, String.class); + + transactionManager.begin(); + try { + xaCache.put(1L, "one"); + } catch (Throwable t) { + transactionManager.rollback(); + } + transactionManager.commit(); + } + transactionManager.shutdown(); + } + + public static void testXmlConfiguration() throws Exception { + BitronixTransactionManager transactionManager = getTransactionManager(); + + try (CacheManager cacheManager = newCacheManager( + new XmlConfiguration(TestMethods.class.getResource("ehcache-xa-osgi.xml"), TestMethods.class.getClassLoader()) + )) { + cacheManager.init(); + + Cache xaCache = cacheManager.getCache("xaCache", Long.class, String.class); + + transactionManager.begin(); + try { + xaCache.put(1L, "one"); + } catch (Throwable t) { + transactionManager.rollback(); + } + transactionManager.commit(); + } + transactionManager.shutdown(); + } + } +} diff --git a/osgi-test/src/test/java/org/ehcache/osgi/VersionUtil.java b/osgi-test/src/test/java/org/ehcache/osgi/VersionUtil.java deleted file mode 100644 index 9746899fbb..0000000000 --- a/osgi-test/src/test/java/org/ehcache/osgi/VersionUtil.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.ehcache.osgi; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Properties; - -/** - * Used to retrieve version of dependencies. Made to work with Gradle and in an IDE. - */ -public final class VersionUtil { - - private static Properties properties; - - private VersionUtil() { - } - - private static Properties get() { - // No need to support multithreading - if(properties == null) { - properties = new Properties(); - try { - properties.load(Files.newBufferedReader(Paths.get("../gradle.properties"), StandardCharsets.UTF_8)); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - return properties; - } - - public static String version(String systemProperty, String gradleProperty) { - String version = System.getProperty(systemProperty); - if(version != null) { - return version; - } - return get().getProperty(gradleProperty); - } - - public static String ehcacheOsgiJar() { - String version = System.getProperty("ehcache.osgi.jar"); - if(version != null) { - return version; - } - return "../dist/build/libs/ehcache-" + properties.getProperty("ehcacheVersion") + ".jar"; - } -} diff --git a/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-xa-osgi.xml b/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-xa-osgi.xml new file mode 100644 index 0000000000..497e95814d --- /dev/null +++ b/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-xa-osgi.xml @@ -0,0 +1,32 @@ + + + + + + + + + java.lang.Long + java.lang.String + 10 + + + + diff --git a/settings.gradle b/settings.gradle index 3d830fcd1e..1c204fa6d3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,4 +16,4 @@ include "api", "spi-tester", "core", "core-spi-test", "impl", "management", "transactions", "107", "xml", "clustered", "clustered:common", "clustered:client", "clustered:server", "clustered:integration-test", "clustered:clustered-dist", "clustered:ops-tool", - "integration-test", "dist", "osgi-test", "demos", "demos:00-NoCache", "demos:01-CacheAside", "docs" + "integration-test", "dist", "osgi-test", "clustered:osgi-test", "demos", "demos:00-NoCache", "demos:01-CacheAside", "docs" diff --git a/transactions/build.gradle b/transactions/build.gradle index a257a3e46a..361b4523ce 100644 --- a/transactions/build.gradle +++ b/transactions/build.gradle @@ -16,7 +16,8 @@ group = 'org.ehcache' -apply plugin: EhOsgi +apply plugin: 'osgi' +apply plugin: 'osgi-ds' apply plugin: EhPomMangle dependencies { @@ -28,6 +29,7 @@ dependencies { implementation (group: 'org.codehaus.btm', name: 'btm', version: '2.1.4') { exclude group:'org.slf4j', module:'slf4j-api' } + compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':core-spi-test') testCompile project(path: ':xml', configuration: 'testArchives') } @@ -44,6 +46,14 @@ test { } } +jar { + manifest { + instruction 'Export-Package', 'org.ehcache.transactions.xa.*' + instruction 'Import-Package', 'bitronix.tm.*;resolution:=optional', 'javax.transaction.*;resolution:=optional', '*' + instruction 'Service-Component', 'OSGI-INF/*.xml' + } +} + project.signing { required { project.isReleaseVersion && project.gradle.taskGraph.hasTask("uploadArchives") } sign project.configurations.getByName('archives') diff --git a/transactions/gradle.properties b/transactions/gradle.properties index e685b39fac..6a1f373c75 100644 --- a/transactions/gradle.properties +++ b/transactions/gradle.properties @@ -1,5 +1,2 @@ subPomName = Ehcache 3 transactions module subPomDesc = The transactions module of Ehcache 3 -osgi = {"Export-Package" : ["!org.ehcache.transactions.xa.internal.*"],\ - "Import-Package" : ["bitronix.tm.*;resolution:=optional", "javax.transaction.*;resolution:=optional",\ - "!sun.misc.*", "!sun.security.action.*", "!org.ehcache.transactions.*"]} diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java index 3427f5fa24..b405504892 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java @@ -19,10 +19,12 @@ import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.transactions.xa.internal.XAStore; +import org.osgi.service.component.annotations.Component; /** * @author Ludovic Orban */ +@Component public class XAStoreProviderFactory implements ServiceFactory { @Override public XAStore.Provider create(ServiceCreationConfiguration configuration) { diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java index 3ae49dee0a..a0c8ef818d 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java @@ -18,10 +18,12 @@ import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.core.spi.service.ServiceFactory; +import org.osgi.service.component.annotations.Component; /** * @author Ludovic Orban */ +@Component public class DefaultJournalProviderFactory implements ServiceFactory { @Override diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java index 5edb71e685..71db33048a 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java @@ -21,12 +21,14 @@ import org.ehcache.transactions.xa.txmgr.provider.LookupTransactionManagerProvider; import org.ehcache.transactions.xa.txmgr.provider.LookupTransactionManagerProviderConfiguration; import org.ehcache.transactions.xa.txmgr.provider.TransactionManagerProvider; +import org.osgi.service.component.annotations.Component; /** * {@link ServiceFactory} for the default {@link TransactionManagerProvider} * * @see LookupTransactionManagerProvider */ +@Component @ServiceFactory.RequiresConfiguration public class DefaultTransactionManagerProviderFactory implements ServiceFactory { diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java index 9f9b1f934e..28f8133eaa 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java @@ -22,8 +22,8 @@ import org.ehcache.xml.BaseConfigParser; import org.ehcache.xml.CacheManagerServiceConfigurationParser; import org.ehcache.spi.service.ServiceCreationConfiguration; -import org.ehcache.core.internal.util.ClassLoading; import org.ehcache.xml.exceptions.XmlConfigurationException; +import org.osgi.service.component.annotations.Component; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -34,11 +34,13 @@ import java.net.URI; import java.net.URL; +import static org.ehcache.core.internal.util.ClassLoading.delegationChain; import static org.ehcache.core.internal.util.TypeUtil.uncheckedCast; /** * @author Ludovic Orban */ +@Component public class TxCacheManagerServiceConfigurationParser extends BaseConfigParser implements CacheManagerServiceConfigurationParser { private static final URI NAMESPACE = URI.create("http://www.ehcache.org/v3/tx"); private static final URL XML_SCHEMA = TxCacheManagerServiceConfigurationParser.class.getResource("/ehcache-tx-ext.xsd"); @@ -57,13 +59,16 @@ public URI getNamespace() { } @Override - public ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment) { + public ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment, ClassLoader classLoader) { String localName = fragment.getLocalName(); if ("jta-tm".equals(localName)) { String transactionManagerProviderConfigurationClassName = fragment.getAttribute("transaction-manager-lookup-class"); try { - ClassLoader defaultClassLoader = ClassLoading.getDefaultClassLoader(); - Class aClass = Class.forName(transactionManagerProviderConfigurationClassName, true, defaultClassLoader); + Class aClass = Class.forName(transactionManagerProviderConfigurationClassName, true, delegationChain( + () -> Thread.currentThread().getContextClassLoader(), + getClass().getClassLoader(), + classLoader + )); Class clazz = uncheckedCast(aClass); return new LookupTransactionManagerProviderConfiguration(clazz); } catch (Exception e) { diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java index 1e3b054c40..200cb10e80 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java @@ -22,6 +22,7 @@ import org.ehcache.transactions.xa.internal.XAStore; import org.ehcache.transactions.xa.configuration.XAStoreConfiguration; import org.ehcache.xml.exceptions.XmlConfigurationException; +import org.osgi.service.component.annotations.Component; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -36,6 +37,7 @@ /** * @author Ludovic Orban */ +@Component public class TxCacheServiceConfigurationParser extends BaseConfigParser implements CacheServiceConfigurationParser { private static final URI NAMESPACE = URI.create("http://www.ehcache.org/v3/tx"); @@ -54,7 +56,7 @@ public URI getNamespace() { } @Override - public ServiceConfiguration parseServiceConfiguration(Element fragment) { + public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { String localName = fragment.getLocalName(); if ("xa-store".equals(localName)) { String uniqueXAResourceId = fragment.getAttribute("unique-XAResource-id"); diff --git a/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java b/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java index 803fb297d0..e7cc9f62a4 100644 --- a/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java @@ -27,13 +27,12 @@ import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.transactions.xa.internal.XAStore; import org.ehcache.transactions.xa.txmgr.provider.TransactionManagerProvider; -import org.hamcrest.Matchers; import org.junit.Test; -import java.util.HashSet; -import java.util.Set; - -import static org.hamcrest.core.Is.is; +import static java.util.Spliterators.spliterator; +import static java.util.stream.Collectors.toList; +import static java.util.stream.StreamSupport.stream; +import static org.hamcrest.core.IsCollectionContaining.hasItems; import static org.junit.Assert.assertThat; /** @@ -48,17 +47,8 @@ public void testNonXA() throws Exception { /* * Ensure the XA provider classes are loadable through the ServiceLoader mechanism. */ - Set> targetProviders = new HashSet<>(); - targetProviders.add(XAStore.Provider.class); - targetProviders.add(TransactionManagerProvider.class); - for (ServiceFactory factory : ClassLoading.libraryServiceLoaderFor(ServiceFactory.class)) { - if (targetProviders.remove(factory.getServiceType())) { - if (targetProviders.isEmpty()) { - break; - } - } - } - assertThat(targetProviders, is(Matchers.empty())); + assertThat(stream(spliterator(ClassLoading.servicesOfType(ServiceFactory.class).iterator(), Long.MAX_VALUE, 0), false).map(s -> s.getServiceType()).collect(toList()), + hasItems(XAStore.Provider.class, TransactionManagerProvider.class)); CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder( String.class, diff --git a/xml/build.gradle b/xml/build.gradle index 6b58528797..a2cf8ce0ca 100644 --- a/xml/build.gradle +++ b/xml/build.gradle @@ -20,6 +20,7 @@ plugins { } apply plugin: EhDeploy +apply plugin: 'osgi' apply plugin: 'com.github.hauner.jarTest' dependencies { @@ -37,6 +38,13 @@ test { } } +jar { + manifest { + instruction 'Export-Package', 'org.ehcache.xml.*' + instruction 'Import-Package', '!sun.misc.*', '*' + } +} + xjcGenerate { source = ['src/main/resources/ehcache-core.xsd', 'src/main/resources/ehcache-multi.xsd'] extension = true diff --git a/xml/gradle.properties b/xml/gradle.properties index ce44fae982..c5f4931900 100644 --- a/xml/gradle.properties +++ b/xml/gradle.properties @@ -16,5 +16,3 @@ subPomName = Ehcache 3 XML Parsing module subPomDesc = The module containing all XML parsing logic Ehcache 3 -osgi = {"Export-Package" : ["!org.ehcache.xml.model.*"],\ - "Import-Package" : ["!sun.misc.*", "!sun.security.action.*"]} diff --git a/xml/src/main/java/org/ehcache/xml/CacheManagerServiceConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/CacheManagerServiceConfigurationParser.java index 6151902582..b5e9180c53 100644 --- a/xml/src/main/java/org/ehcache/xml/CacheManagerServiceConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/CacheManagerServiceConfigurationParser.java @@ -33,7 +33,7 @@ public interface CacheManagerServiceConfigurationParser { URI getNamespace(); - ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment); + ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment, ClassLoader classLoader); Class getServiceType(); diff --git a/xml/src/main/java/org/ehcache/xml/CacheServiceConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/CacheServiceConfigurationParser.java index c57c476e80..49e0fef1ae 100644 --- a/xml/src/main/java/org/ehcache/xml/CacheServiceConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/CacheServiceConfigurationParser.java @@ -34,7 +34,7 @@ public interface CacheServiceConfigurationParser { URI getNamespace(); - ServiceConfiguration parseServiceConfiguration(Element fragment); + ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader); Class getServiceType(); diff --git a/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java index cd27012f19..d2bad1584f 100644 --- a/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java @@ -92,7 +92,7 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ConfigurationBuilder.newConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.core.internal.util.ClassLoading.libraryServiceLoaderFor; +import static org.ehcache.core.internal.util.ClassLoading.servicesOfType; import static org.ehcache.xml.XmlConfiguration.CORE_SCHEMA_URL; import static org.ehcache.xml.XmlConfiguration.getClassForName; @@ -150,16 +150,16 @@ private static Stream stream(Iterable iterable) { ConfigurationParser() throws IOException, SAXException, JAXBException, ParserConfigurationException { serviceCreationConfigurationParser = ConfigurationParser.>stream( - libraryServiceLoaderFor(CacheManagerServiceConfigurationParser.class)) + servicesOfType(CacheManagerServiceConfigurationParser.class)) .collect(collectingAndThen(toMap(CacheManagerServiceConfigurationParser::getServiceType, identity(), (a, b) -> a.getClass().isInstance(b) ? b : a), ServiceCreationConfigurationParser::new)); serviceConfigurationParser = ConfigurationParser.>stream( - libraryServiceLoaderFor(CacheServiceConfigurationParser.class)) + servicesOfType(CacheServiceConfigurationParser.class)) .collect(collectingAndThen(toMap(CacheServiceConfigurationParser::getServiceType, identity(), (a, b) -> a.getClass().isInstance(b) ? b : a), ServiceConfigurationParser::new)); - resourceConfigurationParser = stream(libraryServiceLoaderFor(CacheResourceConfigurationParser.class)) + resourceConfigurationParser = stream(servicesOfType(CacheResourceConfigurationParser.class)) .flatMap(p -> p.getResourceTypes().stream().map(t -> new AbstractMap.SimpleImmutableEntry<>(t, p))) .collect(collectingAndThen(toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a.getClass().isInstance(b) ? b : a), m -> new ResourceConfigurationParser(new HashSet<>(m.values())))); @@ -245,8 +245,8 @@ private XmlConfiguration.Template parseTemplate(CacheTemplate template) { return new XmlConfiguration.Template() { @Override public CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resources) throws ClassNotFoundException, InstantiationException, IllegalAccessException { - checkTemplateTypeConsistency("key", keyType, template); - checkTemplateTypeConsistency("value", valueType, template); + checkTemplateTypeConsistency("key", classLoader, keyType, template); + checkTemplateTypeConsistency("value", classLoader, valueType, template); if ((resources == null || resources.getResourceTypeSet().isEmpty()) && template.getHeap() == null && template.getResources().isEmpty()) { throw new IllegalStateException("Template defines no resources, and none were provided"); @@ -261,13 +261,12 @@ public CacheConfigurationBuilder builderFor(ClassLoader classLoader }; } - private static void checkTemplateTypeConsistency(String type, Class providedType, CacheTemplate template) throws ClassNotFoundException { - ClassLoader defaultClassLoader = ClassLoading.getDefaultClassLoader(); + private static void checkTemplateTypeConsistency(String type, ClassLoader classLoader, Class providedType, CacheTemplate template) throws ClassNotFoundException { Class templateType; if (type.equals("key")) { - templateType = getClassForName(template.keyType(), defaultClassLoader); + templateType = getClassForName(template.keyType(), classLoader); } else { - templateType = getClassForName(template.valueType(), defaultClassLoader); + templateType = getClassForName(template.valueType(), classLoader); } if(providedType == null || !templateType.isAssignableFrom(providedType)) { @@ -425,13 +424,13 @@ public static DocumentBuilder documentBuilder(Schema schema) throws ParserConfig public static Schema discoverSchema(Source ... fixedSources) throws SAXException, IOException { ArrayList schemaSources = new ArrayList<>(asList(fixedSources)); - for (CacheManagerServiceConfigurationParser p : libraryServiceLoaderFor(CacheManagerServiceConfigurationParser.class)) { + for (CacheManagerServiceConfigurationParser p : servicesOfType(CacheManagerServiceConfigurationParser.class)) { schemaSources.add(p.getXmlSchema()); } - for (CacheServiceConfigurationParser p : libraryServiceLoaderFor(CacheServiceConfigurationParser.class)) { + for (CacheServiceConfigurationParser p : servicesOfType(CacheServiceConfigurationParser.class)) { schemaSources.add(p.getXmlSchema()); } - for (CacheResourceConfigurationParser p : libraryServiceLoaderFor(CacheResourceConfigurationParser.class)) { + for (CacheResourceConfigurationParser p : servicesOfType(CacheResourceConfigurationParser.class)) { schemaSources.add(p.getXmlSchema()); } return newSchema(schemaSources.toArray(new Source[0])); diff --git a/xml/src/main/java/org/ehcache/xml/ServiceConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/ServiceConfigurationParser.java index 0fe49da50e..f187c33525 100644 --- a/xml/src/main/java/org/ehcache/xml/ServiceConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/ServiceConfigurationParser.java @@ -74,7 +74,7 @@ public CacheConfigurationBuilder parseConfiguration(CacheTemplate c if(xmlConfigurationParser == null) { throw new IllegalArgumentException("Can't find parser for namespace: " + namespace); } - cacheBuilder = cacheBuilder.add(xmlConfigurationParser.parseServiceConfiguration(element)); + cacheBuilder = cacheBuilder.add(xmlConfigurationParser.parseServiceConfiguration(element, cacheClassLoader)); } return cacheBuilder; diff --git a/xml/src/main/java/org/ehcache/xml/ServiceCreationConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/ServiceCreationConfigurationParser.java index a1a9876409..944da7e4cf 100644 --- a/xml/src/main/java/org/ehcache/xml/ServiceCreationConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/ServiceCreationConfigurationParser.java @@ -73,7 +73,7 @@ ConfigurationBuilder parseServiceCreationConfiguration(ConfigType configRoot, Cl if(cacheManagerServiceConfigurationParser == null) { throw new IllegalArgumentException("Can't find parser for namespace: " + namespace); } - ServiceCreationConfiguration serviceConfiguration = cacheManagerServiceConfigurationParser.parseServiceCreationConfiguration(element); + ServiceCreationConfiguration serviceConfiguration = cacheManagerServiceConfigurationParser.parseServiceCreationConfiguration(element, classLoader); managerBuilder = managerBuilder.addService(serviceConfiguration); } diff --git a/xml/src/test/java/org/ehcache/xml/BarParser.java b/xml/src/test/java/org/ehcache/xml/BarParser.java index bbe96740c3..3a3a396952 100644 --- a/xml/src/test/java/org/ehcache/xml/BarParser.java +++ b/xml/src/test/java/org/ehcache/xml/BarParser.java @@ -50,7 +50,7 @@ public URI getNamespace() { } @Override - public ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment) { + public ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment, ClassLoader classLoader) { return new BarConfiguration(); } diff --git a/xml/src/test/java/org/ehcache/xml/FancyParser.java b/xml/src/test/java/org/ehcache/xml/FancyParser.java index 2e997fdf20..794f29f63d 100644 --- a/xml/src/test/java/org/ehcache/xml/FancyParser.java +++ b/xml/src/test/java/org/ehcache/xml/FancyParser.java @@ -42,7 +42,7 @@ public Source getXmlSchema() throws IOException { } @Override - public ServiceConfiguration parseServiceConfiguration(Element fragment) { + public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { return new FooConfiguration(); } diff --git a/xml/src/test/java/org/ehcache/xml/FooParser.java b/xml/src/test/java/org/ehcache/xml/FooParser.java index 21c0184a71..f4c70a65c5 100644 --- a/xml/src/test/java/org/ehcache/xml/FooParser.java +++ b/xml/src/test/java/org/ehcache/xml/FooParser.java @@ -46,7 +46,7 @@ public Source getXmlSchema() throws IOException { } @Override - public ServiceConfiguration parseServiceConfiguration(Element fragment) { + public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { return new FooConfiguration(); } From e215211a83d0d4e4b8432d8db1f47b8d69c3c769 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 4 Jan 2019 14:26:17 -0500 Subject: [PATCH 074/372] Clean OSGi bundle cache after execution... and disable OSGi txn test due to windows instability --- .../test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java | 5 +---- osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java | 1 + .../test/java/org/ehcache/osgi/TransactionalOsgiTest.java | 6 ++---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java index e14b7dda7a..c816e513ef 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java @@ -21,7 +21,6 @@ import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; -import static org.ops4j.pax.exam.CoreOptions.junitBundles; import static org.ops4j.pax.exam.CoreOptions.options; import org.ehcache.Cache; @@ -51,9 +50,7 @@ public Option[] individualModules() { wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), - baseConfiguration(), - - junitBundles() + baseConfiguration() ); } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java index 2196e83700..c04689f945 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -40,6 +40,7 @@ public static Option baseConfiguration() { gradleBundle("org.slf4j:slf4j-simple").noStart(), gradleBundle("org.apache.felix:org.apache.felix.scr"), systemProperty("pax.exam.osgi.unresolved.fail").value("true"), + cleanCaches(true), junitBundles() ); } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java index aff82795cf..5ee115648f 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java @@ -28,6 +28,7 @@ import org.ehcache.xml.XmlConfiguration; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Configuration; @@ -39,16 +40,14 @@ import static bitronix.tm.TransactionManagerServices.getTransactionManager; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManager; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; -import static org.ehcache.core.osgi.EhcacheActivator.OSGI_LOADING; import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; -import static org.ops4j.pax.exam.CoreOptions.cleanCaches; -import static org.ops4j.pax.exam.CoreOptions.frameworkProperty; import static org.ops4j.pax.exam.CoreOptions.options; @RunWith(PaxExam.class) @ExamReactorStrategy(PerMethod.class) +@Ignore("Not stable under windows") public class TransactionalOsgiTest { @Configuration @@ -82,7 +81,6 @@ public Option[] uberJar() { .instructions("Fragment-Host=org.apache.felix.framework"), wrappedGradleBundle("org.codehaus.btm:btm"), - cleanCaches(true), baseConfiguration() ); } From e8594cbd3a24e777cb33a2f18c66a506f57a0fcb Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 7 Jan 2019 13:46:38 -0500 Subject: [PATCH 075/372] Force distinct working directories for OSGi instances --- .../src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java | 4 ++-- .../src/test/java/org/ehcache/osgi/OsgiTestUtils.java | 7 ++++++- .../java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java | 4 ++-- .../src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java | 4 ++-- .../src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java | 6 +++--- .../src/test/java/org/ehcache/osgi/OsgiTestUtils.java | 6 +++++- .../src/test/java/org/ehcache/osgi/SimpleOsgiTest.java | 6 +++--- .../test/java/org/ehcache/osgi/TransactionalOsgiTest.java | 6 ++---- 8 files changed, 25 insertions(+), 18 deletions(-) diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java index 3dcf98e8e2..59c41de9df 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java @@ -88,7 +88,7 @@ public Option[] individualModules() { wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), - baseConfiguration() + baseConfiguration("ClusteredOsgiTest", "individualModules") ); } @@ -98,7 +98,7 @@ public Option[] uberJar() { gradleBundle("org.ehcache:dist"), gradleBundle("org.ehcache:clustered-dist"), - baseConfiguration() + baseConfiguration("ClusteredOsgiTest", "uberJar") ); } diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java index 3f6e6dfd2e..f8ee55a22f 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -33,24 +33,29 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Stream; +import static java.lang.String.join; import static java.nio.file.Files.find; import static java.nio.file.Files.isRegularFile; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.joining; import static org.ops4j.pax.exam.CoreOptions.bundle; +import static org.ops4j.pax.exam.CoreOptions.cleanCaches; import static org.ops4j.pax.exam.CoreOptions.composite; import static org.ops4j.pax.exam.CoreOptions.junitBundles; import static org.ops4j.pax.exam.CoreOptions.systemProperty; +import static org.ops4j.pax.exam.CoreOptions.workingDirectory; import static org.ops4j.pax.exam.CoreOptions.wrappedBundle; public class OsgiTestUtils { - public static Option baseConfiguration() { + public static Option baseConfiguration(String ... path) { return composite( gradleBundle("org.slf4j:slf4j-api"), gradleBundle("org.slf4j:slf4j-simple").noStart(), gradleBundle("org.apache.felix:org.apache.felix.scr"), systemProperty("pax.exam.osgi.unresolved.fail").value("true"), + cleanCaches(true), + workingDirectory(join(File.separator, "build", "osgi-container", join(File.separator, path))), junitBundles() ); } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java index c816e513ef..12790ea81e 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java @@ -50,7 +50,7 @@ public Option[] individualModules() { wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), - baseConfiguration() + baseConfiguration("ByteSizedOnHeapOsgiTest", "individualModules") ); } @@ -59,7 +59,7 @@ public Option[] uberJar() { return options( gradleBundle("org.ehcache:dist"), - baseConfiguration() + baseConfiguration("ByteSizedOnHeapOsgiTest", "uberJar") ); } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java index 472c49be5b..ebd32b7579 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java @@ -69,7 +69,7 @@ public Option[] individualModules() { wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), - baseConfiguration() + baseConfiguration("Jsr107OsgiTest", "individualModules") ); } @@ -79,7 +79,7 @@ public Option[] uberJar() { gradleBundle("org.ehcache:dist"), gradleBundle("javax.cache:cache-api"), - baseConfiguration() + baseConfiguration("Jsr107OsgiTest", "uberJar") ); } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java index a7ecbe48b5..7083d7c67a 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java @@ -57,7 +57,7 @@ public Option[] individualModules() { wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), - baseConfiguration() + baseConfiguration("OffHeapOsgiTest", "individualModules") ); } @@ -66,7 +66,7 @@ public Option[] uberJarWithOsgiServiceLoading() { return options( gradleBundle("org.ehcache:dist"), - baseConfiguration() + baseConfiguration("OffHeapOsgiTest", "uberJarWithOsgiServiceLoading") ); } @@ -77,7 +77,7 @@ public Option[] uberJarWithJdkServiceLoading() { gradleBundle("org.ehcache:dist"), - baseConfiguration() + baseConfiguration("OffHeapOsgiTest", "uberJarWithJdkServiceLoading") ); } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java index c04689f945..b017d13227 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -20,9 +20,11 @@ import org.ops4j.pax.exam.options.UrlProvisionOption; import org.ops4j.pax.exam.options.WrappedUrlProvisionOption; +import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; +import static java.lang.String.join; import static java.nio.file.Files.isRegularFile; import static java.util.Objects.requireNonNull; import static org.ops4j.pax.exam.CoreOptions.bundle; @@ -30,17 +32,19 @@ import static org.ops4j.pax.exam.CoreOptions.composite; import static org.ops4j.pax.exam.CoreOptions.junitBundles; import static org.ops4j.pax.exam.CoreOptions.systemProperty; +import static org.ops4j.pax.exam.CoreOptions.workingDirectory; import static org.ops4j.pax.exam.CoreOptions.wrappedBundle; public class OsgiTestUtils { - public static Option baseConfiguration() { + public static Option baseConfiguration(String ... path) { return composite( gradleBundle("org.slf4j:slf4j-api"), gradleBundle("org.slf4j:slf4j-simple").noStart(), gradleBundle("org.apache.felix:org.apache.felix.scr"), systemProperty("pax.exam.osgi.unresolved.fail").value("true"), cleanCaches(true), + workingDirectory(join(File.separator, "build", "osgi-container", join(File.separator, path))), junitBundles() ); } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java index f240116c78..f5250233c2 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java @@ -71,7 +71,7 @@ public Option[] individualModules() { wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), - baseConfiguration() + baseConfiguration("SimpleOsgiTest", "individualModules") ); } @@ -80,7 +80,7 @@ public Option[] uberJarWithOsgiServiceLoading() { return options( gradleBundle("org.ehcache:dist"), - baseConfiguration() + baseConfiguration("SimpleOsgiTest", "uberJarWithOsgiServiceLoading") ); } @@ -91,7 +91,7 @@ public Option[] uberJarWithJdkServiceLoading() { gradleBundle("org.ehcache:dist"), - baseConfiguration() + baseConfiguration("SimpleOsgiTest", "uberJarWithJdkServiceLoading") ); } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java index 5ee115648f..5cda12d76d 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java @@ -28,7 +28,6 @@ import org.ehcache.xml.XmlConfiguration; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Configuration; @@ -47,7 +46,6 @@ @RunWith(PaxExam.class) @ExamReactorStrategy(PerMethod.class) -@Ignore("Not stable under windows") public class TransactionalOsgiTest { @Configuration @@ -67,7 +65,7 @@ public Option[] individualModules() { .instructions("Fragment-Host=org.apache.felix.framework"), wrappedGradleBundle("org.codehaus.btm:btm"), - baseConfiguration() + baseConfiguration("TransactionalOsgiTest", "individualModules") ); } @@ -81,7 +79,7 @@ public Option[] uberJar() { .instructions("Fragment-Host=org.apache.felix.framework"), wrappedGradleBundle("org.codehaus.btm:btm"), - baseConfiguration() + baseConfiguration("TransactionalOsgiTest", "uberJar") ); } From 7767a344f956a65c03db1c6b6f67bece00acc701 Mon Sep 17 00:00:00 2001 From: esebasti Date: Wed, 9 Jan 2019 11:39:51 -0800 Subject: [PATCH 076/372] bump core and platform versions --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 10a3644ae6..69debd8175 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,9 +9,9 @@ slf4jVersion = 1.7.25 sizeofVersion = 0.3.0 # Terracotta clustered -terracottaPlatformVersion = 5.6.0-pre5 +terracottaPlatformVersion = 5.6.0-pre6 terracottaApisVersion = 1.6.0-pre2 -terracottaCoreVersion = 5.6.0-pre6 +terracottaCoreVersion = 5.6.0-pre7 terracottaPassthroughTestingVersion = 1.6.0-pre2 # Test lib versions From 77c3f91a2714015affe2330ce279cd5c88837067 Mon Sep 17 00:00:00 2001 From: Albin Suresh Date: Tue, 22 Jan 2019 18:36:08 +0530 Subject: [PATCH 077/372] Bump up core and platform versions --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 69debd8175..e8a61a0652 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,9 +9,9 @@ slf4jVersion = 1.7.25 sizeofVersion = 0.3.0 # Terracotta clustered -terracottaPlatformVersion = 5.6.0-pre6 +terracottaPlatformVersion = 5.6.0-pre7 terracottaApisVersion = 1.6.0-pre2 -terracottaCoreVersion = 5.6.0-pre7 +terracottaCoreVersion = 5.6.0-pre8 terracottaPassthroughTestingVersion = 1.6.0-pre2 # Test lib versions From 82c03791175d6f8a19abc7c5745c866c6e36e407 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 21 Jun 2018 17:32:35 -0400 Subject: [PATCH 078/372] Add OWASP dependency checking --- build.gradle | 9 +++++++++ buildSrc/src/main/groovy/EhPomMangle.groovy | 4 ++++ demos/build.gradle | 4 ++++ docs/build.gradle | 3 +++ 4 files changed, 20 insertions(+) diff --git a/build.gradle b/build.gradle index e798721546..87eb3e3aa1 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,8 @@ plugins { id 'com.github.spotbugs' version '1.6.5' apply false // Declare osgi-ds at the top id 'org.jayware.osgi-ds' version '0.5.5' apply false + //OWASP Security Vulnerability Detection + id 'org.owasp.dependencycheck' version '4.0.2' apply false } wrapper { @@ -89,6 +91,7 @@ subprojects { apply plugin: 'checkstyle' apply plugin: 'com.github.spotbugs' apply plugin: 'jacoco' + apply plugin: 'org.owasp.dependencycheck' group = 'org.ehcache.modules' version = baseVersion @@ -202,6 +205,12 @@ subprojects { } } + dependencyCheck { + failBuildOnCVSS = 0 + skipConfigurations += ['checkstyle'] + } + check.dependsOn(dependencyCheckAnalyze) + tasks.withType(AbstractCompile) { options.with { fork = true diff --git a/buildSrc/src/main/groovy/EhPomMangle.groovy b/buildSrc/src/main/groovy/EhPomMangle.groovy index 2bc761fdb9..959b5e2b98 100644 --- a/buildSrc/src/main/groovy/EhPomMangle.groovy +++ b/buildSrc/src/main/groovy/EhPomMangle.groovy @@ -55,6 +55,10 @@ class EhPomMangle implements Plugin { pomOnlyProvided } + project.dependencyCheck { + skipConfigurations += ['pomOnlyCompile', 'pomOnlyProvided'] + } + def artifactFiltering = { project.configurations.forEach { pom.scopeMappings.mappings.remove(it) diff --git a/demos/build.gradle b/demos/build.gradle index 8653acdb1f..0fcee799ff 100644 --- a/demos/build.gradle +++ b/demos/build.gradle @@ -22,4 +22,8 @@ subprojects { runtimeOnly 'ch.qos.logback:logback-classic:1.2.3' runtimeOnly 'com.h2database:h2:1.4.196' } + + dependencyCheck { + skipConfigurations += configurations.matching{it.name.startsWith 'gretty'}.names + } } diff --git a/docs/build.gradle b/docs/build.gradle index f0f744c5d1..363aab12f1 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -68,3 +68,6 @@ liveReload { docRoot asciidoctor.outputDir.canonicalPath } +dependencyCheck { + skip = true +} From 2bb513e2bd2d44c4f3e1ba2bcd5127e5dcc20435 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 14 Jan 2019 13:18:13 -0500 Subject: [PATCH 079/372] Fixes #2559 : Validate XML doc element when parsing multi-configs --- .../xml/multi/XmlMultiConfiguration.java | 26 ++++++++++--------- .../xml/multi/XmlMultiConfigurationTest.java | 8 +++++- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java b/xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java index ec887ddbc7..bb90059857 100644 --- a/xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java +++ b/xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java @@ -31,6 +31,9 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; @@ -38,28 +41,17 @@ import javax.xml.validation.Schema; import java.io.IOException; import java.net.URL; -import java.util.AbstractMap.SimpleImmutableEntry; -import java.util.AbstractSet; -import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; import static java.util.Collections.emptyMap; import static java.util.Collections.emptySet; import static java.util.Collections.singleton; import static java.util.Collections.unmodifiableSet; -import static java.util.function.Function.identity; -import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import static org.ehcache.xml.ConfigurationParser.discoverSchema; @@ -74,6 +66,9 @@ public class XmlMultiConfiguration { private static final URL MULTI_SCHEMA_URL = XmlMultiConfiguration.class.getResource("/ehcache-multi.xsd"); + private static final QName MULTI_SCHEMA_ROOT_NAME = new QName( + Configurations.class.getPackage().getAnnotation(XmlSchema.class).namespace(), + Configurations.class.getAnnotation(XmlRootElement.class).name()); private final Map configurations; @@ -88,9 +83,16 @@ private XmlMultiConfiguration(URL url, BiFunction { diff --git a/xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java index da0fb0a466..a44145115c 100644 --- a/xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java @@ -19,6 +19,7 @@ import org.ehcache.config.builders.ConfigurationBuilder; import org.ehcache.xml.XmlConfiguration; import org.ehcache.xml.XmlConfigurationTest; +import org.ehcache.xml.exceptions.XmlConfigurationException; import org.junit.Test; import org.xmlunit.builder.Input; import org.xmlunit.diff.DefaultNodeMatcher; @@ -367,7 +368,7 @@ public void testGenerateExtendedConfiguration() throws URISyntaxException { } @Test - public void testParseExtendedConfiguration() throws URISyntaxException { + public void testParseExtendedConfiguration() { XmlMultiConfiguration xmlMultiConfiguration = XmlMultiConfiguration.from(getClass().getResource("/configs/multi/extended.xml")).build(); assertThat(xmlMultiConfiguration.configuration("foo"), notNullValue()); @@ -394,6 +395,11 @@ public void testParseExtendedConfiguration() throws URISyntaxException { "").ignoreWhitespace().ignoreComments()); } + @Test(expected = XmlConfigurationException.class) + public void testParseOrdinaryConfiguration() { + XmlMultiConfiguration.from(getClass().getResource("/configs/one-cache.xml")).build(); + } + private static Configuration emptyConfiguration() { return ConfigurationBuilder.newConfigurationBuilder().build(); } From 0a0008f7e05f15ed18da2170fd10acba58f6a9db Mon Sep 17 00:00:00 2001 From: akomakom Date: Wed, 6 Feb 2019 09:24:24 -0500 Subject: [PATCH 080/372] Create azure-pipelines-windows.yml --- azure-pipelines-windows.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 azure-pipelines-windows.yml diff --git a/azure-pipelines-windows.yml b/azure-pipelines-windows.yml new file mode 100644 index 0000000000..12a9a3895a --- /dev/null +++ b/azure-pipelines-windows.yml @@ -0,0 +1,30 @@ +# +# Copyright Terracotta, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# See shared code location for steps and parameters: +# https://dev.azure.com/TerracottaCI/_git/terracotta + +resources: + repositories: + - repository: templates + type: git + name: terracotta/terracotta + +jobs: +- template: build-templates/gradle-common.yml@templates + parameters: + gradleTasks: 'check' + vmImage: 'vs2017-win2016' From a51de520adf268fdd488aee0688e0c745c571802 Mon Sep 17 00:00:00 2001 From: akomakom Date: Wed, 6 Feb 2019 10:46:02 -0500 Subject: [PATCH 081/372] verbose debugging --- azure-pipelines-windows.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines-windows.yml b/azure-pipelines-windows.yml index 12a9a3895a..6980cd8008 100644 --- a/azure-pipelines-windows.yml +++ b/azure-pipelines-windows.yml @@ -28,3 +28,4 @@ jobs: parameters: gradleTasks: 'check' vmImage: 'vs2017-win2016' + options: '-i' From 25c5fce3a98d31112a4024e3be4cac65cf66c675 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 7 Feb 2019 17:17:43 -0500 Subject: [PATCH 082/372] Fixes #2567 : CompactJavaSerializer must re-sync itself to the state repository after failures --- .../serialization/CompactJavaSerializer.java | 149 +++++++++++------- .../CompactJavaSerializerTest.java | 86 ++++++++++ 2 files changed, 177 insertions(+), 58 deletions(-) create mode 100644 impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerTest.java diff --git a/impl/src/main/java/org/ehcache/impl/serialization/CompactJavaSerializer.java b/impl/src/main/java/org/ehcache/impl/serialization/CompactJavaSerializer.java index 3f9ba594a1..c4f0450ddb 100644 --- a/impl/src/main/java/org/ehcache/impl/serialization/CompactJavaSerializer.java +++ b/impl/src/main/java/org/ehcache/impl/serialization/CompactJavaSerializer.java @@ -18,7 +18,6 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; @@ -32,19 +31,19 @@ import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import org.ehcache.core.spi.function.NullaryFunction; +import org.ehcache.core.spi.function.BiFunction; import org.ehcache.spi.persistence.StateRepository; import org.ehcache.spi.serialization.SerializerException; import org.ehcache.impl.internal.util.ByteBufferInputStream; import org.ehcache.spi.serialization.Serializer; +import static java.lang.Math.max; + /** * A trivially compressed Java serialization based serializer. *

@@ -55,12 +54,13 @@ */ public class CompactJavaSerializer implements Serializer { - private final ConcurrentMap readLookup; - private final ConcurrentMap readLookupLocalCache = new ConcurrentHashMap(); - private final ConcurrentMap writeLookup = new ConcurrentHashMap(); + private final ConcurrentMap persistentState; + private final ConcurrentMap readLookupCache = new ConcurrentHashMap(); + private final ConcurrentMap writeLookupCache = new ConcurrentHashMap(); private final Lock lock = new ReentrantLock(); private int nextStreamIndex = 0; + private boolean potentiallyInconsistent; private final transient ClassLoader loader; @@ -77,28 +77,20 @@ public CompactJavaSerializer(ClassLoader loader) { public CompactJavaSerializer(ClassLoader loader, StateRepository stateRepository) { this.loader = loader; - this.readLookup = stateRepository.getPersistentConcurrentMap("CompactJavaSerializer-ObjectStreamClassIndex"); - loadMappingsInWriteContext(readLookup.entrySet(), true); + this.persistentState = stateRepository.getPersistentConcurrentMap("CompactJavaSerializer-ObjectStreamClassIndex"); + refreshMappingsFromStateRepository(); } CompactJavaSerializer(ClassLoader loader, Map mappings) { this(loader); for (Entry e : mappings.entrySet()) { - Integer encoding = e.getKey(); - ObjectStreamClass disconnectedOsc = disconnect(e.getValue()); - readLookup.put(encoding, disconnectedOsc); - readLookupLocalCache.put(encoding, disconnectedOsc); - if (writeLookup.putIfAbsent(new SerializableDataKey(disconnectedOsc, true), encoding) != null) { - throw new AssertionError("Corrupted data " + mappings); - } - if (nextStreamIndex < encoding + 1) { - nextStreamIndex = encoding + 1; - } + persistentState.put(e.getKey(), disconnect(e.getValue())); } + refreshMappingsFromStateRepository(); } Map getSerializationMappings() { - return Collections.unmodifiableMap(new HashMap(readLookup)); + return Collections.unmodifiableMap(new HashMap(persistentState)); } /** @@ -153,53 +145,96 @@ public boolean equals(T object, ByteBuffer binary) throws ClassNotFoundException return object.equals(read(binary)); } - private int getOrAddMapping(ObjectStreamClass desc) throws IOException { + private int getOrAddMapping(ObjectStreamClass desc) { SerializableDataKey probe = new SerializableDataKey(desc, false); - Integer rep = writeLookup.get(probe); - if (rep != null) { + Integer rep = writeLookupCache.get(probe); + if (rep == null) { + return addMappingUnderLock(desc, probe); + } else { return rep; } + } - // Install new rep - locking + private int addMappingUnderLock(ObjectStreamClass desc, SerializableDataKey probe) { lock.lock(); try { - return addMappingUnderLock(desc, probe); + if (potentiallyInconsistent) { + refreshMappingsFromStateRepository(); + potentiallyInconsistent = false; + } + while (true) { + Integer rep = writeLookupCache.get(probe); + if (rep != null) { + return rep; + } + rep = nextStreamIndex++; + + //this true/false setting can be cleaner in 1.8+ with a rethrowing Throwable catch + potentiallyInconsistent = true; + ObjectStreamClass disconnected = disconnect(desc); + ObjectStreamClass existingOsc = persistentState.putIfAbsent(rep, disconnected); + if (existingOsc == null) { + cacheMapping(rep, disconnected); + return rep; + } else { + cacheMapping(rep, disconnect(existingOsc)); + } + potentiallyInconsistent = false; + } } finally { lock.unlock(); } } - private int addMappingUnderLock(ObjectStreamClass desc, SerializableDataKey probe) throws IOException { - ObjectStreamClass disconnected = disconnect(desc); - SerializableDataKey key = new SerializableDataKey(disconnected, true); - while (true) { - Integer rep = writeLookup.get(probe); - if (rep != null) { - return rep; - } - rep = nextStreamIndex++; - - ObjectStreamClass existingOsc = readLookup.putIfAbsent(rep, disconnected); - if (existingOsc == null) { - writeLookup.put(key, rep); - return rep; - } else { - // StateRepository map updated somewhere else - reload - loadMappingsInWriteContext(readLookup.entrySet(), false); - } + private void refreshMappingsFromStateRepository() { + int highestIndex = -1; + for (Entry entry : persistentState.entrySet()) { + Integer index = entry.getKey(); + cacheMapping(entry.getKey(), disconnect(entry.getValue())); + highestIndex = max(highestIndex, index); } + nextStreamIndex = highestIndex + 1; } - private void loadMappingsInWriteContext(Set> entries, boolean throwOnFailedPutIfAbsent) { - for (Entry entry : entries) { - Integer index = entry.getKey(); - ObjectStreamClass discOsc = disconnect(entry.getValue()); - readLookupLocalCache.putIfAbsent(index, discOsc); - if (writeLookup.putIfAbsent(new SerializableDataKey(discOsc, true), index) != null && throwOnFailedPutIfAbsent) { - throw new AssertionError("Corrupted data " + readLookup); + private void cacheMapping(Integer index, ObjectStreamClass disconnectedOsc) { + merge(readLookupCache, index, disconnectedOsc, new BiFunction() { + @Override + public ObjectStreamClass apply(ObjectStreamClass existing, ObjectStreamClass update) { + if (CompactJavaSerializer.equals(existing, update)) { + return existing; + } else { + throw new AssertionError("Corrupted data:\n" + + "State Repository: " + persistentState + "\n" + + "Local Write Lookup: " + writeLookupCache + "\n" + + "Local Read Lookup: " + readLookupCache); + } } - if (nextStreamIndex < index + 1) { - nextStreamIndex = index + 1; + }); + merge(writeLookupCache, new SerializableDataKey(disconnectedOsc, true), index, new BiFunction() { + @Override + public Integer apply(Integer existing, Integer update) { + if (existing.equals(update)) { + return existing; + } else { + throw new AssertionError("Corrupted data:\n" + + "State Repository: " + persistentState + "\n" + + "Local Write Lookup: " + writeLookupCache + "\n" + + "Local Read Lookup: " + readLookupCache); + } + } + }); + } + + //Replica of JDK 1.8 ConcurrentMap.merge(...) behavior + private static void merge(ConcurrentMap map, K key, V value, BiFunction merger) { + while (true) { + V existing = map.get(key); + if (existing == null) { + if (map.putIfAbsent(key, value) == null) { + return; + } + } else if (map.replace(key, existing, merger.apply(existing, value))) { + return; } } } @@ -226,16 +261,14 @@ class OIS extends ObjectInputStream { } @Override - protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { + protected ObjectStreamClass readClassDescriptor() throws IOException { int key = readInt(); - ObjectStreamClass objectStreamClass = readLookupLocalCache.get(key); + ObjectStreamClass objectStreamClass = readLookupCache.get(key); if (objectStreamClass != null) { return objectStreamClass; } - objectStreamClass = readLookup.get(key); - ObjectStreamClass discOsc = disconnect(objectStreamClass); - readLookupLocalCache.putIfAbsent(key, discOsc); - writeLookup.putIfAbsent(new SerializableDataKey(discOsc, true), key); + objectStreamClass = persistentState.get(key); + cacheMapping(key, disconnect(objectStreamClass)); return objectStreamClass; } diff --git a/impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerTest.java b/impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerTest.java new file mode 100644 index 0000000000..6778488cf5 --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerTest.java @@ -0,0 +1,86 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.impl.serialization; + +import org.ehcache.spi.persistence.StateRepository; +import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.util.Date; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +public class CompactJavaSerializerTest { + + @Test + public void testStateHolderFailureRereadBehavior() throws ClassNotFoundException { + ConcurrentMap stateMap = spy(new ConcurrentHashMap()); + StateRepository stateRepository = mock(StateRepository.class); + when(stateRepository.getPersistentConcurrentMap("CompactJavaSerializer-ObjectStreamClassIndex")).thenReturn(stateMap); + + final AtomicBoolean failing = new AtomicBoolean(); + Answer optionalFailure = new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + try { + return invocation.callRealMethod(); + } finally { + if (failing.get()) { + throw new RuntimeException(); + } + } + } + }; + + doAnswer(optionalFailure).when(stateMap).entrySet(); + doAnswer(optionalFailure).when(stateMap).get(any()); + doAnswer(optionalFailure).when(stateMap).putIfAbsent(any(Serializable.class), any(Serializable.class)); + + CompactJavaSerializer serializerA = new CompactJavaSerializer(getClass().getClassLoader(), stateRepository); + + Date object = new Date(); + + failing.set(true); + try { + serializerA.serialize(object); + fail("Expected RuntimeException"); + } catch (RuntimeException e) { + //expected + } + + failing.set(false); + ByteBuffer serialized = serializerA.serialize(object); + assertThat(serializerA.read(serialized), is(object)); + + assertThat(stateMap.size(), is(1)); + + CompactJavaSerializer serializerB = new CompactJavaSerializer(getClass().getClassLoader(), stateRepository); + assertThat(serializerB.read(serialized), is(object)); + } +} From fa7bcc5d55eb1dff8119bf48f2ccffb266dcdaac Mon Sep 17 00:00:00 2001 From: akomakom Date: Fri, 8 Feb 2019 11:55:10 -0500 Subject: [PATCH 083/372] Running default targets --- azure-pipelines-windows.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/azure-pipelines-windows.yml b/azure-pipelines-windows.yml index 6980cd8008..5e260e51d6 100644 --- a/azure-pipelines-windows.yml +++ b/azure-pipelines-windows.yml @@ -26,6 +26,4 @@ resources: jobs: - template: build-templates/gradle-common.yml@templates parameters: - gradleTasks: 'check' vmImage: 'vs2017-win2016' - options: '-i' From 49eea14a0317ddbc2a0192d0f58e18fd5011fb00 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Fri, 8 Feb 2019 08:17:01 -0800 Subject: [PATCH 084/372] bump terracotta dependencies --- gradle.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index e8a61a0652..77e2179ba8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,10 +9,10 @@ slf4jVersion = 1.7.25 sizeofVersion = 0.3.0 # Terracotta clustered -terracottaPlatformVersion = 5.6.0-pre7 -terracottaApisVersion = 1.6.0-pre2 -terracottaCoreVersion = 5.6.0-pre8 -terracottaPassthroughTestingVersion = 1.6.0-pre2 +terracottaPlatformVersion = 5.6.0-pre9 +terracottaApisVersion = 1.6.0-pre3 +terracottaCoreVersion = 5.6.0-pre11 +terracottaPassthroughTestingVersion = 1.6.0-pre3 # Test lib versions junitVersion = 4.12 From e8edc1ec2d09a7cea17c144c9bb408642658ccd6 Mon Sep 17 00:00:00 2001 From: Abhilash Date: Fri, 8 Feb 2019 17:00:28 +0530 Subject: [PATCH 085/372] Clear local lock state #2548 --- .../ClusteredLoaderWriterStore.java | 28 +++++------------- .../writebehind/ClusteredWriteBehind.java | 2 +- .../ClusteredWriteBehindStore.java | 6 ++-- .../store/ReconnectingServerStoreProxy.java | 8 ++--- .../internal/store/lock/LockManager.java | 3 +- .../internal/store/lock/LockManagerImpl.java | 8 +++-- .../store/lock/LockingServerStoreProxy.java | 4 +-- .../writebehind/ClusteredWriteBehindTest.java | 2 +- .../store/lock/LockManagerImplTest.java | 29 +++++++++++++++++-- 9 files changed, 51 insertions(+), 39 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java index 4083faa783..d08126d3ac 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java @@ -101,9 +101,7 @@ protected ValueHolder getInternal(K key) throws StoreAccessException, Timeout unlocked = true; return new ClusteredValueHolder<>(value); } finally { - if (!unlocked) { - getProxy().unlock(hash); - } + getProxy().unlock(hash, unlocked); } } } catch (RuntimeException re) { @@ -130,9 +128,7 @@ protected PutStatus silentPut(K key, V value) throws StoreAccessException { append(key, value); unlocked = true; } finally { - if (!unlocked) { - getProxy().unlock(hash); - } + getProxy().unlock(hash, unlocked); } return PutStatus.PUT; } catch (Exception e) { @@ -159,9 +155,7 @@ protected boolean silentRemove(K key) throws StoreAccessException { return false; } } finally { - if (!unlocked) { - getProxy().unlock(hash); - } + getProxy().unlock(hash, unlocked); } } catch (Exception e) { throw handleException(e); @@ -192,9 +186,7 @@ protected V silentPutIfAbsent(K key, V value) throws StoreAccessException { return existingVal; } } finally { - if (!unlocked) { - getProxy().unlock(hash); - } + getProxy().unlock(hash, unlocked); } } catch (Exception e) { throw handleException(e); @@ -232,9 +224,7 @@ protected V silentReplace(K key, V value) throws StoreAccessException { } } } finally { - if (!unlocked) { - getProxy().unlock(hash); - } + getProxy().unlock(hash, unlocked); } } catch (Exception e) { throw handleException(e); @@ -263,9 +253,7 @@ protected V silentRemove(K key, V value) throws StoreAccessException { } return existingVal; } finally { - if (!unlocked) { - getProxy().unlock(hash); - } + getProxy().unlock(hash, unlocked); } } catch (Exception e) { throw handleException(e); @@ -294,9 +282,7 @@ protected V silentReplace(K key, V oldValue, V newValue) throws StoreAccessExcep } return existingVal; } finally { - if (!unlocked) { - getProxy().unlock(hash); - } + getProxy().unlock(hash, unlocked); } } catch (Exception e) { throw handleException(e); diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java index 4df49d721a..8d9881dbf1 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java @@ -97,7 +97,7 @@ void flushWriteBehindQueue(Chain ignored, long hash) { clusteredWriteBehindStore.replaceAtHead(hash, chain, builder.build()); } } finally { - clusteredWriteBehindStore.unlock(hash); + clusteredWriteBehindStore.unlock(hash, false); } } catch (TimeoutException e) { throw new RuntimeException(e); diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java index 152424f760..1f288b709c 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java @@ -78,8 +78,8 @@ Chain lock(long hash) throws TimeoutException { return ((LockManager) storeProxy).lock(hash); } - void unlock(long hash) throws TimeoutException { - ((LockManager) storeProxy).unlock(hash); + void unlock(long hash, boolean localOnly) throws TimeoutException { + ((LockManager) storeProxy).unlock(hash, localOnly); } void replaceAtHead(long key, Chain expected, Chain replacement) { @@ -120,7 +120,7 @@ protected ValueHolder getInternal(K key) throws StoreAccessException, Timeout append(key, value); return new ClusteredValueHolder<>(value); } finally { - unlock(hash); + unlock(hash, false); } } } catch (RuntimeException re) { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java index 7bc88d1703..f2982de3be 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java @@ -121,9 +121,9 @@ public Chain lock(long hash) throws TimeoutException { } @Override - public void unlock(long hash) throws TimeoutException { + public void unlock(long hash, boolean localonly) throws TimeoutException { onStoreProxy(lockingServerStoreProxy -> { - lockingServerStoreProxy.unlock(hash); + lockingServerStoreProxy.unlock(hash, localonly); return null; }); } @@ -183,7 +183,7 @@ public Chain lock(long hash) throws TimeoutException { } @Override - public void unlock(long hash) throws TimeoutException { + public void unlock(long hash, boolean localonly) throws TimeoutException { throw new ReconnectInProgressException(); } } @@ -196,7 +196,7 @@ public Chain lock(long hash) throws TimeoutException { } @Override - public void unlock(long hash) throws TimeoutException { + public void unlock(long hash, boolean localonly) throws TimeoutException { throw new UnsupportedOperationException("Lock ops are not supported"); } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManager.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManager.java index 164ac3009b..53e3e59b33 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManager.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManager.java @@ -29,7 +29,8 @@ public interface LockManager { /** * * @param hash + * @param localonly */ - void unlock(long hash) throws TimeoutException; + void unlock(long hash, boolean localonly) throws TimeoutException; } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImpl.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImpl.java index 9306765a72..7fa2121ec0 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImpl.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImpl.java @@ -41,7 +41,7 @@ public LockManagerImpl(ClusterTierClientEntity clientEntity) { clientEntity.addReconnectListener(this::reconnectListener); } - private void reconnectListener(ClusterTierReconnectMessage reconnectMessage) { + void reconnectListener(ClusterTierReconnectMessage reconnectMessage) { reconnectMessage.addLocksHeld(locksHeld); } @@ -70,9 +70,11 @@ private LockSuccess getlockResponse(long hash) throws TimeoutException { } @Override - public void unlock(long hash) throws TimeoutException { + public void unlock(long hash, boolean localonly) throws TimeoutException { try { - clientEntity.invokeAndWaitForComplete(new UnlockMessage(hash), false); + if (!localonly) { + clientEntity.invokeAndWaitForComplete(new UnlockMessage(hash), false); + } locksHeld.remove(hash); } catch (TimeoutException tme) { throw tme; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java index d231aac923..c65f24f227 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java @@ -47,8 +47,8 @@ public Chain lock(long hash) throws TimeoutException { } @Override - public void unlock(long hash) throws TimeoutException { - lockManager.unlock(hash); + public void unlock(long hash, boolean localonly) throws TimeoutException { + lockManager.unlock(hash, localonly); } @Override diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java index 036b08c8c0..9511d5ed4d 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java @@ -188,7 +188,7 @@ private void verifyEvents(List expected, Map expectedCh assertThat(entry.getValue(), is(expectedChainContents.get(entry.getKey()))); } - verify(clusteredWriteBehindStore).unlock(1L); + verify(clusteredWriteBehindStore).unlock(1L, false); } private Map convert(Chain chain, OperationsCodec codec, diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImplTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImplTest.java index d3c7ec4759..525b331ffd 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImplTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImplTest.java @@ -18,14 +18,17 @@ import org.ehcache.clustered.client.internal.store.ClusterTierClientEntity; import org.ehcache.clustered.client.internal.store.ServerStoreProxyException; import org.ehcache.clustered.common.internal.exceptions.UnknownClusterException; +import org.ehcache.clustered.common.internal.messages.ClusterTierReconnectMessage; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.LockSuccess; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.LockMessage; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.Util; import org.junit.Test; +import org.mockito.ArgumentCaptor; import java.nio.ByteBuffer; +import java.util.Set; import java.util.concurrent.TimeoutException; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.lockFailure; @@ -36,8 +39,7 @@ import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; public class LockManagerImplTest { @@ -101,6 +103,27 @@ public void testLockWhenFailure() throws Exception { assertThat(lock.length(), is(3)); } + @SuppressWarnings("unchecked") + @Test + public void testUnlockClearsLocksHeldState() throws Exception { + ClusterTierClientEntity clusterTierClientEntity = mock(ClusterTierClientEntity.class); + LockManagerImpl lockManager = new LockManagerImpl(clusterTierClientEntity); + + LockSuccess lockSuccess = getLockSuccessResponse(); + when(clusterTierClientEntity.invokeAndWaitForComplete(any(LockMessage.class), anyBoolean())) + .thenReturn(lockSuccess); + + Chain lock = lockManager.lock(2L); + lockManager.unlock(2L, false); + + ClusterTierReconnectMessage reconnectMessage = mock(ClusterTierReconnectMessage.class); + ArgumentCaptor> locks = ArgumentCaptor.forClass(Set.class); + doNothing().when(reconnectMessage).addLocksHeld(locks.capture()); + lockManager.reconnectListener(reconnectMessage); + assertThat(locks.getValue().size(), is(0)); + + } + private LockSuccess getLockSuccessResponse() { ByteBuffer[] buffers = new ByteBuffer[3]; for (int i = 1; i <= 3; i++) { @@ -112,4 +135,4 @@ private LockSuccess getLockSuccessResponse() { return EhcacheEntityResponse.lockSuccess(chain); } -} \ No newline at end of file +} From 18cbdfc894d1e15dd72704d3fbb23e8d355feb3e Mon Sep 17 00:00:00 2001 From: Anthony Dahanne Date: Tue, 12 Feb 2019 23:56:24 -0500 Subject: [PATCH 086/372] Fix potential NPE in tc core when validating response --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 77e2179ba8..307fae0bac 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,9 +9,9 @@ slf4jVersion = 1.7.25 sizeofVersion = 0.3.0 # Terracotta clustered -terracottaPlatformVersion = 5.6.0-pre9 +terracottaPlatformVersion = 5.6.0-pre10 terracottaApisVersion = 1.6.0-pre3 -terracottaCoreVersion = 5.6.0-pre11 +terracottaCoreVersion = 5.6.0-pre12 terracottaPassthroughTestingVersion = 1.6.0-pre3 # Test lib versions From f0f01786665bb33d291ed08f6163dca7c1af0fd8 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 11 Feb 2019 09:18:55 -0500 Subject: [PATCH 087/372] Disable clustered tests on windows. --- azure-pipelines-windows.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines-windows.yml b/azure-pipelines-windows.yml index 5e260e51d6..3b7e1d0210 100644 --- a/azure-pipelines-windows.yml +++ b/azure-pipelines-windows.yml @@ -27,3 +27,4 @@ jobs: - template: build-templates/gradle-common.yml@templates parameters: vmImage: 'vs2017-win2016' + gradleTasks: 'test -x :clustered:integration-test:test' From 0188a7b9b1e773e98022e19961c1215315839f97 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 18 Jan 2019 16:00:22 -0500 Subject: [PATCH 088/372] Upgrade to Gradle 5.1.1 --- gradle/wrapper/gradle-wrapper.jar | Bin 56177 -> 55741 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- gradlew.bat | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 29953ea141f55e3b8fc691d31b5ca8816d89fa87..457aad0d98108420a977756b7145c93c8910b076 100644 GIT binary patch delta 46476 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

d1ZzV`PJaf;LURr$w8USfDLW+{$cK=5Uq0( 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�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 V;3?$)Jo1M@amx&F&%^&5`+o%ZZcYFI diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ee671127ff..c4486d47dc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index cccdd3d517..af6708ff22 100755 --- a/gradlew +++ b/gradlew @@ -28,7 +28,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" diff --git a/gradlew.bat b/gradlew.bat index f9553162f1..6d57edc706 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome From 423125b6b38f519b8c35354570c70f257252eeb0 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 17 Jan 2019 16:42:09 -0500 Subject: [PATCH 089/372] Convert to BND plugin --- 107/build.gradle | 12 +++++----- api/build.gradle | 10 ++++----- build.gradle | 23 +++++++++++--------- buildSrc/src/main/groovy/EhDistribute.groovy | 21 ++++++++---------- clustered/client/build.gradle | 1 - clustered/clustered-dist/build.gradle | 10 +++++---- core/build.gradle | 11 +++++----- dist/build.gradle | 16 +++++++------- impl/build.gradle | 14 ++++++------ transactions/build.gradle | 13 ++++++----- xml/build.gradle | 8 +++---- 11 files changed, 71 insertions(+), 68 deletions(-) diff --git a/107/build.gradle b/107/build.gradle index ff0914e8d6..047379815a 100644 --- a/107/build.gradle +++ b/107/build.gradle @@ -15,7 +15,7 @@ */ apply plugin: EhDeploy -apply plugin: 'osgi' +apply plugin: 'biz.aQute.bnd.builder' apply plugin: 'osgi-ds' configurations { @@ -53,11 +53,11 @@ javadoc { } jar { - manifest { - instruction 'Export-Package', '!org.ehcache.jsr107.tck', '!org.ehcache.jsr107.internal.*', 'org.ehcache.jsr107.*' - instruction 'Import-Package', 'javax.cache.*;resolution:=optional', '*' - instruction 'Service-Component', 'OSGI-INF/*.xml' - } + bnd( + 'Export-Package': '!org.ehcache.jsr107.tck, !org.ehcache.jsr107.internal.*, org.ehcache.jsr107.*', + 'Import-Package': 'javax.cache.*;resolution:=optional, *', + 'Service-Component': 'OSGI-INF/*.xml' + ) } test { diff --git a/api/build.gradle b/api/build.gradle index ca291e48b1..5c5512d3f4 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -15,15 +15,15 @@ */ apply plugin: EhDeploy -apply plugin: 'osgi' +apply plugin: 'biz.aQute.bnd.builder' checkstyle { configFile = file("$projectDir/config/checkstyle.xml") } jar { - manifest { - instruction 'Export-Package', 'org.ehcache.*' - instruction 'Import-Package', '*' - } + bnd( + 'Export-Package': 'org.ehcache.*', + 'Import-Package': '*' + ) } diff --git a/build.gradle b/build.gradle index 87eb3e3aa1..a432f745a1 100644 --- a/build.gradle +++ b/build.gradle @@ -29,6 +29,8 @@ plugins { id 'org.jayware.osgi-ds' version '0.5.5' apply false //OWASP Security Vulnerability Detection id 'org.owasp.dependencycheck' version '4.0.2' apply false + // Declare bnd at the top + id 'biz.aQute.bnd.builder' version '4.1.0' apply false } wrapper { @@ -231,18 +233,19 @@ subprojects { } } - if (plugins.hasPlugin('osgi')) { + plugins.withType(aQute.bnd.gradle.BndBuilderPlugin) { jar { - manifest { - instruction 'Bundle-Name', project.properties.subPomName - instruction 'Bundle-Description', project.properties.subPomDesc - instruction 'Bundle-SymbolicName', "org.ehcache.$project.archivesBaseName" - instruction 'Bundle-DocURL', 'http://ehcache.org' - instruction 'Bundle-License', 'LICENSE' - instruction 'Bundle-Vendor', 'Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.' - instruction 'Bundle-RequiredExecutionEnvironment', 'JavaSE-1.8' - } + bnd( + 'Bundle-Name': project.properties.subPomName, + 'Bundle-Description': project.properties.subPomDesc, + 'Bundle-SymbolicName': "org.ehcache.modules.$project.archivesBaseName", + 'Bundle-DocURL': 'http://ehcache.org', + 'Bundle-License': 'LICENSE', + 'Bundle-Vendor': 'Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.', + 'Bundle-RequiredExecutionEnvironment': 'JavaSE-1.8', + ) } + check.dependsOn(baseline) } } diff --git a/buildSrc/src/main/groovy/EhDistribute.groovy b/buildSrc/src/main/groovy/EhDistribute.groovy index 2d388cb495..2b016b97cc 100644 --- a/buildSrc/src/main/groovy/EhDistribute.groovy +++ b/buildSrc/src/main/groovy/EhDistribute.groovy @@ -33,6 +33,7 @@ class EhDistribute implements Plugin { project.plugins.apply 'java-library' project.plugins.apply 'maven' project.plugins.apply 'signing' + project.plugins.apply 'biz.aQute.bnd.builder' project.plugins.apply 'com.github.johnrengelman.shadow' project.plugins.apply EhPomMangle project.plugins.apply EhDocs @@ -62,18 +63,14 @@ class EhDistribute implements Plugin { from "$project.rootDir/NOTICE" duplicatesStrategy = 'exclude' - def osgiConvention = new OsgiPluginConvention(project) - manifest = osgiConvention.osgiManifest { - classesDir = project.shadowJar.archivePath - classpath = project.files(project.configurations.shadowCompile, project.configurations.shadowProvided) - - // Metadata - instruction 'Bundle-DocURL', 'http://ehcache.org' - instruction 'Bundle-License', 'LICENSE' - instruction 'Bundle-Vendor', 'Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.' - instruction 'Bundle-RequiredExecutionEnvironment', 'JavaSE-1.8' - instruction 'Service-Component', 'OSGI-INF/*.xml' - } + classpath = project.files(project.configurations.shadowCompile, project.configurations.shadowProvided) + bnd( + 'Bundle-DocURL': 'http://ehcache.org', + 'Bundle-License': 'LICENSE', + 'Bundle-Vendor': 'Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.', + 'Bundle-RequiredExecutionEnvironment': 'JavaSE-1.8', + 'Service-Component': 'OSGI-INF/*.xml' + ) utils.fillManifest(manifest, project.archivesBaseName) } diff --git a/clustered/client/build.gradle b/clustered/client/build.gradle index 087c922191..370402dcb3 100644 --- a/clustered/client/build.gradle +++ b/clustered/client/build.gradle @@ -15,7 +15,6 @@ */ apply plugin: EhDeploy -apply plugin: 'osgi' apply plugin: 'osgi-ds' dependencies { diff --git a/clustered/clustered-dist/build.gradle b/clustered/clustered-dist/build.gradle index 84dde04b37..c88112a666 100644 --- a/clustered/clustered-dist/build.gradle +++ b/clustered/clustered-dist/build.gradle @@ -74,10 +74,12 @@ task copyDocs(type: Copy) { } jar { - manifest { - instruction 'Export-Package', '!com.tc.*', '!com.terracotta.*', '!org.terracotta.*', '!org.ehcache.*.internal.*', '!sun.misc', 'org.ehcache.clustered.client.*' - instruction 'Import-Package', '!sun.misc.*', 'org.ehcache.xml.*;resolution:=optional', '*' - } + bnd ( + 'Bundle-SymbolicName': 'org.ehcache.clustered', + 'Export-Package': '!com.tc.*, !com.terracotta.*, !org.terracotta.*, !org.ehcache.*.internal.*, !sun.misc, ' + + 'org.ehcache.clustered.client.*, org.ehcache.clustered.common.*', + 'Import-Package': '!sun.misc.*, org.ehcache.xml.*;resolution:=optional, *' + ) } distributions { diff --git a/core/build.gradle b/core/build.gradle index 1cdb5fe99d..8a3a64aad8 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -15,7 +15,7 @@ */ apply plugin: EhDeploy -apply plugin: 'osgi' +apply plugin: 'biz.aQute.bnd.builder' dependencies { api project(':api') @@ -25,8 +25,9 @@ dependencies { } jar { - manifest { - instruction 'Bundle-Activator', 'org.ehcache.core.osgi.EhcacheActivator' - instruction 'Export-Package', '!org.ehcache.core.internal.*', 'org.ehcache.core.*' - } + bnd ( + 'Bundle-Activator': 'org.ehcache.core.osgi.EhcacheActivator', + 'Import-Package': '!javax.annotation, *', + 'Export-Package': '!org.ehcache.core.internal.*, org.ehcache.core.*', + ) } diff --git a/dist/build.gradle b/dist/build.gradle index c4c636d865..a00ef74888 100644 --- a/dist/build.gradle +++ b/dist/build.gradle @@ -32,13 +32,13 @@ dependencies { } jar { - manifest { - instructionReplace 'Bundle-Name', "Ehcache 3" - instructionReplace 'Bundle-SymbolicName', "org.ehcache" - instructionReplace 'Bundle-Description', 'Ehcache is an open-source caching library, compliant with the JSR-107 standard.' + bnd ( + 'Bundle-Name': 'Ehcache 3', + 'Bundle-SymbolicName': 'org.ehcache', + 'Bundle-Description': 'Ehcache is an open-source caching library, compliant with the JSR-107 standard.', - instruction 'Bundle-Activator', 'org.ehcache.core.osgi.EhcacheActivator' - instruction 'Export-Package', '!org.ehcache.jsr107.tck', '!org.ehcache.*.internal.*', 'org.ehcache.*', 'org.terracotta.statistics.*', 'org.terracotta.context' - instruction 'Import-Package', 'javax.cache.*;resolution:=optional', '!sun.misc', '*' - } + 'Bundle-Activator': 'org.ehcache.core.osgi.EhcacheActivator', + 'Export-Package': '!org.ehcache.jsr107.tck, !org.ehcache.*.internal.*, org.ehcache.*, org.terracotta.statistics.*, org.terracotta.context', + 'Import-Package': 'javax.cache.*;resolution:=optional, !sun.misc, *' + ) } diff --git a/impl/build.gradle b/impl/build.gradle index 6752b6bebd..c7429bd6f8 100644 --- a/impl/build.gradle +++ b/impl/build.gradle @@ -15,7 +15,7 @@ */ apply plugin: EhDeploy -apply plugin: 'osgi' +apply plugin: 'biz.aQute.bnd.builder' apply plugin: 'osgi-ds' dependencies { @@ -33,12 +33,12 @@ dependencies { jar { from "$rootDir/NOTICE" - manifest { - instruction 'Export-Package', '!org.ehcache.impl.internal.*', 'org.ehcache.impl.*', 'org.ehcache.config.builders', - 'org.ehcache.impl.internal.spi.loaderwriter' //ugly 107 induced internal export wart - instruction 'Import-Package', '!sun.misc', '*' - instruction 'Service-Component', 'OSGI-INF/*.xml' - } + bnd ( + 'Export-Package': '!org.ehcache.impl.internal.*, org.ehcache.impl.*, org.ehcache.config.builders, ' + + 'org.ehcache.impl.internal.spi.loaderwriter', //ugly 107 induced internal export wart + 'Import-Package': '!sun.misc, *', + 'Service-Component': 'OSGI-INF/*.xml' + ) } compileJava { diff --git a/transactions/build.gradle b/transactions/build.gradle index 6357b5f0d9..e3f34ad07a 100644 --- a/transactions/build.gradle +++ b/transactions/build.gradle @@ -16,7 +16,7 @@ group = 'org.ehcache' -apply plugin: 'osgi' +apply plugin: 'biz.aQute.bnd.builder' apply plugin: 'osgi-ds' apply plugin: EhPomMangle @@ -47,11 +47,12 @@ test { } jar { - manifest { - instruction 'Export-Package', 'org.ehcache.transactions.xa.*' - instruction 'Import-Package', 'bitronix.tm.*;resolution:=optional', 'javax.transaction.*;resolution:=optional', 'org.ehcache.xml.*;resolution:=optional', '*' - instruction 'Service-Component', 'OSGI-INF/*.xml' - } + bnd ( + 'Bundle-SymbolicName': 'org.ehcache.transactions', + 'Export-Package': 'org.ehcache.transactions.xa.*', + 'Import-Package': 'bitronix.tm.*;resolution:=optional, javax.transaction.*;resolution:=optional, org.ehcache.xml.*;resolution:=optional, *', + 'Service-Component': 'OSGI-INF/*.xml' + ) } project.signing { diff --git a/xml/build.gradle b/xml/build.gradle index 36ce752054..c46743f1f3 100644 --- a/xml/build.gradle +++ b/xml/build.gradle @@ -20,7 +20,7 @@ plugins { } apply plugin: EhDeploy -apply plugin: 'osgi' +apply plugin: 'biz.aQute.bnd.builder' apply plugin: 'com.github.hauner.jarTest' dependencies { @@ -39,9 +39,9 @@ test { } jar { - manifest { - instruction 'Export-Package', 'org.ehcache.xml', 'org.ehcache.xml.exceptions', 'org.ehcache.xml.model' - } + bnd ( + 'Export-Package': 'org.ehcache.xml, org.ehcache.xml.exceptions, org.ehcache.xml.model', + ) } xjcGenerate { From 9ff6944d57852b0559301da7bef06676a6fa79de Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 18 Jan 2019 16:15:43 -0500 Subject: [PATCH 090/372] Upgrade to SpotBugs Plugin 1.6.9 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a432f745a1..41fea8b0bd 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ plugins { // ./gradlew ... taskTree id "com.dorongold.task-tree" version "1.3.1" // Declare spotbugs at the top - id 'com.github.spotbugs' version '1.6.5' apply false + id 'com.github.spotbugs' version '1.6.9' apply false // Declare osgi-ds at the top id 'org.jayware.osgi-ds' version '0.5.5' apply false //OWASP Security Vulnerability Detection From f06d9993ee0222f439f0b37151d4b65f5a3ce9a1 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 13 Feb 2019 11:51:26 -0500 Subject: [PATCH 091/372] Upgrade to Gradle 5.2.1 --- gradle/wrapper/gradle-wrapper.jar | Bin 55741 -> 55190 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 457aad0d98108420a977756b7145c93c8910b076..87b738cbd051603d91cc39de6cb000dd98fe6b02 100644 GIT binary patch delta 19106 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 Q;k^UD+~FQ?)`rgh1-4RH;Q#;t diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c4486d47dc..1b2b07cfb0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 0fb7f3db93eef03b9c06e718e4e9a8090bb0dcb0 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 15 Feb 2019 12:12:37 -0500 Subject: [PATCH 092/372] No need to add jar artifact: java-library already did, and duplicate artifacts upset the signing plugin --- build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.gradle b/build.gradle index 41fea8b0bd..58e4011050 100644 --- a/build.gradle +++ b/build.gradle @@ -170,8 +170,6 @@ subprojects { } artifacts { - archives jar - archives javadocJar archives sourceJar } From 253dfdc0fad86710af23015cab67b7f5beefd45b Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 15 Feb 2019 12:50:23 -0500 Subject: [PATCH 093/372] Static analysis job should use gradle --- azure-pipelines-static-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines-static-analysis.yml b/azure-pipelines-static-analysis.yml index 481793ad3e..4c3f99b9a8 100644 --- a/azure-pipelines-static-analysis.yml +++ b/azure-pipelines-static-analysis.yml @@ -24,6 +24,6 @@ resources: name: terracotta/terracotta jobs: -- template: build-templates/maven-common.yml@templates +- template: build-templates/gradle-common.yml@templates parameters: gradleTasks: 'check' From a16a79e2bd812b040d723dcfd054da24ef3a961f Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 4 Feb 2019 10:23:34 -0500 Subject: [PATCH 094/372] Cleanup testing and chain building infrastructure --- clustered/client/build.gradle | 1 + .../writebehind/ClusteredWriteBehind.java | 2 +- .../store/operations/ChainResolver.java | 2 +- .../ClusteredLoaderWriterStoreTest.java | 44 +- .../writebehind/ClusteredWriteBehindTest.java | 43 +- .../internal/store/ChainBuilderTest.java | 40 +- .../store/CommonServerStoreProxyTest.java | 39 +- .../store/EventualServerStoreProxyTest.java | 6 +- ...ltiThreadedStrongServerStoreProxyTest.java | 2 +- .../store/StrongServerStoreProxyTest.java | 6 +- .../store/lock/LockManagerImplTest.java | 9 +- .../ActivePassiveClientIdTest.java | 13 +- .../operations/AbstractChainResolverTest.java | 602 ++++++++++++++++ .../operations/EternalChainResolverTest.java | 498 +------------- .../ExpiryChainResolverExpiryTest.java | 293 -------- .../operations/ExpiryChainResolverTest.java | 645 +++++------------- clustered/common/build.gradle | 2 + .../common/internal/messages/ChainCodec.java | 19 +- .../common/internal/store/Chain.java | 9 - .../clustered/common/internal/store/Util.java | 138 ---- .../common/internal/util}/ChainBuilder.java | 45 +- .../internal/messages/ChainCodecTest.java | 49 +- .../internal/messages/ResponseCodecTest.java | 20 +- .../messages/ServerStoreOpCodecTest.java | 20 +- .../messages/ServerStoreOpMessageTest.java | 15 +- .../common/internal/messages/Util.java | 43 -- clustered/server/build.gradle | 2 + .../messages/PassiveReplicationMessage.java | 11 +- .../server/offheap/OffHeapChainMap.java | 65 +- .../offheap/OffHeapChainStorageEngine.java | 35 +- .../messages/EhcacheSyncMessageCodecTest.java | 15 +- .../PassiveReplicationMessageCodecTest.java | 11 +- .../server/offheap/ChainMapExtensionTest.java | 6 +- .../server/offheap/ChainMapTest.java | 36 +- .../offheap/OffHeapServerStoreTest.java | 8 +- .../offheap/PinningOffHeapChainMapTest.java | 55 +- .../store/ClusterTierActiveEntityTest.java | 3 +- .../store/ClusterTierPassiveEntityTest.java | 14 +- .../server/store/LockManagerImplTest.java | 2 +- .../server/store/ServerStoreTest.java | 69 +- .../server/store/impl/HeapChainImpl.java | 36 - .../server/store/impl/HeapElementImpl.java | 2 +- clustered/test-utils/build.gradle | 4 + .../config/checkstyle-suppressions.xml | 9 + .../org/ehcache/clustered/ChainUtils.java | 109 +++ .../java/org/ehcache/clustered/Matchers.java | 105 +++ settings.gradle | 2 +- 47 files changed, 1277 insertions(+), 1927 deletions(-) create mode 100644 clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java delete mode 100644 clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverExpiryTest.java rename clustered/{client/src/main/java/org/ehcache/clustered/client/internal/store => common/src/main/java/org/ehcache/clustered/common/internal/util}/ChainBuilder.java (59%) delete mode 100644 clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/Util.java create mode 100644 clustered/test-utils/build.gradle create mode 100644 clustered/test-utils/config/checkstyle-suppressions.xml create mode 100644 clustered/test-utils/src/main/java/org/ehcache/clustered/ChainUtils.java create mode 100644 clustered/test-utils/src/main/java/org/ehcache/clustered/Matchers.java diff --git a/clustered/client/build.gradle b/clustered/client/build.gradle index 370402dcb3..05c60a3242 100644 --- a/clustered/client/build.gradle +++ b/clustered/client/build.gradle @@ -35,6 +35,7 @@ dependencies { testImplementation(project(':clustered:server')) { exclude group: 'org.terracotta.internal', module: 'tc-config-parser' } + testImplementation project(':clustered:test-utils') testImplementation "org.terracotta:entity-test-lib:$terracottaPassthroughTestingVersion" testImplementation "org.terracotta:passthrough-server:$terracottaPassthroughTestingVersion" testImplementation "org.terracotta.internal:common:$terracottaCoreVersion" diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java index 8d9881dbf1..6ab6de747d 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java @@ -15,7 +15,7 @@ */ package org.ehcache.clustered.client.internal.loaderwriter.writebehind; -import org.ehcache.clustered.client.internal.store.ChainBuilder; +import org.ehcache.clustered.common.internal.util.ChainBuilder; import org.ehcache.clustered.client.internal.store.operations.ChainResolver; import org.ehcache.clustered.common.internal.store.operations.ConditionalRemoveOperation; import org.ehcache.clustered.common.internal.store.operations.Operation; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java index 09e30cd6c4..42f4c16853 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java @@ -16,7 +16,7 @@ package org.ehcache.clustered.client.internal.store.operations; -import org.ehcache.clustered.client.internal.store.ChainBuilder; +import org.ehcache.clustered.common.internal.util.ChainBuilder; import org.ehcache.clustered.client.internal.store.ResolvedChain; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.Element; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java index 0f29847eab..ce6c14e85e 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java @@ -21,7 +21,6 @@ import org.ehcache.clustered.common.internal.store.operations.PutOperation; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; import org.ehcache.clustered.common.internal.store.Chain; -import org.ehcache.clustered.common.internal.store.Util; import org.ehcache.clustered.loaderWriter.TestCacheLoaderWriter; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.time.TimeSource; @@ -33,7 +32,8 @@ import java.nio.ByteBuffer; -import static org.ehcache.clustered.common.internal.store.Util.EMPTY_CHAIN; +import static java.util.Collections.emptyList; +import static org.ehcache.clustered.ChainUtils.chainOf; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; @@ -59,7 +59,7 @@ public class ClusteredLoaderWriterStoreTest { public void testGetValueAbsentInSOR() throws Exception { ServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); CacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.get(eq(1L))).thenReturn(EMPTY_CHAIN); + when(storeProxy.get(eq(1L))).thenReturn(chainOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(store.get(1L), is(nullValue())); @@ -70,7 +70,7 @@ public void testGetValuePresentInSOR() throws Exception { ServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); loaderWriter.storeMap.put(1L, "one"); - when(storeProxy.get(eq(1L))).thenReturn(EMPTY_CHAIN); + when(storeProxy.get(eq(1L))).thenReturn(chainOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(store.get(1L).get(), equalTo("one")); @@ -82,7 +82,7 @@ public void testGetValuePresentInCache() throws Exception { @SuppressWarnings("unchecked") CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); PutOperation operation = new PutOperation<>(1L, "one", System.currentTimeMillis()); - Chain toReturn = Util.getChain(false, codec.encode(operation)); + Chain toReturn = chainOf(codec.encode(operation)); when(storeProxy.get(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); @@ -106,7 +106,7 @@ public void testPut() throws Exception { public void testRemoveValueAbsentInCachePresentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(EMPTY_CHAIN); + when(storeProxy.lock(anyLong())).thenReturn(chainOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); loaderWriter.storeMap.put(1L, "one"); @@ -119,7 +119,7 @@ public void testRemoveValuePresentInCachePresentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); PutOperation operation = new PutOperation<>(1L, "one", System.currentTimeMillis()); - Chain toReturn = Util.getChain(false, codec.encode(operation)); + Chain toReturn = chainOf(codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); when(storeProxy.get(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, @@ -135,7 +135,7 @@ public void testRemoveValueAbsentInCacheAbsentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); @SuppressWarnings("unchecked") CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); - when(storeProxy.lock(anyLong())).thenReturn(EMPTY_CHAIN); + when(storeProxy.lock(anyLong())).thenReturn(chainOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(store.remove(1L), is(false)); @@ -146,7 +146,7 @@ public void testRemoveValueAbsentInCacheAbsentInSOR() throws Exception { public void testPufIfAbsentValueAbsentInCacheAbsentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(EMPTY_CHAIN); + when(storeProxy.lock(anyLong())).thenReturn(chainOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(loaderWriter.storeMap.isEmpty(), is(true)); @@ -158,7 +158,7 @@ public void testPufIfAbsentValueAbsentInCacheAbsentInSOR() throws Exception { public void testPufIfAbsentValueAbsentInCachePresentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(EMPTY_CHAIN); + when(storeProxy.lock(anyLong())).thenReturn(chainOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); loaderWriter.storeMap.put(1L, "one"); @@ -172,7 +172,7 @@ public void testPufIfAbsentValuePresentInCachePresentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); PutOperation operation = new PutOperation<>(1L, "one", System.currentTimeMillis()); - Chain toReturn = Util.getChain(false, codec.encode(operation)); + Chain toReturn = chainOf(codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); @@ -186,7 +186,7 @@ public void testPufIfAbsentValuePresentInCachePresentInSOR() throws Exception { public void testReplaceValueAbsentInCacheAbsentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(EMPTY_CHAIN); + when(storeProxy.lock(anyLong())).thenReturn(chainOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(loaderWriter.storeMap.isEmpty(), is(true)); @@ -199,7 +199,7 @@ public void testReplaceValueAbsentInCacheAbsentInSOR() throws Exception { public void testReplaceValueAbsentInCachePresentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(EMPTY_CHAIN); + when(storeProxy.lock(anyLong())).thenReturn(chainOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); loaderWriter.storeMap.put(1L, "one"); @@ -213,7 +213,7 @@ public void testReplaceValuePresentInCachePresentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); PutOperation operation = new PutOperation<>(1L, "one", System.currentTimeMillis()); - Chain toReturn = Util.getChain(false, codec.encode(operation)); + Chain toReturn = chainOf(codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); @@ -228,7 +228,7 @@ public void testRemove2ArgsValueAbsentInCacheAbsentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); @SuppressWarnings("unchecked") CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); - when(storeProxy.lock(anyLong())).thenReturn(EMPTY_CHAIN); + when(storeProxy.lock(anyLong())).thenReturn(chainOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(store.remove(1L, "one"), is(Store.RemoveStatus.KEY_MISSING)); @@ -239,7 +239,7 @@ public void testRemove2ArgsValueAbsentInCacheAbsentInSOR() throws Exception { public void testRemove2ArgsValueAbsentInCachePresentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(EMPTY_CHAIN); + when(storeProxy.lock(anyLong())).thenReturn(chainOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); loaderWriter.storeMap.put(1L, "one"); @@ -254,7 +254,7 @@ public void testRemove2ArgsValuePresentInCachePresentInSOR() throws Exception { @SuppressWarnings("unchecked") CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); PutOperation operation = new PutOperation<>(1L, "one", System.currentTimeMillis()); - Chain toReturn = Util.getChain(false, codec.encode(operation)); + Chain toReturn = chainOf(codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); @@ -268,7 +268,7 @@ public void testRemove2ArgsValuePresentInCachePresentInSOR() throws Exception { public void testRemove2ArgsValueAbsentInCacheDiffValuePresentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(EMPTY_CHAIN); + when(storeProxy.lock(anyLong())).thenReturn(chainOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); loaderWriter.storeMap.put(1L, "one"); @@ -282,7 +282,7 @@ public void testReplace2ArgsValueAbsentInCacheAbsentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); @SuppressWarnings("unchecked") CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); - when(storeProxy.lock(anyLong())).thenReturn(EMPTY_CHAIN); + when(storeProxy.lock(anyLong())).thenReturn(chainOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(store.replace(1L, "one", "Again"), is(Store.ReplaceStatus.MISS_NOT_PRESENT)); @@ -295,7 +295,7 @@ public void testReplace2ArgsValueAbsentInCacheAbsentInSOR() throws Exception { public void testReplace2ArgsValueAbsentInCachePresentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(EMPTY_CHAIN); + when(storeProxy.lock(anyLong())).thenReturn(chainOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); loaderWriter.storeMap.put(1L, "one"); @@ -310,7 +310,7 @@ public void testReplace2ArgsValuePresentInCachePresentInSOR() throws Exception { @SuppressWarnings("unchecked") CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); PutOperation operation = new PutOperation<>(1L, "one", System.currentTimeMillis()); - Chain toReturn = Util.getChain(false, codec.encode(operation)); + Chain toReturn = chainOf(codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); @@ -324,7 +324,7 @@ public void testReplace2ArgsValuePresentInCachePresentInSOR() throws Exception { public void testReplace2ArgsValueAbsentInCacheDiffValueInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(EMPTY_CHAIN); + when(storeProxy.lock(anyLong())).thenReturn(chainOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); loaderWriter.storeMap.put(1L, "one"); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java index 9511d5ed4d..3e25e1f3c0 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java @@ -15,6 +15,7 @@ */ package org.ehcache.clustered.client.internal.loaderwriter.writebehind; +import org.ehcache.clustered.common.internal.util.ChainBuilder; import org.ehcache.clustered.client.internal.store.operations.ChainResolver; import org.ehcache.clustered.client.internal.store.operations.ExpiryChainResolver; import org.ehcache.clustered.common.internal.store.operations.ConditionalRemoveOperation; @@ -26,7 +27,6 @@ import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.Element; -import org.ehcache.clustered.common.internal.store.Util; import org.ehcache.clustered.loaderWriter.writebehind.RecordingLoaderWriter; import org.ehcache.core.spi.time.SystemTimeSource; import org.ehcache.core.spi.time.TimeSource; @@ -40,7 +40,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.AbstractExecutorService; @@ -208,11 +207,11 @@ private Map convert(Chain chain, OperationsCodec cod } private Chain makeChain(List expected, OperationsCodec operationsCodec) { - ByteBuffer[] byteBuffers = new ByteBuffer[expected.size()]; - for (int i = 0; i < byteBuffers.length; i++) { - byteBuffers[i] = operationsCodec.encode(expected.get(i).operation); + ChainBuilder builder = new ChainBuilder(); + for (EventInfo eventInfo : expected) { + builder.add(operationsCodec.encode(eventInfo.operation)); } - return chain(byteBuffers); + return builder.build(); } @@ -249,38 +248,6 @@ public void execute(Runnable command) { } } - public static Chain chain(ByteBuffer... buffers) { - final List list = new ArrayList<>(); - for (ByteBuffer b : buffers) { - list.add(b::asReadOnlyBuffer); - } - - return new Chain() { - - final List elements = Collections.unmodifiableList(list); - - @Override - public Iterator iterator() { - return elements.iterator(); - } - - @Override - public Iterator reverseIterator() { - return Util.reverseIterator(elements); - } - - @Override - public boolean isEmpty() { - return elements.isEmpty(); - } - - @Override - public int length() { - return elements.size(); - } - }; - } - private class EventInfo { private final Long key; private final Operation operation; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ChainBuilderTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ChainBuilderTest.java index 725ba42a48..e15ffd2b58 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ChainBuilderTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ChainBuilderTest.java @@ -16,16 +16,11 @@ package org.ehcache.clustered.client.internal.store; import org.ehcache.clustered.common.internal.store.Chain; -import org.ehcache.clustered.common.internal.store.Element; -import org.ehcache.clustered.common.internal.store.Util; +import org.ehcache.clustered.common.internal.util.ChainBuilder; import org.junit.Test; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - +import static org.ehcache.clustered.ChainUtils.createPayload; +import static org.ehcache.clustered.Matchers.hasPayloads; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; @@ -35,29 +30,12 @@ public class ChainBuilderTest { @Test public void testChainBuilder() { - ChainBuilder cb1 = new ChainBuilder(); - - ChainBuilder cb2 = cb1.add(Util.createPayload(1L)) - .add(Util.createPayload(3L)) - .add(Util.createPayload(4L)); - - ChainBuilder cb3 = cb2.add(Util.createPayload(2L)); - - Chain chain1 = cb1.build(); - Chain chain2 = cb2.build(); - Chain chain3 = cb3.build(); - - assertChainHas(chain1); - assertChainHas(chain2, 1L, 3L, 4L); - assertChainHas(chain3, 1L, 3L, 4L, 2L); - - } + Chain chain = new ChainBuilder() + .add(createPayload(1L)) + .add(createPayload(3L)) + .add(createPayload(4L)) + .add(createPayload(2L)).build(); - private static void assertChainHas(Chain chain, long... payLoads) { - Iterator elements = chain.iterator(); - for (long payLoad : payLoads) { - assertThat(Util.readPayLoad(elements.next().getPayload()), is(Long.valueOf(payLoad))); - } - assertThat(elements.hasNext(), is(false)); + assertThat(chain, hasPayloads(1L, 3L, 4L, 2L)); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java index 0f7e9bf24b..74b02f9d74 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java @@ -20,17 +20,15 @@ import org.ehcache.clustered.client.internal.store.ServerStoreProxy.ServerCallback; import org.ehcache.clustered.common.internal.ServerStoreConfiguration; import org.ehcache.clustered.common.internal.store.Chain; -import org.ehcache.clustered.common.internal.store.Element; import org.ehcache.config.units.MemoryUnit; import org.ehcache.impl.serialization.LongSerializer; import org.junit.Test; import java.nio.ByteBuffer; -import java.util.Iterator; -import static org.ehcache.clustered.common.internal.store.Util.createPayload; -import static org.ehcache.clustered.common.internal.store.Util.getChain; -import static org.ehcache.clustered.common.internal.store.Util.readPayLoad; +import static org.ehcache.clustered.ChainUtils.chainOf; +import static org.ehcache.clustered.ChainUtils.createPayload; +import static org.ehcache.clustered.Matchers.hasPayloads; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -72,7 +70,7 @@ public void testAppendKeyNotPresent() throws Exception { Chain chain = serverStoreProxy.get(2); assertThat(chain.isEmpty(), is(false)); - assertThat(readPayLoad(chain.iterator().next().getPayload()), is(2L)); + assertThat(chain, hasPayloads(2L)); } @Test @@ -88,7 +86,7 @@ public void testGetAfterMultipleAppendsOnSameKey() throws Exception { assertThat(chain.isEmpty(), is(false)); - assertChainHas(chain, 3L, 33L, 333l); + assertThat(chain, hasPayloads(3L, 33L, 333l)); } @Test @@ -102,7 +100,7 @@ public void testGetAndAppendKeyNotPresent() throws Exception { chain = serverStoreProxy.get(4L); assertThat(chain.isEmpty(), is(false)); - assertChainHas(chain, 4L); + assertThat(chain, hasPayloads(4L)); } @Test @@ -115,7 +113,7 @@ public void testGetAndAppendMultipleTimesOnSameKey() throws Exception { Chain chain = serverStoreProxy.getAndAppend(5l, createPayload(5555L)); assertThat(chain.isEmpty(), is(false)); - assertChainHas(chain, 5L, 55L, 555L); + assertThat(chain, hasPayloads(5L, 55L, 555L)); } @Test @@ -127,21 +125,21 @@ public void testReplaceAtHeadSuccessFull() throws Exception { serverStoreProxy.append(20L, createPayload(20000L)); Chain expect = serverStoreProxy.get(20L); - Chain update = getChain(false, createPayload(400L)); + Chain update = chainOf(createPayload(400L)); serverStoreProxy.replaceAtHead(20l, expect, update); Chain afterReplace = serverStoreProxy.get(20L); - assertChainHas(afterReplace, 400L); + assertThat(afterReplace, hasPayloads(400L)); serverStoreProxy.append(20L, createPayload(4000L)); serverStoreProxy.append(20L, createPayload(40000L)); - serverStoreProxy.replaceAtHead(20L, afterReplace, getChain(false, createPayload(800L))); + serverStoreProxy.replaceAtHead(20L, afterReplace, chainOf(createPayload(800L))); Chain anotherReplace = serverStoreProxy.get(20L); - assertChainHas(anotherReplace, 800L, 4000L, 40000L); + assertThat(anotherReplace, hasPayloads(800L, 4000L, 40000L)); } @Test @@ -161,27 +159,18 @@ public void testResolveRequestIsProcessedAtThreshold() throws Exception { ClusterTierClientEntity clientEntity = createClientEntity("testResolveRequestIsProcessed"); ServerCallback serverCallback = mock(ServerCallback.class); - when(serverCallback.compact(any(Chain.class), any(long.class))).thenReturn(getChain(false, buffer.duplicate())); + when(serverCallback.compact(any(Chain.class), any(long.class))).thenReturn(chainOf(buffer.duplicate())); CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testResolveRequestIsProcessed", clientEntity, serverCallback); for (int i = 0; i < 8; i++) { serverStoreProxy.append(1L, buffer.duplicate()); } verify(serverCallback, never()).compact(any(Chain.class)); - assertChainHas(serverStoreProxy.get(1L), 42L, 42L, 42L, 42L, 42L, 42L, 42L, 42L); + assertThat(serverStoreProxy.get(1L), hasPayloads(42L, 42L, 42L, 42L, 42L, 42L, 42L, 42L)); //trigger compaction at > 8 entries serverStoreProxy.append(1L, buffer.duplicate()); verify(serverCallback).compact(any(Chain.class), any(long.class)); - assertChainHas(serverStoreProxy.get(1L), 42L); + assertThat(serverStoreProxy.get(1L), hasPayloads(42L)); } - - private static void assertChainHas(Chain chain, long... payLoads) { - Iterator elements = chain.iterator(); - for (long payLoad : payLoads) { - assertThat(readPayLoad(elements.next().getPayload()), is(Long.valueOf(payLoad))); - } - assertThat(elements.hasNext(), is(false)); - } - } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java index 7bed2fef30..6b0d0003ac 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java @@ -15,6 +15,7 @@ */ package org.ehcache.clustered.client.internal.store; +import org.ehcache.clustered.Matchers; import org.ehcache.clustered.client.config.ClusteredResourcePool; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.internal.store.ServerStoreProxy.ServerCallback; @@ -33,8 +34,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import static org.ehcache.clustered.common.internal.store.Util.chainsEqual; -import static org.ehcache.clustered.common.internal.store.Util.createPayload; +import static org.ehcache.clustered.ChainUtils.createPayload; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.core.Is.is; @@ -104,7 +104,7 @@ public Chain compact(Chain chain) { for (int i = 0; i < ITERATIONS; i++) { Chain elements1 = serverStoreProxy1.get(i); Chain elements2 = serverStoreProxy2.get(i); - assertThat(chainsEqual(elements1, elements2), is(true)); + assertThat(elements1, Matchers.matchesChain(elements2)); if (!elements1.isEmpty()) { entryCount++; } else { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java index 2dc34d4c2c..0aee490af3 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java @@ -32,7 +32,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -import static org.ehcache.clustered.common.internal.store.Util.createPayload; +import static org.ehcache.clustered.ChainUtils.createPayload; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertNotNull; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java index fab62756a8..b783593649 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java @@ -34,8 +34,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import static org.ehcache.clustered.common.internal.store.Util.chainsEqual; -import static org.ehcache.clustered.common.internal.store.Util.createPayload; +import static org.ehcache.clustered.ChainUtils.createPayload; +import static org.ehcache.clustered.Matchers.matchesChain; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.core.Is.is; @@ -106,7 +106,7 @@ public Chain compact(Chain chain) { for (int i = 0; i < ITERATIONS; i++) { Chain elements1 = serverStoreProxy1.get(i); Chain elements2 = serverStoreProxy2.get(i); - assertThat(chainsEqual(elements1, elements2), is(true)); + assertThat(elements2, matchesChain(elements2)); if (!elements1.isEmpty()) { entryCount++; } else { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImplTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImplTest.java index 525b331ffd..5dbb8241e4 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImplTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImplTest.java @@ -23,7 +23,6 @@ import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.LockSuccess; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.LockMessage; import org.ehcache.clustered.common.internal.store.Chain; -import org.ehcache.clustered.common.internal.store.Util; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -31,6 +30,8 @@ import java.util.Set; import java.util.concurrent.TimeoutException; +import static org.ehcache.clustered.ChainUtils.chainOf; +import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.lockFailure; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; @@ -126,11 +127,11 @@ public void testUnlockClearsLocksHeldState() throws Exception { private LockSuccess getLockSuccessResponse() { ByteBuffer[] buffers = new ByteBuffer[3]; - for (int i = 1; i <= 3; i++) { - buffers[i-1] = Util.createPayload(i); + for (int i = 0; i < 3; i++) { + buffers[i] = createPayload(i + 1); } - Chain chain = Util.getChain(false, buffers); + Chain chain = chainOf(buffers); return EhcacheEntityResponse.lockSuccess(chain); } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java index 27ceb521cc..598a83e2e5 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java @@ -29,7 +29,6 @@ import org.ehcache.clustered.common.Consistency; import org.ehcache.clustered.common.internal.messages.EhcacheEntityMessage; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse; -import org.ehcache.clustered.common.internal.store.Element; import org.ehcache.clustered.lock.server.VoltronReadWriteLockServerEntityService; import org.ehcache.clustered.server.ObservableEhcacheServerEntityService; import org.ehcache.clustered.server.store.ObservableClusterTierServerEntityService; @@ -46,18 +45,15 @@ import org.terracotta.passthrough.PassthroughTestHelpers; import java.net.URI; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.function.Predicate; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; +import static org.ehcache.clustered.ChainUtils.chainOf; +import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.internal.UnitTestConnectionService.getOffheapResourcesType; -import static org.ehcache.clustered.common.internal.store.Util.createPayload; -import static org.ehcache.clustered.common.internal.store.Util.getChain; -import static org.ehcache.clustered.common.internal.store.Util.getElement; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.mockito.Mockito.mock; @@ -161,11 +157,8 @@ public void untrackedMessageAreNotStored() throws Exception { // Nothing tracked assertThat(activeMessageHandler.getTrackedClients().count()).isZero(); - List elements = new ArrayList<>(1); - elements.add(getElement(createPayload(44L))); - // Send a replace message, those are not tracked - storeProxy.replaceAtHead(44L, getChain(elements), getChain(new ArrayList<>(0))); + storeProxy.replaceAtHead(44L, chainOf(createPayload(44L)), chainOf()); // Not tracked as well storeProxy.get(42L); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java new file mode 100644 index 0000000000..7de6428481 --- /dev/null +++ b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java @@ -0,0 +1,602 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered.common.internal.store.operations; + +import org.ehcache.clustered.common.internal.util.ChainBuilder; +import org.ehcache.clustered.client.internal.store.ResolvedChain; +import org.ehcache.clustered.client.internal.store.operations.ChainResolver; +import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; +import org.ehcache.clustered.common.internal.store.Chain; +import org.ehcache.clustered.common.internal.store.Element; +import org.ehcache.config.builders.ExpiryPolicyBuilder; +import org.ehcache.expiry.ExpiryPolicy; +import org.ehcache.impl.serialization.LongSerializer; +import org.ehcache.impl.serialization.StringSerializer; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.junit.Test; + +import java.nio.ByteBuffer; +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import static org.hamcrest.Matchers.emptyIterable; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; +import static org.hamcrest.collection.IsIterableContainingInOrder.contains; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +public abstract class AbstractChainResolverTest { + + private static OperationsCodec codec = new OperationsCodec<>(new LongSerializer(), new StringSerializer()); + + protected abstract ChainResolver createChainResolver(ExpiryPolicy expiryPolicy, OperationsCodec codec); + + @Test + @SuppressWarnings("unchecked") + public void testResolveMaintainsOtherKeysInOrder() { + Operation expected = new PutOperation<>(1L, "Suresh", 0L); + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L), + new PutOperation<>(2L, "Albin", 0L), + expected, + new PutOperation<>(2L, "Suresh", 0L), + new PutOperation<>(2L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); + Result result = resolvedChain.getResolvedResult(1L); + assertEquals(expected, result); + assertThat(resolvedChain.isCompacted(), is(true)); + + Chain compactedChain = resolvedChain.getCompactedChain(); + assertThat(compactedChain, contains( //@SuppressWarnings("unchecked") + operation(new PutOperation<>(2L, "Albin", 0L)), + operation(new PutOperation<>(2L, "Suresh", 0L)), + operation(new PutOperation<>(2L, "Matthew", 0L)), + operation(new PutOperation<>(1L, "Suresh", 0L)))); + } + + @Test + public void testResolveEmptyChain() { + Chain chain = getChainFromOperations(); + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); + Result result = resolvedChain.getResolvedResult(1L); + assertNull(result); + + assertThat(resolvedChain.isCompacted(), is(false)); + } + + @Test + public void testResolveChainWithNonExistentKey() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L), + new PutOperation<>(2L, "Suresh", 0L), + new PutOperation<>(2L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + ResolvedChain resolvedChain = resolver.resolve(chain, 3L, 0L); + Result result = resolvedChain.getResolvedResult(3L); + assertNull(result); + assertThat(resolvedChain.isCompacted(), is(false)); + } + + @Test + public void testResolveSinglePut() { + Operation expected = new PutOperation<>(1L, "Albin", 0L); + Chain chain = getChainFromOperations(expected); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); + Result result = resolvedChain.getResolvedResult(1L); + assertEquals(expected, result); + assertThat(resolvedChain.isCompacted(), is(false)); + } + + @Test + public void testResolvePutsOnly() { + Operation expected = new PutOperation<>(1L, "Matthew", 0L); + + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L), + new PutOperation<>(1L, "Suresh", 0L), + new PutOperation<>(1L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); + Result result = resolvedChain.getResolvedResult(1L); + assertEquals(expected, result); + assertThat(resolvedChain.isCompacted(), is(true)); + assertThat(resolvedChain.getCompactionCount(), is(2)); + } + + @Test + public void testResolveSingleRemove() { + Chain chain = getChainFromOperations(new RemoveOperation<>(1L, 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); + Result result = resolvedChain.getResolvedResult(1L); + assertNull(result); + assertThat(resolvedChain.isCompacted(), is(true)); + assertThat(resolvedChain.getCompactionCount(), is(1)); + } + + @Test + public void testResolveRemovesOnly() { + Chain chain = getChainFromOperations( + new RemoveOperation<>(1L, 0L), + new RemoveOperation<>(1L, 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); + Result result = resolvedChain.getResolvedResult(1L); + assertNull(result); + assertThat(resolvedChain.isCompacted(), is(true)); + assertThat(resolvedChain.getCompactionCount(), is(2)); + } + + @Test + public void testPutAndRemove() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L), + new RemoveOperation<>(1L, 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); + Result result = resolvedChain.getResolvedResult(1L); + assertNull(result); + assertThat(resolvedChain.isCompacted(), is(true)); + } + + @Test + public void testResolvePutIfAbsentOnly() { + Operation expected = new PutOperation<>(1L, "Matthew", 0L); + Chain chain = getChainFromOperations(new PutIfAbsentOperation<>(1L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); + Result result = resolvedChain.getResolvedResult(1L); + assertEquals(expected, result); + assertThat(resolvedChain.isCompacted(), is(false)); + } + + @Test + public void testResolvePutIfAbsentsOnly() { + Operation expected = new PutOperation<>(1L, "Albin", 0L); + Chain chain = getChainFromOperations( + new PutIfAbsentOperation<>(1L, "Albin", 0L), + new PutIfAbsentOperation<>(1L, "Suresh", 0L), + new PutIfAbsentOperation<>(1L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); + Result result = resolvedChain.getResolvedResult(1L); + assertEquals(expected, result); + assertThat(resolvedChain.isCompacted(), is(true)); + } + + @Test + public void testResolvePutIfAbsentSucceeds() { + Operation expected = new PutOperation<>(1L, "Matthew", 0L); + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L), + new RemoveOperation<>(1L, 0L), + new PutIfAbsentOperation<>(1L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); + Result result = resolvedChain.getResolvedResult(1L); + assertEquals(expected, result); + assertThat(resolvedChain.isCompacted(), is(true)); + } + + @Test + public void testResolveForSingleOperationDoesNotCompact() { + Chain chain = getChainFromOperations(new PutOperation<>(1L, "Albin", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); + assertThat(resolvedChain.isCompacted(), is(false)); + assertThat(resolvedChain.getCompactionCount(), is(0)); + } + + @Test + public void testResolveForMultiplesOperationsAlwaysCompact() { + //create a random mix of operations + Chain chain = getChainFromOperations( + new PutIfAbsentOperation<>(1L, "Albin", 0L), + new PutOperation<>(1L, "Suresh", 0L), + new PutOperation<>(1L, "Matthew", 0L), + new PutOperation<>(2L, "Melvin", 0L), + new ReplaceOperation<>(1L, "Joseph", 0L), + new RemoveOperation<>(2L, 0L), + new ConditionalRemoveOperation<>(1L, "Albin", 0L), + new PutOperation<>(1L, "Gregory", 0L), + new ConditionalReplaceOperation<>(1L, "Albin", "Abraham", 0L), + new RemoveOperation<>(1L, 0L), + new PutIfAbsentOperation<>(2L, "Albin", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); + assertThat(resolvedChain.isCompacted(), is(true)); + assertThat(resolvedChain.getCompactionCount(), is(8)); + } + + @Test + public void testResolveDoesNotDecodeOtherKeyOperationValues() { + Chain chain = getChainFromOperations( + new PutOperation<>(2L, "Albin", 0L), + new PutOperation<>(2L, "Suresh", 0L), + new PutOperation<>(2L, "Matthew", 0L)); + + CountingLongSerializer keySerializer = new CountingLongSerializer(); + CountingStringSerializer valueSerializer = new CountingStringSerializer(); + OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration(), customCodec); + resolver.resolve(chain, 1L, 0L); + + assertThat(keySerializer.decodeCount, is(3)); + assertThat(valueSerializer.decodeCount, is(0)); + assertThat(keySerializer.encodeCount, is(0)); + assertThat(valueSerializer.encodeCount, is(0)); //No operation to resolve + } + + @Test + public void testResolveDecodesOperationValueOnlyOnDemand() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 1), + new PutOperation<>(1L, "Suresh", 2), + new PutOperation<>(1L, "Matthew", 3)); + + CountingLongSerializer keySerializer = new CountingLongSerializer(); + CountingStringSerializer valueSerializer = new CountingStringSerializer(); + OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration(), customCodec); + resolver.resolve(chain, 1L, 0L); + + assertThat(keySerializer.decodeCount, is(3)); + assertThat(valueSerializer.decodeCount, is(0)); + assertThat(valueSerializer.encodeCount, is(0)); + assertThat(keySerializer.encodeCount, is(1)); //One encode from encoding the resolved operation's key + } + + @Test + @SuppressWarnings("unchecked") + public void testCompactingTwoKeys() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L), + new PutOperation<>(2L, "Albin", 0L), + new PutOperation<>(1L, "Suresh", 0L), + new PutOperation<>(2L, "Suresh", 0L), + new PutOperation<>(2L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + + Chain compactedChain = resolver.applyOperation(chain, 0L); + + assertThat(compactedChain, containsInAnyOrder( //@SuppressWarnings("unchecked") + operation(new PutOperation<>(2L, "Matthew", 0L)), + operation(new PutOperation<>(1L, "Suresh", 0L)) + )); + } + + @Test + public void testCompactEmptyChain() { + Chain chain = (new ChainBuilder()).build(); + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Chain compacted = resolver.applyOperation(chain, 0L); + assertThat(compacted, emptyIterable()); + } + + @Test + public void testCompactSinglePut() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L) + ); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Chain compacted = resolver.applyOperation(chain, 0L); + + assertThat(compacted, contains(operation(new PutOperation<>(1L, "Albin", 0L)))); + } + + @Test + public void testCompactMultiplePuts() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L), + new PutOperation<>(1L, "Suresh", 0L), + new PutOperation<>(1L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Chain compactedChain = resolver.applyOperation(chain, 0L); + assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Matthew", 0L)))); + } + + @Test + public void testCompactSingleRemove() { + Chain chain = getChainFromOperations(new RemoveOperation<>(1L, 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Chain compactedChain = resolver.applyOperation(chain, 0L); + assertThat(compactedChain, emptyIterable()); + } + + @Test + public void testCompactMultipleRemoves() { + Chain chain = getChainFromOperations( + new RemoveOperation<>(1L, 0L), + new RemoveOperation<>(1L, 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Chain compactedChain = resolver.applyOperation(chain, 0L); + assertThat(compactedChain, emptyIterable()); + } + + @Test + public void testCompactPutAndRemove() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L), + new RemoveOperation<>(1L, 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Chain compactedChain = resolver.applyOperation(chain, 0L); + assertThat(compactedChain, emptyIterable()); + } + + @Test + public void testCompactSinglePutIfAbsent() { + Chain chain = getChainFromOperations(new PutIfAbsentOperation<>(1L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Chain compactedChain = resolver.applyOperation(chain, 0L); + assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Matthew", 0L)))); + } + + @Test + public void testCompactMultiplePutIfAbsents() { + Chain chain = getChainFromOperations( + new PutIfAbsentOperation<>(1L, "Albin", 0L), + new PutIfAbsentOperation<>(1L, "Suresh", 0L), + new PutIfAbsentOperation<>(1L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Chain compactedChain = resolver.applyOperation(chain, 0L); + assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin", 0L)))); + } + + @Test + public void testCompactPutIfAbsentAfterRemove() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L), + new RemoveOperation<>(1L, 0L), + new PutIfAbsentOperation<>(1L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Chain compactedChain = resolver.applyOperation(chain, 0L); + assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Matthew", 0L)))); + } + + @Test + public void testCompactForMultipleKeysAndOperations() { + //create a random mix of operations + Chain chain = getChainFromOperations( + new PutIfAbsentOperation<>(1L, "Albin", 0L), + new PutOperation<>(1L, "Suresh", 0L), + new PutOperation<>(1L, "Matthew", 0L), + new PutOperation<>(2L, "Melvin", 0L), + new ReplaceOperation<>(1L, "Joseph", 0L), + new RemoveOperation<>(2L, 0L), + new ConditionalRemoveOperation<>(1L, "Albin", 0L), + new PutOperation<>(1L, "Gregory", 0L), + new ConditionalReplaceOperation<>(1L, "Albin", "Abraham", 0L), + new RemoveOperation<>(1L, 0L), + new PutIfAbsentOperation<>(2L, "Albin", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Chain compactedChain = resolver.applyOperation(chain, 0L); + assertThat(compactedChain, contains(operation(new PutOperation<>(2L, "Albin", 0L)))); + } + + @Test + public void testCompactHasCorrectTimeStamp() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin1", 0), + new PutOperation<>(1L, "Albin2", 1), + new RemoveOperation<>(1L, 2), + new PutOperation<>(1L, "Albin3", 3)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Chain compactedChain = resolver.applyOperation(chain, 3); + + assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin3", 3)))); + } + + @Test + public void testCompactDecodesOperationValueOnlyOnDemand() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 1), + new PutOperation<>(1L, "Suresh", 2), + new PutOperation<>(1L, "Matthew", 3)); + + CountingLongSerializer keySerializer = new CountingLongSerializer(); + CountingStringSerializer valueSerializer = new CountingStringSerializer(); + OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration(), customCodec); + resolver.applyOperation(chain, 0L); + + assertThat(keySerializer.decodeCount, is(3)); + assertThat(valueSerializer.decodeCount, is(0)); //Only one decode on creation of the resolved operation + assertThat(valueSerializer.encodeCount, is(0)); //One encode from encoding the resolved operation's key + assertThat(keySerializer.encodeCount, is(1)); //One encode from encoding the resolved operation's key + } + + @Test + public void testResolveForMultipleOperationHasCorrectIsFirstAndTimeStamp() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin1", 0), + new PutOperation<>(1L, "Albin2", 1), + new RemoveOperation<>(1L, 2), + new PutOperation<>(1L, "AlbinAfterRemove", 3)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofHours(1))); + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 3); + + Operation operation = codec.decode(resolvedChain.getCompactedChain().iterator().next().getPayload()); + + assertThat(operation.isExpiryAvailable(), is(true)); + assertThat(operation.expirationTime(), is(TimeUnit.HOURS.toMillis(1) + 3)); + try { + operation.timeStamp(); + fail(); + } catch (Exception ex) { + assertThat(ex.getMessage(), is("Timestamp not available")); + } + assertThat(resolvedChain.isCompacted(), is(true)); + } + + @Test + public void testResolveForMultipleOperationHasCorrectIsFirstAndTimeStampWithExpiry() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin1", 0L), + new PutOperation<>(1L, "Albin2", 1L), + new PutOperation<>(1L, "Albin3", 2L), + new PutOperation<>(1L, "Albin4", 3L) + ); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(1L))); + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 3L); + + Operation operation = codec.decode(resolvedChain.getCompactedChain().iterator().next().getPayload()); + + assertThat(operation.isExpiryAvailable(), is(true)); + assertThat(operation.expirationTime(), is(4L)); + + try { + operation.timeStamp(); + fail(); + } catch (Exception ex) { + assertThat(ex.getMessage(), is("Timestamp not available")); + } + assertThat(resolvedChain.isCompacted(), is(true)); + } + + @Test + public void testCompactHasCorrectWithExpiry() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin1", 0L), + new PutOperation<>(1L, "Albin2", 1L), + new PutOperation<>(1L, "Albin3", 2L), + new PutOperation<>(1L, "Albin4", 3L) + ); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(1L))); + Chain compactedChain = resolver.applyOperation(chain, 3L); + + assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin4", 3L)))); + } + + protected ChainResolver createChainResolver(ExpiryPolicy expiryPolicy) { + return createChainResolver(expiryPolicy, codec); + } + + @SafeVarargs + protected final Chain getChainFromOperations(Operation ... operations) { + ChainBuilder chainBuilder = new ChainBuilder(); + for(Operation operation: operations) { + chainBuilder = chainBuilder.add(codec.encode(operation)); + } + return chainBuilder.build(); + } + + protected List> getOperationsListFromChain(Chain chain) { + List> list = new ArrayList<>(); + for (Element element : chain) { + Operation operation = codec.decode(element.getPayload()); + list.add(operation); + } + return list; + } + + private Matcher operation(Operation operation) { + return new TypeSafeMatcher() { + @Override + protected boolean matchesSafely(Element item) { + return operation.equals(codec.decode(item.getPayload())); + } + + @Override + public void describeTo(Description description) { + description.appendText("is ").appendValue(operation); + } + }; + } + + protected static class CountingLongSerializer extends LongSerializer { + + protected int encodeCount = 0; + protected int decodeCount = 0; + + @Override + public ByteBuffer serialize(final Long object) { + encodeCount++; + return super.serialize(object); + } + + @Override + public Long read(final ByteBuffer binary) throws ClassNotFoundException { + decodeCount++; + return super.read(binary); + } + + @Override + public boolean equals(final Long object, final ByteBuffer binary) throws ClassNotFoundException { + return super.equals(object, binary); + } + } + + protected static class CountingStringSerializer extends StringSerializer { + + protected int encodeCount = 0; + protected int decodeCount = 0; + + @Override + public ByteBuffer serialize(final String object) { + encodeCount++; + return super.serialize(object); + } + + @Override + public String read(final ByteBuffer binary) throws ClassNotFoundException { + decodeCount++; + return super.read(binary); + } + + @Override + public boolean equals(final String object, final ByteBuffer binary) throws ClassNotFoundException { + return super.equals(object, binary); + } + } +} diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/EternalChainResolverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/EternalChainResolverTest.java index a2b03aa605..e3ddfb8717 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/EternalChainResolverTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/EternalChainResolverTest.java @@ -16,500 +16,20 @@ package org.ehcache.clustered.common.internal.store.operations; -import org.ehcache.clustered.client.internal.store.ChainBuilder; -import org.ehcache.clustered.client.internal.store.ResolvedChain; +import org.ehcache.clustered.client.internal.store.operations.ChainResolver; import org.ehcache.clustered.client.internal.store.operations.EternalChainResolver; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; -import org.ehcache.clustered.common.internal.store.Chain; -import org.ehcache.clustered.common.internal.store.Element; -import org.ehcache.impl.serialization.LongSerializer; -import org.ehcache.impl.serialization.StringSerializer; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; -import org.junit.Test; +import org.ehcache.expiry.ExpiryPolicy; -import java.nio.ByteBuffer; - -import static org.hamcrest.Matchers.emptyIterable; +import static org.ehcache.config.builders.ExpiryPolicyBuilder.noExpiration; import static org.hamcrest.Matchers.is; -import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; -import static org.hamcrest.collection.IsIterableContainingInOrder.contains; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; - -public class EternalChainResolverTest { - - private static OperationsCodec codec = new OperationsCodec<>(new LongSerializer(), new StringSerializer()); - - @Test - @SuppressWarnings("unchecked") - public void testResolveMaintainsOtherKeysInOrder() throws Exception { - Operation expected = new PutOperation<>(1L, "Suresh", 0L); - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new PutOperation<>(2L, "Albin", 0L), - expected, - new PutOperation<>(2L, "Suresh", 0L), - new PutOperation<>(2L, "Mathew", 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(true)); - - Chain compactedChain = resolvedChain.getCompactedChain(); - assertThat(compactedChain, contains( //@SuppressWarnings("unchecked") - operation(new PutOperation<>(2L, "Albin", 0L)), - operation(new PutOperation<>(2L, "Suresh", 0L)), - operation(new PutOperation<>(2L, "Mathew", 0L)), - operation(new PutOperation<>(1L, "Suresh", 0L)))); - } - - @Test - public void testResolveEmptyChain() throws Exception { - Chain chain = getChainFromOperations(); - EternalChainResolver resolver = new EternalChainResolver<>(codec); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertNull(result); - - assertThat(resolvedChain.isCompacted(), is(false)); - } - - @Test - public void testResolveChainWithNonExistentKey() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new PutOperation<>(2L, "Suresh", 0L), - new PutOperation<>(2L, "Mathew", 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - ResolvedChain resolvedChain = resolver.resolve(chain, 3L, 0L); - Result result = resolvedChain.getResolvedResult(3L); - assertNull(result); - assertThat(resolvedChain.isCompacted(), is(false)); - } - - @Test - public void testResolveSinglePut() throws Exception { - Operation expected = new PutOperation<>(1L, "Albin", 0L); - Chain chain = getChainFromOperations(expected); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(false)); - } - - @Test - public void testResolvePutsOnly() throws Exception { - Operation expected = new PutOperation<>(1L, "Mathew", 0L); - - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new PutOperation<>(1L, "Suresh", 0L), - new PutOperation<>(1L, "Mathew", 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(2)); - } - - @Test - public void testResolveSingleRemove() throws Exception { - Chain chain = getChainFromOperations(new RemoveOperation<>(1L, 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertNull(result); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(1)); - } - - @Test - public void testResolveRemovesOnly() throws Exception { - Chain chain = getChainFromOperations( - new RemoveOperation<>(1L, 0L), - new RemoveOperation<>(1L, 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertNull(result); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(2)); - } - - @Test - public void testPutAndRemove() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new RemoveOperation<>(1L, 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertNull(result); - assertThat(resolvedChain.isCompacted(), is(true)); - } - - @Test - public void testResolvePutIfAbsentOnly() throws Exception { - Operation expected = new PutOperation<>(1L, "Mathew", 0L); - Chain chain = getChainFromOperations(new PutIfAbsentOperation<>(1L, "Mathew", 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(false)); - } - - @Test - public void testResolvePutIfAbsentsOnly() throws Exception { - Operation expected = new PutOperation<>(1L, "Albin", 0L); - Chain chain = getChainFromOperations( - new PutIfAbsentOperation<>(1L, "Albin", 0L), - new PutIfAbsentOperation<>(1L, "Suresh", 0L), - new PutIfAbsentOperation<>(1L, "Mathew", 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(true)); - } - - @Test - public void testResolvePutIfAbsentSucceeds() throws Exception { - Operation expected = new PutOperation<>(1L, "Mathew", 0L); - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new RemoveOperation<>(1L, 0L), - new PutIfAbsentOperation<>(1L, "Mathew", 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(true)); - } - - @Test - public void testResolveForSingleOperationDoesNotCompact() { - Chain chain = getChainFromOperations(new PutOperation<>(1L, "Albin", 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - assertThat(resolvedChain.isCompacted(), is(false)); - assertThat(resolvedChain.getCompactionCount(), is(0)); - } - - @Test - public void testResolveForMultiplesOperationsAlwaysCompact() { - //create a random mix of operations - Chain chain = getChainFromOperations( - new PutIfAbsentOperation<>(1L, "Albin", 0L), - new PutOperation<>(1L, "Suresh", 0L), - new PutOperation<>(1L, "Mathew", 0L), - new PutOperation<>(2L, "Melbin", 0L), - new ReplaceOperation<>(1L, "Joseph", 0L), - new RemoveOperation<>(2L, 0L), - new ConditionalRemoveOperation<>(1L, "Albin", 0L), - new PutOperation<>(1L, "Gregory", 0L), - new ConditionalReplaceOperation<>(1L, "Albin", "Abraham", 0L), - new RemoveOperation<>(1L, 0L), - new PutIfAbsentOperation<>(2L, "Albin", 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(8)); - } - - @Test - public void testResolveDoesNotDecodeOtherKeyOperationValues() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(2L, "Albin", 0L), - new PutOperation<>(2L, "Suresh", 0L), - new PutOperation<>(2L, "Mathew", 0L)); - - CountingLongSerializer keySerializer = new CountingLongSerializer(); - CountingStringSerializer valueSerializer = new CountingStringSerializer(); - OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); - EternalChainResolver resolver = new EternalChainResolver<>(customCodec); - resolver.resolve(chain, 1L, 0L); - - assertThat(keySerializer.decodeCount, is(3)); - assertThat(valueSerializer.decodeCount, is(0)); - assertThat(keySerializer.encodeCount, is(0)); - assertThat(valueSerializer.encodeCount, is(0)); //No operation to resolve - } - - @Test - public void testResolveDecodesOperationValueOnlyOnDemand() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 1), - new PutOperation<>(1L, "Suresh", 2), - new PutOperation<>(1L, "Mathew", 3)); - - CountingLongSerializer keySerializer = new CountingLongSerializer(); - CountingStringSerializer valueSerializer = new CountingStringSerializer(); - OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); - EternalChainResolver resolver = new EternalChainResolver<>(customCodec); - resolver.resolve(chain, 1L, 0L); - - assertThat(keySerializer.decodeCount, is(3)); - assertThat(valueSerializer.decodeCount, is(0)); - assertThat(valueSerializer.encodeCount, is(0)); - assertThat(keySerializer.encodeCount, is(1)); //One encode from encoding the resolved operation's key - } - - @Test - @SuppressWarnings("unchecked") - public void testCompactingTwoKeys() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new PutOperation<>(2L, "Albin", 0L), - new PutOperation<>(1L, "Suresh", 0L), - new PutOperation<>(2L, "Suresh", 0L), - new PutOperation<>(2L, "Mathew", 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - - Chain compactedChain = resolver.applyOperation(chain, 0L); - - assertThat(compactedChain, containsInAnyOrder( //@SuppressWarnings("unchecked") - operation(new PutOperation<>(2L, "Mathew", 0L)), - operation(new PutOperation<>(1L, "Suresh", 0L)) - )); - } - - @Test - public void testCompactEmptyChain() throws Exception { - Chain chain = (new ChainBuilder()).build(); - EternalChainResolver resolver = new EternalChainResolver<>(codec); - Chain compacted = resolver.applyOperation(chain, 0L); - assertThat(compacted, emptyIterable()); - } - - @Test - public void testCompactSinglePut() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L) - ); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - Chain compacted = resolver.applyOperation(chain, 0L); - - assertThat(compacted, contains(operation(new PutOperation<>(1L, "Albin", 0L)))); - } - - @Test - public void testCompactMultiplePuts() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new PutOperation<>(1L, "Suresh", 0L), - new PutOperation<>(1L, "Mathew", 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Mathew", 0L)))); - } - - @Test - public void testCompactSingleRemove() throws Exception { - Chain chain = getChainFromOperations(new RemoveOperation<>(1L, 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, emptyIterable()); - } - - @Test - public void testCompactMultipleRemoves() throws Exception { - Chain chain = getChainFromOperations( - new RemoveOperation<>(1L, 0L), - new RemoveOperation<>(1L, 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, emptyIterable()); - } - - @Test - public void testCompactPutAndRemove() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new RemoveOperation<>(1L, 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, emptyIterable()); - } - - @Test - public void testCompactSinglePutIfAbsent() throws Exception { - Chain chain = getChainFromOperations(new PutIfAbsentOperation<>(1L, "Mathew", 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Mathew", 0L)))); - } - - @Test - public void testCompactMultiplePutIfAbsents() throws Exception { - Chain chain = getChainFromOperations( - new PutIfAbsentOperation<>(1L, "Albin", 0L), - new PutIfAbsentOperation<>(1L, "Suresh", 0L), - new PutIfAbsentOperation<>(1L, "Mathew", 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin", 0L)))); - } - - @Test - public void testCompactPutIfAbsentAfterRemove() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new RemoveOperation<>(1L, 0L), - new PutIfAbsentOperation<>(1L, "Mathew", 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Mathew", 0L)))); - } - - @Test - public void testCompactForMultipleKeysAndOperations() { - //create a random mix of operations - Chain chain = getChainFromOperations( - new PutIfAbsentOperation<>(1L, "Albin", 0L), - new PutOperation<>(1L, "Suresh", 0L), - new PutOperation<>(1L, "Mathew", 0L), - new PutOperation<>(2L, "Melbin", 0L), - new ReplaceOperation<>(1L, "Joseph", 0L), - new RemoveOperation<>(2L, 0L), - new ConditionalRemoveOperation<>(1L, "Albin", 0L), - new PutOperation<>(1L, "Gregory", 0L), - new ConditionalReplaceOperation<>(1L, "Albin", "Abraham", 0L), - new RemoveOperation<>(1L, 0L), - new PutIfAbsentOperation<>(2L, "Albin", 0L)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(2L, "Albin", 0L)))); - } - - @Test - public void testCompactHasCorrectTimeStamp() { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin1", 0), - new PutOperation<>(1L, "Albin2", 1), - new RemoveOperation<>(1L, 2), - new PutOperation<>(1L, "Albin3", 3)); - - EternalChainResolver resolver = new EternalChainResolver<>(codec); - Chain compactedChain = resolver.applyOperation(chain, 3); - - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin3", 3)))); - } - - @Test - public void testCompactDecodesOperationValueOnlyOnDemand() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 1), - new PutOperation<>(1L, "Suresh", 2), - new PutOperation<>(1L, "Mathew", 3)); - - CountingLongSerializer keySerializer = new CountingLongSerializer(); - CountingStringSerializer valueSerializer = new CountingStringSerializer(); - OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); - EternalChainResolver resolver = new EternalChainResolver<>(customCodec); - resolver.applyOperation(chain, 0L); - - assertThat(keySerializer.decodeCount, is(3)); - assertThat(valueSerializer.decodeCount, is(0)); //Only one decode on creation of the resolved operation - assertThat(valueSerializer.encodeCount, is(0)); //One encode from encoding the resolved operation's key - assertThat(keySerializer.encodeCount, is(1)); //One encode from encoding the resolved operation's key - } - - @SafeVarargs - private final Chain getChainFromOperations(Operation ... operations) { - ChainBuilder chainBuilder = new ChainBuilder(); - for(Operation operation: operations) { - chainBuilder = chainBuilder.add(codec.encode(operation)); - } - return chainBuilder.build(); - } - - private Matcher operation(Operation operation) { - return new TypeSafeMatcher() { - @Override - protected boolean matchesSafely(Element item) { - return operation.equals(codec.decode(item.getPayload())); - } - - @Override - public void describeTo(Description description) { - description.appendText("is ").appendValue(operation); - } - }; - } - - private static class CountingLongSerializer extends LongSerializer { - - private int encodeCount = 0; - private int decodeCount = 0; - - @Override - public ByteBuffer serialize(final Long object) { - encodeCount++; - return super.serialize(object); - } - - @Override - public Long read(final ByteBuffer binary) throws ClassNotFoundException { - decodeCount++; - return super.read(binary); - } - - @Override - public boolean equals(final Long object, final ByteBuffer binary) throws ClassNotFoundException { - return super.equals(object, binary); - } - } - - private static class CountingStringSerializer extends StringSerializer { - - private int encodeCount = 0; - private int decodeCount = 0; - - @Override - public ByteBuffer serialize(final String object) { - encodeCount++; - return super.serialize(object); - } +import static org.junit.Assume.assumeThat; - @Override - public String read(final ByteBuffer binary) throws ClassNotFoundException { - decodeCount++; - return super.read(binary); - } +public class EternalChainResolverTest extends AbstractChainResolverTest { - @Override - public boolean equals(final String object, final ByteBuffer binary) throws ClassNotFoundException { - return super.equals(object, binary); - } + @Override + protected ChainResolver createChainResolver(ExpiryPolicy expiryPolicy, OperationsCodec codec) { + assumeThat(expiryPolicy, is(noExpiration())); + return new EternalChainResolver<>(codec); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverExpiryTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverExpiryTest.java deleted file mode 100644 index f1468cb6c4..0000000000 --- a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverExpiryTest.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.ehcache.clustered.common.internal.store.operations; - -import org.ehcache.clustered.client.TestTimeSource; -import org.ehcache.clustered.client.internal.store.ChainBuilder; -import org.ehcache.clustered.client.internal.store.ResolvedChain; -import org.ehcache.clustered.client.internal.store.operations.ExpiryChainResolver; -import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; -import org.ehcache.clustered.common.internal.store.Chain; -import org.ehcache.clustered.common.internal.store.Element; -import org.ehcache.expiry.ExpiryPolicy; -import org.ehcache.impl.serialization.LongSerializer; -import org.ehcache.impl.serialization.StringSerializer; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; - -import java.time.Duration; -import java.util.ArrayList; -import java.util.List; - -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.hamcrest.Matchers.is; - -public class ExpiryChainResolverExpiryTest { - - private static final OperationsCodec codec = new OperationsCodec<>(new LongSerializer(), new StringSerializer()); - - private static TestTimeSource timeSource = null; - - @Before - public void initialSetup() { - timeSource = new TestTimeSource(); - } - - @Test - @SuppressWarnings("unchecked") - public void testGetExpiryForAccessIsIgnored() { - ExpiryPolicy expiry = mock(ExpiryPolicy.class); - ExpiryChainResolver chainResolver = new ExpiryChainResolver<>(codec, expiry); - - when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - - List> list = new ArrayList<>(); - list.add(new PutOperation<>(1L, "One", timeSource.getTimeMillis())); - list.add(new PutOperation<>(1L, "Second", timeSource.getTimeMillis())); - - Chain chain = getChainFromOperations(list); - - ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - - verify(expiry, times(0)).getExpiryForAccess(anyLong(), any()); - verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); - verify(expiry, times(1)).getExpiryForUpdate(anyLong(), any(), anyString()); - - assertThat(resolvedChain.isCompacted(), is(true)); - } - - @Test - @SuppressWarnings("unchecked") - public void testGetExpiryForCreationIsInvokedOnlyOnce() { - ExpiryPolicy expiry = mock(ExpiryPolicy.class); - ExpiryChainResolver chainResolver = new ExpiryChainResolver<>(codec, expiry); - - when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - - List> list = new ArrayList<>(); - list.add(new PutOperation<>(1L, "One", timeSource.getTimeMillis())); - list.add(new PutOperation<>(1L, "Second", timeSource.getTimeMillis())); - list.add(new PutOperation<>(1L, "Three", timeSource.getTimeMillis())); - list.add(new PutOperation<>(1L, "Four", timeSource.getTimeMillis())); - - Chain chain = getChainFromOperations(list); - - ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - - InOrder inOrder = inOrder(expiry); - - inOrder.verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); - inOrder.verify(expiry, times(3)).getExpiryForUpdate(anyLong(), any(), anyString()); - - assertThat(resolvedChain.isCompacted(), is(true)); - } - - @Test - @SuppressWarnings("unchecked") - public void testGetExpiryForCreationIsNotInvokedForReplacedChains() { - ExpiryPolicy expiry = mock(ExpiryPolicy.class); - ExpiryChainResolver chainResolver = new ExpiryChainResolver<>(codec, expiry); - - when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - - List> list = new ArrayList<>(); - list.add(new PutOperation<>(1L, "Replaced", -10L)); - list.add(new PutOperation<>(1L, "SecondAfterReplace", timeSource.getTimeMillis())); - list.add(new PutOperation<>(1L, "ThirdAfterReplace", timeSource.getTimeMillis())); - list.add(new PutOperation<>(1L, "FourthAfterReplace", timeSource.getTimeMillis())); - - Chain chain = getChainFromOperations(list); - - ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - verify(expiry, times(0)).getExpiryForCreation(anyLong(), anyString()); - verify(expiry, times(3)).getExpiryForUpdate(anyLong(), any(), anyString()); - - assertThat(resolvedChain.isCompacted(), is(true)); - } - - @Test - @SuppressWarnings("unchecked") - public void testGetExpiryForCreationIsInvokedAfterRemoveOperations() { - - ExpiryPolicy expiry = mock(ExpiryPolicy.class); - ExpiryChainResolver chainResolver = new ExpiryChainResolver<>(codec, expiry); - - when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - - List> list = new ArrayList<>(); - list.add(new PutOperation<>(1L, "Replaced", 10L)); - list.add(new PutOperation<>(1L, "SecondAfterReplace", 3L)); - list.add(new RemoveOperation<>(1L, 4L)); - list.add(new PutOperation<>(1L, "FourthAfterReplace", 5L)); - - Chain replacedChain = getChainFromOperations(list); - - ResolvedChain resolvedChain = chainResolver.resolve(replacedChain, 1L, timeSource.getTimeMillis()); - - InOrder inOrder = inOrder(expiry); - - verify(expiry, times(0)).getExpiryForAccess(anyLong(), any()); - inOrder.verify(expiry, times(1)).getExpiryForUpdate(anyLong(), any(), anyString()); - inOrder.verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); - - assertThat(resolvedChain.isCompacted(), is(true)); - - reset(expiry); - - when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - - list = new ArrayList<>(); - list.add(new PutOperation<>(1L, "One", timeSource.getTimeMillis())); - list.add(new PutOperation<>(1L, "Second", timeSource.getTimeMillis())); - list.add(new RemoveOperation<>(1L, timeSource.getTimeMillis())); - list.add(new PutOperation<>(1L, "Four", timeSource.getTimeMillis())); - - Chain chain = getChainFromOperations(list); - - chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - - inOrder = inOrder(expiry); - - verify(expiry, times(0)).getExpiryForAccess(anyLong(), any()); - inOrder.verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); - inOrder.verify(expiry, times(1)).getExpiryForUpdate(anyLong(), any(), anyString()); - inOrder.verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); - - assertThat(resolvedChain.isCompacted(), is(true)); - } - - @Test - @SuppressWarnings("unchecked") - public void testNullGetExpiryForCreation() { - ExpiryPolicy expiry = mock(ExpiryPolicy.class); - ExpiryChainResolver chainResolver = new ExpiryChainResolver<>(codec, expiry); - - when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(null); - - List> list = new ArrayList<>(); - list.add(new PutOperation<>(1L, "Replaced", 10L)); - - Chain chain = getChainFromOperations(list); - - ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - - assertTrue(resolvedChain.getCompactedChain().isEmpty()); - assertThat(resolvedChain.isCompacted(), is(true)); - } - - @Test - @SuppressWarnings("unchecked") - public void testNullGetExpiryForUpdate() { - ExpiryPolicy expiry = mock(ExpiryPolicy.class); - ExpiryChainResolver chainResolver = new ExpiryChainResolver<>(codec, expiry); - - when(expiry.getExpiryForUpdate(anyLong(), any(), anyString())).thenReturn(null); - - List> list = new ArrayList<>(); - list.add(new PutOperation<>(1L, "Replaced", -10L)); - list.add(new PutOperation<>(1L, "New", timeSource.getTimeMillis())); - Chain chain = getChainFromOperations(list); - - ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - - assertThat(resolvedChain.getResolvedResult(1L).getValue(), is("New")); - assertTrue(getOperationsListFromChain(resolvedChain.getCompactedChain()).get(0).isExpiryAvailable()); - assertThat(getOperationsListFromChain(resolvedChain.getCompactedChain()).get(0).expirationTime(), is(10L)); - assertThat(resolvedChain.isCompacted(), is(true)); - } - - @Test - @SuppressWarnings("unchecked") - public void testGetExpiryForUpdateUpdatesExpirationTimeStamp() { - ExpiryPolicy expiry = mock(ExpiryPolicy.class); - ExpiryChainResolver chainResolver = new ExpiryChainResolver<>(codec, expiry); - - when(expiry.getExpiryForUpdate(anyLong(), any(), anyString())).thenReturn(Duration.ofMillis(2L)); - - List> list = new ArrayList<>(); - list.add(new PutOperation<>(1L, "Replaced", -10L)); - list.add(new PutOperation<>(1L, "New", timeSource.getTimeMillis())); - Chain chain = getChainFromOperations(list); - - ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - - assertThat(resolvedChain.getResolvedResult(1L).getValue(), is("New")); - assertTrue(getOperationsListFromChain(resolvedChain.getCompactedChain()).get(0).isExpiryAvailable()); - assertThat(getOperationsListFromChain(resolvedChain.getCompactedChain()).get(0).expirationTime(), is(2L)); - assertThat(resolvedChain.isCompacted(), is(true)); - } - - @Test - @SuppressWarnings("unchecked") - public void testExpiryThrowsException() { - ExpiryPolicy expiry = mock(ExpiryPolicy.class); - ExpiryChainResolver chainResolver = new ExpiryChainResolver<>(codec, expiry); - - when(expiry.getExpiryForUpdate(anyLong(), any(), anyString())).thenThrow(new RuntimeException("Test Update Expiry")); - when(expiry.getExpiryForCreation(anyLong(), anyString())).thenThrow(new RuntimeException("Test Create Expiry")); - - List> list = new ArrayList<>(); - list.add(new PutOperation<>(1L, "One", -10L)); - list.add(new PutOperation<>(1L, "Two", timeSource.getTimeMillis())); - Chain chain = getChainFromOperations(list); - - ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - - assertThat(resolvedChain.getResolvedResult(1L), nullValue()); - - list = new ArrayList<>(); - list.add(new PutOperation<>(1L, "One", timeSource.getTimeMillis())); - list.add(new PutOperation<>(1L, "Two", timeSource.getTimeMillis())); - chain = getChainFromOperations(list); - - resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - - assertThat(resolvedChain.getResolvedResult(1L), nullValue()); - - assertThat(resolvedChain.isCompacted(), is(true)); - } - - private Chain getChainFromOperations(List> operations) { - ChainBuilder chainBuilder = new ChainBuilder(); - for(Operation operation: operations) { - chainBuilder = chainBuilder.add(codec.encode(operation)); - } - return chainBuilder.build(); - } - - private List> getOperationsListFromChain(Chain chain) { - List> list = new ArrayList<>(); - for (Element element : chain) { - Operation operation = codec.decode(element.getPayload()); - list.add(operation); - } - return list; - } - -} diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java index 4bf85351b1..db3690c263 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java @@ -16,568 +16,293 @@ package org.ehcache.clustered.common.internal.store.operations; -import org.ehcache.clustered.client.internal.store.ChainBuilder; +import org.ehcache.clustered.client.TestTimeSource; import org.ehcache.clustered.client.internal.store.ResolvedChain; +import org.ehcache.clustered.client.internal.store.operations.ChainResolver; import org.ehcache.clustered.client.internal.store.operations.ExpiryChainResolver; -import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; import org.ehcache.clustered.common.internal.store.Chain; -import org.ehcache.clustered.common.internal.store.Element; +import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.impl.serialization.LongSerializer; -import org.ehcache.impl.serialization.StringSerializer; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; +import org.ehcache.core.spi.time.TimeSource; +import org.ehcache.expiry.ExpiryPolicy; import org.junit.Test; +import org.mockito.InOrder; -import java.nio.ByteBuffer; import java.time.Duration; -import java.util.concurrent.TimeUnit; -import static org.hamcrest.Matchers.emptyIterable; import static org.hamcrest.Matchers.is; -import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; -import static org.hamcrest.collection.IsIterableContainingInOrder.contains; -import static org.junit.Assert.assertNull; +import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -public class ExpiryChainResolverTest { - - private static OperationsCodec codec = new OperationsCodec<>(new LongSerializer(), new StringSerializer()); - - @Test - @SuppressWarnings("unchecked") - public void testResolveMaintainsOtherKeysInOrder() throws Exception { - Operation expected = new PutOperation<>(1L, "Suresh", 0L); +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class ExpiryChainResolverTest extends AbstractChainResolverTest { + + @Override + protected ChainResolver createChainResolver(ExpiryPolicy expiryPolicy, OperationsCodec codec) { + return new ExpiryChainResolver<>(codec, expiryPolicy); + } + + @Test @Override + public void testCompactDecodesOperationValueOnlyOnDemand() { Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new PutOperation<>(2L, "Albin", 0L), - expected, - new PutOperation<>(2L, "Suresh", 0L), - new PutOperation<>(2L, "Mathew", 0L)); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(true)); + new PutOperation<>(1L, "Albin", 1), + new PutOperation<>(1L, "Suresh", 2), + new PutOperation<>(1L, "Matthew", 3)); - Chain compactedChain = resolvedChain.getCompactedChain(); - assertThat(compactedChain, contains( //@SuppressWarnings("unchecked") - operation(new PutOperation<>(2L, "Albin", 0L)), - operation(new PutOperation<>(2L, "Suresh", 0L)), - operation(new PutOperation<>(2L, "Mathew", 0L)), - operation(new PutOperation<>(1L, "Suresh", 0L)))); - } + CountingLongSerializer keySerializer = new CountingLongSerializer(); + CountingStringSerializer valueSerializer = new CountingStringSerializer(); + OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration(), customCodec); + resolver.applyOperation(chain, 0L); - @Test - public void testResolveEmptyChain() throws Exception { - Chain chain = getChainFromOperations(); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertNull(result); - - assertThat(resolvedChain.isCompacted(), is(false)); + assertThat(keySerializer.decodeCount, is(3)); + assertThat(valueSerializer.decodeCount, is(3)); + assertThat(valueSerializer.encodeCount, is(0)); + assertThat(keySerializer.encodeCount, is(1)); //One encode from encoding the resolved operation's key } - @Test - public void testResolveChainWithNonExistentKey() throws Exception { + @Test @Override + public void testResolveDecodesOperationValueOnlyOnDemand() { Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new PutOperation<>(2L, "Suresh", 0L), - new PutOperation<>(2L, "Mathew", 0L)); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 3L, 0L); - Result result = resolvedChain.getResolvedResult(3L); - assertNull(result); - assertThat(resolvedChain.isCompacted(), is(false)); - } - - @Test - public void testResolveSinglePut() throws Exception { - Operation expected = new PutOperation<>(1L, "Albin", 0L); - Chain chain = getChainFromOperations(expected); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(false)); - } + new PutOperation<>(1L, "Albin", 1), + new PutOperation<>(1L, "Suresh", 2), + new PutOperation<>(1L, "Matthew", 3)); - @Test - public void testResolvePutsOnly() throws Exception { - Operation expected = new PutOperation<>(1L, "Mathew", 0L); + CountingLongSerializer keySerializer = new CountingLongSerializer(); + CountingStringSerializer valueSerializer = new CountingStringSerializer(); + OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration(), customCodec); + resolver.resolve(chain, 1L, 0L); - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new PutOperation<>(1L, "Suresh", 0L), - new PutOperation<>(1L, "Mathew", 0L)); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(2)); + assertThat(keySerializer.decodeCount, is(3)); + assertThat(valueSerializer.decodeCount, is(3)); + assertThat(valueSerializer.encodeCount, is(0)); + assertThat(keySerializer.encodeCount, is(1)); //One encode from encoding the resolved operation's key } @Test - public void testResolveSingleRemove() throws Exception { - Chain chain = getChainFromOperations(new RemoveOperation<>(1L, 0L)); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertNull(result); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(1)); - } + @SuppressWarnings("unchecked") + public void testGetExpiryForAccessIsIgnored() { + TimeSource timeSource = new TestTimeSource(); + ExpiryPolicy expiry = mock(ExpiryPolicy.class); + ChainResolver chainResolver = createChainResolver(expiry); - @Test - public void testResolveRemovesOnly() throws Exception { - Chain chain = getChainFromOperations( - new RemoveOperation<>(1L, 0L), - new RemoveOperation<>(1L, 0L)); + when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertNull(result); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(2)); - } - @Test - public void testPutAndRemove() throws Exception { Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new RemoveOperation<>(1L, 0L)); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertNull(result); - assertThat(resolvedChain.isCompacted(), is(true)); - } + new PutOperation<>(1L, "One", timeSource.getTimeMillis()), + new PutOperation<>(1L, "Second", timeSource.getTimeMillis()) + ); - @Test - public void testResolvePutIfAbsentOnly() throws Exception { - Operation expected = new PutOperation<>(1L, "Mathew", 0L); - Chain chain = getChainFromOperations(new PutIfAbsentOperation<>(1L, "Mathew", 0L)); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(false)); - } + ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - @Test - public void testResolvePutIfAbsentsOnly() throws Exception { - Operation expected = new PutOperation<>(1L, "Albin", 0L); - Chain chain = getChainFromOperations( - new PutIfAbsentOperation<>(1L, "Albin", 0L), - new PutIfAbsentOperation<>(1L, "Suresh", 0L), - new PutIfAbsentOperation<>(1L, "Mathew", 0L)); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(true)); - } + verify(expiry, times(0)).getExpiryForAccess(anyLong(), any()); + verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); + verify(expiry, times(1)).getExpiryForUpdate(anyLong(), any(), anyString()); - @Test - public void testResolvePutIfAbsentSucceeds() throws Exception { - Operation expected = new PutOperation<>(1L, "Mathew", 0L); - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new RemoveOperation<>(1L, 0L), - new PutIfAbsentOperation<>(1L, "Mathew", 0L)); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); assertThat(resolvedChain.isCompacted(), is(true)); } @Test - public void testResolveForSingleOperationDoesNotCompact() { - Chain chain = getChainFromOperations(new PutOperation<>(1L, "Albin", 0L)); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - assertThat(resolvedChain.isCompacted(), is(false)); - assertThat(resolvedChain.getCompactionCount(), is(0)); - } + @SuppressWarnings("unchecked") + public void testGetExpiryForCreationIsInvokedOnlyOnce() { + TimeSource timeSource = new TestTimeSource(); + ExpiryPolicy expiry = mock(ExpiryPolicy.class); + ChainResolver chainResolver = createChainResolver(expiry); - @Test - public void testResolveForMultiplesOperationsAlwaysCompact() { - //create a random mix of operations - Chain chain = getChainFromOperations( - new PutIfAbsentOperation<>(1L, "Albin", 0L), - new PutOperation<>(1L, "Suresh", 0L), - new PutOperation<>(1L, "Mathew", 0L), - new PutOperation<>(2L, "Melbin", 0L), - new ReplaceOperation<>(1L, "Joseph", 0L), - new RemoveOperation<>(2L, 0L), - new ConditionalRemoveOperation<>(1L, "Albin", 0L), - new PutOperation<>(1L, "Gregory", 0L), - new ConditionalReplaceOperation<>(1L, "Albin", "Abraham", 0L), - new RemoveOperation<>(1L, 0L), - new PutIfAbsentOperation<>(2L, "Albin", 0L)); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(8)); - } + when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - @Test - public void testResolveForMultipleOperationHasCorrectIsFirstAndTimeStamp() { Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin1", 0), - new PutOperation<>(1L, "Albin2", 1), - new RemoveOperation<>(1L, 2), - new PutOperation<>(1L, "AlbinAfterRemove", 3)); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofHours(1))); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 3); - - Operation operation = codec.decode(resolvedChain.getCompactedChain().iterator().next().getPayload()); - - assertThat(operation.isExpiryAvailable(), is(true)); - assertThat(operation.expirationTime(), is(TimeUnit.HOURS.toMillis(1) + 3)); - try { - operation.timeStamp(); - fail(); - } catch (Exception ex) { - assertThat(ex.getMessage(), is("Timestamp not available")); - } - assertThat(resolvedChain.isCompacted(), is(true)); - } - - @Test - public void testResolveForMultipleOperationHasCorrectIsFirstAndTimeStampWithExpiry() { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin1", 0L), - new PutOperation<>(1L, "Albin2", 1L), - new PutOperation<>(1L, "Albin3", 2L), - new PutOperation<>(1L, "Albin4", 3L) + new PutOperation<>(1L, "One", timeSource.getTimeMillis()), + new PutOperation<>(1L, "Second", timeSource.getTimeMillis()), + new PutOperation<>(1L, "Three", timeSource.getTimeMillis()), + new PutOperation<>(1L, "Four", timeSource.getTimeMillis()) ); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(1L))); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 3L); + ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - Operation operation = codec.decode(resolvedChain.getCompactedChain().iterator().next().getPayload()); + InOrder inOrder = inOrder(expiry); - assertThat(operation.isExpiryAvailable(), is(true)); - assertThat(operation.expirationTime(), is(4L)); + inOrder.verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); + inOrder.verify(expiry, times(3)).getExpiryForUpdate(anyLong(), any(), anyString()); - try { - operation.timeStamp(); - fail(); - } catch (Exception ex) { - assertThat(ex.getMessage(), is("Timestamp not available")); - } assertThat(resolvedChain.isCompacted(), is(true)); } @Test - public void testResolveDoesNotDecodeOtherKeyOperationValues() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(2L, "Albin", 0L), - new PutOperation<>(2L, "Suresh", 0L), - new PutOperation<>(2L, "Mathew", 0L)); + @SuppressWarnings("unchecked") + public void testGetExpiryForCreationIsNotInvokedForReplacedChains() { + TimeSource timeSource = new TestTimeSource(); + ExpiryPolicy expiry = mock(ExpiryPolicy.class); + ChainResolver chainResolver = createChainResolver(expiry); - CountingLongSerializer keySerializer = new CountingLongSerializer(); - CountingStringSerializer valueSerializer = new CountingStringSerializer(); - OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(customCodec, ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofSeconds(5))); - resolver.resolve(chain, 1L, 0L); + when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - assertThat(keySerializer.decodeCount, is(3)); - assertThat(valueSerializer.decodeCount, is(0)); - assertThat(keySerializer.encodeCount, is(0)); - assertThat(valueSerializer.encodeCount, is(0)); - } - @Test - public void testResolveDecodesOperationValueOnlyOnDemand() throws Exception { Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 1), - new PutOperation<>(1L, "Suresh", 2), - new PutOperation<>(1L, "Mathew", 3)); + new PutOperation<>(1L, "Replaced", -10L), + new PutOperation<>(1L, "SecondAfterReplace", timeSource.getTimeMillis()), + new PutOperation<>(1L, "ThirdAfterReplace", timeSource.getTimeMillis()), + new PutOperation<>(1L, "FourthAfterReplace", timeSource.getTimeMillis()) + ); - CountingLongSerializer keySerializer = new CountingLongSerializer(); - CountingStringSerializer valueSerializer = new CountingStringSerializer(); - OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(customCodec, ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofSeconds(5))); - resolver.resolve(chain, 1L, 0L); + ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); + verify(expiry, times(0)).getExpiryForCreation(anyLong(), anyString()); + verify(expiry, times(3)).getExpiryForUpdate(anyLong(), any(), anyString()); - assertThat(keySerializer.decodeCount, is(3)); - assertThat(valueSerializer.decodeCount, is(3)); - assertThat(valueSerializer.encodeCount, is(0)); - assertThat(keySerializer.encodeCount, is(1)); + assertThat(resolvedChain.isCompacted(), is(true)); } @Test @SuppressWarnings("unchecked") - public void testCompactingTwoKeys() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new PutOperation<>(2L, "Albin", 0L), - new PutOperation<>(1L, "Suresh", 0L), - new PutOperation<>(2L, "Suresh", 0L), - new PutOperation<>(2L, "Mathew", 0L)); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); + public void testGetExpiryForCreationIsInvokedAfterRemoveOperations() { + TimeSource timeSource = new TestTimeSource(); + ExpiryPolicy expiry = mock(ExpiryPolicy.class); + ChainResolver chainResolver = createChainResolver(expiry); - Chain compactedChain = resolver.applyOperation(chain, 0L); + when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - assertThat(compactedChain, containsInAnyOrder( //@SuppressWarnings("unchecked") - operation(new PutOperation<>(2L, "Mathew", 0L)), - operation(new PutOperation<>(1L, "Suresh", 0L)) - )); - } - @Test - public void testCompactEmptyChain() throws Exception { - Chain chain = (new ChainBuilder()).build(); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - Chain compacted = resolver.applyOperation(chain, 0L); - assertThat(compacted, emptyIterable()); - } - - @Test - public void testCompactSinglePut() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L) + Chain replacedChain = getChainFromOperations( + new PutOperation<>(1L, "Replaced", 10L), + new PutOperation<>(1L, "SecondAfterReplace", 3L), + new RemoveOperation<>(1L, 4L), + new PutOperation<>(1L, "FourthAfterReplace", 5L) ); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - Chain compacted = resolver.applyOperation(chain, 0L); + ResolvedChain resolvedChain = chainResolver.resolve(replacedChain, 1L, timeSource.getTimeMillis()); - assertThat(compacted, contains(operation(new PutOperation<>(1L, "Albin", 0L)))); - } + InOrder inOrder = inOrder(expiry); - @Test - public void testCompactMultiplePuts() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new PutOperation<>(1L, "Suresh", 0L), - new PutOperation<>(1L, "Mathew", 0L)); + verify(expiry, times(0)).getExpiryForAccess(anyLong(), any()); + inOrder.verify(expiry, times(1)).getExpiryForUpdate(anyLong(), any(), anyString()); + inOrder.verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Mathew", 0L)))); - } + assertThat(resolvedChain.isCompacted(), is(true)); - @Test - public void testCompactSingleRemove() throws Exception { - Chain chain = getChainFromOperations(new RemoveOperation<>(1L, 0L)); + reset(expiry); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, emptyIterable()); - } + when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - @Test - public void testCompactMultipleRemoves() throws Exception { - Chain chain = getChainFromOperations( - new RemoveOperation<>(1L, 0L), - new RemoveOperation<>(1L, 0L)); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, emptyIterable()); - } - - @Test - public void testCompactPutAndRemove() throws Exception { Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new RemoveOperation<>(1L, 0L)); + new PutOperation(1L, "One", timeSource.getTimeMillis()), + new PutOperation(1L, "Second", timeSource.getTimeMillis()), + new RemoveOperation(1L, timeSource.getTimeMillis()), + new PutOperation(1L, "Four", timeSource.getTimeMillis()) + ); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, emptyIterable()); - } + chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - @Test - public void testCompactSinglePutIfAbsent() throws Exception { - Chain chain = getChainFromOperations(new PutIfAbsentOperation<>(1L, "Mathew", 0L)); + inOrder = inOrder(expiry); + + verify(expiry, times(0)).getExpiryForAccess(anyLong(), any()); + inOrder.verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); + inOrder.verify(expiry, times(1)).getExpiryForUpdate(anyLong(), any(), anyString()); + inOrder.verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Mathew", 0L)))); + assertThat(resolvedChain.isCompacted(), is(true)); } @Test - public void testCompactMultiplePutIfAbsents() throws Exception { - Chain chain = getChainFromOperations( - new PutIfAbsentOperation<>(1L, "Albin", 0L), - new PutIfAbsentOperation<>(1L, "Suresh", 0L), - new PutIfAbsentOperation<>(1L, "Mathew", 0L)); + @SuppressWarnings("unchecked") + public void testNullGetExpiryForCreation() { + TimeSource timeSource = new TestTimeSource(); + ExpiryPolicy expiry = mock(ExpiryPolicy.class); + ChainResolver chainResolver = createChainResolver(expiry); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin", 0L)))); - } + when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(null); - @Test - public void testCompactPutIfAbsentAfterRemove() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 0L), - new RemoveOperation<>(1L, 0L), - new PutIfAbsentOperation<>(1L, "Mathew", 0L)); + Chain chain = getChainFromOperations(new PutOperation<>(1L, "Replaced", 10L)); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Mathew", 0L)))); - } + ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - @Test - public void testCompactForMultipleKeysAndOperations() { - //create a random mix of operations - Chain chain = getChainFromOperations( - new PutIfAbsentOperation<>(1L, "Albin", 0L), - new PutOperation<>(1L, "Suresh", 0L), - new PutOperation<>(1L, "Mathew", 0L), - new PutOperation<>(2L, "Melbin", 0L), - new ReplaceOperation<>(1L, "Joseph", 0L), - new RemoveOperation<>(2L, 0L), - new ConditionalRemoveOperation<>(1L, "Albin", 0L), - new PutOperation<>(1L, "Gregory", 0L), - new ConditionalReplaceOperation<>(1L, "Albin", "Abraham", 0L), - new RemoveOperation<>(1L, 0L), - new PutIfAbsentOperation<>(2L, "Albin", 0L)); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(2L, "Albin", 0L)))); + assertTrue(resolvedChain.getCompactedChain().isEmpty()); + assertThat(resolvedChain.isCompacted(), is(true)); } @Test - public void testCompactHasCorrectTimeStamp() { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin1", 0), - new PutOperation<>(1L, "Albin2", 1), - new RemoveOperation<>(1L, 2), - new PutOperation<>(1L, "Albin3", 3)); - - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 3); + @SuppressWarnings("unchecked") + public void testNullGetExpiryForUpdate() { + TimeSource timeSource = new TestTimeSource(); + ExpiryPolicy expiry = mock(ExpiryPolicy.class); + ChainResolver chainResolver = createChainResolver(expiry); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin3", 3)))); - } + when(expiry.getExpiryForUpdate(anyLong(), any(), anyString())).thenReturn(null); - @Test - public void testCompactHasCorrectWithExpiry() { Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin1", 0L), - new PutOperation<>(1L, "Albin2", 1L), - new PutOperation<>(1L, "Albin3", 2L), - new PutOperation<>(1L, "Albin4", 3L) + new PutOperation<>(1L, "Replaced", -10L), + new PutOperation<>(1L, "New", timeSource.getTimeMillis()) ); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(1L))); - Chain compactedChain = resolver.applyOperation(chain, 3L); + ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin4", 3L)))); + assertThat(resolvedChain.getResolvedResult(1L).getValue(), is("New")); + assertTrue(getOperationsListFromChain(resolvedChain.getCompactedChain()).get(0).isExpiryAvailable()); + assertThat(getOperationsListFromChain(resolvedChain.getCompactedChain()).get(0).expirationTime(), is(10L)); + assertThat(resolvedChain.isCompacted(), is(true)); } @Test - public void testCompactDecodesOperationValueOnlyOnDemand() throws Exception { - Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin", 1), - new PutOperation<>(1L, "Suresh", 2), - new PutOperation<>(1L, "Mathew", 3)); + @SuppressWarnings("unchecked") + public void testGetExpiryForUpdateUpdatesExpirationTimeStamp() { + TimeSource timeSource = new TestTimeSource(); + ExpiryPolicy expiry = mock(ExpiryPolicy.class); + ChainResolver chainResolver = createChainResolver(expiry); - CountingLongSerializer keySerializer = new CountingLongSerializer(); - CountingStringSerializer valueSerializer = new CountingStringSerializer(); - OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); - ExpiryChainResolver resolver = new ExpiryChainResolver<>(customCodec, ExpiryPolicyBuilder.noExpiration()); - resolver.applyOperation(chain, 0L); + when(expiry.getExpiryForUpdate(anyLong(), any(), anyString())).thenReturn(Duration.ofMillis(2L)); - assertThat(keySerializer.decodeCount, is(3)); - assertThat(valueSerializer.decodeCount, is(3)); - assertThat(valueSerializer.encodeCount, is(0)); - assertThat(keySerializer.encodeCount, is(1)); - } + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Replaced", -10L), + new PutOperation<>(1L, "New", timeSource.getTimeMillis()) + ); - @SafeVarargs - private final Chain getChainFromOperations(Operation ... operations) { - ChainBuilder chainBuilder = new ChainBuilder(); - for(Operation operation: operations) { - chainBuilder = chainBuilder.add(codec.encode(operation)); - } - return chainBuilder.build(); - } + ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - private Matcher operation(Operation operation) { - return new TypeSafeMatcher() { - @Override - protected boolean matchesSafely(Element item) { - return operation.equals(codec.decode(item.getPayload())); - } - - @Override - public void describeTo(Description description) { - description.appendText("is ").appendValue(operation); - } - }; + assertThat(resolvedChain.getResolvedResult(1L).getValue(), is("New")); + assertTrue(getOperationsListFromChain(resolvedChain.getCompactedChain()).get(0).isExpiryAvailable()); + assertThat(getOperationsListFromChain(resolvedChain.getCompactedChain()).get(0).expirationTime(), is(2L)); + assertThat(resolvedChain.isCompacted(), is(true)); } - private static class CountingLongSerializer extends LongSerializer { - - private int encodeCount = 0; - private int decodeCount = 0; + @Test + @SuppressWarnings("unchecked") + public void testExpiryThrowsException() { + TimeSource timeSource = new TestTimeSource(); + ExpiryPolicy expiry = mock(ExpiryPolicy.class); + ChainResolver chainResolver = createChainResolver(expiry); - @Override - public ByteBuffer serialize(final Long object) { - encodeCount++; - return super.serialize(object); - } + when(expiry.getExpiryForUpdate(anyLong(), any(), anyString())).thenThrow(new RuntimeException("Test Update Expiry")); + when(expiry.getExpiryForCreation(anyLong(), anyString())).thenThrow(new RuntimeException("Test Create Expiry")); - @Override - public Long read(final ByteBuffer binary) throws ClassNotFoundException { - decodeCount++; - return super.read(binary); - } + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "One", -10L), + new PutOperation<>(1L, "Two", timeSource.getTimeMillis()) + ); - @Override - public boolean equals(final Long object, final ByteBuffer binary) throws ClassNotFoundException { - return super.equals(object, binary); - } - } + ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - private static class CountingStringSerializer extends StringSerializer { + assertThat(resolvedChain.getResolvedResult(1L), nullValue()); - private int encodeCount = 0; - private int decodeCount = 0; + chain = getChainFromOperations( + new PutOperation<>(1L, "One", timeSource.getTimeMillis()), + new PutOperation<>(1L, "Two", timeSource.getTimeMillis()) + ); - @Override - public ByteBuffer serialize(final String object) { - encodeCount++; - return super.serialize(object); - } + resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - @Override - public String read(final ByteBuffer binary) throws ClassNotFoundException { - decodeCount++; - return super.read(binary); - } + assertThat(resolvedChain.getResolvedResult(1L), nullValue()); - @Override - public boolean equals(final String object, final ByteBuffer binary) throws ClassNotFoundException { - return super.equals(object, binary); - } + assertThat(resolvedChain.isCompacted(), is(true)); } } diff --git a/clustered/common/build.gradle b/clustered/common/build.gradle index 7698facc9a..dc4fe6a9d9 100644 --- a/clustered/common/build.gradle +++ b/clustered/common/build.gradle @@ -20,4 +20,6 @@ dependencies { providedImplementation project(':api') providedImplementation "org.terracotta:entity-common-api:$terracottaApisVersion" providedImplementation "org.terracotta:runnel:$terracottaPlatformVersion" + + testImplementation project(':clustered:test-utils') } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java index 77f6b62852..a12775cfe3 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java @@ -19,7 +19,6 @@ import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.Element; import org.ehcache.clustered.common.internal.store.SequencedElement; -import org.ehcache.clustered.common.internal.store.Util; import org.terracotta.runnel.Struct; import org.terracotta.runnel.StructBuilder; import org.terracotta.runnel.decoding.StructArrayDecoder; @@ -31,6 +30,8 @@ import java.util.ArrayList; import java.util.List; +import static org.ehcache.clustered.common.internal.util.ChainBuilder.chainFromList; + public final class ChainCodec { private ChainCodec() { @@ -84,14 +85,24 @@ public static Chain decode(StructDecoder decoder) { elementDecoder.end(); if (sequence == null) { - elements.add(Util.getElement(byteBuffer)); + elements.add(byteBuffer::asReadOnlyBuffer); } else { - elements.add(Util.getElement(sequence, byteBuffer)); + elements.add(new SequencedElement() { + @Override + public long getSequenceNumber() { + return sequence; + } + + @Override + public ByteBuffer getPayload() { + return byteBuffer.asReadOnlyBuffer(); + } + }); } } elementsDecoder.end(); - return Util.getChain(elements); + return chainFromList(elements); } } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/Chain.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/Chain.java index 2919628a38..836d7193cd 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/Chain.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/Chain.java @@ -34,15 +34,6 @@ */ public interface Chain extends Iterable { - /** - * Returns the iterator to iterate the {@link Chain} of - * {@link Element}s in backwards direction i.e. starting - * from last one. - * - * @return an Iterator. - */ - Iterator reverseIterator(); - /** * Returns true if Chain is empty else false. * diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/Util.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/Util.java index 42c14ba6df..a1ee21c176 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/Util.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/Util.java @@ -32,122 +32,6 @@ public class Util { - public static final Iterator reverseIterator(List list) { - final ListIterator listIterator = list.listIterator(list.size()); - return new Iterator() { - @Override - public boolean hasNext() { - return listIterator.hasPrevious(); - } - - @Override - public T next() { - return listIterator.previous(); - } - - @Override - public void remove() { - listIterator.remove(); - } - }; - } - - public static long readPayLoad(ByteBuffer byteBuffer) { - return byteBuffer.getLong(); - } - - public static ByteBuffer createPayload(long key) { - ByteBuffer byteBuffer = ByteBuffer.allocate(8).putLong(key); - byteBuffer.flip(); - return byteBuffer.asReadOnlyBuffer(); - } - - public static ByteBuffer createPayload(long key, int payloadSize) { - if (payloadSize < 8) { - throw new IllegalArgumentException("payload must be at least 8 bytes long"); - } - ByteBuffer byteBuffer = ByteBuffer.allocate(payloadSize); - byteBuffer.putLong(key); - for (int i = 0; i < payloadSize - 8; i++) { - byteBuffer.put((byte) 0); - } - byteBuffer.flip(); - return byteBuffer.asReadOnlyBuffer(); - } - - public static boolean chainsEqual(Chain chain1, Chain chain2) { - Iterator it1 = chain1.iterator(); - Iterator it2 = chain2.iterator(); - - while (it1.hasNext() && it2.hasNext()) { - Element next1 = it1.next(); - Element next2 = it2.next(); - - if (!next1.getPayload().equals(next2.getPayload())) { - return false; - } - } - - return !it1.hasNext() && !it2.hasNext(); - } - - public static Element getElement(final ByteBuffer payload) { - return payload::duplicate; - } - - public static Chain getChain(boolean isSequenced, ByteBuffer... buffers) { - List elements = new ArrayList<>(); - long counter = 0; - for (final ByteBuffer buffer : buffers) { - if (isSequenced) { - elements.add(getElement(counter++, buffer)); - } else { - elements.add(getElement(buffer)); - } - - } - return getChain(elements); - } - - public static Chain getChain(final List elements) { - return new Chain() { - private final List list = Collections.unmodifiableList(elements); - @Override - public Iterator reverseIterator() { - return Util.reverseIterator(list); - } - - @Override - public boolean isEmpty() { - return list.isEmpty(); - } - - @Override - public int length() { - return list.size(); - } - - @Override - public Iterator iterator() { - return list.iterator(); - } - }; - } - - public static SequencedElement getElement(final long sequence, final ByteBuffer payload) { - return new SequencedElement() { - @Override - public long getSequenceNumber() { - return sequence; - } - - @Override - public ByteBuffer getPayload() { - return payload.duplicate(); - } - }; - } - public static Object unmarshall(ByteBuffer payload, Predicate> isClassPermitted) { try (ObjectInputStream objectInputStream = new FilteredObjectInputStream(new ByteBufferInputStream(payload), isClassPermitted, null)) { @@ -166,26 +50,4 @@ public static byte[] marshall(Object message) { } return out.toByteArray(); } - - public static final Chain EMPTY_CHAIN = new Chain() { - @Override - public Iterator reverseIterator() { - return Collections.emptyList().iterator(); - } - - @Override - public boolean isEmpty() { - return true; - } - - @Override - public int length() { - return 0; - } - - @Override - public Iterator iterator() { - return Collections.emptyList().iterator(); - } - }; } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ChainBuilder.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/util/ChainBuilder.java similarity index 59% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ChainBuilder.java rename to clustered/common/src/main/java/org/ehcache/clustered/common/internal/util/ChainBuilder.java index 00aff2d0c6..8f614bac15 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ChainBuilder.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/util/ChainBuilder.java @@ -13,15 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.clustered.client.internal.store; +package org.ehcache.clustered.common.internal.util; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.Element; -import org.ehcache.clustered.common.internal.store.Util; import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Iterator; import java.util.List; /** @@ -31,25 +30,35 @@ public class ChainBuilder { private List buffers = new ArrayList<>(); - public ChainBuilder() { - } - - private ChainBuilder(List buffers) { - this.buffers = buffers; - } - - //TODO: optimize this & make this mutable public ChainBuilder add(final ByteBuffer payload) { - List newList = new ArrayList<>(buffers.size() + 1); - newList.addAll(buffers); - newList.add(payload); - return new ChainBuilder(newList); + buffers.add(payload); + return this; } public Chain build() { - ByteBuffer[] elements = new ByteBuffer[buffers.size()]; - buffers.toArray(elements); - return Util.getChain(false, elements); + List elements = new ArrayList<>(); + for (final ByteBuffer buffer : buffers) { + elements.add(buffer::asReadOnlyBuffer); + } + return chainFromList(elements); } + public static Chain chainFromList(List elements) { + return new Chain() { + @Override + public boolean isEmpty() { + return elements.isEmpty(); + } + + @Override + public int length() { + return elements.size(); + } + + @Override + public Iterator iterator() { + return elements.iterator(); + } + }; + } } diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java index 31786a9b69..99f5724e89 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java @@ -18,96 +18,89 @@ import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.Element; -import org.ehcache.clustered.common.internal.store.SequencedElement; import org.junit.Test; import java.util.Iterator; -import static org.junit.Assert.assertEquals; +import static org.ehcache.clustered.ChainUtils.chainOf; +import static org.ehcache.clustered.ChainUtils.createPayload; +import static org.ehcache.clustered.ChainUtils.readPayload; +import static org.ehcache.clustered.ChainUtils.sequencedChainOf; +import static org.ehcache.clustered.Matchers.hasPayloads; +import static org.ehcache.clustered.Matchers.sameSequenceAs; import static org.junit.Assert.assertThat; import static org.hamcrest.Matchers.is; -import static org.ehcache.clustered.common.internal.store.Util.createPayload; -import static org.ehcache.clustered.common.internal.store.Util.readPayLoad; -import static org.ehcache.clustered.common.internal.store.Util.getChain; public class ChainCodecTest { @Test public void testChainWithSingleElement() { - Chain chain = getChain(false, createPayload(1L)); + Chain chain = chainOf(createPayload(1L)); assertThat(chain.isEmpty(), is(false)); Iterator chainIterator = chain.iterator(); - assertThat(readPayLoad(chainIterator.next().getPayload()), is(1L)); + assertThat(readPayload(chainIterator.next().getPayload()), is(1L)); assertThat(chainIterator.hasNext(), is(false)); Chain decoded = ChainCodec.decode(ChainCodec.encode(chain)); assertThat(decoded.isEmpty(), is(false)); chainIterator = decoded.iterator(); - assertThat(readPayLoad(chainIterator.next().getPayload()), is(1L)); + assertThat(readPayload(chainIterator.next().getPayload()), is(1L)); assertThat(chainIterator.hasNext(), is(false)); } @Test public void testChainWithSingleSequencedElement() { - Chain chain = getChain(true, createPayload(1L)); + Chain chain = sequencedChainOf(createPayload(1L)); assertThat(chain.isEmpty(), is(false)); Iterator chainIterator = chain.iterator(); - assertThat(readPayLoad(chainIterator.next().getPayload()), is(1L)); + assertThat(readPayload(chainIterator.next().getPayload()), is(1L)); assertThat(chainIterator.hasNext(), is(false)); Chain decoded = ChainCodec.decode(ChainCodec.encode(chain)); assertThat(decoded.isEmpty(), is(false)); chainIterator = decoded.iterator(); - assertThat(readPayLoad(chainIterator.next().getPayload()), is(1L)); + assertThat(readPayload(chainIterator.next().getPayload()), is(1L)); assertThat(chainIterator.hasNext(), is(false)); - assertSameSequenceChain(chain, decoded); + assertThat(decoded, sameSequenceAs(chain)); } @Test public void testChainWithMultipleElements() { - Chain chain = getChain(false, createPayload(1L), createPayload(2L), createPayload(3L)); + Chain chain = chainOf(createPayload(1L), createPayload(2L), createPayload(3L)); assertThat(chain.isEmpty(), is(false)); - Util.assertChainHas(chain, 1L, 2L, 3L); + assertThat(chain, hasPayloads(1L, 2L, 3L)); Chain decoded = ChainCodec.decode(ChainCodec.encode(chain)); assertThat(decoded.isEmpty(), is(false)); - Util.assertChainHas(decoded, 1L, 2L, 3L); + assertThat(decoded, hasPayloads(1L, 2L, 3L)); } @Test public void testChainWithMultipleSequencedElements() { - Chain chain = getChain(true, createPayload(1L), createPayload(2L), createPayload(3L)); + Chain chain = sequencedChainOf(createPayload(1L), createPayload(2L), createPayload(3L)); assertThat(chain.isEmpty(), is(false)); - Util.assertChainHas(chain, 1L, 2L, 3L); + assertThat(chain, hasPayloads(1L, 2L, 3L)); Chain decoded = ChainCodec.decode(ChainCodec.encode(chain)); assertThat(decoded.isEmpty(), is(false)); - Util.assertChainHas(decoded, 1L, 2L, 3L); + assertThat(decoded, hasPayloads(1L, 2L, 3L)); - assertSameSequenceChain(chain, decoded); + assertThat(decoded, sameSequenceAs(chain)); } @Test public void testEmptyChain() { - Chain decoded = ChainCodec.decode(ChainCodec.encode(getChain(false))); + Chain decoded = ChainCodec.decode(ChainCodec.encode(chainOf())); assertThat(decoded.isEmpty(), is(true)); } - - private static void assertSameSequenceChain(Chain original, Chain decoded) { - Iterator decodedIterator = decoded.iterator(); - for (Element element : original) { - assertEquals(((SequencedElement) element).getSequenceNumber(), - ((SequencedElement) decodedIterator.next()).getSequenceNumber()); - } - } } diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java index 32182d3bb3..31079a2d24 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java @@ -21,10 +21,12 @@ import org.hamcrest.Matchers; import org.junit.Test; -import java.util.Date; import java.util.HashSet; import java.util.Set; +import static org.ehcache.clustered.ChainUtils.chainOf; +import static org.ehcache.clustered.ChainUtils.createPayload; +import static org.ehcache.clustered.Matchers.hasPayloads; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.allInvalidationDone; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.clientInvalidateAll; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.clientInvalidateHash; @@ -35,8 +37,6 @@ import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.prepareForDestroy; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.serverInvalidateHash; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.success; -import static org.ehcache.clustered.common.internal.store.Util.createPayload; -import static org.ehcache.clustered.common.internal.store.Util.getChain; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; @@ -58,14 +58,13 @@ public void testFailureResponseCodec() { @Test public void testGetResponseCodec() { - EhcacheEntityResponse getResponse = getResponse(getChain(false, - createPayload(1L), createPayload(11L), createPayload(111L))); + EhcacheEntityResponse getResponse = getResponse(chainOf(createPayload(1L), createPayload(11L), createPayload(111L))); EhcacheEntityResponse decoded = RESPONSE_CODEC.decode(RESPONSE_CODEC.encode(getResponse)); Chain decodedChain = ((EhcacheEntityResponse.GetResponse) decoded).getChain(); - Util.assertChainHas(decodedChain, 1L, 11L, 111L); + assertThat(decodedChain, hasPayloads(1L, 11L, 111L)); } @Test @@ -153,26 +152,25 @@ public void testPrepareForDestroy() throws Exception { @Test public void testResolveRequest() throws Exception { long hash = 42L; - EhcacheEntityResponse.ResolveRequest response = new EhcacheEntityResponse.ResolveRequest(hash, getChain(false, - createPayload(1L), createPayload(11L), createPayload(111L))); + EhcacheEntityResponse.ResolveRequest response = new EhcacheEntityResponse.ResolveRequest(hash, chainOf(createPayload(1L), createPayload(11L), createPayload(111L))); byte[] encoded = RESPONSE_CODEC.encode(response); EhcacheEntityResponse.ResolveRequest decodedResponse = (EhcacheEntityResponse.ResolveRequest) RESPONSE_CODEC.decode(encoded); assertThat(decodedResponse.getResponseType(), is(EhcacheResponseType.RESOLVE_REQUEST)); assertThat(decodedResponse.getKey(), is(42L)); - Util.assertChainHas(decodedResponse.getChain(), 1L, 11L, 111L); + assertThat(decodedResponse.getChain(), hasPayloads(1L, 11L, 111L)); } @Test public void testLockResponse() { - EhcacheEntityResponse.LockSuccess lockSuccess = new EhcacheEntityResponse.LockSuccess(getChain(false, createPayload(1L), createPayload(10L))); + EhcacheEntityResponse.LockSuccess lockSuccess = new EhcacheEntityResponse.LockSuccess(chainOf(createPayload(1L), createPayload(10L))); byte[] sucessEncoded = RESPONSE_CODEC.encode(lockSuccess); EhcacheEntityResponse.LockSuccess successDecoded = (EhcacheEntityResponse.LockSuccess) RESPONSE_CODEC.decode(sucessEncoded); assertThat(successDecoded.getResponseType(), is(EhcacheResponseType.LOCK_SUCCESS)); - Util.assertChainHas(successDecoded.getChain(), 1L, 10L); + assertThat(successDecoded.getChain(), hasPayloads(1L, 10L)); EhcacheEntityResponse.LockFailure lockFailure = EhcacheEntityResponse.lockFailure(); byte[] failureEncoded = RESPONSE_CODEC.encode(lockFailure); diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java index e6c6c1d3bd..4a788f2322 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java @@ -19,9 +19,11 @@ import org.junit.Test; import static java.nio.ByteBuffer.wrap; -import static org.ehcache.clustered.common.internal.store.Util.createPayload; -import static org.ehcache.clustered.common.internal.store.Util.getChain; -import static org.ehcache.clustered.common.internal.store.Util.readPayLoad; +import static org.ehcache.clustered.ChainUtils.chainOf; +import static org.ehcache.clustered.ChainUtils.createPayload; +import static org.ehcache.clustered.ChainUtils.readPayload; +import static org.ehcache.clustered.ChainUtils.sequencedChainOf; +import static org.ehcache.clustered.Matchers.hasPayloads; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; @@ -39,7 +41,7 @@ public void testAppendMessageCodec() { ServerStoreOpMessage.AppendMessage decodedAppendMessage = (ServerStoreOpMessage.AppendMessage) decodedMsg; assertThat(decodedAppendMessage.getKey(), is(1L)); - assertThat(readPayLoad(decodedAppendMessage.getPayload()), is(1L)); + assertThat(readPayload(decodedAppendMessage.getPayload()), is(1L)); assertThat(decodedAppendMessage.getMessageType(), is(EhcacheMessageType.APPEND)); } @@ -64,23 +66,23 @@ public void testGetAndAppendMessageCodec() { ServerStoreOpMessage.GetAndAppendMessage decodedGetAndAppendMessage = (ServerStoreOpMessage.GetAndAppendMessage) decodedMsg; assertThat(decodedGetAndAppendMessage.getKey(), is(10L)); - assertThat(readPayLoad(decodedGetAndAppendMessage.getPayload()), is(10L)); + assertThat(readPayload(decodedGetAndAppendMessage.getPayload()), is(10L)); assertThat(decodedGetAndAppendMessage.getMessageType(), is(EhcacheMessageType.GET_AND_APPEND)); } @Test public void testReplaceAtHeadMessageCodec() { ServerStoreOpMessage replaceAtHeadMessage = new ServerStoreOpMessage.ReplaceAtHeadMessage(10L, - getChain(true, createPayload(10L), createPayload(100L), createPayload(1000L)), - getChain(false, createPayload(2000L))); + sequencedChainOf(createPayload(10L), createPayload(100L), createPayload(1000L)), + chainOf(createPayload(2000L))); byte[] encoded = STORE_OP_CODEC.encode(replaceAtHeadMessage); EhcacheEntityMessage decodedMsg = STORE_OP_CODEC.decode(replaceAtHeadMessage.getMessageType(), wrap(encoded)); ServerStoreOpMessage.ReplaceAtHeadMessage decodedReplaceAtHeadMessage = (ServerStoreOpMessage.ReplaceAtHeadMessage) decodedMsg; assertThat(decodedReplaceAtHeadMessage.getKey(), is(10L)); - Util.assertChainHas(decodedReplaceAtHeadMessage.getExpect(), 10L, 100L, 1000L); - Util.assertChainHas(decodedReplaceAtHeadMessage.getUpdate(), 2000L); + assertThat(decodedReplaceAtHeadMessage.getExpect(), hasPayloads(10L, 100L, 1000L)); + assertThat(decodedReplaceAtHeadMessage.getUpdate(), hasPayloads(2000L)); assertThat(decodedReplaceAtHeadMessage.getMessageType(), is(EhcacheMessageType.REPLACE)); } diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessageTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessageTest.java index 332b0c6b40..ce0c886ed3 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessageTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessageTest.java @@ -16,13 +16,10 @@ package org.ehcache.clustered.common.internal.messages; -import org.ehcache.clustered.common.internal.store.Element; import org.junit.Test; -import java.util.Collections; - -import static org.ehcache.clustered.common.internal.store.Util.createPayload; -import static org.ehcache.clustered.common.internal.store.Util.getChain; +import static org.ehcache.clustered.ChainUtils.chainOf; +import static org.ehcache.clustered.ChainUtils.createPayload; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; @@ -30,17 +27,17 @@ public class ServerStoreOpMessageTest { @Test - public void testConcurrencyKeysEqualForSameCacheAndKey() throws Exception { + public void testConcurrencyKeysEqualForSameCacheAndKey() { ConcurrentEntityMessage m1 = new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L)); ConcurrentEntityMessage m2 = new ServerStoreOpMessage.GetAndAppendMessage(1L, createPayload(1L)); - ConcurrentEntityMessage m3 = new ServerStoreOpMessage.ReplaceAtHeadMessage(1L, getChain(Collections.emptyList()), getChain(Collections.emptyList())); + ConcurrentEntityMessage m3 = new ServerStoreOpMessage.ReplaceAtHeadMessage(1L, chainOf(), chainOf()); assertThat(m1.concurrencyKey(), is(m2.concurrencyKey())); assertThat(m2.concurrencyKey(), is(m3.concurrencyKey())); } @Test - public void testConcurrencyKeysEqualForDifferentCachesSameKey() throws Exception { + public void testConcurrencyKeysEqualForDifferentCachesSameKey() { ConcurrentEntityMessage m1 = new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L)); ConcurrentEntityMessage m2 = new ServerStoreOpMessage.GetAndAppendMessage(1L, createPayload(1L)); @@ -48,7 +45,7 @@ public void testConcurrencyKeysEqualForDifferentCachesSameKey() throws Exception } @Test - public void testConcurrencyKeysNotEqualForDifferentCachesAndKeys() throws Exception { + public void testConcurrencyKeysNotEqualForDifferentCachesAndKeys() { ConcurrentEntityMessage m1 = new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L)); ConcurrentEntityMessage m2 = new ServerStoreOpMessage.GetAndAppendMessage(2L, createPayload(1L)); ConcurrentEntityMessage m3 = new ServerStoreOpMessage.AppendMessage(3L, createPayload(1L)); diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/Util.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/Util.java deleted file mode 100644 index 94a4b350c5..0000000000 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/Util.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.ehcache.clustered.common.internal.messages; - -import org.ehcache.clustered.common.internal.store.Chain; -import org.ehcache.clustered.common.internal.store.Element; - -import java.util.Iterator; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.ehcache.clustered.common.internal.store.Util.readPayLoad; - -/** - * - */ -public final class Util { - - private Util() { - } - - public static void assertChainHas(Chain chain, long... payLoads) { - Iterator elements = chain.iterator(); - for (long payLoad : payLoads) { - assertThat(readPayLoad(elements.next().getPayload()), is(Long.valueOf(payLoad))); - } - assertThat(elements.hasNext(), is(false)); - } -} diff --git a/clustered/server/build.gradle b/clustered/server/build.gradle index 8dfb3d93d9..046ae67c00 100644 --- a/clustered/server/build.gradle +++ b/clustered/server/build.gradle @@ -31,4 +31,6 @@ dependencies { providedImplementation "org.terracotta:entity-server-api:$terracottaApisVersion" providedImplementation "org.terracotta:standard-cluster-services:$terracottaApisVersion" providedImplementation "org.terracotta:runnel:$terracottaPlatformVersion" + + testImplementation project(':clustered:test-utils') } diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessage.java b/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessage.java index 6baace78ca..9150683a93 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessage.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessage.java @@ -21,12 +21,13 @@ import org.ehcache.clustered.common.internal.messages.EhcacheOperationMessage; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.Element; -import org.ehcache.clustered.common.internal.store.Util; import java.util.List; import java.util.stream.Collectors; import java.util.stream.StreamSupport; +import static org.ehcache.clustered.common.internal.util.ChainBuilder.chainFromList; + /** * This message is sent by the Active Entity to Passive Entity. */ @@ -49,13 +50,13 @@ public ChainReplicationMessage(long key, Chain chain, long transactionId, long o } private Chain dropLastElement(Chain chain) { - if (!chain.isEmpty()) { + if (chain.isEmpty()) { + return chain; + } else { List elements = StreamSupport.stream(chain.spliterator(), false) .collect(Collectors.toList()); elements.remove(elements.size() - 1); // remove last - return Util.getChain(elements); - } else { - return chain; + return chainFromList(elements); } } diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java index 68fd8eb964..86b79b15bf 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java @@ -16,17 +16,12 @@ package org.ehcache.clustered.server.offheap; import java.nio.ByteBuffer; -import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.locks.Lock; import org.ehcache.clustered.common.internal.store.Chain; -import org.ehcache.clustered.common.internal.store.Element; -import org.ehcache.clustered.common.internal.store.Util; import org.terracotta.offheapstore.MapInternals; import org.terracotta.offheapstore.ReadWriteLockedOffHeapClockCache; @@ -37,6 +32,8 @@ import org.terracotta.offheapstore.storage.portability.Portability; import org.terracotta.offheapstore.util.Factory; +import static org.ehcache.clustered.common.internal.util.ChainBuilder.chainFromList; + public class OffHeapChainMap implements MapInternals { interface ChainMapEvictionListener { @@ -251,63 +248,7 @@ private void evict() { } } - private static final Chain EMPTY_CHAIN = new Chain() { - @Override - public Iterator reverseIterator() { - return Collections.emptyList().iterator(); - } - - @Override - public boolean isEmpty() { - return true; - } - - @Override - public int length() { - return 0; - } - - @Override - public Iterator iterator() { - return Collections.emptyList().iterator(); - } - }; - - public static Chain chain(ByteBuffer... buffers) { - final List list = new ArrayList<>(); - for (ByteBuffer b : buffers) { - list.add(element(b)); - } - - return new Chain() { - - final List elements = Collections.unmodifiableList(list); - - @Override - public Iterator iterator() { - return elements.iterator(); - } - - @Override - public Iterator reverseIterator() { - return Util.reverseIterator(elements); - } - - @Override - public boolean isEmpty() { - return elements.isEmpty(); - } - - @Override - public int length() { - return elements.size(); - } - }; - } - - private static Element element(final ByteBuffer b) { - return b::asReadOnlyBuffer; - } + private static final Chain EMPTY_CHAIN = chainFromList(Collections.emptyList()); @Override public long getSize() { diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java index accbb335b9..3ae449b172 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java @@ -37,6 +37,7 @@ import org.terracotta.offheapstore.util.Factory; import static java.util.Collections.unmodifiableList; +import static org.ehcache.clustered.common.internal.util.ChainBuilder.chainFromList; public class OffHeapChainStorageEngine implements ChainStorageEngine, BinaryStorageEngine { private static final int ELEMENT_HEADER_SEQUENCE_OFFSET = 0; @@ -386,36 +387,6 @@ private long toExtensionAddress(long chainAddress) { return chainAddress + CHAIN_HEADER_SIZE; } - private static class DetachedChain implements Chain { - - private final List elements; - - private DetachedChain(List buffers) { - this.elements = unmodifiableList(buffers); - } - - @Override - public Iterator reverseIterator() { - return Util.reverseIterator(elements); - } - - @Override - public boolean isEmpty() { - return elements.isEmpty(); - } - - @Override - public int length() { - return elements.size(); - } - - @Override - public Iterator iterator() { - return elements.iterator(); - } - - } - /** * Represents the initial form of a chain before the storage engine writes the chain mapping * to the underlying map against the key. @@ -451,7 +422,7 @@ private static class GenesisLink extends GenesisChain { private final Element element; public GenesisLink(ByteBuffer buffer) { - element = () -> buffer; + element = buffer::asReadOnlyBuffer; } @Override @@ -503,7 +474,7 @@ public Chain detach() { element = storage.readLong(element + ELEMENT_HEADER_NEXT_OFFSET); } while (element != chain); - return new DetachedChain(buffers); + return chainFromList(buffers); } @Override diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java index d3cfbf137b..db772f427d 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java @@ -19,15 +19,16 @@ import org.ehcache.clustered.common.internal.messages.ResponseCodec; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.server.TestClientSourceId; +import org.junit.Assert; import org.junit.Test; import java.util.HashMap; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; -import static org.ehcache.clustered.common.internal.store.Util.chainsEqual; -import static org.ehcache.clustered.common.internal.store.Util.createPayload; -import static org.ehcache.clustered.common.internal.store.Util.getChain; +import static org.ehcache.clustered.ChainUtils.createPayload; +import static org.ehcache.clustered.ChainUtils.sequencedChainOf; +import static org.ehcache.clustered.Matchers.matchesChain; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -41,7 +42,7 @@ public class EhcacheSyncMessageCodecTest { @Test public void testDataSyncMessageEncodeDecode() throws Exception { Map chainMap = new HashMap<>(); - Chain chain = getChain(true, createPayload(10L), createPayload(100L), createPayload(1000L)); + Chain chain = sequencedChainOf(createPayload(10L), createPayload(100L), createPayload(1000L)); chainMap.put(1L, chain); chainMap.put(2L, chain); chainMap.put(3L, chain); @@ -50,9 +51,9 @@ public void testDataSyncMessageEncodeDecode() throws Exception { EhcacheDataSyncMessage decoded = (EhcacheDataSyncMessage) codec.decode(0, encodedMessage); Map decodedChainMap = decoded.getChainMap(); assertThat(decodedChainMap).hasSize(3); - assertThat(chainsEqual(decodedChainMap.get(1L), chain)).isTrue(); - assertThat(chainsEqual(decodedChainMap.get(2L), chain)).isTrue(); - assertThat(chainsEqual(decodedChainMap.get(3L), chain)).isTrue(); + Assert.assertThat(decodedChainMap.get(1L), matchesChain(chain)); + Assert.assertThat(decodedChainMap.get(2L), matchesChain(chain)); + Assert.assertThat(decodedChainMap.get(3L), matchesChain(chain)); } @Test diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java index 264b41105b..1e9cde4484 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java @@ -24,13 +24,12 @@ import org.junit.Test; import static java.nio.ByteBuffer.wrap; -import static org.ehcache.clustered.common.internal.store.Util.chainsEqual; -import static org.ehcache.clustered.common.internal.store.Util.createPayload; -import static org.ehcache.clustered.common.internal.store.Util.getChain; +import static org.ehcache.clustered.ChainUtils.chainOf; +import static org.ehcache.clustered.ChainUtils.createPayload; +import static org.ehcache.clustered.Matchers.matchesChain; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; public class PassiveReplicationMessageCodecTest { @@ -39,7 +38,7 @@ public class PassiveReplicationMessageCodecTest { @Test public void testChainReplicationMessageCodec() { - Chain chain = getChain(false, createPayload(2L), createPayload(20L)); + Chain chain = chainOf(createPayload(2L), createPayload(20L)); ChainReplicationMessage chainReplicationMessage = new ChainReplicationMessage(2L, chain, 200L, 100L, 1L); byte[] encoded = codec.encode(chainReplicationMessage); @@ -49,7 +48,7 @@ public void testChainReplicationMessageCodec() { assertThat(decodedMsg.getTransactionId(), is(chainReplicationMessage.getTransactionId())); assertThat(decodedMsg.getOldestTransactionId(), is(chainReplicationMessage.getOldestTransactionId())); assertThat(decodedMsg.getKey(), is(chainReplicationMessage.getKey())); - assertTrue(chainsEqual(decodedMsg.getChain(), chainReplicationMessage.getChain())); + assertThat(decodedMsg.getChain(), matchesChain(chainReplicationMessage.getChain())); } diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java index ea0690a3a2..3d1ab352f7 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java @@ -36,7 +36,7 @@ import java.util.Set; import java.util.concurrent.locks.Lock; -import static org.ehcache.clustered.server.offheap.OffHeapChainMap.chain; +import static org.ehcache.clustered.ChainUtils.chainOf; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.emptyIterable; @@ -81,7 +81,7 @@ public void testAppendAndReplace() { OffHeapChainMap map = getChainMapWithExtendedStorageEngine(); map.append("foo", buffer(1)); assertThat(map.get("foo"), contains(element(1))); - map.replaceAtHead("foo", chain(buffer(1)), chain()); + map.replaceAtHead("foo", chainOf(buffer(1)), chainOf()); ChainStorageEngine se = map.getStorageEngine(); assertThat(se, is(instanceOf(ExtendedOffHeapChainStorageEngine.class))); @SuppressWarnings("unchecked") @@ -102,7 +102,7 @@ public void testMultipleAppendAndReplace() { assertThat(map.getAndAppend("foo" + i, buffer(1)), contains(element(i))); } for (int i = 10; i < 15; i++) { - map.replaceAtHead("foo" + i, chain(buffer(i), buffer(1)), chain()); + map.replaceAtHead("foo" + i, chainOf(buffer(i), buffer(1)), chainOf()); } ChainStorageEngine se = map.getStorageEngine(); diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java index 5e2cf5e82b..d42a4a2a3c 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java @@ -44,7 +44,7 @@ import org.terracotta.offheapstore.storage.portability.StringPortability; import static java.util.Arrays.asList; -import static org.ehcache.clustered.server.offheap.OffHeapChainMap.chain; +import static org.ehcache.clustered.ChainUtils.chainOf; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.lessThan; import static org.hamcrest.collection.IsEmptyIterable.emptyIterable; @@ -162,7 +162,7 @@ public void testReplaceEmptyChainAtHeadOnEmptyChainFails() { OffHeapChainMap map = new OffHeapChainMap<>(new UnlimitedPageSource(new OffHeapBufferSource()), StringPortability.INSTANCE, minPageSize, maxPageSize, steal); try { - map.replaceAtHead("foo", chain(), chain(buffer(1))); + map.replaceAtHead("foo", chainOf(), chainOf(buffer(1))); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { //expected @@ -175,7 +175,7 @@ public void testReplaceEmptyChainAtHeadOnNonEmptyChain() { map.append("foo", buffer(1)); try { - map.replaceAtHead("foo", chain(), chain(buffer(2))); + map.replaceAtHead("foo", chainOf(), chainOf(buffer(2))); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { //expected @@ -187,7 +187,7 @@ public void testMismatchingReplaceSingletonChainAtHeadOnSingletonChain() { OffHeapChainMap map = new OffHeapChainMap<>(new UnlimitedPageSource(new OffHeapBufferSource()), StringPortability.INSTANCE, minPageSize, maxPageSize, steal); map.append("foo", buffer(1)); - map.replaceAtHead("foo", chain(buffer(2)), chain(buffer(42))); + map.replaceAtHead("foo", chainOf(buffer(2)), chainOf(buffer(42))); assertThat(map.get("foo"), contains(element(1))); } @@ -196,7 +196,7 @@ public void testReplaceSingletonChainAtHeadOnSingletonChain() { OffHeapChainMap map = new OffHeapChainMap<>(new UnlimitedPageSource(new OffHeapBufferSource()), StringPortability.INSTANCE, minPageSize, maxPageSize, steal); map.append("foo", buffer(1)); - map.replaceAtHead("foo", chain(buffer(1)), chain(buffer(42))); + map.replaceAtHead("foo", chainOf(buffer(1)), chainOf(buffer(42))); assertThat(map.get("foo"), contains(element(42))); } @@ -206,7 +206,7 @@ public void testReplaceSingletonChainAtHeadOnDoubleChain() { map.append("foo", buffer(1)); map.append("foo", buffer(2)); - map.replaceAtHead("foo", chain(buffer(1)), chain(buffer(42))); + map.replaceAtHead("foo", chainOf(buffer(1)), chainOf(buffer(42))); assertThat(map.get("foo"), contains(element(42), element(2))); } @@ -217,7 +217,7 @@ public void testReplaceSingletonChainAtHeadOnTripleChain() { map.append("foo", buffer(2)); map.append("foo", buffer(3)); - map.replaceAtHead("foo", chain(buffer(1)), chain(buffer(42))); + map.replaceAtHead("foo", chainOf(buffer(1)), chainOf(buffer(42))); assertThat(map.get("foo"), contains(element(42), element(2), element(3))); } @@ -227,7 +227,7 @@ public void testMismatchingReplacePluralChainAtHead() { map.append("foo", buffer(1)); map.append("foo", buffer(2)); - map.replaceAtHead("foo", chain(buffer(1), buffer(3)), chain(buffer(42))); + map.replaceAtHead("foo", chainOf(buffer(1), buffer(3)), chainOf(buffer(42))); assertThat(map.get("foo"), contains(element(1), element(2))); } @@ -237,7 +237,7 @@ public void testReplacePluralChainAtHeadOnDoubleChain() { map.append("foo", buffer(1)); map.append("foo", buffer(2)); - map.replaceAtHead("foo", chain(buffer(1), buffer(2)), chain(buffer(42))); + map.replaceAtHead("foo", chainOf(buffer(1), buffer(2)), chainOf(buffer(42))); assertThat(map.get("foo"), contains(element(42))); } @@ -248,7 +248,7 @@ public void testReplacePluralChainAtHeadOnTripleChain() { map.append("foo", buffer(2)); map.append("foo", buffer(3)); - map.replaceAtHead("foo", chain(buffer(1), buffer(2)), chain(buffer(42))); + map.replaceAtHead("foo", chainOf(buffer(1), buffer(2)), chainOf(buffer(42))); assertThat(map.get("foo"), contains(element(42), element(3))); } @@ -260,7 +260,7 @@ public void testReplacePluralChainAtHeadWithEmpty() { map.append("foo", buffer(3)); long before = map.getDataOccupiedMemory(); - map.replaceAtHead("foo", chain(buffer(1), buffer(2)), chain()); + map.replaceAtHead("foo", chainOf(buffer(1), buffer(2)), chainOf()); assertThat(map.getDataOccupiedMemory(), lessThan(before)); assertThat(map.get("foo"), contains(element(3))); } @@ -272,7 +272,7 @@ public void testSequenceBasedChainComparison() { map.append("foo", buffer(2)); map.append("foo", buffer(3)); - map.replaceAtHead("foo", map.get("foo"), chain()); + map.replaceAtHead("foo", map.get("foo"), chainOf()); assertThat(map.get("foo"), emptyIterable()); } @@ -284,7 +284,7 @@ public void testReplaceFullPluralChainAtHeadWithEmpty() { map.append("foo", buffer(3)); assertThat(map.getDataOccupiedMemory(), greaterThan(0L)); - map.replaceAtHead("foo", chain(buffer(1), buffer(2), buffer(3)), chain()); + map.replaceAtHead("foo", chainOf(buffer(1), buffer(2), buffer(3)), chainOf()); assertThat(map.getDataOccupiedMemory(), is(0L)); assertThat(map.get("foo"), emptyIterable()); } @@ -336,7 +336,7 @@ public void testContinualAppendCausingEvictionIsStable() { public void testPutWhenKeyIsNotNull() { OffHeapChainMap map = new OffHeapChainMap<>(new UnlimitedPageSource(new OffHeapBufferSource()), StringPortability.INSTANCE, minPageSize, maxPageSize, steal); map.append("key", buffer(3)); - map.put("key", chain(buffer(1), buffer(2))); + map.put("key", chainOf(buffer(1), buffer(2))); assertThat(map.get("key"), contains(element(1), element(2))); } @@ -344,7 +344,7 @@ public void testPutWhenKeyIsNotNull() { @Test public void testPutWhenKeyIsNull() { OffHeapChainMap map = new OffHeapChainMap<>(new UnlimitedPageSource(new OffHeapBufferSource()), StringPortability.INSTANCE, minPageSize, maxPageSize, steal); - map.put("key", chain(buffer(1), buffer(2))); + map.put("key", chainOf(buffer(1), buffer(2))); assertThat(map.get("key"), contains(element(1), element(2))); } @@ -358,7 +358,7 @@ public void testActiveChainsThreadSafety() throws ExecutionException, Interrupte OffHeapChainMap map = new OffHeapChainMap<>(heads, chainStorage); - map.put("key", chain(buffer(1), buffer(2))); + map.put("key", chainOf(buffer(1), buffer(2))); int nThreads = 10; ExecutorService executorService = Executors.newFixedThreadPool(nThreads); @@ -386,8 +386,8 @@ public void testPutDoesNotLeakWhenMappingIsNotNull() { OffHeapChainMap map = new OffHeapChainMap<>(heads, chainStorage); - map.put("key", chain(buffer(1))); - map.put("key", chain(buffer(2))); + map.put("key", chainOf(buffer(1))); + map.put("key", chainOf(buffer(2))); assertThat(chainStorage.getActiveChains().size(), is(0)); diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java index a06f0d7fc5..a2c96625c8 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java @@ -25,6 +25,7 @@ import org.ehcache.clustered.server.store.ElementBuilder; import org.ehcache.clustered.common.internal.store.ServerStore; import org.ehcache.clustered.server.store.ServerStoreTest; +import org.junit.Assert; import org.junit.Test; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -35,11 +36,12 @@ import static java.util.Arrays.asList; import static java.util.Collections.singletonList; +import static org.ehcache.clustered.ChainUtils.chainOf; +import static org.ehcache.clustered.ChainUtils.createPayload; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.hamcrest.core.Is.is; -import org.junit.Assert; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.doNothing; @@ -83,13 +85,13 @@ public ChainBuilder newChainBuilder() { for (int i = 0; i < buffers.length; i++) { buffers[i] = elements[i].getPayload(); } - return OffHeapChainMap.chain(buffers); + return chainOf(buffers); }; } @Override public ElementBuilder newElementBuilder() { - return payLoad -> () -> payLoad; + return payLoad -> () -> payLoad.asReadOnlyBuffer(); } @Test diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java index c1a36790ba..1b455ccbcb 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java @@ -16,19 +16,14 @@ package org.ehcache.clustered.server.offheap; import org.ehcache.clustered.common.internal.store.Chain; -import org.ehcache.clustered.common.internal.store.Element; -import org.ehcache.clustered.common.internal.store.Util; import org.ehcache.clustered.common.internal.store.operations.OperationCode; import org.junit.Test; import org.terracotta.offheapstore.buffersource.OffHeapBufferSource; import org.terracotta.offheapstore.paging.UnlimitedPageSource; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; +import static org.ehcache.clustered.ChainUtils.chainOf; import static org.ehcache.clustered.common.internal.store.operations.OperationCode.PUT; import static org.ehcache.clustered.common.internal.store.operations.OperationCode.PUT_IF_ABSENT; import static org.ehcache.clustered.common.internal.store.operations.OperationCode.PUT_WITH_WRITER; @@ -76,7 +71,7 @@ public void testGetAndAppendWithNormalOperation() { public void testPutWithPinningChain() { PinningOffHeapChainMap pinningOffHeapChainMap = getPinningOffHeapChainMap(); - pinningOffHeapChainMap.put(1L, chain(buffer(PUT), buffer(REMOVE))); + pinningOffHeapChainMap.put(1L, chainOf(buffer(PUT), buffer(REMOVE))); assertThat(pinningOffHeapChainMap.heads.isPinned(1L), is(true)); } @@ -84,7 +79,7 @@ public void testPutWithPinningChain() { public void testPutWithNormalChain() { PinningOffHeapChainMap pinningOffHeapChainMap = getPinningOffHeapChainMap(); - pinningOffHeapChainMap.put(1L, chain(buffer(PUT), buffer(PUT))); + pinningOffHeapChainMap.put(1L, chainOf(buffer(PUT), buffer(PUT))); assertThat(pinningOffHeapChainMap.heads.isPinned(1L), is(false)); } @@ -93,8 +88,8 @@ public void testReplaceAtHeadWithUnpinningChain() { PinningOffHeapChainMap pinningOffHeapChainMap = getPinningOffHeapChainMap(); ByteBuffer buffer = buffer(PUT_IF_ABSENT); - Chain pinningChain = chain(buffer); - Chain unpinningChain = chain(buffer(PUT)); + Chain pinningChain = chainOf(buffer); + Chain unpinningChain = chainOf(buffer(PUT)); pinningOffHeapChainMap.append(1L, buffer); assertThat(pinningOffHeapChainMap.heads.isPinned(1L), is(true)); @@ -108,8 +103,8 @@ public void testReplaceAtHeadWithPinningChain() { PinningOffHeapChainMap pinningOffHeapChainMap = getPinningOffHeapChainMap(); ByteBuffer buffer = buffer(REPLACE); - Chain pinningChain = chain(buffer); - Chain unpinningChain = chain(buffer(REPLACE_CONDITIONAL)); + Chain pinningChain = chainOf(buffer); + Chain unpinningChain = chainOf(buffer(REPLACE_CONDITIONAL)); pinningOffHeapChainMap.append(1L, buffer); assertThat(pinningOffHeapChainMap.heads.isPinned(1L), is(true)); @@ -123,8 +118,8 @@ public void testReplaceAtHeadWithEmptyChain() { PinningOffHeapChainMap pinningOffHeapChainMap = getPinningOffHeapChainMap(); ByteBuffer buffer = buffer(PUT_WITH_WRITER); - Chain pinningChain = chain(buffer); - Chain unpinningChain = chain(); + Chain pinningChain = chainOf(buffer); + Chain unpinningChain = chainOf(); pinningOffHeapChainMap.append(1L, buffer); assertThat(pinningOffHeapChainMap.heads.isPinned(1L), is(true)); @@ -141,36 +136,4 @@ private PinningOffHeapChainMap getPinningOffHeapChainMap() { return new PinningOffHeapChainMap<>(new UnlimitedPageSource(new OffHeapBufferSource()), LongPortability.INSTANCE, 4096, 4096, false); } - - public static Chain chain(ByteBuffer... buffers) { - final List list = new ArrayList<>(); - for (ByteBuffer b : buffers) { - list.add(b::asReadOnlyBuffer); - } - - return new Chain() { - - final List elements = Collections.unmodifiableList(list); - - @Override - public Iterator iterator() { - return elements.iterator(); - } - - @Override - public Iterator reverseIterator() { - return Util.reverseIterator(elements); - } - - @Override - public boolean isEmpty() { - return elements.isEmpty(); - } - - @Override - public int length() { - return elements.size(); - } - }; - } } diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index dfb28860d6..8caa8200d0 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -77,7 +77,7 @@ import java.util.concurrent.ExecutionException; import java.util.function.BiConsumer; -import static org.ehcache.clustered.common.internal.store.Util.createPayload; +import static org.ehcache.clustered.ChainUtils.createPayload; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; @@ -94,7 +94,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNotNull; import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java index abac774f35..566bb4db4a 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java @@ -23,7 +23,6 @@ import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.ClusterTierEntityConfiguration; -import org.ehcache.clustered.common.internal.store.Util; import org.ehcache.clustered.server.EhcacheStateServiceImpl; import org.ehcache.clustered.server.KeySegmentMapper; import org.ehcache.clustered.server.TestInvokeContext; @@ -54,7 +53,8 @@ import java.util.Map; import java.util.Set; -import static org.ehcache.clustered.common.internal.store.Util.createPayload; +import static org.ehcache.clustered.ChainUtils.createPayload; +import static org.ehcache.clustered.ChainUtils.sequencedChainOf; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; @@ -144,7 +144,7 @@ public void testPassiveTracksMessageDuplication() throws Exception { ClusterTierPassiveEntity passiveEntity = new ClusterTierPassiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); passiveEntity.createNew(); - Chain chain = Util.getChain(true, createPayload(1L)); + Chain chain = sequencedChainOf(createPayload(1L)); TestInvokeContext context = new TestInvokeContext(); long clientId = 3; @@ -155,7 +155,7 @@ public void testPassiveTracksMessageDuplication() throws Exception { // Should be added assertThat(passiveEntity.getStateService().getStore(passiveEntity.getStoreIdentifier()).get(2).isEmpty(), is(false)); - Chain emptyChain = Util.getChain(true); + Chain emptyChain = sequencedChainOf(); PassiveReplicationMessage message2 = new PassiveReplicationMessage.ChainReplicationMessage(2, emptyChain, 2L, 1L, clientId); passiveEntity.invokePassive(context, message2); @@ -177,11 +177,11 @@ public void testOversizeReplaceAtHeadMessage() throws Exception { int key = 2; - Chain chain = Util.getChain(true, createPayload(1L)); + Chain chain = sequencedChainOf(createPayload(1L)); PassiveReplicationMessage message = new PassiveReplicationMessage.ChainReplicationMessage(key, chain, 2L, 1L, 3L); passiveEntity.invokePassive(context, message); - Chain oversizeChain = Util.getChain(true, createPayload(2L, 1024 * 1024)); + Chain oversizeChain = sequencedChainOf(createPayload(2L, 1024 * 1024)); ServerStoreOpMessage.ReplaceAtHeadMessage oversizeMsg = new ServerStoreOpMessage.ReplaceAtHeadMessage(key, chain, oversizeChain); passiveEntity.invokePassive(context, oversizeMsg); // Should be evicted, the value is oversize. @@ -195,7 +195,7 @@ public void testOversizeChainReplicationMessage() throws Exception { TestInvokeContext context = new TestInvokeContext(); long key = 2L; - Chain oversizeChain = Util.getChain(true, createPayload(key, 1024 * 1024)); + Chain oversizeChain = sequencedChainOf(createPayload(key, 1024 * 1024)); PassiveReplicationMessage oversizeMsg = new PassiveReplicationMessage.ChainReplicationMessage(key, oversizeChain, 2L, 1L, (long) 3); passiveEntity.invokePassive(context, oversizeMsg); // Should be cleared, the value is oversize. diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java index 6ca4982330..13569cacc4 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java @@ -115,4 +115,4 @@ public void testCreateLockStateAfterFailover() { } -} \ No newline at end of file +} diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java index 62dbfc848f..550c4daca3 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java @@ -24,8 +24,10 @@ import org.junit.Test; import java.nio.ByteBuffer; -import java.util.Iterator; +import static org.ehcache.clustered.ChainUtils.createPayload; +import static org.ehcache.clustered.ChainUtils.readPayload; +import static org.ehcache.clustered.Matchers.hasPayloads; import static org.junit.Assert.assertThat; import static org.hamcrest.Matchers.is; @@ -49,31 +51,6 @@ private static void populateStore(ServerStore store) throws Exception { } } - private static long readPayLoad(ByteBuffer byteBuffer) { - return byteBuffer.getLong(); - } - - protected static ByteBuffer createPayload(long key) { - ByteBuffer byteBuffer = ByteBuffer.allocate(8).putLong(key); - byteBuffer.flip(); - return byteBuffer; - } - - private static void assertChainAndReverseChainOnlyHave(Chain chain, long... payLoads) { - Iterator elements = chain.iterator(); - for (long payLoad : payLoads) { - assertThat(readPayLoad(elements.next().getPayload()), is(Long.valueOf(payLoad))); - } - assertThat(elements.hasNext(), is(false)); - - Iterator reverseElements = chain.reverseIterator(); - - for (int i = payLoads.length -1; i >= 0; i--) { - assertThat(readPayLoad(reverseElements.next().getPayload()), is(Long.valueOf(payLoads[i]))); - } - assertThat(reverseElements.hasNext(), is(false)); - } - @Test public void testGetNoMappingExists() throws Exception { ServerStore store = newStore(); @@ -86,28 +63,28 @@ public void testGetNoMappingExists() throws Exception { public void testGetMappingExists() throws Exception { ServerStore store = newStore(); populateStore(store); - Chain chain = store.get(1); + Chain chain = store.get(1L); assertThat(chain.isEmpty(), is(false)); - assertChainAndReverseChainOnlyHave(chain, 1); + assertThat(chain, hasPayloads(1L)); } @Test public void testAppendNoMappingExists() throws Exception { ServerStore store = newStore(); - store.append(1, createPayload(1)); - Chain chain = store.get(1); + store.append(1L, createPayload(1L)); + Chain chain = store.get(1L); assertThat(chain.isEmpty(), is(false)); - assertChainAndReverseChainOnlyHave(chain, 1); + assertThat(chain, hasPayloads(1L)); } @Test public void testAppendMappingExists() throws Exception { ServerStore store = newStore(); populateStore(store); - store.append(2, createPayload(22)); - Chain chain = store.get(2); + store.append(2L, createPayload(22L)); + Chain chain = store.get(2L); assertThat(chain.isEmpty(), is(false)); - assertChainAndReverseChainOnlyHave(chain, 2, 22); + assertThat(chain, hasPayloads(2L, 22L)); } @Test @@ -116,7 +93,7 @@ public void testGetAndAppendNoMappingExists() throws Exception { Chain chain = store.getAndAppend(1, createPayload(1)); assertThat(chain.isEmpty(), is(true)); chain = store.get(1); - assertChainAndReverseChainOnlyHave(chain, 1); + assertThat(chain, hasPayloads(1L)); } @Test @@ -125,10 +102,10 @@ public void testGetAndAppendMappingExists() throws Exception { populateStore(store); Chain chain = store.getAndAppend(1, createPayload(22)); for (Element element : chain) { - assertThat(readPayLoad(element.getPayload()), is(Long.valueOf(1))); + assertThat(readPayload(element.getPayload()), is(Long.valueOf(1))); } chain = store.get(1); - assertChainAndReverseChainOnlyHave(chain, 1, 22); + assertThat(chain, hasPayloads(1, 22)); } @Test @@ -139,7 +116,7 @@ public void testReplaceAtHeadSucceedsMappingExistsHeadMatchesStrictly() throws E store.replaceAtHead(1, existingMapping, chainBuilder.build(elementBuilder.build(createPayload(11)))); Chain chain = store.get(1); - assertChainAndReverseChainOnlyHave(chain, 11); + assertThat(chain, hasPayloads(11)); store.append(2, createPayload(22)); store.append(2, createPayload(222)); @@ -150,7 +127,7 @@ public void testReplaceAtHeadSucceedsMappingExistsHeadMatchesStrictly() throws E chain = store.get(2); - assertChainAndReverseChainOnlyHave(chain, 2222); + assertThat(chain, hasPayloads(2222)); } @Test @@ -165,7 +142,7 @@ public void testReplaceAtHeadSucceedsMappingExistsHeadMatches() throws Exception store.replaceAtHead(1, existingMapping, chainBuilder.build(elementBuilder.build(createPayload(111)))); Chain chain = store.get(1); - assertChainAndReverseChainOnlyHave(chain, 111, 11); + assertThat(chain, hasPayloads(111, 11)); store.append(2, createPayload(22)); existingMapping = store.get(2); @@ -175,7 +152,7 @@ public void testReplaceAtHeadSucceedsMappingExistsHeadMatches() throws Exception store.replaceAtHead(2, existingMapping, chainBuilder.build(elementBuilder.build(createPayload(2222)))); chain = store.get(2); - assertChainAndReverseChainOnlyHave(chain, 2222, 222); + assertThat(chain, hasPayloads(2222, 222)); } @Test @@ -190,17 +167,16 @@ public void testReplaceAtHeadIgnoredMappingExistsHeadMisMatch() throws Exception store.replaceAtHead(1, mappingReadFirst, chainBuilder.build(elementBuilder.build(createPayload(111)))); Chain current = store.get(1); - assertChainAndReverseChainOnlyHave(current, 111); + assertThat(current, hasPayloads(111)); store.append(1, createPayload(1111)); store.replaceAtHead(1, mappingReadFirst, chainBuilder.build(elementBuilder.build(createPayload(11111)))); Chain toVerify = store.get(1); - assertChainAndReverseChainOnlyHave(toVerify, 111, 1111); + assertThat(toVerify, hasPayloads(111, 1111)); } - @Test public void test_append_doesNotConsumeBuffer() throws Exception { ServerStore store = newStore(); @@ -220,14 +196,13 @@ public void test_getAndAppend_doesNotConsumeBuffer() throws Exception { } @Test - public void test_replaceAtHead_doesNotConsumeBuffer() throws Exception { + public void test_replaceAtHead_doesNotConsumeBuffer() { ServerStore store = newStore(); ByteBuffer payload = createPayload(1L); Chain expected = newChainBuilder().build(newElementBuilder().build(payload), newElementBuilder().build(payload)); Chain update = newChainBuilder().build(newElementBuilder().build(payload)); store.replaceAtHead(1L, expected, update); - MatcherAssert.assertThat(payload.remaining(), Is.is(8)); + assertThat(payload.remaining(), Is.is(8)); } - } diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainImpl.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainImpl.java index 7d44ba5a36..cf4dd0a71a 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainImpl.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainImpl.java @@ -38,11 +38,6 @@ public HeapChainImpl(Element... elements) { createChain(elements); } - @Override - public Iterator reverseIterator() { - return new ReverseChainIterator(); - } - @Override public boolean isEmpty() { return first == null; @@ -135,37 +130,6 @@ public Element next() { this.current = this.current.nextLink; return temp.element; } - - @Override - public void remove() { - throw new UnsupportedOperationException("Remove operation is not supported"); - } - } - - private class ReverseChainIterator implements Iterator { - - private Node current; - - ReverseChainIterator() { - this.current = last; - } - - @Override - public boolean hasNext() { - return current != null; - } - - @Override - public Element next() { - Node temp = this.current; - this.current = this.current.prevLink; - return temp.element; - } - - @Override - public void remove() { - throw new UnsupportedOperationException("Remove operation is not supported"); - } } private static class Node { diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementImpl.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementImpl.java index c4fef8a0cc..db1d88ce18 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementImpl.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementImpl.java @@ -38,6 +38,6 @@ public long getSequenceNumber() { @Override public ByteBuffer getPayload() { - return this.data.duplicate(); + return this.data.asReadOnlyBuffer(); } } diff --git a/clustered/test-utils/build.gradle b/clustered/test-utils/build.gradle new file mode 100644 index 0000000000..b7bfb406d0 --- /dev/null +++ b/clustered/test-utils/build.gradle @@ -0,0 +1,4 @@ +dependencies { + compile project(':clustered:common') + compile "org.hamcrest:hamcrest-core:$hamcrestVersion" +} diff --git a/clustered/test-utils/config/checkstyle-suppressions.xml b/clustered/test-utils/config/checkstyle-suppressions.xml new file mode 100644 index 0000000000..cb41d0baf7 --- /dev/null +++ b/clustered/test-utils/config/checkstyle-suppressions.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/clustered/test-utils/src/main/java/org/ehcache/clustered/ChainUtils.java b/clustered/test-utils/src/main/java/org/ehcache/clustered/ChainUtils.java new file mode 100644 index 0000000000..b6001e1ac2 --- /dev/null +++ b/clustered/test-utils/src/main/java/org/ehcache/clustered/ChainUtils.java @@ -0,0 +1,109 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered; + +import org.ehcache.clustered.common.internal.store.Chain; +import org.ehcache.clustered.common.internal.store.Element; +import org.ehcache.clustered.common.internal.store.SequencedElement; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +public class ChainUtils { + + public static long readPayload(ByteBuffer byteBuffer) { + return byteBuffer.getLong(); + } + + public static ByteBuffer createPayload(long key) { + ByteBuffer byteBuffer = ByteBuffer.allocate(8).putLong(key); + byteBuffer.flip(); + return byteBuffer.asReadOnlyBuffer(); + } + + public static ByteBuffer createPayload(long key, int payloadSize) { + if (payloadSize < 8) { + throw new IllegalArgumentException("payload must be at least 8 bytes long"); + } + ByteBuffer byteBuffer = ByteBuffer.allocate(payloadSize); + byteBuffer.putLong(key); + for (int i = 0; i < payloadSize - 8; i++) { + byteBuffer.put((byte) 0); + } + byteBuffer.flip(); + return byteBuffer.asReadOnlyBuffer(); + } + + public static Element getElement(final ByteBuffer payload) { + return payload::asReadOnlyBuffer; + } + + public static Chain chainOf(ByteBuffer... buffers) { + List elements = new ArrayList<>(); + for (final ByteBuffer buffer : buffers) { + elements.add(getElement(buffer)); + } + return getChain(elements); + } + + public static Chain sequencedChainOf(ByteBuffer ... buffers) { + List elements = new ArrayList<>(); + long counter = 0; + for (final ByteBuffer buffer : buffers) { + elements.add(getElement(counter++, buffer)); + } + return getChain(elements); + } + + private static Chain getChain(final List elements) { + return new Chain() { + private final List list = Collections.unmodifiableList(elements); + + @Override + public boolean isEmpty() { + return list.isEmpty(); + } + + @Override + public int length() { + return list.size(); + } + + @Override + public Iterator iterator() { + return list.iterator(); + } + }; + } + + public static SequencedElement getElement(final long sequence, final ByteBuffer payload) { + return new SequencedElement() { + @Override + public long getSequenceNumber() { + return sequence; + } + + @Override + public ByteBuffer getPayload() { + return payload.asReadOnlyBuffer(); + } + }; + } +} diff --git a/clustered/test-utils/src/main/java/org/ehcache/clustered/Matchers.java b/clustered/test-utils/src/main/java/org/ehcache/clustered/Matchers.java new file mode 100644 index 0000000000..a1d034446f --- /dev/null +++ b/clustered/test-utils/src/main/java/org/ehcache/clustered/Matchers.java @@ -0,0 +1,105 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered; + +import org.ehcache.clustered.common.internal.store.Chain; +import org.ehcache.clustered.common.internal.store.Element; +import org.ehcache.clustered.common.internal.store.SequencedElement; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import static org.ehcache.clustered.ChainUtils.readPayload; + +public class Matchers { + + public static Matcher matchesChain(Chain expected) { + return new TypeSafeMatcher() { + @Override + protected boolean matchesSafely(Chain item) { + Iterator expectedIt = expected.iterator(); + Iterator itemIt = item.iterator(); + + while (expectedIt.hasNext() && itemIt.hasNext()) { + Element expectedNext = expectedIt.next(); + Element itemNext = itemIt.next(); + + if (!expectedNext.getPayload().equals(itemNext.getPayload())) { + return false; + } + } + + return !expectedIt.hasNext() && !itemIt.hasNext(); + } + + @Override + public void describeTo(Description description) { + description.appendText(" a chain matching ").appendValue(expected); + } + }; + } + + public static Matcher hasPayloads(long ... payloads) { + return new TypeSafeMatcher() { + @Override + protected boolean matchesSafely(Chain item) { + Iterator elements = item.iterator(); + for (long payload : payloads) { + if (readPayload(elements.next().getPayload()) != payload) { + return false; + } + } + return !elements.hasNext(); + } + + @Override + public void describeTo(Description description) { + description.appendText(" a chain containing the payloads ").appendValueList("[", ", ", "]", payloads); + } + }; + } + + + public static Matcher sameSequenceAs(Chain original) { + List sequenceNumbers = sequenceNumbersOf(original); + + return new TypeSafeMatcher() { + @Override + protected boolean matchesSafely(Chain item) { + return sequenceNumbers.equals(sequenceNumbersOf(item)); + } + + @Override + public void describeTo(Description description) { + description.appendValue("a chain with sequence numbers matching ").appendValue(original); + } + }; + } + + private static List sequenceNumbersOf(Chain chain) { + List sequenceNumbers = new ArrayList<>(chain.length()); + for (Element element : chain) { + sequenceNumbers.add(((SequencedElement) element).getSequenceNumber()); + } + return sequenceNumbers; + } + +} diff --git a/settings.gradle b/settings.gradle index 1c204fa6d3..279d39141c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -15,5 +15,5 @@ */ include "api", "spi-tester", "core", "core-spi-test", "impl", "management", "transactions", "107", "xml", - "clustered", "clustered:common", "clustered:client", "clustered:server", "clustered:integration-test", "clustered:clustered-dist", "clustered:ops-tool", + "clustered", "clustered:test-utils", "clustered:common", "clustered:client", "clustered:server", "clustered:integration-test", "clustered:clustered-dist", "clustered:ops-tool", "integration-test", "dist", "osgi-test", "clustered:osgi-test", "demos", "demos:00-NoCache", "demos:01-CacheAside", "docs" From c488e18597ae79d3d75986e42b483ffc3fad4c8c Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 12 Feb 2019 11:51:59 -0500 Subject: [PATCH 095/372] Clarify cache iterator contract --- api/src/main/java/org/ehcache/Cache.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/api/src/main/java/org/ehcache/Cache.java b/api/src/main/java/org/ehcache/Cache.java index 011136b6c9..a904dce76d 100644 --- a/api/src/main/java/org/ehcache/Cache.java +++ b/api/src/main/java/org/ehcache/Cache.java @@ -22,6 +22,7 @@ import org.ehcache.spi.loaderwriter.CacheWritingException; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; +import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -254,6 +255,16 @@ public interface Cache extends Iterable> { */ CacheRuntimeConfiguration getRuntimeConfiguration(); + /** + * Returns an iterator over the cache entries. + *

+ * Due to the interactions of the cache and iterator contracts it is possible + * for iteration to return expired entries. + * + * @return an Iterator over the cache entries. + */ + @Override + Iterator> iterator(); /** * A mapping of key to value held in a {@link Cache}. From 54b07d757a34cf0dcf111e1070b34a1c453859b7 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 12 Feb 2019 11:56:38 -0500 Subject: [PATCH 096/372] Rework iterator framework --- .../java/org/ehcache/jsr107/IteratorTest.java | 15 +--- .../java/org/ehcache/core/EhcacheBase.java | 22 +++--- .../core/spi/store/tiering/CachingTier.java | 14 ++++ .../spi/store/tiering/LowerCachingTier.java | 10 +++ .../impl/internal/store/basic/NopStore.java | 3 +- .../impl/internal/store/heap/OnHeapStore.java | 77 +++++++++++++++---- .../store/tiering/CompoundCachingTier.java | 20 +++++ .../internal/store/tiering/TieredStore.java | 75 +++++++++++++++++- .../store/heap/BaseOnHeapStoreTest.java | 7 +- .../integration/EventNotificationTest.java | 1 + .../statistics/CacheCalculationTest.java | 8 +- .../statistics/TierCalculationTest.java | 6 +- 12 files changed, 206 insertions(+), 52 deletions(-) diff --git a/107/src/test/java/org/ehcache/jsr107/IteratorTest.java b/107/src/test/java/org/ehcache/jsr107/IteratorTest.java index 0cf04f6e73..11e200fbb0 100644 --- a/107/src/test/java/org/ehcache/jsr107/IteratorTest.java +++ b/107/src/test/java/org/ehcache/jsr107/IteratorTest.java @@ -23,7 +23,6 @@ import javax.cache.Cache; import javax.cache.CacheManager; import javax.cache.Caching; -import javax.cache.configuration.Factory; import javax.cache.configuration.MutableConfiguration; import javax.cache.expiry.Duration; import javax.cache.expiry.ExpiryPolicy; @@ -33,7 +32,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; /** * @author Ludovic Orban @@ -55,7 +53,7 @@ private void advanceTime(long delta) { } @Test - public void testIterateExpiredReturnsNull() throws Exception { + public void testIterateExpiredIsSkipped() throws Exception { EhcacheCachingProvider provider = (EhcacheCachingProvider) Caching.getCachingProvider(); TestTimeSource testTimeSource = new TestTimeSource(); TimeSourceConfiguration timeSourceConfiguration = new TimeSourceConfiguration(testTimeSource); @@ -86,16 +84,7 @@ public Duration getExpiryForUpdate() { testTimeSource.advanceTime(1000); Iterator> iterator = testCache.iterator(); - assertThat(iterator.hasNext(), is(true)); - - int loopCount = 0; - while (iterator.hasNext()) { - Cache.Entry next = iterator.next(); - assertThat(next, is(nullValue())); - - loopCount++; - } - assertThat(loopCount, is(1)); + assertThat(iterator.hasNext(), is(false)); cacheManager.close(); } diff --git a/core/src/main/java/org/ehcache/core/EhcacheBase.java b/core/src/main/java/org/ehcache/core/EhcacheBase.java index 7d35caa153..aabae905a3 100644 --- a/core/src/main/java/org/ehcache/core/EhcacheBase.java +++ b/core/src/main/java/org/ehcache/core/EhcacheBase.java @@ -320,7 +320,7 @@ public V putIfAbsent(final K key, final V value) { @Override public Iterator> iterator() { statusTransitioner.checkAvailable(); - return new CacheEntryIterator(false); + return new CacheEntryIterator(); } /** @@ -699,15 +699,21 @@ public boolean remove(K key) { @Override public void removeAll() { + Collection failures = new ArrayList<>(); Store.Iterator>> iterator = store.iterator(); while (iterator.hasNext()) { try { Entry> next = iterator.next(); remove(next.getKey()); } catch (StoreAccessException cae) { - // skip + failures.add(cae); } } + if (!failures.isEmpty()) { + StoreAccessException removeAllFailure = new StoreAccessException("Iteration failures may have prevented a complete removal"); + failures.forEach(removeAllFailure::addSuppressed); + resilienceStrategy.clearFailure(removeAllFailure); + } } } @@ -715,13 +721,11 @@ public void removeAll() { private class CacheEntryIterator implements Iterator> { private final Store.Iterator>> iterator; - private final boolean quiet; private Cache.Entry> current; private Cache.Entry> next; private StoreAccessException nextException; - public CacheEntryIterator(boolean quiet) { - this.quiet = quiet; + public CacheEntryIterator() { this.iterator = store.iterator(); advance(); } @@ -730,7 +734,7 @@ private void advance() { try { while (iterator.hasNext()) { next = iterator.next(); - if (getNoLoader(next.getKey()) != null) { + if (next != null) { return; } } @@ -756,14 +760,14 @@ public Entry next() { throw new NoSuchElementException(); } - if (!quiet) getObserver.begin(); + getObserver.begin(); if (nextException == null) { - if (!quiet) getObserver.end(GetOutcome.HIT); + getObserver.end(GetOutcome.HIT); current = next; advance(); return new ValueHolderBasedEntry<>(current); } else { - if (!quiet) getObserver.end(GetOutcome.FAILURE); + getObserver.end(GetOutcome.FAILURE); StoreAccessException cae = nextException; nextException = null; return resilienceStrategy.iteratorFailure(cae); diff --git a/core/src/main/java/org/ehcache/core/spi/store/tiering/CachingTier.java b/core/src/main/java/org/ehcache/core/spi/store/tiering/CachingTier.java index 862aecea15..371862741d 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/tiering/CachingTier.java +++ b/core/src/main/java/org/ehcache/core/spi/store/tiering/CachingTier.java @@ -53,6 +53,20 @@ public interface CachingTier extends ConfigurationChangeSupport { */ Store.ValueHolder getOrComputeIfAbsent(K key, Function> source) throws StoreAccessException; + /** + * Either return the value holder currently in the caching tier, or return the provided default. + *

+ * Note that in case of expired value holders, {@code null} will be returned and the mapping will be invalidated. + * + * @param key the key + * @param source the function that computes the default value when absent from this tier + * + * @return the value holder, or {@code null} + * + * @throws StoreAccessException if the mapping cannot be retrieved or stored + */ + Store.ValueHolder getOrDefault(K key, Function> source) throws StoreAccessException; + /** * Removes a mapping, triggering the {@link InvalidationListener} if registered. * diff --git a/core/src/main/java/org/ehcache/core/spi/store/tiering/LowerCachingTier.java b/core/src/main/java/org/ehcache/core/spi/store/tiering/LowerCachingTier.java index cfee5149f1..5036b15fb1 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/tiering/LowerCachingTier.java +++ b/core/src/main/java/org/ehcache/core/spi/store/tiering/LowerCachingTier.java @@ -48,6 +48,16 @@ public interface LowerCachingTier extends ConfigurationChangeSupport { */ Store.ValueHolder installMapping(K key, Function> source) throws StoreAccessException; + /** + * Return the value holder currently in this tier. + * + * @param key the key + * @return the value holder, or {@code null} + * + * @throws StoreAccessException if the mapping cannot be access + */ + Store.ValueHolder get(K key) throws StoreAccessException; + /** * Return the value holder currently in this tier and removes it atomically. * diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java index f98cb42a6a..2da5ea55be 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java @@ -27,6 +27,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Set; import java.util.function.BiFunction; import java.util.function.Consumer; @@ -151,7 +152,7 @@ public boolean hasNext() { @Override public Cache.Entry> next() { - return null; + throw new NoSuchElementException(); } }; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index 03aeab0f09..6c5853ef92 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -85,10 +85,10 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.NoSuchElementException; import java.util.Objects; import java.util.Random; import java.util.Set; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiFunction; @@ -647,29 +647,47 @@ public void clear() { @Override public Iterator>> iterator() { + java.util.Iterator>> iterator = map.entrySetIterator(); return new Iterator>>() { - private final java.util.Iterator>> it = map.entrySetIterator(); + private Cache.Entry> prefetched = advance(); @Override public boolean hasNext() { - return it.hasNext(); + return prefetched != null; } @Override - public Cache.Entry> next() { - Entry> next = it.next(); - K key = next.getKey(); - OnHeapValueHolder value = next.getValue(); - return new Cache.Entry>() { - @Override - public K getKey() { - return key; - } - @Override - public ValueHolder getValue() { - return value; + public Cache.Entry> next() throws StoreAccessException { + if (prefetched == null) { + throw new NoSuchElementException(); + } else { + Cache.Entry> next = prefetched; + prefetched = advance(); + return next; + } + } + + private Cache.Entry> advance() { + while (iterator.hasNext()) { + Entry> next = iterator.next(); + + if (strategy.isExpired(next.getValue())) { + expireMappingUnderLock(next.getKey(), next.getValue()); + } else { + return new Cache.Entry>() { + @Override + public K getKey() { + return next.getKey(); + } + + @Override + public ValueHolder getValue() { + return next.getValue(); + } + }; } - }; + } + return null; } }; } @@ -721,6 +739,33 @@ public ValueHolder getOrComputeIfAbsent(K key, Function> so } } + @Override + public ValueHolder getOrDefault(K key, Function> source) throws StoreAccessException { + try { + Backend backEnd = map; + + // First try to find the value from heap + OnHeapValueHolder cachedValue = backEnd.get(key); + + if (cachedValue == null) { + return source.apply(key); + } else { + // If we have a real value (not a fault), we make sure it is not expired + if (!(cachedValue instanceof Fault)) { + if (cachedValue.isExpired(timeSource.getTimeMillis())) { + expireMappingUnderLock(key, cachedValue); + return null; + } + } + + // Return the value that we found in the cache (by getting the fault or just returning the plain value depending on what we found) + return getValue(cachedValue); + } + } catch (RuntimeException re) { + throw handleException(re); + } + } + private ValueHolder resolveFault(K key, Backend backEnd, long now, Fault fault) throws StoreAccessException { try { ValueHolder value = fault.getValueHolder(); diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java index 72aa322d17..5362fca370 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java @@ -118,6 +118,26 @@ public Store.ValueHolder getOrComputeIfAbsent(K key, final Function getOrDefault(K key, Function> source) throws StoreAccessException { + try { + return higher.getOrDefault(key, keyParam -> { + try { + Store.ValueHolder valueHolder = lower.get(keyParam); + if (valueHolder != null) { + return valueHolder; + } + + return source.apply(keyParam); + } catch (StoreAccessException cae) { + throw new ComputationException(cae); + } + }); + } catch (ComputationException ce) { + throw ce.getStoreAccessException(); + } + } + @Override public void invalidate(final K key) throws StoreAccessException { try { diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java index 6bad9c8e92..6f66efdaa6 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java @@ -39,6 +39,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Set; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicReference; @@ -213,7 +214,74 @@ public StoreEventSource getStoreEventSource() { @Override public Iterator>> iterator() { - return authoritativeTier.iterator(); + Iterator>> authoritativeIterator = authoritativeTier.iterator(); + + return new Iterator>>() { + + private StoreAccessException prefetchFailure; + private Cache.Entry> prefetched; + + { + try { + prefetched = advance(); + } catch (StoreAccessException sae) { + prefetchFailure = sae; + } + } + + @Override + public boolean hasNext() { + return prefetched != null || prefetchFailure != null; + } + + @Override + public Cache.Entry> next() throws StoreAccessException { + StoreAccessException nextFailure = prefetchFailure; + Cache.Entry> next = prefetched; + + try { + prefetchFailure = null; + prefetched = advance(); + } catch (StoreAccessException sae) { + prefetchFailure = sae; + prefetched = null; + } + if (nextFailure == null) { + if (next == null) { + throw new NoSuchElementException(); + } else { + return next; + } + } else { + throw nextFailure; + } + } + + private Cache.Entry> advance() throws StoreAccessException { + while (authoritativeIterator.hasNext()) { + Cache.Entry> next = authoritativeIterator.next(); + K authKey = next.getKey(); + + ValueHolder checked = cachingTier().getOrDefault(authKey, key -> next.getValue()); + + if (checked != null) { + return new Cache.Entry>() { + @Override + public K getKey() { + return authKey; + } + + @Override + public ValueHolder getValue() { + return checked; + } + }; + } + } + + return null; + } + }; } @Override @@ -485,6 +553,11 @@ public ValueHolder getOrComputeIfAbsent(final K key, final Function getOrDefault(K key, Function> source) { + return source.apply(key); + } + @Override public void invalidate(final K key) { // noop diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java index b8cec4b59b..26b538675f 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java @@ -540,12 +540,9 @@ public void testIteratorExpired() throws Exception { timeSource.advanceTime(1); Map observed = observe(store.iterator()); - assertThat(3, equalTo(observed.size())); - assertThat(observed.get("key1"), equalTo("value1")); - assertThat(observed.get("key2"), equalTo("value2")); - assertThat(observed.get("key3"), equalTo("value3")); + assertThat(0, equalTo(observed.size())); - StatisticsTestUtils.validateStat(store, StoreOperationOutcomes.ExpirationOutcome.SUCCESS, 0L); + StatisticsTestUtils.validateStat(store, StoreOperationOutcomes.ExpirationOutcome.SUCCESS, 3L); } @Test diff --git a/integration-test/src/test/java/org/ehcache/integration/EventNotificationTest.java b/integration-test/src/test/java/org/ehcache/integration/EventNotificationTest.java index c259f43c01..e9e3ff6c55 100644 --- a/integration-test/src/test/java/org/ehcache/integration/EventNotificationTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/EventNotificationTest.java @@ -30,6 +30,7 @@ import org.ehcache.event.EventOrdering; import org.ehcache.event.EventType; import org.ehcache.impl.internal.TimeSourceConfiguration; +import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/integration-test/src/test/java/org/ehcache/integration/statistics/CacheCalculationTest.java b/integration-test/src/test/java/org/ehcache/integration/statistics/CacheCalculationTest.java index dd8b108a63..ca1d07ff7c 100644 --- a/integration-test/src/test/java/org/ehcache/integration/statistics/CacheCalculationTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/statistics/CacheCalculationTest.java @@ -131,10 +131,10 @@ public void iterator() { changesOf(0, 0, 2, 0); Iterator> iterator = cache.iterator(); - changesOf(1, 0, 0, 0); // FIXME Why one?!? + changesOf(0, 0, 0, 0); iterator.next().getKey(); - changesOf(2, 0, 0, 0); // FIXME Why two?!? + changesOf(1, 0, 0, 0); expect(iterator.hasNext()).isTrue(); changesOf(0, 0, 0, 0); @@ -157,7 +157,7 @@ public void foreach() { changesOf(0, 0, 3, 0); cache.forEach(e -> {}); - changesOf(6, 0, 0, 0); // FIXME counted twice but works for JCache + changesOf(3, 0, 0, 0); } @Test @@ -168,7 +168,7 @@ public void spliterator() { changesOf(0, 0, 3, 0); StreamSupport.stream(cache.spliterator(), false).forEach(e -> {}); - changesOf(6, 0, 0, 0); // FIXME counted twice but works for JCache + changesOf(3, 0, 0, 0); } @Test diff --git a/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java b/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java index a6b8d5c03a..4ef8df77b7 100644 --- a/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java @@ -149,16 +149,16 @@ public void iterator() { changesOf(0, 0, 2, 0); Iterator> iterator = cache.iterator(); - changesOf(1, 0, 0, 0); // FIXME Why one?!? + changesOf(0, 0, 0, 0); iterator.next().getKey(); - changesOf(1, 0, 0, 0); // FIXME One hit and on the cache we have two + changesOf(0, 0, 0, 0); expect(iterator.hasNext()).isTrue(); changesOf(0, 0, 0, 0); iterator.next().getKey(); - changesOf(0, 0, 0, 0); // FIXME No hit on a next + changesOf(0, 0, 0, 0); expect(iterator.hasNext()).isFalse(); changesOf(0, 0, 0, 0); From 8ab7107b8b12b50df2d3f9156bf44730224dbcea Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 12 Feb 2019 13:09:19 -0500 Subject: [PATCH 097/372] Rework message codec logic --- .../messages/LifeCycleMessageCodec.java | 13 +-- .../internal/messages/MessageCodecUtils.java | 9 +- .../internal/messages/ServerStoreOpCodec.java | 88 +++++++------------ .../messages/StateRepositoryOpCodec.java | 47 ++++------ .../PassiveReplicationMessageCodec.java | 44 +++------- 5 files changed, 71 insertions(+), 130 deletions(-) diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodec.java index af1c5b5ba9..61edabab5b 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodec.java @@ -29,6 +29,7 @@ import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_INDEX; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_NAME; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.SERVER_STORE_NAME_FIELD; +import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.encodeMandatoryFields; import static org.terracotta.runnel.StructBuilder.newStructBuilder; public class LifeCycleMessageCodec { @@ -45,11 +46,9 @@ public class LifeCycleMessageCodec { private final Struct validateMessageStruct; private final Struct validateStoreMessageStruct; - private final MessageCodecUtils messageCodecUtils; private final ConfigCodec configCodec; public LifeCycleMessageCodec(ConfigCodec configCodec) { - this.messageCodecUtils = new MessageCodecUtils(); this.configCodec = configCodec; StructBuilder validateMessageStructBuilderPrefix = newStructBuilder() @@ -81,14 +80,11 @@ public byte[] encode(LifecycleMessage message) { } private byte[] encodePrepareForDestroyMessage(LifecycleMessage message) { - return PREPARE_FOR_DESTROY_STRUCT.encoder() - .enm(MESSAGE_TYPE_FIELD_NAME, message.getMessageType()) - .encode().array(); + return encodeMandatoryFields(PREPARE_FOR_DESTROY_STRUCT, message).encode().array(); } private byte[] encodeValidateStoreMessage(LifecycleMessage.ValidateServerStore message) { - StructEncoder encoder = validateStoreMessageStruct.encoder(); - messageCodecUtils.encodeMandatoryFields(encoder, message); + StructEncoder encoder = encodeMandatoryFields(validateStoreMessageStruct, message); encoder.string(SERVER_STORE_NAME_FIELD, message.getName()); configCodec.encodeServerStoreConfiguration(encoder, message.getStoreConfiguration()); @@ -96,9 +92,8 @@ private byte[] encodeValidateStoreMessage(LifecycleMessage.ValidateServerStore m } private byte[] encodeTierManagerValidateMessage(LifecycleMessage.ValidateStoreManager message) { - StructEncoder encoder = validateMessageStruct.encoder(); + StructEncoder encoder = encodeMandatoryFields(validateMessageStruct, message); ServerSideConfiguration config = message.getConfiguration(); - messageCodecUtils.encodeMandatoryFields(encoder, message); if (config == null) { encoder.bool(CONFIG_PRESENT_FIELD, false); } else { diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/MessageCodecUtils.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/MessageCodecUtils.java index 0472f0f89c..2959f5a94b 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/MessageCodecUtils.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/MessageCodecUtils.java @@ -16,17 +16,20 @@ package org.ehcache.clustered.common.internal.messages; +import org.terracotta.runnel.Struct; import org.terracotta.runnel.encoding.StructEncoder; /** * MessageCodecUtils */ -public class MessageCodecUtils { +public final class MessageCodecUtils { public static final String SERVER_STORE_NAME_FIELD = "serverStoreName"; public static final String KEY_FIELD = "key"; - public void encodeMandatoryFields(StructEncoder encoder, EhcacheOperationMessage message) { - encoder.enm(EhcacheMessageType.MESSAGE_TYPE_FIELD_NAME, message.getMessageType()); + private MessageCodecUtils() {} + + public static StructEncoder encodeMandatoryFields(Struct struct, EhcacheOperationMessage message) { + return struct.encoder().enm(EhcacheMessageType.MESSAGE_TYPE_FIELD_NAME, message.getMessageType()); } } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java index 89cdffb5fa..43c732bd06 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java @@ -26,7 +26,6 @@ import org.ehcache.clustered.common.internal.store.Chain; import org.terracotta.runnel.Struct; import org.terracotta.runnel.decoding.StructDecoder; -import org.terracotta.runnel.encoding.StructEncoder; import java.nio.ByteBuffer; @@ -35,6 +34,7 @@ import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_INDEX; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_NAME; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.KEY_FIELD; +import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.encodeMandatoryFields; import static org.terracotta.runnel.StructBuilder.newStructBuilder; public class ServerStoreOpCodec { @@ -83,123 +83,95 @@ public class ServerStoreOpCodec { .int64("hash", 30) .build(); - private final MessageCodecUtils messageCodecUtils = new MessageCodecUtils(); - public byte[] encode(ServerStoreOpMessage message) { - StructEncoder encoder; - switch (message.getMessageType()) { case GET_STORE: GetMessage getMessage = (GetMessage) message; - encoder = GET_MESSAGE_STRUCT.encoder(); - return encoder - .enm(MESSAGE_TYPE_FIELD_NAME, message.getMessageType()) + return encodeMandatoryFields(GET_MESSAGE_STRUCT, message) .int64(KEY_FIELD, getMessage.getKey()) - .encode() - .array(); + .encode().array(); case APPEND: AppendMessage appendMessage = (AppendMessage) message; - encoder = APPEND_MESSAGE_STRUCT.encoder(); - messageCodecUtils.encodeMandatoryFields(encoder, message); - return encoder + return encodeMandatoryFields(APPEND_MESSAGE_STRUCT, message) .int64(KEY_FIELD, appendMessage.getKey()) .byteBuffer("payload", appendMessage.getPayload()) - .encode() - .array(); + .encode().array(); case GET_AND_APPEND: GetAndAppendMessage getAndAppendMessage = (GetAndAppendMessage) message; - encoder = GET_AND_APPEND_MESSAGE_STRUCT.encoder(); - messageCodecUtils.encodeMandatoryFields(encoder, message); - return encoder + return encodeMandatoryFields(GET_AND_APPEND_MESSAGE_STRUCT, message) .int64(KEY_FIELD, getAndAppendMessage.getKey()) .byteBuffer("payload", getAndAppendMessage.getPayload()) - .encode() - .array(); + .encode().array(); case REPLACE: final ReplaceAtHeadMessage replaceAtHeadMessage = (ReplaceAtHeadMessage) message; - encoder = REPLACE_MESSAGE_STRUCT.encoder(); - messageCodecUtils.encodeMandatoryFields(encoder, message); - return encoder + return encodeMandatoryFields(REPLACE_MESSAGE_STRUCT, message) .int64(KEY_FIELD, replaceAtHeadMessage.getKey()) .struct("expect", replaceAtHeadMessage.getExpect(), ChainCodec::encode) .struct("update", replaceAtHeadMessage.getUpdate(), ChainCodec::encode) - .encode() - .array(); + .encode().array(); case CLIENT_INVALIDATION_ACK: ClientInvalidationAck clientInvalidationAckMessage = (ClientInvalidationAck) message; - encoder = CLIENT_INVALIDATION_ACK_MESSAGE_STRUCT.encoder(); - return encoder - .enm(MESSAGE_TYPE_FIELD_NAME, message.getMessageType()) + return encodeMandatoryFields(CLIENT_INVALIDATION_ACK_MESSAGE_STRUCT, message) .int64(KEY_FIELD, clientInvalidationAckMessage.getKey()) .int32("invalidationId", clientInvalidationAckMessage.getInvalidationId()) - .encode() - .array(); + .encode().array(); case CLIENT_INVALIDATION_ALL_ACK: ClientInvalidationAllAck clientInvalidationAllAckMessage = (ClientInvalidationAllAck) message; - encoder = CLIENT_INVALIDATION_ALL_ACK_MESSAGE_STRUCT.encoder(); - return encoder - .enm(MESSAGE_TYPE_FIELD_NAME, message.getMessageType()) + return encodeMandatoryFields(CLIENT_INVALIDATION_ALL_ACK_MESSAGE_STRUCT, message) .int32("invalidationId", clientInvalidationAllAckMessage.getInvalidationId()) .encode().array(); case CLEAR: - encoder = CLEAR_MESSAGE_STRUCT.encoder(); - messageCodecUtils.encodeMandatoryFields(encoder, message); - return encoder - .encode() - .array(); + return encodeMandatoryFields(CLEAR_MESSAGE_STRUCT, message) + .encode().array(); case LOCK: - encoder = LOCK_STRUCT.encoder(); - return encoder - .enm(MESSAGE_TYPE_FIELD_NAME, message.getMessageType()) - .int64("hash", ((ServerStoreOpMessage.LockMessage) message).getHash()) - .encode().array(); + ServerStoreOpMessage.LockMessage lockMessage = (ServerStoreOpMessage.LockMessage) message; + return encodeMandatoryFields(LOCK_STRUCT, message) + .int64("hash", lockMessage.getHash()) + .encode().array(); case UNLOCK: - encoder = LOCK_STRUCT.encoder(); - return encoder - .enm(MESSAGE_TYPE_FIELD_NAME, message.getMessageType()) - .int64("hash", ((ServerStoreOpMessage.UnlockMessage) message).getHash()) - .encode().array(); + ServerStoreOpMessage.UnlockMessage unlockMessage = (ServerStoreOpMessage.UnlockMessage) message; + return encodeMandatoryFields(LOCK_STRUCT, message) + .int64("hash", unlockMessage.getHash()) + .encode().array(); default: throw new RuntimeException("Unhandled message operation : " + message.getMessageType()); } } public EhcacheEntityMessage decode(EhcacheMessageType opCode, ByteBuffer messageBuffer) { - StructDecoder decoder; switch (opCode) { case GET_STORE: { - decoder = GET_MESSAGE_STRUCT.decoder(messageBuffer); + StructDecoder decoder = GET_MESSAGE_STRUCT.decoder(messageBuffer); Long key = decoder.int64(KEY_FIELD); return new GetMessage(key); } case GET_AND_APPEND: { - decoder = GET_AND_APPEND_MESSAGE_STRUCT.decoder(messageBuffer); + StructDecoder decoder = GET_AND_APPEND_MESSAGE_STRUCT.decoder(messageBuffer); Long key = decoder.int64(KEY_FIELD); ByteBuffer payload = decoder.byteBuffer("payload"); return new GetAndAppendMessage(key, payload); } case APPEND: { - decoder = APPEND_MESSAGE_STRUCT.decoder(messageBuffer); + StructDecoder decoder = APPEND_MESSAGE_STRUCT.decoder(messageBuffer); Long key = decoder.int64(KEY_FIELD); ByteBuffer payload = decoder.byteBuffer("payload"); return new AppendMessage(key, payload); } case REPLACE: { - decoder = REPLACE_MESSAGE_STRUCT.decoder(messageBuffer); + StructDecoder decoder = REPLACE_MESSAGE_STRUCT.decoder(messageBuffer); Long key = decoder.int64(KEY_FIELD); Chain expect = ChainCodec.decode(decoder.struct("expect")); Chain update = ChainCodec.decode(decoder.struct("update")); return new ReplaceAtHeadMessage(key, expect, update); } case CLIENT_INVALIDATION_ACK: { - decoder = CLIENT_INVALIDATION_ACK_MESSAGE_STRUCT.decoder(messageBuffer); + StructDecoder decoder = CLIENT_INVALIDATION_ACK_MESSAGE_STRUCT.decoder(messageBuffer); Long key = decoder.int64(KEY_FIELD); Integer invalidationId = decoder.int32("invalidationId"); return new ClientInvalidationAck(key, invalidationId); } case CLIENT_INVALIDATION_ALL_ACK: { - decoder = CLIENT_INVALIDATION_ALL_ACK_MESSAGE_STRUCT - .decoder(messageBuffer); + StructDecoder decoder = CLIENT_INVALIDATION_ALL_ACK_MESSAGE_STRUCT.decoder(messageBuffer); Integer invalidationId = decoder.int32("invalidationId"); return new ClientInvalidationAllAck(invalidationId); } @@ -207,12 +179,12 @@ public EhcacheEntityMessage decode(EhcacheMessageType opCode, ByteBuffer message return new ClearMessage(); } case LOCK: { - decoder = LOCK_STRUCT.decoder(messageBuffer); + StructDecoder decoder = LOCK_STRUCT.decoder(messageBuffer); long hash = decoder.int64("hash"); return new ServerStoreOpMessage.LockMessage(hash); } case UNLOCK: { - decoder = LOCK_STRUCT.decoder(messageBuffer); + StructDecoder decoder = LOCK_STRUCT.decoder(messageBuffer); long hash = decoder.int64("hash"); return new ServerStoreOpMessage.UnlockMessage(hash); } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpCodec.java index df669e6213..8507c64a0a 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpCodec.java @@ -19,7 +19,6 @@ import org.ehcache.clustered.common.internal.store.Util; import org.terracotta.runnel.Struct; import org.terracotta.runnel.decoding.StructDecoder; -import org.terracotta.runnel.encoding.StructEncoder; import java.nio.ByteBuffer; import java.util.Arrays; @@ -32,6 +31,7 @@ import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_NAME; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.KEY_FIELD; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.SERVER_STORE_NAME_FIELD; +import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.encodeMandatoryFields; import static org.terracotta.runnel.StructBuilder.newStructBuilder; public class StateRepositoryOpCodec { @@ -60,8 +60,6 @@ public class StateRepositoryOpCodec { .string(MAP_ID_FIELD, 35) .build(); - private final MessageCodecUtils messageCodecUtils = new MessageCodecUtils(); - public byte[] encode(StateRepositoryOpMessage message) { switch (message.getMessageType()) { @@ -77,38 +75,29 @@ public byte[] encode(StateRepositoryOpMessage message) { } private byte[] encodeEntrySetMessage(StateRepositoryOpMessage.EntrySetMessage message) { - StructEncoder encoder = ENTRY_SET_MESSAGE_STRUCT.encoder(); - - messageCodecUtils.encodeMandatoryFields(encoder, message); - encoder.string(SERVER_STORE_NAME_FIELD, message.getCacheId()); - encoder.string(MAP_ID_FIELD, message.getCacheId()); - - return encoder.encode().array(); + return encodeMandatoryFields(ENTRY_SET_MESSAGE_STRUCT, message) + .string(SERVER_STORE_NAME_FIELD, message.getCacheId()) + .string(MAP_ID_FIELD, message.getCacheId()) + .encode().array(); } private byte[] encodePutIfAbsentMessage(StateRepositoryOpMessage.PutIfAbsentMessage message) { - StructEncoder encoder = PUT_IF_ABSENT_MESSAGE_STRUCT.encoder(); - - messageCodecUtils.encodeMandatoryFields(encoder, message); - encoder.string(SERVER_STORE_NAME_FIELD, message.getCacheId()); - encoder.string(MAP_ID_FIELD, message.getCacheId()); - // TODO this needs to change - serialization needs to happen in the StateRepo not here, though we need the hashcode for server side comparison. - encoder.byteBuffer(KEY_FIELD, wrap(Util.marshall(message.getKey()))); - encoder.byteBuffer(VALUE_FIELD, wrap(Util.marshall(message.getValue()))); - - return encoder.encode().array(); + return encodeMandatoryFields(PUT_IF_ABSENT_MESSAGE_STRUCT, message) + .string(SERVER_STORE_NAME_FIELD, message.getCacheId()) + .string(MAP_ID_FIELD, message.getCacheId()) + // TODO this needs to change - serialization needs to happen in the StateRepo not here, though we need the hashcode for server side comparison. + .byteBuffer(KEY_FIELD, wrap(Util.marshall(message.getKey()))) + .byteBuffer(VALUE_FIELD, wrap(Util.marshall(message.getValue()))) + .encode().array(); } private byte[] encodeGetMessage(StateRepositoryOpMessage.GetMessage message) { - StructEncoder encoder = GET_MESSAGE_STRUCT.encoder(); - - messageCodecUtils.encodeMandatoryFields(encoder, message); - encoder.string(SERVER_STORE_NAME_FIELD, message.getCacheId()); - encoder.string(MAP_ID_FIELD, message.getCacheId()); - // TODO this needs to change - serialization needs to happen in the StateRepo not here, though we need the hashcode for server side comparison. - encoder.byteBuffer(KEY_FIELD, wrap(Util.marshall(message.getKey()))); - - return encoder.encode().array(); + return encodeMandatoryFields(GET_MESSAGE_STRUCT, message) + .string(SERVER_STORE_NAME_FIELD, message.getCacheId()) + .string(MAP_ID_FIELD, message.getCacheId()) + // TODO this needs to change - serialization needs to happen in the StateRepo not here, though we need the hashcode for server side comparison. + .byteBuffer(KEY_FIELD, wrap(Util.marshall(message.getKey()))) + .encode().array(); } public StateRepositoryOpMessage decode(EhcacheMessageType messageType, ByteBuffer messageBuffer) { diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java b/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java index 3d902a6610..929af99b9d 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java @@ -19,11 +19,9 @@ import org.ehcache.clustered.common.internal.messages.ChainCodec; import org.ehcache.clustered.common.internal.messages.EhcacheEntityMessage; import org.ehcache.clustered.common.internal.messages.EhcacheMessageType; -import org.ehcache.clustered.common.internal.messages.MessageCodecUtils; import org.ehcache.clustered.common.internal.store.Chain; import org.terracotta.runnel.Struct; import org.terracotta.runnel.decoding.StructDecoder; -import org.terracotta.runnel.encoding.StructEncoder; import java.nio.ByteBuffer; @@ -32,6 +30,7 @@ import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_NAME; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.KEY_FIELD; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.SERVER_STORE_NAME_FIELD; +import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.encodeMandatoryFields; import static org.terracotta.runnel.StructBuilder.newStructBuilder; public class PassiveReplicationMessageCodec { @@ -60,14 +59,7 @@ public class PassiveReplicationMessageCodec { .int64(KEY_FIELD, 20) .build(); - private final MessageCodecUtils messageCodecUtils; - - public PassiveReplicationMessageCodec() { - this.messageCodecUtils = new MessageCodecUtils(); - } - public byte[] encode(PassiveReplicationMessage message) { - switch (message.getMessageType()) { case CHAIN_REPLICATION_OP: return encodeChainReplicationMessage((PassiveReplicationMessage.ChainReplicationMessage) message); @@ -81,34 +73,24 @@ public byte[] encode(PassiveReplicationMessage message) { } private byte[] encodeInvalidationCompleteMessage(PassiveReplicationMessage.InvalidationCompleteMessage message) { - StructEncoder encoder = INVALIDATION_COMPLETE_STRUCT.encoder(); - - encoder.enm(MESSAGE_TYPE_FIELD_NAME, message.getMessageType()) - .int64(KEY_FIELD, message.getKey()); - - return encoder.encode().array(); + return encodeMandatoryFields(INVALIDATION_COMPLETE_STRUCT, message) + .int64(KEY_FIELD, message.getKey()) + .encode().array(); } private byte[] encodeClearInvalidationCompleteMessage(PassiveReplicationMessage.ClearInvalidationCompleteMessage message) { - StructEncoder encoder = CLEAR_INVALIDATION_COMPLETE_STRUCT.encoder(); - - encoder.enm(MESSAGE_TYPE_FIELD_NAME, message.getMessageType()); - - return encoder.encode().array(); + return encodeMandatoryFields(CLEAR_INVALIDATION_COMPLETE_STRUCT, message) + .encode().array(); } private byte[] encodeChainReplicationMessage(PassiveReplicationMessage.ChainReplicationMessage message) { - StructEncoder encoder = CHAIN_REPLICATION_STRUCT.encoder(); - - messageCodecUtils.encodeMandatoryFields(encoder, message); - - encoder.int64(TRANSACTION_ID_FIELD, message.getTransactionId()); - encoder.int64(CLIENT_ID_FIELD, message.getClientId()); - encoder.int64(OLDEST_TRANSACTION_ID_FIELD, message.getOldestTransactionId()); - encoder.int64(KEY_FIELD, message.getKey()); - encoder.struct(CHAIN_FIELD, message.getChain(), ChainCodec::encode); - - return encoder.encode().array(); + return encodeMandatoryFields(CHAIN_REPLICATION_STRUCT, message) + .int64(TRANSACTION_ID_FIELD, message.getTransactionId()) + .int64(CLIENT_ID_FIELD, message.getClientId()) + .int64(OLDEST_TRANSACTION_ID_FIELD, message.getOldestTransactionId()) + .int64(KEY_FIELD, message.getKey()) + .struct(CHAIN_FIELD, message.getChain(), ChainCodec::encode) + .encode().array(); } public EhcacheEntityMessage decode(EhcacheMessageType messageType, ByteBuffer messageBuffer) { From cdd38155740ba9d0ddabe5c47d2dc5693f809114 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 12 Feb 2019 14:24:05 -0500 Subject: [PATCH 098/372] Add succeeds and failsWith matchers --- .../store/ClusterTierActiveEntityTest.java | 244 ++++++++---------- 1 file changed, 101 insertions(+), 143 deletions(-) diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index 8caa8200d0..a62354e4ec 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -22,6 +22,7 @@ import org.ehcache.clustered.common.PoolAllocation.Shared; import org.ehcache.clustered.common.ServerSideConfiguration; import org.ehcache.clustered.common.internal.ServerStoreConfiguration; +import org.ehcache.clustered.common.internal.exceptions.InvalidOperationException; import org.ehcache.clustered.common.internal.exceptions.InvalidServerStoreConfigurationException; import org.ehcache.clustered.common.internal.messages.ConcurrentEntityMessage; import org.ehcache.clustered.common.internal.messages.EhcacheEntityMessage; @@ -29,6 +30,7 @@ import org.ehcache.clustered.common.internal.messages.EhcacheResponseType; import org.ehcache.clustered.common.internal.messages.LifecycleMessage; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage; +import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.ClusterTierEntityConfiguration; import org.ehcache.clustered.server.ConcurrencyStrategies; import org.ehcache.clustered.server.EhcacheStateServiceImpl; @@ -42,6 +44,10 @@ import org.ehcache.clustered.server.state.EhcacheStateService; import org.ehcache.clustered.server.state.InvalidationTracker; import org.ehcache.clustered.server.store.ClusterTierActiveEntity.InvalidationHolder; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.hamcrest.core.IsInstanceOf; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -70,7 +76,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Random; import java.util.Set; @@ -78,6 +83,7 @@ import java.util.function.BiConsumer; import static org.ehcache.clustered.ChainUtils.createPayload; +import static org.ehcache.clustered.Matchers.hasPayloads; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; @@ -88,6 +94,8 @@ import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.sameInstance; +import static org.hamcrest.core.CombinableMatcher.both; +import static org.hamcrest.core.CombinableMatcher.either; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; @@ -238,20 +246,12 @@ public void testAppendInvalidationAcksTakenIntoAccount() throws Exception { // attach to the store - assertSuccess( - activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)) - ); - assertSuccess( - activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)) - ); - assertSuccess( - activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)) - ); + assertThat(activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); // perform an append - assertSuccess( - activeEntity.invokeActive(context1, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))) - ); + assertThat(activeEntity.invokeActive(context1, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))), succeeds()); // assert that an invalidation request is pending assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(1)); @@ -261,9 +261,7 @@ public void testAppendInvalidationAcksTakenIntoAccount() throws Exception { assertThat(invalidationHolder.clientsHavingToInvalidate, containsInAnyOrder(context2.getClientDescriptor(), context3.getClientDescriptor())); // client 2 acks - assertSuccess( - activeEntity.invokeActive(context2, new ServerStoreOpMessage.ClientInvalidationAck(1L, activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())) - ); + assertThat(activeEntity.invokeActive(context2, new ServerStoreOpMessage.ClientInvalidationAck(1L, activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())), succeeds()); // assert that client 2 is not waited for anymore assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(1)); @@ -273,9 +271,7 @@ public void testAppendInvalidationAcksTakenIntoAccount() throws Exception { assertThat(invalidationHolder.clientsHavingToInvalidate, contains(context3.getClientDescriptor())); // client 3 acks - assertSuccess( - activeEntity.invokeActive(context3, new ServerStoreOpMessage.ClientInvalidationAck(1L, activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())) - ); + assertThat(activeEntity.invokeActive(context3, new ServerStoreOpMessage.ClientInvalidationAck(1L, activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())), succeeds()); // assert that the invalidation request is done since all clients disconnected assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(0)); @@ -294,20 +290,12 @@ public void testClearInvalidationAcksTakenIntoAccount() throws Exception { activeEntity.connected(context3.getClientDescriptor()); // attach to the store - assertSuccess( - activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)) - ); - assertSuccess( - activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)) - ); - assertSuccess( - activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)) - ); + assertThat(activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); // perform a clear - assertSuccess( - activeEntity.invokeActive(context1, new ServerStoreOpMessage.ClearMessage()) - ); + assertThat(activeEntity.invokeActive(context1, new ServerStoreOpMessage.ClearMessage()), succeeds()); // assert that an invalidation request is pending assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(1)); @@ -317,9 +305,7 @@ public void testClearInvalidationAcksTakenIntoAccount() throws Exception { assertThat(invalidationHolder.clientsHavingToInvalidate, containsInAnyOrder(context2.getClientDescriptor(), context3.getClientDescriptor())); // client 2 acks - assertSuccess( - activeEntity.invokeActive(context2, new ServerStoreOpMessage.ClientInvalidationAllAck(activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())) - ); + assertThat(activeEntity.invokeActive(context2, new ServerStoreOpMessage.ClientInvalidationAllAck(activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())), succeeds()); // assert that client 2 is not waited for anymore assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(1)); @@ -329,9 +315,7 @@ public void testClearInvalidationAcksTakenIntoAccount() throws Exception { assertThat(invalidationHolder.clientsHavingToInvalidate, contains(context3.getClientDescriptor())); // client 3 acks - assertSuccess( - activeEntity.invokeActive(context3, new ServerStoreOpMessage.ClientInvalidationAllAck(activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())) - ); + assertThat(activeEntity.invokeActive(context3, new ServerStoreOpMessage.ClientInvalidationAllAck(activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())), succeeds()); // assert that the invalidation request is done since all clients disconnected assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(0)); @@ -350,20 +334,12 @@ public void testAppendInvalidationDisconnectionOfInvalidatingClientsTakenIntoAcc activeEntity.connected(context3.getClientDescriptor()); // attach to the store - assertSuccess( - activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)) - ); - assertSuccess( - activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)) - ); - assertSuccess( - activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)) - ); + assertThat(activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); // perform an append - assertSuccess( - activeEntity.invokeActive(context1, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))) - ); + assertThat(activeEntity.invokeActive(context1, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))), succeeds()); // disconnect client2 activeEntity.disconnected(context2.getClientDescriptor()); @@ -395,20 +371,12 @@ public void testClearInvalidationDisconnectionOfInvalidatingClientsTakenIntoAcco activeEntity.connected(context3.getClientDescriptor()); // attach to the store - assertSuccess( - activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)) - ); - assertSuccess( - activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)) - ); - assertSuccess( - activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)) - ); + assertThat(activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); // perform an append - assertSuccess( - activeEntity.invokeActive(context1, new ServerStoreOpMessage.ClearMessage()) - ); + assertThat(activeEntity.invokeActive(context1, new ServerStoreOpMessage.ClearMessage()), succeeds()); // disconnect client2 activeEntity.disconnected(context2.getClientDescriptor()); @@ -445,20 +413,12 @@ public void testAppendInvalidationDisconnectionOfBlockingClientTakenIntoAccount( activeEntity.connected(context3.getClientDescriptor()); // attach to the store - assertSuccess( - activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)) - ); - assertSuccess( - activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)) - ); - assertSuccess( - activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)) - ); + assertThat(activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); // perform an append - assertSuccess( - activeEntity.invokeActive(context1, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))) - ); + assertThat(activeEntity.invokeActive(context1, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))), succeeds()); // disconnect client1 activeEntity.disconnected(context1.getClientDescriptor()); @@ -485,20 +445,12 @@ public void testClearInvalidationDisconnectionOfBlockingClientTakenIntoAccount() activeEntity.connected(context3.getClientDescriptor()); // attach to the store - assertSuccess( - activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)) - ); - assertSuccess( - activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)) - ); - assertSuccess( - activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)) - ); + assertThat(activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); // perform an append - assertSuccess( - activeEntity.invokeActive(context1, new ServerStoreOpMessage.ClearMessage()) - ); + assertThat(activeEntity.invokeActive(context1, new ServerStoreOpMessage.ClearMessage()), succeeds()); // disconnect client1 activeEntity.disconnected(context1.getClientDescriptor()); @@ -516,13 +468,9 @@ public void testWithAttachmentSucceedsInvokingServerStoreOperation() throws Exce activeEntity.connected(context.getClientDescriptor()); // attach to the store - assertSuccess( - activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)) - ); + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - assertSuccess( - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))) - ); + assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))), succeeds()); EhcacheEntityResponse response = activeEntity.invokeActive(context, new ServerStoreOpMessage.GetMessage(1L)); assertThat(response, instanceOf(EhcacheEntityResponse.GetResponse.class)); @@ -545,9 +493,7 @@ public void testCreateDedicatedServerStore() throws Exception { TestInvokeContext context = new TestInvokeContext(); activeEntity.connected(context.getClientDescriptor()); - assertSuccess( - activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)) - ); + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); assertThat(activeEntity.getConnectedClients(), contains(context.getClientDescriptor())); @@ -587,8 +533,7 @@ public void testValidateDedicatedServerStore() throws Exception { TestInvokeContext context2 = new TestInvokeContext(); activeEntity.connected(context2.getClientDescriptor()); - assertSuccess(activeEntity.invokeActive(context2, - new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration))); + assertThat(activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); assertThat(defaultRegistry.getStoreManagerService().getDedicatedResourcePoolIds(), containsInAnyOrder(defaultStoreName)); @@ -607,13 +552,12 @@ public void testValidateDedicatedServerStoreBad() throws Exception { TestInvokeContext context = new TestInvokeContext(); activeEntity.connected(context.getClientDescriptor()); - assertFailure(activeEntity.invokeActive(context, + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, new ServerStoreConfigBuilder() .dedicated(defaultResource, 8, MemoryUnit.MEGABYTES) .build())), - InvalidServerStoreConfigurationException.class); - + failsWith(instanceOf(InvalidServerStoreConfigurationException.class))); } @Test @@ -624,8 +568,8 @@ public void testValidateUnknown() throws Exception { TestInvokeContext context = new TestInvokeContext(); activeEntity.connected(context.getClientDescriptor()); - assertSuccess(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, - new ServerStoreConfigBuilder().unknown().build()))); + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, + new ServerStoreConfigBuilder().unknown().build())), succeeds()); } @Test @@ -681,7 +625,7 @@ public void testValidateSharedServerStore() throws Exception { TestInvokeContext context = new TestInvokeContext(); activeEntity.connected(context.getClientDescriptor()); - assertSuccess(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, storeConfiguration))); + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, storeConfiguration)), succeeds()); assertThat(activeEntity.getConnectedClients(), contains(context.getClientDescriptor())); } @@ -705,8 +649,8 @@ public void testValidateServerStore_DedicatedStoresDifferentSizes() throws Excep ", desired: " + storeConfiguration.getPoolAllocation(); - assertFailure(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, storeConfiguration)), - InvalidServerStoreConfigurationException.class, expectedMessageContent); + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, storeConfiguration)), + failsWith(both(IsInstanceOf.any(InvalidServerStoreConfigurationException.class)).and(withMessage(containsString(expectedMessageContent))))); } @Test @@ -728,8 +672,8 @@ public void testValidateServerStore_DedicatedStoreResourceNamesDifferent() throw ", desired: " + storeConfiguration.getPoolAllocation(); - assertFailure(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, storeConfiguration)), - InvalidServerStoreConfigurationException.class, expectedMessageContent); + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, storeConfiguration)), + failsWith(both(IsInstanceOf.any(InvalidServerStoreConfigurationException.class)).and(withMessage(containsString(expectedMessageContent))))); } @Test @@ -756,9 +700,8 @@ public void testValidateServerStore_DifferentSharedPools() throws Exception { ", desired: " + otherConfiguration.getPoolAllocation(); - assertFailure(activeEntity.invokeActive(context, - new LifecycleMessage.ValidateServerStore(defaultStoreName, - otherConfiguration)),InvalidServerStoreConfigurationException.class,expectedMessageContent); + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, otherConfiguration)), + failsWith(both(IsInstanceOf.any(InvalidServerStoreConfigurationException.class)).and(withMessage(containsString(expectedMessageContent))))); } @Test @@ -831,7 +774,7 @@ public void testSyncToPassiveNoData() throws Exception { activeEntity.connected(context.getClientDescriptor()); - assertSuccess(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration))); + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); @SuppressWarnings("unchecked") PassiveSynchronizationChannel syncChannel = mock(PassiveSynchronizationChannel.class); @@ -849,13 +792,13 @@ public void testSyncToPassiveBatchedByDefault() throws Exception { activeEntity.connected(context.getClientDescriptor()); - assertSuccess(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration))); + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); ByteBuffer payload = ByteBuffer.allocate(512); // Put keys that maps to the same concurrency key - assertSuccess(activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, payload))); - assertSuccess(activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(-2L, payload))); - assertSuccess(activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(17L, payload))); + assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, payload)), succeeds()); + assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(-2L, payload)), succeeds()); + assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(17L, payload)), succeeds()); @SuppressWarnings("unchecked") PassiveSynchronizationChannel syncChannel = mock(PassiveSynchronizationChannel.class); @@ -942,7 +885,7 @@ public void testReplicationMessageAndOriginalServerStoreOpMessageHasSameConcurre TestInvokeContext context = new TestInvokeContext(); activeEntity.connected(context.getClientDescriptor()); - assertSuccess(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration))); + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); reset(entityMessenger); EhcacheEntityMessage getAndAppend = new ServerStoreOpMessage.GetAndAppendMessage(1L, createPayload(1L)); @@ -977,7 +920,7 @@ public void testActiveTracksMessageDuplication() throws Exception { TestInvokeContext context = new TestInvokeContext(); activeEntity.connected(context.getClientDescriptor()); - assertSuccess(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration))); + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); ServerStoreOpMessage.AppendMessage message = new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L)); activeEntity.invokeActive(context, message); @@ -1001,7 +944,7 @@ public void testActiveMessageTracking() throws Exception { TestInvokeContext context = new TestInvokeContext(); activeEntity.connected(context.getClientDescriptor()); - assertSuccess(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration))); + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); context.incrementCurrentTransactionId(); @@ -1022,7 +965,7 @@ private void prepareAndRunActiveEntityForPassiveSync(BiConsumer succeeds() { + return new TypeSafeMatcher() { + @Override + protected boolean matchesSafely(EhcacheEntityResponse item) { + return EhcacheResponseType.SUCCESS.equals(item.getResponseType()); + } + + @Override + public void describeTo(Description description) { + description.appendText(" a success response"); + } + }; } - private void assertFailure(EhcacheEntityResponse response, Class expectedException) { - assertThat(response.getResponseType(), is(EhcacheResponseType.FAILURE)); - assertThat(((EhcacheEntityResponse.Failure) response).getCause(), is(instanceOf(expectedException))); + private Matcher failsWith(Matcher failure) { + return new TypeSafeMatcher() { + @Override + protected boolean matchesSafely(EhcacheEntityResponse item) { + if (EhcacheResponseType.FAILURE.equals(item.getResponseType())) { + return failure.matches(((EhcacheEntityResponse.Failure) item).getCause()); + } else { + return false; + } + } + + @Override + public void describeTo(Description description) { + description.appendText(" failure caused by ").appendDescriptionOf(failure); + } + }; } - private void assertFailure(EhcacheEntityResponse response, Class expectedException, String expectedMessageContent) { - assertThat(response.getResponseType(), is(EhcacheResponseType.FAILURE)); - Exception cause = ((EhcacheEntityResponse.Failure) response).getCause(); - assertThat(cause, is(instanceOf(expectedException))); - assertThat(cause.getMessage(), containsString(expectedMessageContent)); + private Matcher withMessage(Matcher message) { + return new TypeSafeMatcher() { + @Override + protected boolean matchesSafely(Throwable item) { + return message.matches(item.getMessage()); + } + + @Override + public void describeTo(Description description) { + description.appendText(" throwable with message ").appendDescriptionOf(message); + } + }; } @SuppressWarnings("unchecked") @@ -1212,19 +1183,6 @@ private IEntityMessenger getEntityM return entityMessenger; } - private ClientCommunicator getClientCommunicator() { - return clientCommunicator; - } - - private static Set getIdentifiers(Set pools) { - Set names = new HashSet<>(); - for (OffHeapResourceIdentifier identifier: pools) { - names.add(identifier.getName()); - } - - return Collections.unmodifiableSet(names); - } - @SuppressWarnings("unchecked") @Override public T getService(ServiceConfiguration serviceConfiguration) { From 50fcce08a5d8315798bb6d1037e5841801677483 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 12 Feb 2019 14:24:35 -0500 Subject: [PATCH 099/372] Fixes #2440 : Implement clustered iterator --- .../client/internal/store/ClusteredStore.java | 84 ++++++- .../store/CommonServerStoreProxy.java | 75 +++++++ .../store/EventualServerStoreProxy.java | 6 + .../store/ReconnectingServerStoreProxy.java | 19 +- .../store/SimpleClusterTierClientEntity.java | 6 +- .../store/StrongServerStoreProxy.java | 6 + .../store/lock/LockingServerStoreProxy.java | 6 + .../store/operations/ChainResolver.java | 24 +- .../internal/store/ClusteredStoreTest.java | 142 +++++++++++- .../store/CommonServerStoreProxyTest.java | 99 +++++++++ .../ReconnectingServerStoreProxyTest.java | 9 +- .../operations/AbstractChainResolverTest.java | 206 ++++++++++++++++-- .../operations/ExpiryChainResolverTest.java | 11 +- .../messages/EhcacheEntityResponse.java | 36 +++ .../internal/messages/EhcacheMessageType.java | 8 +- .../messages/EhcacheResponseType.java | 4 +- .../internal/messages/ResponseCodec.java | 31 +++ .../internal/messages/ServerStoreOpCodec.java | 46 ++++ .../messages/ServerStoreOpMessage.java | 61 ++++++ .../common/internal/store/ServerStore.java | 8 + .../internal/messages/ResponseCodecTest.java | 23 ++ .../messages/ServerStoreOpCodecTest.java | 38 ++++ .../clustered/BasicClusteredCacheOpsTest.java | 17 ++ .../IterationFailureBehaviorTest.java | 197 +++++++++++++++++ .../clustered/server/ServerStoreImpl.java | 6 + .../server/offheap/OffHeapChainMap.java | 35 ++- .../server/offheap/OffHeapServerStore.java | 75 +++++++ .../server/store/ClusterTierActiveEntity.java | 85 +++++++- .../store/ClusterTierActiveEntityTest.java | 88 ++++++++ .../server/store/ServerStoreTest.java | 77 ++++++- .../server/store/impl/ReferenceStoreImpl.java | 126 +++-------- 31 files changed, 1503 insertions(+), 151 deletions(-) create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index 42b02d9042..eb09daf760 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -78,6 +78,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.LinkedBlockingQueue; @@ -89,6 +90,7 @@ import java.util.function.Function; import java.util.function.Supplier; +import static java.util.Collections.emptyIterator; import static org.ehcache.core.exceptions.StorePassThroughException.handleException; import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; @@ -433,8 +435,84 @@ public StoreEventSource getStoreEventSource() { @Override public Iterator>> iterator() { - // TODO: Make appropriate ServerStoreProxy call - throw new UnsupportedOperationException("Implement me"); + try { + java.util.Iterator chainIterator = storeProxy.iterator(); + + return new Iterator>>() { + + private java.util.Iterator>> chain = nextChain(); + + @Override + public boolean hasNext() { + return chain.hasNext() || (chain = nextChain()).hasNext(); + } + + @Override + public Cache.Entry> next() { + try { + return chain.next(); + } catch (NoSuchElementException e) { + return (chain = nextChain()).next(); + } + } + + private java.util.Iterator>> nextChain() { + try { + while (true) { + Map> chainContents = resolver.resolveChain(chainIterator.next(), timeSource.getTimeMillis()); + if (!chainContents.isEmpty()) { + return chainContents.entrySet().stream().map(entry -> { + K key = entry.getKey(); + + PutOperation operation = entry.getValue(); + ValueHolder valueHolder; + if (operation.isExpiryAvailable()) { + valueHolder = new ClusteredValueHolder<>(operation.getValue(), operation.expirationTime()); + } else { + valueHolder = new ClusteredValueHolder<>(operation.getValue()); + } + return new Cache.Entry>() { + + @Override + public K getKey() { + return key; + } + + @Override + public ValueHolder getValue() { + return valueHolder; + } + + @Override + public String toString() { + return getKey() + "=" + getValue(); + } + }; + }).iterator(); + } + } + } catch (NoSuchElementException e) { + return emptyIterator(); + } + } + }; + } catch (Exception e) { + return new Iterator>>() { + + private boolean accessed; + + @Override + public boolean hasNext() { + return !accessed; + } + + @Override + public Cache.Entry> next() throws StoreAccessException { + accessed = true; + throw handleException(e); + } + }; + } } @Override @@ -769,7 +847,7 @@ public void onInvalidateAll() { @Override public Chain compact(Chain chain) { - return clusteredStore.resolver.applyOperation(chain, clusteredStore.timeSource.getTimeMillis()); + return clusteredStore.resolver.compactChain(chain, clusteredStore.timeSource.getTimeMillis()); } }; } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java index 6537b70f41..2dcce719c3 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java @@ -20,6 +20,7 @@ import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.ClientInvalidateAll; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.ClientInvalidateHash; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.ServerInvalidateHash; +import org.ehcache.clustered.common.internal.messages.EhcacheOperationMessage; import org.ehcache.clustered.common.internal.messages.EhcacheResponseType; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.AppendMessage; @@ -29,12 +30,16 @@ import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.GetMessage; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.ReplaceAtHeadMessage; import org.ehcache.clustered.common.internal.store.Chain; +import org.ehcache.config.units.MemoryUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; +import java.util.Iterator; +import java.util.UUID; import java.util.concurrent.TimeoutException; +import static java.lang.Math.toIntExact; import static java.util.Objects.requireNonNull; /** @@ -42,6 +47,8 @@ */ class CommonServerStoreProxy implements ServerStoreProxy { + private static final int ITERATOR_BATCH_SIZE = toIntExact(MemoryUnit.KB.toBytes(100)); + private static final Logger LOGGER = LoggerFactory.getLogger(CommonServerStoreProxy.class); private final String cacheId; @@ -177,4 +184,72 @@ public void clear() throws TimeoutException { throw new ServerStoreProxyException(e); } } + + @Override + public Iterator iterator() throws TimeoutException { + EhcacheEntityResponse.IteratorBatch iteratorBatch = openIterator(); + if (iteratorBatch.isLast()) { + return iteratorBatch.getChains().iterator(); + } else { + UUID iteratorId = iteratorBatch.getIdentity(); + return new Iterator() { + + private boolean lastBatch = false; + private Iterator batch = iteratorBatch.getChains().iterator(); + + @Override + public boolean hasNext() { + return !lastBatch || batch.hasNext(); + } + + @Override + public Chain next() { + if (batch.hasNext()) { + return batch.next(); + } else { + try { + EhcacheEntityResponse.IteratorBatch batchResponse = fetchBatch(iteratorId); + batch = batchResponse.getChains().iterator(); + lastBatch = batchResponse.isLast(); + return batch.next(); + } catch (TimeoutException e) { + throw new RuntimeException(e); + } + } + } + + @Override + protected void finalize() throws Throwable { + if (!lastBatch) { + entity.invokeAndWaitForReceive(new ServerStoreOpMessage.IteratorCloseMessage(iteratorId), false); + } + } + }; + } + } + + private EhcacheEntityResponse.IteratorBatch openIterator() throws TimeoutException { + return fetchBatch(new ServerStoreOpMessage.IteratorOpenMessage(ITERATOR_BATCH_SIZE)); + } + + private EhcacheEntityResponse.IteratorBatch fetchBatch(UUID id) throws TimeoutException { + return fetchBatch(new ServerStoreOpMessage.IteratorAdvanceMessage(id, ITERATOR_BATCH_SIZE)); + } + + private EhcacheEntityResponse.IteratorBatch fetchBatch(EhcacheOperationMessage message) throws TimeoutException { + EhcacheEntityResponse response; + try { + response = entity.invokeAndWaitForComplete(message, false); + } catch (TimeoutException e) { + throw e; + } catch (Exception e) { + throw new ServerStoreProxyException(e); + } + if (response != null && response.getResponseType() == EhcacheResponseType.ITERATOR_BATCH) { + return (EhcacheEntityResponse.IteratorBatch) response; + } else { + throw new ServerStoreProxyException("Response for iterator operation was invalid : " + + (response != null ? response.getResponseType() : "null message")); + } + } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java index f9f35ab1f3..4a38399e43 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java @@ -18,6 +18,7 @@ import org.ehcache.clustered.common.internal.store.Chain; import java.nio.ByteBuffer; +import java.util.Iterator; import java.util.concurrent.TimeoutException; public class EventualServerStoreProxy implements ServerStoreProxy { @@ -62,4 +63,9 @@ public void replaceAtHead(long key, Chain expect, Chain update) { public void clear() throws TimeoutException { delegate.clear(); } + + @Override + public Iterator iterator() throws TimeoutException { + return delegate.iterator(); + } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java index f2982de3be..54c1420386 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java @@ -24,6 +24,7 @@ import org.terracotta.exception.ConnectionShutdownException; import java.nio.ByteBuffer; +import java.util.Iterator; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; @@ -95,6 +96,11 @@ public void clear() throws TimeoutException { }); } + @Override + public Iterator iterator() throws TimeoutException { + return onStoreProxy(LockingServerStoreProxy::iterator); + } + private LockingServerStoreProxy proxy() { return delegateRef.get(); } @@ -178,12 +184,17 @@ public void clear() { } @Override - public Chain lock(long hash) throws TimeoutException { + public Iterator iterator() { + throw new ReconnectInProgressException(); + } + + @Override + public Chain lock(long hash) { throw new ReconnectInProgressException(); } @Override - public void unlock(long hash, boolean localonly) throws TimeoutException { + public void unlock(long hash, boolean localonly) { throw new ReconnectInProgressException(); } } @@ -191,12 +202,12 @@ public void unlock(long hash, boolean localonly) throws TimeoutException { private static class UnSupportedLockManager implements LockManager { @Override - public Chain lock(long hash) throws TimeoutException { + public Chain lock(long hash) { throw new UnsupportedOperationException("Lock ops are not supported"); } @Override - public void unlock(long hash, boolean localonly) throws TimeoutException { + public void unlock(long hash, boolean localonly) { throw new UnsupportedOperationException("Lock ops are not supported"); } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java index e166f8d3ab..1ab2e5a4f4 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java @@ -60,7 +60,11 @@ public class SimpleClusterTierClientEntity implements InternalClusterTierClientEntity { private static final Logger LOGGER = LoggerFactory.getLogger(SimpleClusterTierClientEntity.class); - private static final Set GET_STORE_OPS = EnumSet.of(EhcacheMessageType.GET_STORE); + private static final Set GET_STORE_OPS = EnumSet.of( + EhcacheMessageType.GET_STORE, + EhcacheMessageType.ITERATOR_ADVANCE, + EhcacheMessageType.ITERATOR_OPEN, + EhcacheMessageType.ITERATOR_CLOSE); private final EntityClientEndpoint endpoint; private final LifeCycleMessageFactory messageFactory; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java index 0d5c7d1d43..72d838cfea 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java @@ -23,6 +23,7 @@ import java.nio.ByteBuffer; import java.time.Duration; +import java.util.Iterator; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; @@ -226,4 +227,9 @@ public void clear() throws TimeoutException { return null; }, entity.getTimeouts().getWriteOperationTimeout()); } + + @Override + public Iterator iterator() throws TimeoutException { + return delegate.iterator(); + } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java index c65f24f227..3d68efdbfa 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java @@ -19,6 +19,7 @@ import org.ehcache.clustered.common.internal.store.Chain; import java.nio.ByteBuffer; +import java.util.Iterator; import java.util.concurrent.TimeoutException; public class LockingServerStoreProxy implements ServerStoreProxy, LockManager { @@ -75,4 +76,9 @@ public void replaceAtHead(long key, Chain expect, Chain update) { public void clear() throws TimeoutException { storeProxy.clear(); } + + @Override + public Iterator iterator() throws TimeoutException { + return storeProxy.iterator(); + } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java index 42f4c16853..a1bd911646 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java @@ -96,7 +96,22 @@ public ResolvedChain resolve(Chain chain, K key, long now) { * @param now time when the chain is being resolved * @return a compacted chain */ - public Chain applyOperation(Chain chain, long now) { + public Chain compactChain(Chain chain, long now) { + ChainBuilder builder = new ChainBuilder(); + for (PutOperation operation : resolveChain(chain, now).values()) { + builder = builder.add(codec.encode(operation)); + } + return builder.build(); + } + + /** + * Resolves all keys within the given chain. + * + * @param chain a compacted heterogenous {@code Chain} + * @param now time when the chain is being resolved + * @return a compacted chain + */ + public Map> resolveChain(Chain chain, long now) { //absent hash-collisions this should always be a 1 entry map Map> compacted = new HashMap<>(2); for (Element element : chain) { @@ -104,12 +119,7 @@ public Chain applyOperation(Chain chain, long now) { Operation operation = codec.decode(payload); compacted.compute(operation.getKey(), (k, v) -> applyOperation(k, v, operation, now)); } - - ChainBuilder builder = new ChainBuilder(); - for (PutOperation operation : compacted.values()) { - builder = builder.add(codec.encode(operation)); - } - return builder.build(); + return compacted; } /** diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java index 7928b86eb6..be8881520d 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java @@ -16,7 +16,9 @@ package org.ehcache.clustered.client.internal.store; +import com.google.common.base.Objects; import org.assertj.core.api.ThrowableAssert; +import org.ehcache.Cache; import org.ehcache.clustered.client.TestTimeSource; import org.ehcache.clustered.client.config.ClusteredResourcePool; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; @@ -43,6 +45,9 @@ import org.ehcache.impl.serialization.LongSerializer; import org.ehcache.impl.serialization.StringSerializer; import org.ehcache.spi.serialization.Serializer; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -56,8 +61,8 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Properties; -import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Function; @@ -69,6 +74,7 @@ import static org.ehcache.core.spi.store.Store.ValueHolder.NO_EXPIRE; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.core.CombinableMatcher.either; import static org.junit.Assert.*; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.any; @@ -911,4 +917,138 @@ public void testNoExpireIsSentToHigherTiers() throws Exception { long expirationTime = vh.expirationTime(); assertThat(expirationTime, is(NO_EXPIRE)); } + + @Test + public void testEmptyChainIteratorIsEmpty() throws StoreAccessException { + + Store.Iterator>> iterator = store.iterator(); + + assertThat(iterator.hasNext(), is(false)); + try { + iterator.next(); + fail("Expected NoSuchElementException"); + } catch (NoSuchElementException e) { + //expected + } + } + + @Test + public void testSingleChainSingleValue() throws StoreAccessException { + store.put(1L, "foo"); + + Store.Iterator>> iterator = store.iterator(); + + assertThat(iterator.hasNext(), is(true)); + assertThat(iterator.next(), isEntry(1L, "foo")); + assertThat(iterator.hasNext(), is(false)); + try { + iterator.next(); + fail("Expected NoSuchElementException"); + } catch (NoSuchElementException e) { + //expected + } + } + + @Test + public void testSingleChainMultipleValues() throws StoreAccessException { + assertThat(Long.hashCode(1L), is(Long.hashCode(~1L))); + + store.put(1L, "foo"); + store.put(~1L, "bar"); + + Store.Iterator>> iterator = store.iterator(); + + Matcher>> entryOne = isEntry(1L, "foo"); + Matcher>> entryTwo = isEntry(~1L, "bar"); + + assertThat(iterator.hasNext(), is(true)); + + Cache.Entry> next = iterator.next(); + assertThat(next, either(entryOne).or(entryTwo)); + + if (entryOne.matches(next)) { + assertThat(iterator.hasNext(), is(true)); + assertThat(iterator.next(), is(entryTwo)); + assertThat(iterator.hasNext(), is(false)); + } else { + assertThat(iterator.hasNext(), is(true)); + assertThat(iterator.next(), is(entryOne)); + assertThat(iterator.hasNext(), is(false)); + } + + try { + iterator.next(); + fail("Expected NoSuchElementException"); + } catch (NoSuchElementException e) { + //expected + } + } + + @Test + public void testSingleChainRequiresResolution() throws StoreAccessException { + + store.put(~1L, "bar"); + store.put(1L, "foo"); + store.remove(~1L); + + Store.Iterator>> iterator = store.iterator(); + + assertThat(iterator.hasNext(), is(true)); + assertThat(iterator.next(), isEntry(1L, "foo")); + assertThat(iterator.hasNext(), is(false)); + try { + iterator.next(); + fail("Expected NoSuchElementException"); + } catch (NoSuchElementException e) { + //expected + } + } + + @Test + public void testMultipleChains() throws StoreAccessException { + + store.put(1L, "foo"); + store.put(2L, "bar"); + + Store.Iterator>> iterator = store.iterator(); + + Matcher>> entryOne = isEntry(1L, "foo"); + Matcher>> entryTwo = isEntry(2L, "bar"); + + assertThat(iterator.hasNext(), is(true)); + + Cache.Entry> next = iterator.next(); + assertThat(next, either(entryOne).or(entryTwo)); + + if (entryOne.matches(next)) { + assertThat(iterator.hasNext(), is(true)); + assertThat(iterator.next(), is(entryTwo)); + assertThat(iterator.hasNext(), is(false)); + } else { + assertThat(iterator.hasNext(), is(true)); + assertThat(iterator.next(), is(entryOne)); + assertThat(iterator.hasNext(), is(false)); + } + + try { + iterator.next(); + fail("Expected NoSuchElementException"); + } catch (NoSuchElementException e) { + //expected + } + } + + private Matcher>> isEntry(K key, V value) { + return new TypeSafeMatcher>>() { + @Override + public void describeTo(Description description) { + description.appendText(" the cache entry { ").appendValue(key).appendText(": ").appendValue(value).appendText(" }"); + } + + @Override + protected boolean matchesSafely(Cache.Entry> item) { + return Objects.equal(key, item.getKey()) && Objects.equal(value, item.getValue().get()); + } + }; + } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java index 74b02f9d74..b6aad89406 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java @@ -22,15 +22,21 @@ import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.config.units.MemoryUnit; import org.ehcache.impl.serialization.LongSerializer; +import org.hamcrest.CoreMatchers; +import org.hamcrest.Matcher; import org.junit.Test; import java.nio.ByteBuffer; +import java.util.Iterator; +import java.util.NoSuchElementException; import static org.ehcache.clustered.ChainUtils.chainOf; import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.Matchers.hasPayloads; import static org.hamcrest.Matchers.is; +import static org.hamcrest.core.CombinableMatcher.either; import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -173,4 +179,97 @@ public void testResolveRequestIsProcessedAtThreshold() throws Exception { verify(serverCallback).compact(any(Chain.class), any(long.class)); assertThat(serverStoreProxy.get(1L), hasPayloads(42L)); } + + @Test + public void testEmptyStoreIteratorIsEmpty() throws Exception { + ClusterTierClientEntity clientEntity = createClientEntity("testEmptyStoreIteratorIsEmpty"); + CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testEmptyStoreIteratorIsEmpty", clientEntity, mock(ServerCallback.class)); + + Iterator iterator = serverStoreProxy.iterator(); + + assertThat(iterator.hasNext(), is(false)); + try { + iterator.next(); + fail("Expected NoSuchElementException"); + } catch (NoSuchElementException e) { + //expected + } + } + + @Test + public void testSingleChainIterator() throws Exception { + ClusterTierClientEntity clientEntity = createClientEntity("testSingleChainIterator"); + CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testSingleChainIterator", clientEntity, mock(ServerCallback.class)); + + serverStoreProxy.append(1L, createPayload(42L)); + + Iterator iterator = serverStoreProxy.iterator(); + + assertThat(iterator.hasNext(), is(true)); + assertThat(iterator.next(), hasPayloads(42L)); + assertThat(iterator.hasNext(), is(false)); + try { + iterator.next(); + fail("Expected NoSuchElementException"); + } catch (NoSuchElementException e) { + //expected + } + } + + @Test + public void testSingleChainMultipleElements() throws Exception { + ClusterTierClientEntity clientEntity = createClientEntity("testSingleChainMultipleElements"); + CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testSingleChainMultipleElements", clientEntity, mock(ServerCallback.class)); + + serverStoreProxy.append(1L, createPayload(42L)); + serverStoreProxy.append(1L, createPayload(43L)); + + Iterator iterator = serverStoreProxy.iterator(); + + assertThat(iterator.hasNext(), is(true)); + assertThat(iterator.next(), hasPayloads(42L, 43L)); + assertThat(iterator.hasNext(), CoreMatchers.is(false)); + try { + iterator.next(); + fail("Expected NoSuchElementException"); + } catch (NoSuchElementException e) { + //expected + } + } + + @Test + public void testMultipleChains() throws Exception { + ClusterTierClientEntity clientEntity = createClientEntity("testMultipleChains"); + CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testMultipleChains", clientEntity, mock(ServerCallback.class)); + + serverStoreProxy.append(1L, createPayload(42L)); + serverStoreProxy.append(2L, createPayload(43L)); + + Iterator iterator = serverStoreProxy.iterator(); + + Matcher chainOne = hasPayloads(42L); + Matcher chainTwo = hasPayloads(43L); + + assertThat(iterator.hasNext(), CoreMatchers.is(true)); + + Chain next = iterator.next(); + assertThat(next, either(chainOne).or(chainTwo)); + + if (chainOne.matches(next)) { + assertThat(iterator.hasNext(), is(true)); + assertThat(iterator.next(), is(chainTwo)); + assertThat(iterator.hasNext(), is(false)); + } else { + assertThat(iterator.hasNext(), is(true)); + assertThat(iterator.next(), is(chainOne)); + assertThat(iterator.hasNext(), is(false)); + } + + try { + iterator.next(); + fail("Expected NoSuchElementException"); + } catch (NoSuchElementException e) { + //expected + } + } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxyTest.java index 16cfe1768e..5a05b4cbf3 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxyTest.java @@ -76,4 +76,11 @@ public void testGet() throws Exception { serverStoreProxy.get(0); } -} \ No newline at end of file + @Test + public void testIterator() throws Exception { + doThrow(storeProxyException).when(proxy).iterator(); + + exception.expect(ReconnectInProgressException.class); + serverStoreProxy.iterator(); + } +} diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java index 7de6428481..1ecb50a87a 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java @@ -38,10 +38,12 @@ import java.util.Map; import java.util.concurrent.TimeUnit; +import static java.util.Collections.emptyMap; import static org.hamcrest.Matchers.emptyIterable; import static org.hamcrest.Matchers.is; import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; +import static org.hamcrest.collection.IsMapContaining.hasEntry; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; @@ -69,6 +71,7 @@ public void testResolveMaintainsOtherKeysInOrder() { Result result = resolvedChain.getResolvedResult(1L); assertEquals(expected, result); assertThat(resolvedChain.isCompacted(), is(true)); + assertThat(resolvedChain.getCompactionCount(), is(1)); Chain compactedChain = resolvedChain.getCompactedChain(); assertThat(compactedChain, contains( //@SuppressWarnings("unchecked") @@ -87,6 +90,7 @@ public void testResolveEmptyChain() { assertNull(result); assertThat(resolvedChain.isCompacted(), is(false)); + assertThat(resolvedChain.getCompactionCount(), is(0)); } @Test @@ -101,6 +105,7 @@ public void testResolveChainWithNonExistentKey() { Result result = resolvedChain.getResolvedResult(3L); assertNull(result); assertThat(resolvedChain.isCompacted(), is(false)); + assertThat(resolvedChain.getCompactionCount(), is(0)); } @Test @@ -113,6 +118,7 @@ public void testResolveSinglePut() { Result result = resolvedChain.getResolvedResult(1L); assertEquals(expected, result); assertThat(resolvedChain.isCompacted(), is(false)); + assertThat(resolvedChain.getCompactionCount(), is(0)); } @Test @@ -122,7 +128,7 @@ public void testResolvePutsOnly() { Chain chain = getChainFromOperations( new PutOperation<>(1L, "Albin", 0L), new PutOperation<>(1L, "Suresh", 0L), - new PutOperation<>(1L, "Matthew", 0L)); + expected); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); @@ -169,6 +175,7 @@ public void testPutAndRemove() { Result result = resolvedChain.getResolvedResult(1L); assertNull(result); assertThat(resolvedChain.isCompacted(), is(true)); + assertThat(resolvedChain.getCompactionCount(), is(2)); } @Test @@ -181,6 +188,7 @@ public void testResolvePutIfAbsentOnly() { Result result = resolvedChain.getResolvedResult(1L); assertEquals(expected, result); assertThat(resolvedChain.isCompacted(), is(false)); + assertThat(resolvedChain.getCompactionCount(), is(0)); } @Test @@ -196,6 +204,7 @@ public void testResolvePutIfAbsentsOnly() { Result result = resolvedChain.getResolvedResult(1L); assertEquals(expected, result); assertThat(resolvedChain.isCompacted(), is(true)); + assertThat(resolvedChain.getCompactionCount(), is(2)); } @Test @@ -211,6 +220,7 @@ public void testResolvePutIfAbsentSucceeds() { Result result = resolvedChain.getResolvedResult(1L); assertEquals(expected, result); assertThat(resolvedChain.isCompacted(), is(true)); + assertThat(resolvedChain.getCompactionCount(), is(2)); } @Test @@ -295,7 +305,7 @@ public void testCompactingTwoKeys() { ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); + Chain compactedChain = resolver.compactChain(chain, 0L); assertThat(compactedChain, containsInAnyOrder( //@SuppressWarnings("unchecked") operation(new PutOperation<>(2L, "Matthew", 0L)), @@ -307,7 +317,7 @@ public void testCompactingTwoKeys() { public void testCompactEmptyChain() { Chain chain = (new ChainBuilder()).build(); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compacted = resolver.applyOperation(chain, 0L); + Chain compacted = resolver.compactChain(chain, 0L); assertThat(compacted, emptyIterable()); } @@ -318,7 +328,7 @@ public void testCompactSinglePut() { ); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compacted = resolver.applyOperation(chain, 0L); + Chain compacted = resolver.compactChain(chain, 0L); assertThat(compacted, contains(operation(new PutOperation<>(1L, "Albin", 0L)))); } @@ -331,7 +341,7 @@ public void testCompactMultiplePuts() { new PutOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); + Chain compactedChain = resolver.compactChain(chain, 0L); assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Matthew", 0L)))); } @@ -340,7 +350,7 @@ public void testCompactSingleRemove() { Chain chain = getChainFromOperations(new RemoveOperation<>(1L, 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); + Chain compactedChain = resolver.compactChain(chain, 0L); assertThat(compactedChain, emptyIterable()); } @@ -351,7 +361,7 @@ public void testCompactMultipleRemoves() { new RemoveOperation<>(1L, 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); + Chain compactedChain = resolver.compactChain(chain, 0L); assertThat(compactedChain, emptyIterable()); } @@ -362,7 +372,7 @@ public void testCompactPutAndRemove() { new RemoveOperation<>(1L, 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); + Chain compactedChain = resolver.compactChain(chain, 0L); assertThat(compactedChain, emptyIterable()); } @@ -371,7 +381,7 @@ public void testCompactSinglePutIfAbsent() { Chain chain = getChainFromOperations(new PutIfAbsentOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); + Chain compactedChain = resolver.compactChain(chain, 0L); assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Matthew", 0L)))); } @@ -383,7 +393,7 @@ public void testCompactMultiplePutIfAbsents() { new PutIfAbsentOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); + Chain compactedChain = resolver.compactChain(chain, 0L); assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin", 0L)))); } @@ -395,7 +405,7 @@ public void testCompactPutIfAbsentAfterRemove() { new PutIfAbsentOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); + Chain compactedChain = resolver.compactChain(chain, 0L); assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Matthew", 0L)))); } @@ -416,22 +426,22 @@ public void testCompactForMultipleKeysAndOperations() { new PutIfAbsentOperation<>(2L, "Albin", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 0L); + Chain compactedChain = resolver.compactChain(chain, 0L); assertThat(compactedChain, contains(operation(new PutOperation<>(2L, "Albin", 0L)))); } @Test public void testCompactHasCorrectTimeStamp() { Chain chain = getChainFromOperations( - new PutOperation<>(1L, "Albin1", 0), - new PutOperation<>(1L, "Albin2", 1), + new PutOperation<>(1L, "Albin", 0), + new PutOperation<>(1L, "Albin", 1), new RemoveOperation<>(1L, 2), - new PutOperation<>(1L, "Albin3", 3)); + new PutOperation<>(1L, "Albin", 3)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.applyOperation(chain, 3); + Chain compactedChain = resolver.compactChain(chain, 3); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin3", 3)))); + assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin", 3)))); } @Test @@ -445,12 +455,162 @@ public void testCompactDecodesOperationValueOnlyOnDemand() { CountingStringSerializer valueSerializer = new CountingStringSerializer(); OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration(), customCodec); - resolver.applyOperation(chain, 0L); + resolver.compactChain(chain, 0L); - assertThat(keySerializer.decodeCount, is(3)); - assertThat(valueSerializer.decodeCount, is(0)); //Only one decode on creation of the resolved operation - assertThat(valueSerializer.encodeCount, is(0)); //One encode from encoding the resolved operation's key + assertThat(keySerializer.decodeCount, is(3)); //Three decodes: one for each operation assertThat(keySerializer.encodeCount, is(1)); //One encode from encoding the resolved operation's key + + assertThat(valueSerializer.decodeCount, is(0)); + assertThat(valueSerializer.encodeCount, is(0)); + } + + @Test + @SuppressWarnings("unchecked") + public void testResolvingTwoKeys() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L), + new PutOperation<>(2L, "Albin", 0L), + new PutOperation<>(1L, "Suresh", 0L), + new PutOperation<>(2L, "Suresh", 0L), + new PutOperation<>(2L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + + Map> resolved = resolver.resolveChain(chain, 0L); + + assertThat(resolved, hasEntry(2L, new PutOperation<>(2L, "Matthew", 0L))); + assertThat(resolved, hasEntry(1L, new PutOperation<>(1L, "Suresh", 0L))); + } + + @Test + public void testFullResolveEmptyChain() { + Chain chain = (new ChainBuilder()).build(); + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Map> resolved = resolver.resolveChain(chain, 0L); + assertThat(resolved, is(emptyMap())); + } + + @Test + public void testFullResolveSinglePut() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L) + ); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Map> resolved = resolver.resolveChain(chain, 0L); + + assertThat(resolved, hasEntry(1L, new PutOperation<>(1L, "Albin", 0L))); + } + + @Test + public void testFullResolveMultiplePuts() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L), + new PutOperation<>(1L, "Suresh", 0L), + new PutOperation<>(1L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Map> resolved = resolver.resolveChain(chain, 0L); + assertThat(resolved, hasEntry(1L, new PutOperation<>(1L, "Matthew", 0L))); + } + + @Test + public void testFullResolveSingleRemove() { + Chain chain = getChainFromOperations(new RemoveOperation<>(1L, 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Map> resolved = resolver.resolveChain(chain, 0L); + assertThat(resolved, is(emptyMap())); + } + + @Test + public void testFullResolveMultipleRemoves() { + Chain chain = getChainFromOperations( + new RemoveOperation<>(1L, 0L), + new RemoveOperation<>(1L, 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Map> resolved = resolver.resolveChain(chain, 0L); + assertThat(resolved, is(emptyMap())); + } + + @Test + public void testFullResolvePutAndRemove() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L), + new RemoveOperation<>(1L, 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Map> resolved = resolver.resolveChain(chain, 0L); + assertThat(resolved, is(emptyMap())); + } + + @Test + public void testFullResolveSinglePutIfAbsent() { + Chain chain = getChainFromOperations(new PutIfAbsentOperation<>(1L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Map> resolved = resolver.resolveChain(chain, 0L); + assertThat(resolved, hasEntry(1L, new PutOperation<>(1L, "Matthew", 0L))); + } + + @Test + public void testFullResolveMultiplePutIfAbsents() { + Chain chain = getChainFromOperations( + new PutIfAbsentOperation<>(1L, "Albin", 0L), + new PutIfAbsentOperation<>(1L, "Suresh", 0L), + new PutIfAbsentOperation<>(1L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Map> resolved = resolver.resolveChain(chain, 0L); + assertThat(resolved, hasEntry(1L, new PutOperation<>(1L, "Albin", 0L))); + } + + @Test + public void testFullResolvePutIfAbsentAfterRemove() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0L), + new RemoveOperation<>(1L, 0L), + new PutIfAbsentOperation<>(1L, "Matthew", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Map> resolved = resolver.resolveChain(chain, 0L); + assertThat(resolved, hasEntry(1L, new PutOperation<>(1L, "Matthew", 0L))); + } + + @Test + public void testFullResolveForMultipleKeysAndOperations() { + //create a random mix of operations + Chain chain = getChainFromOperations( + new PutIfAbsentOperation<>(1L, "Albin", 0L), + new PutOperation<>(1L, "Suresh", 0L), + new PutOperation<>(1L, "Matthew", 0L), + new PutOperation<>(2L, "Melvin", 0L), + new ReplaceOperation<>(1L, "Joseph", 0L), + new RemoveOperation<>(2L, 0L), + new ConditionalRemoveOperation<>(1L, "Albin", 0L), + new PutOperation<>(1L, "Gregory", 0L), + new ConditionalReplaceOperation<>(1L, "Albin", "Abraham", 0L), + new RemoveOperation<>(1L, 0L), + new PutIfAbsentOperation<>(2L, "Albin", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Map> resolved = resolver.resolveChain(chain, 0L); + assertThat(resolved, hasEntry(2L, new PutOperation<>(2L, "Albin", 0L))); + } + + @Test + public void testFullResolveHasCorrectTimeStamp() { + Chain chain = getChainFromOperations( + new PutOperation<>(1L, "Albin", 0), + new PutOperation<>(1L, "Albin", 1), + new RemoveOperation<>(1L, 2), + new PutOperation<>(1L, "Albin", 3)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + Map> resolved = resolver.resolveChain(chain, 3); + + assertThat(resolved, hasEntry(1L, new PutOperation<>(1L, "Albin", 3))); } @Test @@ -475,6 +635,7 @@ public void testResolveForMultipleOperationHasCorrectIsFirstAndTimeStamp() { assertThat(ex.getMessage(), is("Timestamp not available")); } assertThat(resolvedChain.isCompacted(), is(true)); + assertThat(resolvedChain.getCompactionCount(), is(3)); } @Test @@ -501,6 +662,7 @@ public void testResolveForMultipleOperationHasCorrectIsFirstAndTimeStampWithExpi assertThat(ex.getMessage(), is("Timestamp not available")); } assertThat(resolvedChain.isCompacted(), is(true)); + assertThat(resolvedChain.getCompactionCount(), is(3)); } @Test @@ -513,7 +675,7 @@ public void testCompactHasCorrectWithExpiry() { ); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(1L))); - Chain compactedChain = resolver.applyOperation(chain, 3L); + Chain compactedChain = resolver.compactChain(chain, 3L); assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin4", 3L)))); } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java index db3690c263..c13d4726c5 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java @@ -62,7 +62,7 @@ public void testCompactDecodesOperationValueOnlyOnDemand() { CountingStringSerializer valueSerializer = new CountingStringSerializer(); OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration(), customCodec); - resolver.applyOperation(chain, 0L); + resolver.compactChain(chain, 0L); assertThat(keySerializer.decodeCount, is(3)); assertThat(valueSerializer.decodeCount, is(3)); @@ -185,6 +185,7 @@ public void testGetExpiryForCreationIsInvokedAfterRemoveOperations() { InOrder inOrder = inOrder(expiry); verify(expiry, times(0)).getExpiryForAccess(anyLong(), any()); + inOrder.verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); inOrder.verify(expiry, times(1)).getExpiryForUpdate(anyLong(), any(), anyString()); inOrder.verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); @@ -196,10 +197,10 @@ public void testGetExpiryForCreationIsInvokedAfterRemoveOperations() { Chain chain = getChainFromOperations( - new PutOperation(1L, "One", timeSource.getTimeMillis()), - new PutOperation(1L, "Second", timeSource.getTimeMillis()), - new RemoveOperation(1L, timeSource.getTimeMillis()), - new PutOperation(1L, "Four", timeSource.getTimeMillis()) + new PutOperation<>(1L, "One", timeSource.getTimeMillis()), + new PutOperation<>(1L, "Second", timeSource.getTimeMillis()), + new RemoveOperation<>(1L, timeSource.getTimeMillis()), + new PutOperation<>(1L, "Four", timeSource.getTimeMillis()) ); chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java index 99da5edee5..dc4cb79056 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java @@ -21,7 +21,9 @@ import org.ehcache.clustered.common.internal.store.Chain; import org.terracotta.entity.EntityResponse; +import java.util.List; import java.util.Set; +import java.util.UUID; public abstract class EhcacheEntityResponse implements EntityResponse { @@ -303,4 +305,38 @@ public EhcacheResponseType getResponseType() { return EhcacheResponseType.LOCK_FAILURE; } } + + public static IteratorBatch iteratorBatchResponse(UUID id, List chains, boolean last) { + return new IteratorBatch(id, chains, last); + } + + public static class IteratorBatch extends EhcacheEntityResponse { + + private final UUID id; + private final List chains; + private final boolean last; + + public IteratorBatch(UUID id, List chains, boolean last) { + this.id = id; + this.chains = chains; + this.last = last; + } + + @Override + public EhcacheResponseType getResponseType() { + return EhcacheResponseType.ITERATOR_BATCH; + } + + public boolean isLast() { + return last; + } + + public List getChains() { + return chains; + } + + public UUID getIdentity() { + return id; + } + } } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java index f05d542dc3..c1243b4ef0 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java @@ -44,6 +44,9 @@ public enum EhcacheMessageType { GET_STORE, LOCK, UNLOCK, + ITERATOR_OPEN, + ITERATOR_CLOSE, + ITERATOR_ADVANCE, // StateRepository operation messages GET_STATE_REPO, @@ -71,6 +74,9 @@ public enum EhcacheMessageType { .mapping(GET_STORE, 27) .mapping(LOCK, 28) .mapping(UNLOCK, 29) + .mapping(ITERATOR_OPEN, 30) + .mapping(ITERATOR_CLOSE, 31) + .mapping(ITERATOR_ADVANCE, 32) .mapping(GET_STATE_REPO, 41) .mapping(PUT_IF_ABSENT, 42) @@ -87,7 +93,7 @@ public static boolean isLifecycleMessage(EhcacheMessageType value) { } public static final EnumSet STORE_OPERATION_MESSAGES = of(GET_AND_APPEND, APPEND, - REPLACE, CLIENT_INVALIDATION_ACK, CLIENT_INVALIDATION_ALL_ACK, CLEAR, GET_STORE, LOCK, UNLOCK); + REPLACE, CLIENT_INVALIDATION_ACK, CLIENT_INVALIDATION_ALL_ACK, CLEAR, GET_STORE, LOCK, UNLOCK, ITERATOR_OPEN, ITERATOR_CLOSE, ITERATOR_ADVANCE); public static boolean isStoreOperationMessage(EhcacheMessageType value) { return STORE_OPERATION_MESSAGES.contains(value); } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java index fe4804e3e8..6fa8c80e61 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java @@ -36,7 +36,8 @@ public enum EhcacheResponseType { PREPARE_FOR_DESTROY, RESOLVE_REQUEST, LOCK_SUCCESS, - LOCK_FAILURE; + LOCK_FAILURE, + ITERATOR_BATCH; public static final String RESPONSE_TYPE_FIELD_NAME = "opCode"; @@ -55,5 +56,6 @@ public enum EhcacheResponseType { .mapping(EhcacheResponseType.RESOLVE_REQUEST, 90) .mapping(EhcacheResponseType.LOCK_SUCCESS, 91) .mapping(EhcacheResponseType.LOCK_FAILURE, 92) + .mapping(EhcacheResponseType.ITERATOR_BATCH, 93) .build(); } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java index 2230519a53..bb08715a35 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java @@ -25,13 +25,17 @@ import org.terracotta.runnel.StructBuilder; import org.terracotta.runnel.decoding.ArrayDecoder; import org.terracotta.runnel.decoding.Enm; +import org.terracotta.runnel.decoding.StructArrayDecoder; import org.terracotta.runnel.decoding.StructDecoder; import org.terracotta.runnel.encoding.ArrayEncoder; import org.terracotta.runnel.encoding.StructEncoder; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; +import java.util.UUID; import static java.nio.ByteBuffer.wrap; import static org.ehcache.clustered.common.internal.messages.ChainCodec.CHAIN_STRUCT; @@ -104,6 +108,12 @@ public class ResponseCodec { .enm(RESPONSE_TYPE_FIELD_NAME, RESPONSE_TYPE_FIELD_INDEX, EHCACHE_RESPONSE_TYPES_ENUM_MAPPING) .struct(CHAIN_FIELD, 20, CHAIN_STRUCT) .build(); + private static final Struct ITERATOR_BATCH_STRUCT = newStructBuilder() + .enm(RESPONSE_TYPE_FIELD_NAME, RESPONSE_TYPE_FIELD_INDEX, EHCACHE_RESPONSE_TYPES_ENUM_MAPPING) + .string("id", 20) + .structs("chains", 30, CHAIN_STRUCT) + .bool("last", 40) + .build(); public byte[] encode(EhcacheEntityResponse response) { switch (response.getResponseType()) { @@ -198,6 +208,15 @@ public byte[] encode(EhcacheEntityResponse response) { .enm(RESPONSE_TYPE_FIELD_NAME, lockFailure.getResponseType()) .encode().array(); } + case ITERATOR_BATCH: { + EhcacheEntityResponse.IteratorBatch iteratorBatch = (EhcacheEntityResponse.IteratorBatch) response; + return ITERATOR_BATCH_STRUCT.encoder() + .enm(RESPONSE_TYPE_FIELD_NAME, iteratorBatch.getResponseType()) + .string("id", iteratorBatch.getIdentity().toString()) + .structs("chains", iteratorBatch.getChains(), ChainCodec::encode) + .bool("last", iteratorBatch.isLast()) + .encode().array(); + } default: throw new UnsupportedOperationException("The operation is not supported : " + response.getResponseType()); } @@ -280,6 +299,18 @@ public EhcacheEntityResponse decode(byte[] payload) { case LOCK_FAILURE: { return EhcacheEntityResponse.lockFailure(); } + case ITERATOR_BATCH: { + decoder = ITERATOR_BATCH_STRUCT.decoder(buffer); + UUID id = UUID.fromString(decoder.string("id")); + StructArrayDecoder> chainsDecoder = decoder.structs("chains"); + List chains = new ArrayList<>(chainsDecoder.length()); + while (chainsDecoder.hasNext()) { + chains.add(ChainCodec.decode(chainsDecoder.next())); + } + boolean last = decoder.bool("last"); + return new EhcacheEntityResponse.IteratorBatch(id, chains, last); + } + default: throw new UnsupportedOperationException("The operation is not supported with opCode : " + opCode); } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java index 43c732bd06..6bb3a53242 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java @@ -28,6 +28,7 @@ import org.terracotta.runnel.decoding.StructDecoder; import java.nio.ByteBuffer; +import java.util.UUID; import static org.ehcache.clustered.common.internal.messages.ChainCodec.CHAIN_STRUCT; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.EHCACHE_MESSAGE_TYPES_ENUM_MAPPING; @@ -83,6 +84,22 @@ public class ServerStoreOpCodec { .int64("hash", 30) .build(); + private static final Struct ITERATOR_OPEN_STRUCT = newStructBuilder() + .enm(MESSAGE_TYPE_FIELD_NAME, MESSAGE_TYPE_FIELD_INDEX, EHCACHE_MESSAGE_TYPES_ENUM_MAPPING) + .int32("batchSize", 20) + .build(); + + private static final Struct ITERATOR_CLOSE_STRUCT = newStructBuilder() + .enm(MESSAGE_TYPE_FIELD_NAME, MESSAGE_TYPE_FIELD_INDEX, EHCACHE_MESSAGE_TYPES_ENUM_MAPPING) + .string("id", 20) + .build(); + + private static final Struct ITERATOR_ADVANCE_STRUCT = newStructBuilder() + .enm(MESSAGE_TYPE_FIELD_NAME, MESSAGE_TYPE_FIELD_INDEX, EHCACHE_MESSAGE_TYPES_ENUM_MAPPING) + .string("id", 20) + .int32("batchSize", 30) + .build(); + public byte[] encode(ServerStoreOpMessage message) { switch (message.getMessageType()) { case GET_STORE: @@ -133,6 +150,19 @@ public byte[] encode(ServerStoreOpMessage message) { return encodeMandatoryFields(LOCK_STRUCT, message) .int64("hash", unlockMessage.getHash()) .encode().array(); + case ITERATOR_OPEN: + return encodeMandatoryFields(ITERATOR_OPEN_STRUCT, message) + .int32("batchSize", ((ServerStoreOpMessage.IteratorOpenMessage) message).getBatchSize()) + .encode().array(); + case ITERATOR_CLOSE: + return encodeMandatoryFields(ITERATOR_CLOSE_STRUCT, message) + .string("id", ((ServerStoreOpMessage.IteratorCloseMessage) message).getIdentity().toString()) + .encode().array(); + case ITERATOR_ADVANCE: + return encodeMandatoryFields(ITERATOR_ADVANCE_STRUCT, message) + .string("id", ((ServerStoreOpMessage.IteratorAdvanceMessage) message).getIdentity().toString()) + .int32("batchSize", ((ServerStoreOpMessage.IteratorAdvanceMessage) message).getBatchSize()) + .encode().array(); default: throw new RuntimeException("Unhandled message operation : " + message.getMessageType()); } @@ -188,6 +218,22 @@ public EhcacheEntityMessage decode(EhcacheMessageType opCode, ByteBuffer message long hash = decoder.int64("hash"); return new ServerStoreOpMessage.UnlockMessage(hash); } + case ITERATOR_OPEN: { + StructDecoder decoder = ITERATOR_OPEN_STRUCT.decoder(messageBuffer); + int batchSize = decoder.int32("batchSize"); + return new ServerStoreOpMessage.IteratorOpenMessage(batchSize); + } + case ITERATOR_CLOSE: { + StructDecoder decoder = ITERATOR_CLOSE_STRUCT.decoder(messageBuffer); + UUID identity = UUID.fromString(decoder.string("id")); + return new ServerStoreOpMessage.IteratorCloseMessage(identity); + } + case ITERATOR_ADVANCE: { + StructDecoder decoder = ITERATOR_ADVANCE_STRUCT.decoder(messageBuffer); + UUID identity = UUID.fromString(decoder.string("id")); + int batchSize = decoder.int32("batchSize"); + return new ServerStoreOpMessage.IteratorAdvanceMessage(identity, batchSize); + } default: throw new RuntimeException("Unhandled message operation : " + opCode); } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessage.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessage.java index 50c52a8f20..9096a59aa6 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessage.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessage.java @@ -19,6 +19,7 @@ import org.ehcache.clustered.common.internal.store.Chain; import java.nio.ByteBuffer; +import java.util.UUID; public abstract class ServerStoreOpMessage extends EhcacheOperationMessage { @@ -202,5 +203,65 @@ public EhcacheMessageType getMessageType() { } } + public static class IteratorOpenMessage extends ServerStoreOpMessage { + + private final int batchSize; + + public IteratorOpenMessage(int batchSize) { + this.batchSize = batchSize; + } + + public int getBatchSize() { + return batchSize; + } + + @Override + public EhcacheMessageType getMessageType() { + return EhcacheMessageType.ITERATOR_OPEN; + } + } + + public static class IteratorCloseMessage extends ServerStoreOpMessage { + + private final UUID id; + + public IteratorCloseMessage(UUID id) { + this.id = id; + } + + public UUID getIdentity() { + return id; + } + + @Override + public EhcacheMessageType getMessageType() { + return EhcacheMessageType.ITERATOR_CLOSE; + } + } + + public static class IteratorAdvanceMessage extends ServerStoreOpMessage { + + private final UUID id; + private final int batchSize; + + public IteratorAdvanceMessage(UUID id, int batchSize) { + this.id = id; + this.batchSize = batchSize; + + } + + public UUID getIdentity() { + return id; + } + + public int getBatchSize() { + return batchSize; + } + + @Override + public EhcacheMessageType getMessageType() { + return EhcacheMessageType.ITERATOR_ADVANCE; + } + } } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java index e59bea92ac..5e232bca9a 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java @@ -17,6 +17,7 @@ package org.ehcache.clustered.common.internal.store; import java.nio.ByteBuffer; +import java.util.Iterator; import java.util.concurrent.TimeoutException; /** @@ -128,4 +129,11 @@ public interface ServerStore { * @throws TimeoutException if the get exceeds the timeout configured for write operations */ void clear() throws TimeoutException; + + /** + * Returns an iterator over the chains. + * + * @return an chain iterator. + */ + Iterator iterator() throws TimeoutException; } diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java index 31079a2d24..4cf537c017 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java @@ -22,11 +22,15 @@ import org.junit.Test; import java.util.HashSet; +import java.util.List; import java.util.Set; +import java.util.UUID; import static org.ehcache.clustered.ChainUtils.chainOf; import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.Matchers.hasPayloads; +import static java.util.Arrays.asList; +import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.allInvalidationDone; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.clientInvalidateAll; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.clientInvalidateHash; @@ -178,4 +182,23 @@ public void testLockResponse() { assertThat(failureDecoded.getResponseType(), is(EhcacheResponseType.LOCK_FAILURE)); } + + @Test + public void testIteratorBatchResponse() { + UUID uuid = UUID.randomUUID(); + List chains = asList( + chainOf(createPayload(1L), createPayload(10L)), + chainOf(createPayload(2L), createPayload(20L)) + ); + EhcacheEntityResponse.IteratorBatch iteratorBatch = new EhcacheEntityResponse.IteratorBatch(uuid, chains, true); + + byte[] encoded = RESPONSE_CODEC.encode(iteratorBatch); + EhcacheEntityResponse.IteratorBatch batchDecoded = (EhcacheEntityResponse.IteratorBatch) RESPONSE_CODEC.decode(encoded); + + assertThat(batchDecoded.getResponseType(), is(EhcacheResponseType.ITERATOR_BATCH)); + assertThat(batchDecoded.getIdentity(), is(uuid)); + assertThat(batchDecoded.getChains().get(0), hasPayloads(1L, 10L)); + assertThat(batchDecoded.getChains().get(1), hasPayloads(2L, 20L)); + assertThat(batchDecoded.isLast(), is(true)); + } } diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java index 4a788f2322..29e36e9bc6 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java @@ -18,6 +18,8 @@ import org.junit.Test; +import java.util.UUID; + import static java.nio.ByteBuffer.wrap; import static org.ehcache.clustered.ChainUtils.chainOf; import static org.ehcache.clustered.ChainUtils.createPayload; @@ -135,4 +137,40 @@ public void testUnlockMessage() throws Exception { assertThat(decodedLockMessage.getMessageType(), is(EhcacheMessageType.UNLOCK)); } + @Test + public void testIteratorOpenMessage() { + ServerStoreOpMessage iteratorOpenMessage = new ServerStoreOpMessage.IteratorOpenMessage(42); + + byte[] encoded = STORE_OP_CODEC.encode(iteratorOpenMessage); + ServerStoreOpMessage.IteratorOpenMessage decoded = (ServerStoreOpMessage.IteratorOpenMessage) STORE_OP_CODEC.decode(iteratorOpenMessage.getMessageType(), wrap(encoded)); + + assertThat(decoded.getMessageType(), is(EhcacheMessageType.ITERATOR_OPEN)); + assertThat(decoded.getBatchSize(), is(42)); + } + + @Test + public void testIteratorCloseMessage() { + UUID uuid = UUID.randomUUID(); + ServerStoreOpMessage iteratorCloseMessage = new ServerStoreOpMessage.IteratorCloseMessage(uuid); + + byte[] encoded = STORE_OP_CODEC.encode(iteratorCloseMessage); + ServerStoreOpMessage.IteratorCloseMessage decoded = (ServerStoreOpMessage.IteratorCloseMessage) STORE_OP_CODEC.decode(iteratorCloseMessage.getMessageType(), wrap(encoded)); + + assertThat(decoded.getMessageType(), is(EhcacheMessageType.ITERATOR_CLOSE)); + assertThat(decoded.getIdentity(), is(uuid)); + } + + @Test + public void testIteratorAdvanceMessage() { + UUID uuid = UUID.randomUUID(); + ServerStoreOpMessage iteratorAdvanceMessage = new ServerStoreOpMessage.IteratorAdvanceMessage(uuid, 42); + + byte[] encoded = STORE_OP_CODEC.encode(iteratorAdvanceMessage); + ServerStoreOpMessage.IteratorAdvanceMessage decoded = (ServerStoreOpMessage.IteratorAdvanceMessage) STORE_OP_CODEC.decode(iteratorAdvanceMessage.getMessageType(), wrap(encoded)); + + assertThat(decoded.getMessageType(), is(EhcacheMessageType.ITERATOR_ADVANCE)); + assertThat(decoded.getIdentity(), is(uuid)); + assertThat(decoded.getBatchSize(), is(42)); + } + } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java index b21174d0ea..bff2b8cda4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java @@ -28,6 +28,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; +import org.hamcrest.collection.IsIterableWithSize; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -37,6 +38,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -44,8 +46,10 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.collection.IsIterableWithSize.iterableWithSize; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; @@ -160,6 +164,19 @@ public void basicClusteredBulk() throws Exception { assertThat(all.get(2L), is("two")); assertThat(all.get(3L), is("three")); + Map entries1 = new HashMap<>(); + assertThat(cache1, iterableWithSize(3)); + cache1.forEach(e -> entries1.putIfAbsent(e.getKey(), e.getValue())); + assertThat(entries1, hasEntry(1L, "one")); + assertThat(entries1, hasEntry(2L, "two")); + assertThat(entries1, hasEntry(3L, "three")); + + Map entries2 = new HashMap<>(); + assertThat(cache2, iterableWithSize(3)); + cache2.forEach(e -> entries2.putIfAbsent(e.getKey(), e.getValue())); + assertThat(entries2, hasEntry(1L, "one")); + assertThat(entries2, hasEntry(2L, "two")); + assertThat(entries2, hasEntry(3L, "three")); cache2.removeAll(keySet); all = cache1.getAll(keySet); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java new file mode 100644 index 0000000000..5bba702ccf --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java @@ -0,0 +1,197 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered; + +import org.ehcache.Cache; +import org.ehcache.CacheIterationException; +import org.ehcache.PersistentCacheManager; +import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; +import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; +import org.ehcache.clustered.client.internal.store.ServerStoreProxyException; +import org.ehcache.config.CacheConfiguration; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.config.units.MemoryUnit; +import org.ehcache.spi.resilience.StoreAccessException; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.terracotta.exception.ConnectionClosedException; +import org.terracotta.testing.rules.Cluster; + +import java.io.File; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.toMap; +import static java.util.stream.LongStream.range; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + +public class IterationFailureBehaviorTest extends ClusteredTests { + + private static final int KEYS = 100; + + private static final String RESOURCE_CONFIG = + "" + + "" + + "64" + + "" + + "" + + "" + + "" + + "5" + + "" + + ""; + + @ClassRule + public static Cluster CLUSTER = + newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + + @BeforeClass + public static void waitForActive() throws Exception { + CLUSTER.getClusterControl().startAllServers(); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); + } + + @Test + public void testIteratorFailover() throws Exception { + final CacheManagerBuilder clusteredCacheManagerBuilder + = CacheManagerBuilder.newCacheManagerBuilder() + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/iterator-cm")) + .autoCreate() + .defaultServerResource("primary-server-resource")); + final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); + cacheManager.init(); + + try { + CacheConfiguration smallConfig = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, + ResourcePoolsBuilder.newResourcePoolsBuilder() + .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB))).build(); + + Cache smallCache = cacheManager.createCache("small-cache", smallConfig); + range(0, KEYS).forEach(k -> smallCache.put(k, Long.toString(k))); + + CacheConfiguration largeConfig = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, byte[].class, + ResourcePoolsBuilder.newResourcePoolsBuilder() + .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 4, MemoryUnit.MB))).build(); + + Cache largeCache = cacheManager.createCache("large-cache", largeConfig); + byte[] value = new byte[10 * 1024]; + range(0, KEYS).forEach(k -> { + largeCache.put(k, value); + }); + + Map smallMap = new HashMap<>(); + + Iterator> smallIterator = smallCache.iterator(); + Cache.Entry smallNext = smallIterator.next(); + smallMap.put(smallNext.getKey(), smallNext.getValue()); + + Iterator> largeIterator = largeCache.iterator(); + Cache.Entry largeNext = largeIterator.next(); + assertThat(largeCache.get(largeNext.getKey()), notNullValue()); + + CLUSTER.getClusterControl().terminateActive(); + + //large iterator fails + try { + largeIterator.forEachRemaining(k -> {}); + fail("Expected CacheIterationException"); + } catch (CacheIterationException e) { + assertThat(e.getCause(), instanceOf(StoreAccessException.class)); + assertThat(e.getCause().getCause(), instanceOf(ServerStoreProxyException.class)); + assertThat(e.getCause().getCause().getCause(), instanceOf(ConnectionClosedException.class)); + } + + //small iterator completes... it fetched the entire batch in one shot + smallIterator.forEachRemaining(k -> smallMap.put(k.getKey(), k.getValue())); + + assertThat(smallMap, is(range(0, KEYS).boxed().collect(toMap(identity(), k -> Long.toString(k))))); + } finally { + cacheManager.close(); + } + } + + @Test + public void testIteratorReconnect() throws Exception { + final CacheManagerBuilder clusteredCacheManagerBuilder + = CacheManagerBuilder.newCacheManagerBuilder() + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/iterator-cm")) + .autoCreate() + .defaultServerResource("primary-server-resource")); + final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); + cacheManager.init(); + + try { + CacheConfiguration smallConfig = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, + ResourcePoolsBuilder.newResourcePoolsBuilder() + .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB))).build(); + + Cache smallCache = cacheManager.createCache("small-cache", smallConfig); + range(0, KEYS).forEach(k -> smallCache.put(k, Long.toString(k))); + + CacheConfiguration largeConfig = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, byte[].class, + ResourcePoolsBuilder.newResourcePoolsBuilder() + .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 4, MemoryUnit.MB))).build(); + + Cache largeCache = cacheManager.createCache("large-cache", largeConfig); + byte[] value = new byte[10 * 1024]; + range(0, KEYS).forEach(k -> { + largeCache.put(k, value); + }); + + Map smallMap = new HashMap<>(); + + Iterator> smallIterator = smallCache.iterator(); + Cache.Entry smallNext = smallIterator.next(); + smallMap.put(smallNext.getKey(), smallNext.getValue()); + + Iterator> largeIterator = largeCache.iterator(); + Cache.Entry largeNext = largeIterator.next(); + assertThat(largeCache.get(largeNext.getKey()), notNullValue()); + + CLUSTER.getClusterControl().terminateAllServers(); + Thread.sleep(10000); + CLUSTER.getClusterControl().startAllServers(); + CLUSTER.getClusterControl().waitForActive(); + + //large iterator fails + try { + largeIterator.forEachRemaining(k -> {}); + fail("Expected CacheIterationException"); + } catch (CacheIterationException e) { + assertThat(e.getCause(), instanceOf(StoreAccessException.class)); + assertThat(e.getCause().getCause(), instanceOf(ServerStoreProxyException.class)); + assertThat(e.getCause().getCause().getCause(), instanceOf(ConnectionClosedException.class)); + } + + //small iterator completes... it fetched the entire batch in one shot + smallIterator.forEachRemaining(k -> smallMap.put(k.getKey(), k.getValue())); + + assertThat(smallMap, is(range(0, KEYS).boxed().collect(toMap(identity(), k -> Long.toString(k))))); + } finally { + cacheManager.close(); + } + } +} diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java b/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java index 72bee490e2..1a2131436a 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java @@ -28,6 +28,7 @@ import java.nio.ByteBuffer; import java.util.AbstractList; +import java.util.Iterator; import java.util.List; import java.util.Set; @@ -198,4 +199,9 @@ private void checkPayLoadSize(ByteBuffer payLoad) { ") bigger than pool size (" + pageSource.getPool().getSize() + ")"); } } + + @Override + public Iterator iterator() { + return store.iterator(); + } } diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java index 86b79b15bf..ec792c55cf 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java @@ -17,6 +17,7 @@ import java.nio.ByteBuffer; import java.util.Collections; +import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.concurrent.locks.Lock; @@ -34,7 +35,7 @@ import static org.ehcache.clustered.common.internal.util.ChainBuilder.chainFromList; -public class OffHeapChainMap implements MapInternals { +public class OffHeapChainMap implements MapInternals, Iterable { interface ChainMapEvictionListener { void onEviction(K key); @@ -239,6 +240,38 @@ public Set keySet() { } } + @Override + public Iterator iterator() { + Iterator> headsIterator = heads.entrySet().iterator(); + + return new Iterator() { + @Override + public boolean hasNext() { + return headsIterator.hasNext(); + } + + @Override + public Chain next() { + final Lock lock = heads.readLock(); + lock.lock(); + try { + InternalChain chain = headsIterator.next().getValue(); + if (chain == null) { + return EMPTY_CHAIN; + } else { + try { + return chain.detach(); + } finally { + chain.close(); + } + } + } finally { + lock.unlock(); + } + } + }; + } + private void evict() { int evictionIndex = heads.getEvictionIndex(); if (evictionIndex < 0) { diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java index 3547c6137a..c4cb03b056 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java @@ -17,7 +17,9 @@ import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; +import java.util.NoSuchElementException; import java.util.function.LongConsumer; import java.util.function.LongFunction; @@ -337,4 +339,77 @@ public long getDataVitalMemory() { return total; } + @Override + public Iterator iterator() { + return new AggregateIterator() { + @Override + protected Iterator getNextIterator() { + return listIterator.next().iterator(); + } + }; + } + + + protected abstract class AggregateIterator implements Iterator { + + protected final Iterator> listIterator; + protected Iterator currentIterator; + + protected abstract Iterator getNextIterator(); + + public AggregateIterator() { + listIterator = segments.iterator(); + while (listIterator.hasNext()) { + currentIterator = getNextIterator(); + if (currentIterator.hasNext()) { + return; + } + } + } + + @Override + public boolean hasNext() { + if (currentIterator == null) { + return false; + } + + if (currentIterator.hasNext()) { + return true; + } else { + while (listIterator.hasNext()) { + currentIterator = getNextIterator(); + if (currentIterator.hasNext()) { + return true; + } + } + return false; + } + } + + @Override + public T next() { + if (currentIterator == null) { + throw new NoSuchElementException(); + } + + if (currentIterator.hasNext()) { + return currentIterator.next(); + } else { + while (listIterator.hasNext()) { + currentIterator = getNextIterator(); + + if (currentIterator.hasNext()) { + return currentIterator.next(); + } + } + } + + throw new NoSuchElementException(); + } + + @Override + public void remove() { + currentIterator.remove(); + } + } } diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java b/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java index d62d74df62..860e00fe7e 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java @@ -35,6 +35,9 @@ import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.ClientInvalidationAck; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.ClientInvalidationAllAck; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.GetMessage; +import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.IteratorAdvanceMessage; +import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.IteratorCloseMessage; +import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.IteratorOpenMessage; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.KeyBasedServerStoreOpMessage; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.LockMessage; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.ReplaceAtHeadMessage; @@ -78,12 +81,14 @@ import org.terracotta.entity.StateDumpCollector; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; @@ -98,6 +103,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import static java.util.Collections.emptyMap; import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toSet; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.allInvalidationDone; @@ -106,6 +112,7 @@ import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.failure; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.getResponse; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.hashInvalidationDone; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.iteratorBatchResponse; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.lockFailure; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.lockSuccess; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.resolveRequest; @@ -154,6 +161,7 @@ public class ClusterTierActiveEntity implements ActiveServerEntity inflightInvalidations; private final Map connectedClients = new ConcurrentHashMap<>(); + private final Map>> liveIterators = new ConcurrentHashMap<>(); private final int chainCompactionLimit; private final ServerLockManager lockManager; @@ -273,6 +281,8 @@ public void disconnected(ClientDescriptor clientDescriptor) { lockManager.sweepLocksForClient(clientDescriptor, configuration.isWriteBehindConfigured() ? null : heldKeys -> heldKeys.forEach(stateService.getStore(storeIdentifier)::remove)); + liveIterators.remove(clientDescriptor); + connectedClients.remove(clientDescriptor); } @@ -372,7 +382,7 @@ private EhcacheEntityResponse invokeServerStoreOperation(InvokeContext context, try { return getResponse(cacheStore.get(getMessage.getKey())); } catch (TimeoutException e) { - throw new AssertionError("Server side store is not expected to throw timeout exception"); + throw new AssertionError("Server side store is not expected to throw timeout exception", e); } } case APPEND: { @@ -389,7 +399,7 @@ private EhcacheEntityResponse invokeServerStoreOperation(InvokeContext context, cacheStore.append(key, appendMessage.getPayload()); newChain = cacheStore.get(key); } catch (TimeoutException e) { - throw new AssertionError("Server side store is not expected to throw timeout exception"); + throw new AssertionError("Server side store is not expected to throw timeout exception", e); } sendMessageToSelfAndDeferRetirement(activeInvokeContext, appendMessage, newChain); invalidateHashForClient(clientDescriptor, key); @@ -416,7 +426,7 @@ private EhcacheEntityResponse invokeServerStoreOperation(InvokeContext context, result = cacheStore.getAndAppend(getAndAppendMessage.getKey(), getAndAppendMessage.getPayload()); newChain = cacheStore.get(getAndAppendMessage.getKey()); } catch (TimeoutException e) { - throw new AssertionError("Server side store is not expected to throw timeout exception"); + throw new AssertionError("Server side store is not expected to throw timeout exception", e); } sendMessageToSelfAndDeferRetirement(activeInvokeContext, getAndAppendMessage, newChain); LOGGER.debug("Send invalidations for key {}", getAndAppendMessage.getKey()); @@ -447,7 +457,7 @@ private EhcacheEntityResponse invokeServerStoreOperation(InvokeContext context, try { cacheStore.clear(); } catch (TimeoutException e) { - throw new AssertionError("Server side store is not expected to throw timeout exception"); + throw new AssertionError("Server side store is not expected to throw timeout exception", e); } InvalidationTracker invalidationTracker = stateService.getInvalidationTracker(storeIdentifier); @@ -464,7 +474,7 @@ private EhcacheEntityResponse invokeServerStoreOperation(InvokeContext context, Chain chain = cacheStore.get(lockMessage.getHash()); return lockSuccess(chain); } catch (TimeoutException e) { - throw new AssertionError("Server side store is not expected to throw timeout exception"); + throw new AssertionError("Server side store is not expected to throw timeout exception", e); } } else { return lockFailure(); @@ -475,11 +485,76 @@ private EhcacheEntityResponse invokeServerStoreOperation(InvokeContext context, lockManager.unlock(unlockMessage.getHash()); return success(); } + case ITERATOR_OPEN: { + IteratorOpenMessage iteratorOpenMessage = (IteratorOpenMessage) message; + try { + Iterator iterator = cacheStore.iterator(); + List batch = iteratorBatch(iterator, iteratorOpenMessage.getBatchSize()); + + if (iterator.hasNext()) { + Map> liveIterators = this.liveIterators.computeIfAbsent(clientDescriptor, client -> new ConcurrentHashMap<>()); + UUID id; + do { + id = UUID.randomUUID(); + } while (liveIterators.putIfAbsent(id, iterator) != null); + return iteratorBatchResponse(id, batch, false); + } else { + return iteratorBatchResponse(UUID.randomUUID(), batch, true); + } + } catch (TimeoutException e) { + throw new AssertionError("Server side store is not expected to throw timeout exception", e); + } + } + case ITERATOR_CLOSE: { + IteratorCloseMessage iteratorCloseMessage = (IteratorCloseMessage) message; + liveIterators.computeIfPresent(clientDescriptor, (client, iterators) -> { + iterators.remove(iteratorCloseMessage.getIdentity()); + if (iterators.isEmpty()) { + return null; + } else { + return iterators; + } + }); + return success(); + } + case ITERATOR_ADVANCE: { + IteratorAdvanceMessage iteratorAdvanceMessage = (IteratorAdvanceMessage) message; + UUID id = iteratorAdvanceMessage.getIdentity(); + + Iterator iterator = liveIterators.getOrDefault(clientDescriptor, emptyMap()).get(id); + if (iterator == null) { + return failure(new InvalidOperationException("Referenced iterator is already closed (or never existed)")); + } else { + List batch = iteratorBatch(iterator, iteratorAdvanceMessage.getBatchSize()); + if (iterator.hasNext()) { + return iteratorBatchResponse(id, batch, false); + } else { + liveIterators.computeIfPresent(clientDescriptor, (client, iterators) -> { + iterators.remove(id); + return iterators.isEmpty() ? null : iterators; + }); + return iteratorBatchResponse(id, batch, true); + } + } + } default: throw new AssertionError("Unsupported ServerStore operation : " + message); } } + private List iteratorBatch(Iterator iterator, int batchSize) { + List chains = new ArrayList<>(); + int size = 0; + while (iterator.hasNext() && size < batchSize && size >= 0) { + Chain nextChain = iterator.next(); + chains.add(nextChain); + for (Element e: nextChain) { + size += e.getPayload().remaining(); + } + } + return chains; + } + private void invalidateAll(ClientDescriptor originatingClientDescriptor) { int invalidationId = invalidationIdGenerator.getAndIncrement(); Set clientsToInvalidate = new HashSet<>(getValidatedClients()); diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index a62354e4ec..4090cd5e84 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -958,6 +958,94 @@ public void testActiveMessageTracking() throws Exception { assertThat(actual, sameInstance(expected)); } + @Test @SuppressWarnings("unchecked") + public void testShortIterationIsNotTracked() throws Exception { + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + EhcacheStateServiceImpl ehcacheStateService = defaultRegistry.getStoreManagerService(); + ehcacheStateService.createStore(defaultStoreName, defaultStoreConfiguration, false); //hack to enable message tracking on active + + TestInvokeContext context = new TestInvokeContext(); + activeEntity.connected(context.getClientDescriptor()); + + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + + activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))); + activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(2L))); + activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(2L, createPayload(3L))); + activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(2L, createPayload(4L))); + + EhcacheEntityResponse.IteratorBatch iteratorBatch = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorOpenMessage(Integer.MAX_VALUE)); + + assertThat(iteratorBatch.isLast(), is(true)); + assertThat(iteratorBatch.getChains(), containsInAnyOrder(hasPayloads(1L, 2L), hasPayloads(3L, 4L))); + + assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorAdvanceMessage(iteratorBatch.getIdentity(), Integer.MAX_VALUE)), failsWith(instanceOf(InvalidOperationException.class))); + } + + @Test + public void testLongIteration() throws Exception { + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + EhcacheStateServiceImpl ehcacheStateService = defaultRegistry.getStoreManagerService(); + ehcacheStateService.createStore(defaultStoreName, defaultStoreConfiguration, false); //hack to enable message tracking on active + + TestInvokeContext context = new TestInvokeContext(); + activeEntity.connected(context.getClientDescriptor()); + + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + + activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))); + activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(2L))); + activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(2L, createPayload(3L))); + activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(2L, createPayload(4L))); + + EhcacheEntityResponse.IteratorBatch batchOne = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorOpenMessage(1)); + + Matcher chainOne = hasPayloads(1L, 2L); + Matcher chainTwo = hasPayloads(3L, 4L); + + assertThat(batchOne.isLast(), is(false)); + assertThat(batchOne.getChains(), either(contains(chainOne)).or(contains(chainTwo))); + + EhcacheEntityResponse.IteratorBatch batchTwo = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorAdvanceMessage(batchOne.getIdentity(), Integer.MAX_VALUE)); + assertThat(batchTwo.isLast(), is(true)); + if (contains(chainOne).matches(batchOne.getChains())) { + assertThat(batchTwo.getChains(), contains(chainTwo)); + } else { + assertThat(batchTwo.getChains(), contains(chainOne)); + } + + assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorAdvanceMessage(batchOne.getIdentity(), Integer.MAX_VALUE)), failsWith(instanceOf(InvalidOperationException.class))); + } + + @Test + public void testExplicitIteratorClose() throws Exception { + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + EhcacheStateServiceImpl ehcacheStateService = defaultRegistry.getStoreManagerService(); + ehcacheStateService.createStore(defaultStoreName, defaultStoreConfiguration, false); //hack to enable message tracking on active + + TestInvokeContext context = new TestInvokeContext(); + activeEntity.connected(context.getClientDescriptor()); + + assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + + activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))); + activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(2L))); + activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(2L, createPayload(3L))); + activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(2L, createPayload(4L))); + + EhcacheEntityResponse.IteratorBatch batchOne = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorOpenMessage(1)); + + Matcher chainOne = hasPayloads(1L, 2L); + Matcher chainTwo = hasPayloads(3L, 4L); + + assertThat(batchOne.isLast(), is(false)); + assertThat(batchOne.getChains(), either(contains(chainOne)).or(contains(chainTwo))); + + assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorCloseMessage(batchOne.getIdentity())), succeeds()); + + assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorAdvanceMessage(batchOne.getIdentity(), Integer.MAX_VALUE)), failsWith(instanceOf(InvalidOperationException.class))); + } + private void prepareAndRunActiveEntityForPassiveSync(BiConsumer testConsumer) throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java index 550c4daca3..be1f6da111 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java @@ -19,17 +19,26 @@ import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.Element; import org.ehcache.clustered.common.internal.store.ServerStore; -import org.hamcrest.MatcherAssert; import org.hamcrest.core.Is; import org.junit.Test; import java.nio.ByteBuffer; +import java.util.HashSet; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.concurrent.TimeoutException; import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.ChainUtils.readPayload; import static org.ehcache.clustered.Matchers.hasPayloads; +import static java.util.stream.LongStream.range; +import static org.hamcrest.core.IsCollectionContaining.hasItem; +import static org.hamcrest.core.IsCollectionContaining.hasItems; +import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertThat; -import static org.hamcrest.Matchers.is; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.fail; /** * Verify Server Store @@ -183,7 +192,7 @@ public void test_append_doesNotConsumeBuffer() throws Exception { ByteBuffer payload = createPayload(1L); store.append(1L, payload); - MatcherAssert.assertThat(payload.remaining(), Is.is(8)); + assertThat(payload.remaining(), Is.is(8)); } @Test @@ -192,7 +201,7 @@ public void test_getAndAppend_doesNotConsumeBuffer() throws Exception { ByteBuffer payload = createPayload(1L); store.getAndAppend(1L, payload); - MatcherAssert.assertThat(payload.remaining(), Is.is(8)); + assertThat(payload.remaining(), Is.is(8)); } @Test @@ -205,4 +214,64 @@ public void test_replaceAtHead_doesNotConsumeBuffer() { store.replaceAtHead(1L, expected, update); assertThat(payload.remaining(), Is.is(8)); } + + @Test + public void testEmptyIterator() throws TimeoutException { + ServerStore store = newStore(); + + Iterator chainIterator = store.iterator(); + + assertThat(chainIterator.hasNext(), Is.is(false)); + try { + chainIterator.next(); + fail("Expected NoSuchElementException"); + } catch (NoSuchElementException e) { + //expected + } + } + + @Test + public void testSingleElementIterator() throws TimeoutException { + ServerStore store = newStore(); + + store.append(1L, createPayload(42L)); + Iterator chainIterator = store.iterator(); + + assertThat(chainIterator.hasNext(), is(true)); + assertThat(chainIterator.next(), hasPayloads(42L)); + assertThat(chainIterator.hasNext(), is(false)); + try { + chainIterator.next(); + fail("Expected NoSuchElementException"); + } catch (NoSuchElementException e) { + //expected + } + } + + @Test + public void testHeavilyPopulatedIterator() throws TimeoutException { + ServerStore store = newStore(); + + range(0, 100).forEach(k -> { + try { + store.append(k, createPayload(k)); + } catch (TimeoutException e) { + throw new AssertionError(); + } + }); + + Iterator chainIterator = store.iterator(); + + Set longs = new HashSet<>(); + while (chainIterator.hasNext()) { + Chain chain = chainIterator.next(); + for (Element e: chain) { + long l = readPayload(e.getPayload()); + assertThat(longs, not(hasItem(l))); + longs.add(l); + } + } + + assertThat(longs, hasItems(range(0, 100).boxed().toArray(Long[]::new))); + } } diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java index 287bee99a7..18cec76fdc 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java @@ -26,6 +26,8 @@ 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.atomic.AtomicLong; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; @@ -36,139 +38,73 @@ */ public class ReferenceStoreImpl implements ServerStore { - private final Map map = new HashMap<>(); - private final List locks = new ArrayList<>(); + private final ConcurrentMap map = new ConcurrentHashMap<>(); private final AtomicLong sequenceGenerator = new AtomicLong(); - private final int LOCK_COUNT = 16; - - public ReferenceStoreImpl() { - for (int i = 0; i < LOCK_COUNT; i++) { - locks.add(new ReentrantReadWriteLock()); - } - } - - private ReadWriteLock getLock(long key) { - return locks.get((int)Math.abs(key)%LOCK_COUNT); - } - @Override public Chain get(long key) { - Lock lock = getLock(key).readLock(); - lock.lock(); - try { - Chain chain = map.get(key); - if (chain != null) { - return chain; - } else { - return new HeapChainImpl(); - } - } finally { - lock.unlock(); - } + return map.getOrDefault(key, new HeapChainImpl()); } @Override public void append(long key, ByteBuffer payLoad) { - Lock lock = getLock(key).writeLock(); - lock.lock(); - try { - Chain mapping = map.get(key); - if (mapping == null) { - map.put(key, new HeapChainImpl(new HeapElementImpl(sequenceGenerator.incrementAndGet(), payLoad))); - return; - } - Chain newMapping = cast(mapping).append(new HeapElementImpl(sequenceGenerator.incrementAndGet(), payLoad)); - map.put(key, newMapping); - } finally { - lock.unlock(); - } + getAndAppend(key, payLoad); } @Override public Chain getAndAppend(long key, ByteBuffer payLoad) { - Lock lock = getLock(key).writeLock(); - lock.lock(); - try { - Chain mapping = map.get(key); - if (mapping != null) { - Chain newMapping = cast(mapping).append(new HeapElementImpl(sequenceGenerator.incrementAndGet(), payLoad)); - map.put(key, newMapping); - return mapping; + while (true) { + Chain existing = map.get(key); + if (existing == null) { + if (map.putIfAbsent(key, new HeapChainImpl(new HeapElementImpl(sequenceGenerator.incrementAndGet(), payLoad))) == null) { + return new HeapChainImpl(); + } } else { - map.put(key, new HeapChainImpl(new HeapElementImpl(sequenceGenerator.incrementAndGet(), payLoad))); - return new HeapChainImpl(); + if (map.replace(key, existing, cast(existing).append(new HeapElementImpl(sequenceGenerator.incrementAndGet(), payLoad)))) { + return existing; + } } - } finally { - lock.unlock(); } } @Override public void replaceAtHead(long key, Chain expect, Chain update) { - Lock lock = getLock(key).writeLock(); - lock.lock(); - try { - Chain mapping = map.get(key); - if (mapping == null) { - return; - } - boolean replaceable = true; - List elements = new LinkedList<>(); - Iterator current = mapping.iterator(); + map.computeIfPresent(key, (k, existing) -> { + Iterator current = existing.iterator(); Iterator expected = expect.iterator(); while (expected.hasNext()) { if (current.hasNext()) { HeapElementImpl expectedLink = (HeapElementImpl)expected.next(); if (expectedLink.getSequenceNumber() != ((HeapElementImpl)current.next()).getSequenceNumber()) { - replaceable = false; - break; + return existing; } } else { - replaceable = false; - break; + return existing; } } - if (replaceable) { - for (Element element : update) { - elements.add(element); - } - while(current.hasNext()) { - elements.add(current.next()); - } - map.put(key, new HeapChainImpl(elements.toArray(new Element[elements.size()]))); + List elements = new LinkedList<>(); + for (Element element : update) { + elements.add(element); } - - } finally { - lock.unlock(); - } - } - - private void writeLockAll() { - for (ReadWriteLock lock : locks) { - lock.writeLock().lock(); - } + while(current.hasNext()) { + elements.add(current.next()); + } + return new HeapChainImpl(elements.toArray(new Element[elements.size()])); + }); } - private void writeUnlockAll() { - for (ReadWriteLock lock : locks) { - lock.writeLock().unlock(); - } + @Override + public void clear() { + map.clear(); } @Override - public void clear() { - writeLockAll(); - try { - map.clear(); - } finally { - writeUnlockAll(); - } + public Iterator iterator() { + return map.values().iterator(); } private HeapChainImpl cast(Chain chain) { return (HeapChainImpl)chain; } - } From 9a57a12dfdbceedb6fdff6642a16b9f8fa00c556 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 13 Feb 2019 13:55:27 -0500 Subject: [PATCH 100/372] Fixes #2542 : Ensure offheap values are detached or deserialized before unlocking --- build.gradle | 6 ++-- ...PersistentConcurrentOffHeapClockCache.java | 6 ++-- .../internal/store/disk/OffHeapDiskStore.java | 6 ++-- .../EhcachePersistentSegmentFactory.java | 29 ++++++++++++++++++ .../store/offheap/AbstractOffHeapStore.java | 1 + .../EhcacheConcurrentOffHeapClockCache.java | 6 ++-- .../factories/EhcacheSegmentFactory.java | 30 ++++++++++++++++++- ...istentConcurrentOffHeapClockCacheTest.java | 3 +- .../EhcachePersistentSegmentTest.java | 3 +- 9 files changed, 76 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index ab66a8dc16..bc8f2b70c6 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ import scripts.* ext { baseVersion = '3.0.0-SNAPSHOT' - offheapVersion = '2.2.1' + offheapVersion = '2.4.2' managementVersion = '2.2.0' statisticVersion = '1.1.0' jcacheVersion = '1.0.0' @@ -47,8 +47,8 @@ subprojects { archivesBaseName = "ehcache-${project.name}" - sourceCompatibility = 1.6 - targetCompatibility = 1.6 + sourceCompatibility = 1.8 + targetCompatibility = 1.8 repositories { mavenCentral() diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCache.java b/impl/src/main/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCache.java index 20f82b2427..4d7103a111 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCache.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCache.java @@ -58,7 +58,7 @@ public EhcachePersistentConcurrentOffHeapClockCache(EvictionVeto mappingFunction, final boolean pin) { - MetadataTuple result = computeWithMetadata(key, new org.terracotta.offheapstore.jdk8.BiFunction, MetadataTuple>() { + MetadataTuple result = computeWithMetadata(key, new java.util.function.BiFunction, MetadataTuple>() { @Override public MetadataTuple apply(K k, MetadataTuple current) { V oldValue = current == null ? null : current.value(); @@ -78,7 +78,7 @@ public MetadataTuple apply(K k, MetadataTuple current) { @Override public V computeIfPresent(K key, final BiFunction mappingFunction) { - MetadataTuple result = computeIfPresentWithMetadata(key, new org.terracotta.offheapstore.jdk8.BiFunction, MetadataTuple>() { + MetadataTuple result = computeIfPresentWithMetadata(key, new java.util.function.BiFunction, MetadataTuple>() { @Override public MetadataTuple apply(K k, MetadataTuple current) { V oldValue = current.value(); @@ -105,7 +105,7 @@ public V computeIfPresentAndPin(K key, BiFunction mappingFunction) { @Override public boolean computeIfPinned(final K key, final BiFunction remappingFunction, final Function unpinFunction) { final AtomicBoolean unpin = new AtomicBoolean(); - computeIfPresentWithMetadata(key, new org.terracotta.offheapstore.jdk8.BiFunction, MetadataTuple>() { + computeIfPresentWithMetadata(key, new java.util.function.BiFunction, MetadataTuple>() { @Override public MetadataTuple apply(K k, MetadataTuple current) { if ((current.metadata() & Metadata.PINNED) != 0) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java index 9f685c4e5d..5dc3ba1e10 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java @@ -74,8 +74,10 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import static java.lang.Long.max; import static org.ehcache.core.spi.ServiceLocator.findSingletonAmongst; import static org.ehcache.core.spi.ServiceLocator.findSingletonAmongst; +import static org.terracotta.offheapstore.util.MemoryUnit.BYTES; /** * @@ -171,7 +173,7 @@ private EhcachePersistentConcurrentOffHeapClockCache> r DiskWriteThreadPool writeWorkers = new DiskWriteThreadPool(executionService, threadPoolAlias, writerConcurrency); Factory>> storageEngineFactory = FileBackedStorageEngine.createFactory(source, - keyPortability, elementPortability, writeWorkers, false); + max((size / 16) / 10, 1024), BYTES, keyPortability, elementPortability, writeWorkers, false); EhcachePersistentSegmentFactory> factory = new EhcachePersistentSegmentFactory>( source, @@ -212,7 +214,7 @@ private EhcachePersistentConcurrentOffHeapClockCache> c DiskWriteThreadPool writeWorkers = new DiskWriteThreadPool(executionService, threadPoolAlias, writerConcurrency); Factory>> storageEngineFactory = FileBackedStorageEngine.createFactory(source, - keyPortability, elementPortability, writeWorkers, true); + max((size / 16) / 10, 1024), BYTES, keyPortability, elementPortability, writeWorkers, true); EhcachePersistentSegmentFactory> factory = new EhcachePersistentSegmentFactory>( source, diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentFactory.java index 04d14ef8a0..69d2c7d973 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentFactory.java @@ -17,6 +17,7 @@ package org.ehcache.impl.internal.store.disk.factories; import org.ehcache.config.EvictionVeto; +import org.ehcache.core.spi.cache.Store; import org.ehcache.function.BiFunction; import org.ehcache.impl.internal.store.offheap.factories.EhcacheSegmentFactory.EhcacheSegment; import org.ehcache.impl.internal.store.offheap.factories.EhcacheSegmentFactory.EhcacheSegment.EvictionListener; @@ -27,6 +28,10 @@ import org.terracotta.offheapstore.pinning.PinnableSegment; import org.terracotta.offheapstore.util.Factory; +import java.nio.IntBuffer; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; import java.util.concurrent.locks.Lock; import static org.ehcache.impl.internal.store.offheap.factories.EhcacheSegmentFactory.EhcacheSegment.VETOED; @@ -136,5 +141,29 @@ public boolean evict(int index, boolean shrink) { lock.unlock(); } } + + @Override + protected Set> createEntrySet() { + return new EntrySet(); + } + + private class EntrySet extends LockedEntrySet { + @Override + public Iterator> iterator() { + readLock().lock(); + try { + return new LockedEntryIterator() { + @Override + protected Map.Entry create(IntBuffer entry) { + Map.Entry entryObject = super.create(entry); + ((Store.ValueHolder) entryObject.getValue()).value(); + return entryObject; + } + }; + } finally { + readLock().unlock(); + } + } + } } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java index a5463a0cf8..3e7b3d6c75 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java @@ -406,6 +406,7 @@ public OffHeapValueHolder apply(K mappedKey, OffHeapValueHolder mappedValu } return null; } else { + mappedValue.forceDeserialization(); returnValue.set(mappedValue); return newUpdatedValueHolder(mappedKey, value, mappedValue, now, eventSink); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/EhcacheConcurrentOffHeapClockCache.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/EhcacheConcurrentOffHeapClockCache.java index 064d9189cc..5ca9d119b0 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/EhcacheConcurrentOffHeapClockCache.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/EhcacheConcurrentOffHeapClockCache.java @@ -53,7 +53,7 @@ protected EhcacheConcurrentOffHeapClockCache(EvictionVeto @Override public V compute(K key, final BiFunction mappingFunction, final boolean pin) { - MetadataTuple result = computeWithMetadata(key, new org.terracotta.offheapstore.jdk8.BiFunction, MetadataTuple>() { + MetadataTuple result = computeWithMetadata(key, new java.util.function.BiFunction, MetadataTuple>() { @Override public MetadataTuple apply(K k, MetadataTuple current) { V oldValue = current == null ? null : current.value(); @@ -73,7 +73,7 @@ public MetadataTuple apply(K k, MetadataTuple current) { @Override public V computeIfPresent(K key, final BiFunction mappingFunction) { - MetadataTuple result = computeIfPresentWithMetadata(key, new org.terracotta.offheapstore.jdk8.BiFunction, MetadataTuple>() { + MetadataTuple result = computeIfPresentWithMetadata(key, new java.util.function.BiFunction, MetadataTuple>() { @Override public MetadataTuple apply(K k, MetadataTuple current) { V oldValue = current.value(); @@ -100,7 +100,7 @@ public V computeIfPresentAndPin(K key, BiFunction mappingFunction) { @Override public boolean computeIfPinned(final K key, final BiFunction remappingFunction, final Function unpinFunction) { final AtomicBoolean unpin = new AtomicBoolean(); - computeIfPresentWithMetadata(key, new org.terracotta.offheapstore.jdk8.BiFunction, MetadataTuple>() { + computeIfPresentWithMetadata(key, new java.util.function.BiFunction, MetadataTuple>() { @Override public MetadataTuple apply(K k, MetadataTuple current) { if ((current.metadata() & Metadata.PINNED) != 0) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentFactory.java index 84270a34cf..9881ac5635 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentFactory.java @@ -17,8 +17,8 @@ package org.ehcache.impl.internal.store.offheap.factories; import org.ehcache.config.EvictionVeto; +import org.ehcache.core.spi.cache.Store; import org.ehcache.function.BiFunction; -import org.ehcache.function.Function; import org.terracotta.offheapstore.Metadata; import org.terracotta.offheapstore.ReadWriteLockedOffHeapClockCache; @@ -27,6 +27,9 @@ import org.terracotta.offheapstore.storage.StorageEngine; import org.terracotta.offheapstore.util.Factory; +import java.nio.IntBuffer; +import java.util.Iterator; +import java.util.Set; import java.util.concurrent.locks.Lock; /** @@ -131,8 +134,33 @@ public boolean evict(int index, boolean shrink) { } } + @Override + protected Set> createEntrySet() { + return new EntrySet(); + } + public interface EvictionListener { void onEviction(K key, V value); } + + private class EntrySet extends LockedEntrySet { + @Override + public Iterator> iterator() { + readLock().lock(); + try { + return new LockedEntryIterator() { + + @Override + protected Entry create(IntBuffer entry) { + Entry entryObject = super.create(entry); + ((Store.ValueHolder) entryObject.getValue()).value(); + return entryObject; + } + }; + } finally { + readLock().unlock(); + } + } + } } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java index 3c524c1b7c..c3497c0986 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java @@ -40,6 +40,7 @@ import static org.ehcache.impl.internal.spi.TestServiceProvider.providerContaining; import org.ehcache.impl.internal.store.disk.factories.EhcachePersistentSegmentFactory; import static org.mockito.Mockito.mock; +import static org.terracotta.offheapstore.util.MemoryUnit.BYTES; public class EhcachePersistentConcurrentOffHeapClockCacheTest extends AbstractEhcacheOffHeapBackingMapTest { @@ -66,7 +67,7 @@ private EhcachePersistentConcurrentOffHeapClockCache createTestS Serializer valueSerializer = serializationProvider.createValueSerializer(String.class, EhcachePersistentConcurrentOffHeapClockCacheTest.class.getClassLoader()); PersistentPortability keyPortability = persistent(new SerializerPortability(keySerializer)); PersistentPortability elementPortability = persistent(new SerializerPortability(valueSerializer)); - Factory> storageEngineFactory = FileBackedStorageEngine.createFactory(pageSource, keyPortability, elementPortability); + Factory> storageEngineFactory = FileBackedStorageEngine.createFactory(pageSource, configuration.getMaximumSize() / 10, BYTES, keyPortability, elementPortability); EhcachePersistentSegmentFactory segmentFactory = new EhcachePersistentSegmentFactory(pageSource, storageEngineFactory, 0, evictionPredicate, evictionListener, true); return new EhcachePersistentConcurrentOffHeapClockCache(evictionPredicate, segmentFactory, 1); } catch (UnsupportedTypeException e) { diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java index f3cceae43f..9d922cfdbd 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java @@ -43,6 +43,7 @@ import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.terracotta.offheapstore.util.MemoryUnit.BYTES; public class EhcachePersistentSegmentTest { @@ -71,7 +72,7 @@ private EhcachePersistentSegmentFactory.EhcachePersistentSegment Serializer valueSerializer = serializationProvider.createValueSerializer(String.class, EhcachePersistentSegmentTest.class.getClassLoader()); PersistentPortability keyPortability = persistent(new SerializerPortability(keySerializer)); PersistentPortability elementPortability = persistent(new SerializerPortability(valueSerializer)); - Factory> storageEngineFactory = FileBackedStorageEngine.createFactory(pageSource, keyPortability, elementPortability); + Factory> storageEngineFactory = FileBackedStorageEngine.createFactory(pageSource, configuration.getMaximumSize() / 10, BYTES, keyPortability, elementPortability); return new EhcachePersistentSegmentFactory.EhcachePersistentSegment(pageSource, storageEngineFactory.newInstance(), 1, true, evictionPredicate, evictionListener); } catch (UnsupportedTypeException e) { throw new AssertionError(e); From 74239a93e14eb7477841fffa36c971ef9e930686 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 13 Feb 2019 13:55:45 -0500 Subject: [PATCH 101/372] Issue #2542 : Ensure locks are correctly held when manipulating offheap value holders --- build.gradle | 2 +- .../internal/store/disk/OffHeapDiskStore.java | 32 +-- .../store/offheap/AbstractOffHeapStore.java | 6 + .../internal/store/offheap/OffHeapStore.java | 4 +- .../store/offheap/OffHeapValueHolder.java | 26 +-- .../OffHeapValueHolderPortability.java | 7 +- .../store/disk/OffHeapDiskStoreTest.java | 16 +- .../offheap/AbstractOffHeapStoreTest.java | 3 + .../offheap/AssertingOffHeapValueHolder.java | 187 ++++++++++++++++++ .../AssertingOffHeapValueHolderTest.java | 62 ++++++ .../store/offheap/OffHeapStoreTest.java | 16 +- ...ssertingOffHeapValueHolderPortability.java | 36 ++++ 12 files changed, 363 insertions(+), 34 deletions(-) create mode 100644 impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolder.java create mode 100644 impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolderTest.java create mode 100644 impl/src/test/java/org/ehcache/impl/internal/store/offheap/portability/AssertingOffHeapValueHolderPortability.java diff --git a/build.gradle b/build.gradle index bc8f2b70c6..d08f9d90ad 100644 --- a/build.gradle +++ b/build.gradle @@ -124,7 +124,7 @@ subprojects { checkstyle { configFile = file("$rootDir/config/checkstyle.xml") configProperties = ['projectDir':projectDir, 'rootDir':rootDir] - toolVersion = '5.7' + toolVersion = '5.9' } findbugs { diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java index 5dc3ba1e10..d0c9f08e74 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java @@ -69,12 +69,14 @@ import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import static java.lang.Long.max; +import static java.util.Arrays.asList; import static org.ehcache.core.spi.ServiceLocator.findSingletonAmongst; import static org.ehcache.core.spi.ServiceLocator.findSingletonAmongst; import static org.terracotta.offheapstore.util.MemoryUnit.BYTES; @@ -169,11 +171,11 @@ private EhcachePersistentConcurrentOffHeapClockCache> r MappedPageSource source = new MappedPageSource(dataFile, false, size); try { PersistentPortability keyPortability = persistent(new SerializerPortability(keySerializer)); - PersistentPortability> elementPortability = persistent(new OffHeapValueHolderPortability(valueSerializer)); + PersistentPortability> valuePortability = persistent(createValuePortability(valueSerializer)); DiskWriteThreadPool writeWorkers = new DiskWriteThreadPool(executionService, threadPoolAlias, writerConcurrency); Factory>> storageEngineFactory = FileBackedStorageEngine.createFactory(source, - max((size / 16) / 10, 1024), BYTES, keyPortability, elementPortability, writeWorkers, false); + max((size / 16) / 10, 1024), BYTES, keyPortability, valuePortability, writeWorkers, false); EhcachePersistentSegmentFactory> factory = new EhcachePersistentSegmentFactory>( source, @@ -210,11 +212,11 @@ private EhcachePersistentConcurrentOffHeapClockCache> c throw new RuntimeException(e); } PersistentPortability keyPortability = persistent(new SerializerPortability(keySerializer)); - PersistentPortability> elementPortability = persistent(new OffHeapValueHolderPortability(valueSerializer)); + PersistentPortability> valuePortability = persistent(createValuePortability(valueSerializer)); DiskWriteThreadPool writeWorkers = new DiskWriteThreadPool(executionService, threadPoolAlias, writerConcurrency); Factory>> storageEngineFactory = FileBackedStorageEngine.createFactory(source, - max((size / 16) / 10, 1024), BYTES, keyPortability, elementPortability, writeWorkers, true); + max((size / 16) / 10, 1024), BYTES, keyPortability, valuePortability, writeWorkers, true); EhcachePersistentSegmentFactory> factory = new EhcachePersistentSegmentFactory>( source, @@ -373,22 +375,24 @@ public void initAuthoritativeTier(AuthoritativeTier resource) { * This is kind of a hack, but it's safe to use this if the regular portability * is stateless. */ + @SuppressWarnings("unchecked") public static PersistentPortability persistent(final Portability normal) { - final Class normalKlazz = normal.getClass(); - Class[] delegateInterfaces = normalKlazz.getInterfaces(); - Class[] proxyInterfaces = Arrays.copyOf(delegateInterfaces, delegateInterfaces.length + 1); - proxyInterfaces[delegateInterfaces.length] = PersistentPortability.class; - - return (PersistentPortability) Proxy.newProxyInstance(normal.getClass().getClassLoader(), proxyInterfaces, new InvocationHandler() { + if (normal instanceof PersistentPortability) { + return (PersistentPortability) normal; + } else { + LinkedHashSet> proxyInterfaces = new LinkedHashSet<>(); + for (Class klazz = normal.getClass(); klazz != null; klazz = klazz.getSuperclass()) { + proxyInterfaces.addAll(asList(klazz.getInterfaces())); + } + proxyInterfaces.add(PersistentPortability.class); - @Override - public Object invoke(Object o, Method method, Object[] os) throws Throwable { + return (PersistentPortability) Proxy.newProxyInstance(normal.getClass().getClassLoader(), proxyInterfaces.toArray(new Class[0]), (o, method, os) -> { if (method.getDeclaringClass().equals(Persistent.class)) { return null; } else { return method.invoke(normal, os); } - } - }); + }); + } } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java index 3e7b3d6c75..680e30ee22 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java @@ -37,6 +37,7 @@ import org.ehcache.function.BiFunction; import org.ehcache.function.Function; import org.ehcache.function.NullaryFunction; +import org.ehcache.impl.internal.store.offheap.portability.OffHeapValueHolderPortability; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.impl.internal.store.offheap.factories.EhcacheSegmentFactory; import org.ehcache.core.spi.cache.Store; @@ -47,6 +48,7 @@ import org.ehcache.core.statistics.AuthoritativeTierOperationOutcomes; import org.ehcache.core.statistics.LowerCachingTierOperationsOutcome; import org.ehcache.core.statistics.StoreOperationOutcomes; +import org.ehcache.spi.serialization.Serializer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.terracotta.offheapstore.Segment; @@ -1229,6 +1231,10 @@ protected static EvictionVeto> wrap(EvictionVeto return new OffHeapEvictionVetoWrapper(delegate); } + protected OffHeapValueHolderPortability createValuePortability(Serializer serializer) { + return new OffHeapValueHolderPortability<>(serializer); + } + private static class OffHeapEvictionVetoWrapper implements EvictionVeto> { private final EvictionVeto delegate; diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java index b4d9ca561d..c6b8050f87 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java @@ -91,9 +91,9 @@ private EhcacheConcurrentOffHeapClockCache> createBacki HeuristicConfiguration config = new HeuristicConfiguration(size); PageSource source = new UpfrontAllocatingPageSource(getBufferSource(), config.getMaximumSize(), config.getMaximumChunkSize(), config.getMinimumChunkSize()); Portability keyPortability = new SerializerPortability(keySerializer); - Portability> elementPortability = new OffHeapValueHolderPortability(valueSerializer); + Portability> valuePortability = createValuePortability(valueSerializer); Factory>> storageEngineFactory = OffHeapBufferStorageEngine.createFactory(PointerSize.INT, source, config - .getSegmentDataPageSize(), keyPortability, elementPortability, false, true); + .getSegmentDataPageSize(), keyPortability, valuePortability, false, true); Factory>> segmentFactory = new EhcacheSegmentFactory>( source, diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolder.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolder.java index ceae61a36c..f999e90ec7 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolder.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolder.java @@ -33,7 +33,7 @@ * OffHeapValueHolder */ @FindbugsSuppressWarnings("SE_NO_SERIALVERSIONID") -public final class OffHeapValueHolder extends AbstractValueHolder implements BinaryValueHolder { +public class OffHeapValueHolder extends AbstractValueHolder implements BinaryValueHolder { public static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS; @@ -124,16 +124,20 @@ void writeBack() { void forceDeserialization() { if (value == null && mode != Mode.VALUE) { - try { - value = valueSerializer.read(binaryValue.duplicate()); - } catch (ClassNotFoundException e) { - throw new SerializerException(e); - } finally { - if (mode == Mode.BINARY) { - binaryValue = null; - valueSerializer = null; - mode = Mode.VALUE; - } + value = deserialize(); + } + } + + V deserialize() { + try { + return valueSerializer.read(binaryValue.duplicate()); + } catch (ClassNotFoundException e) { + throw new SerializerException(e); + } finally { + if (mode == Mode.BINARY) { + binaryValue = null; + valueSerializer = null; + mode = Mode.VALUE; } } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java index 8e46854d44..338de9d016 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java @@ -73,7 +73,10 @@ public OffHeapValueHolder decode(ByteBuffer byteBuffer, WriteContext writeCon long lastAccessTime = byteBuffer.getLong(); long expireTime = byteBuffer.getLong(); long hits = byteBuffer.getLong(); - OffHeapValueHolder valueHolder = new OffHeapValueHolder(id, byteBuffer.slice(), serializer, creationTime, expireTime, lastAccessTime, hits, writeContext); - return valueHolder; + return createLazyOffHeapValueHolder(id, byteBuffer.slice(), serializer, creationTime, expireTime, lastAccessTime, hits, writeContext); + } + + protected OffHeapValueHolder createLazyOffHeapValueHolder(long id, ByteBuffer byteBuffer, Serializer serializer, long creationTime, long expireTime, long lastAccessTime, long hits, WriteContext writeContext) { + return new OffHeapValueHolder(id, byteBuffer.slice(), serializer, creationTime, expireTime, lastAccessTime, hits, writeContext); } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java index 0345fc85ee..0f162abb31 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java @@ -23,6 +23,8 @@ import org.ehcache.exceptions.CacheAccessException; import org.ehcache.exceptions.CachePersistenceException; import org.ehcache.expiry.Expiry; +import org.ehcache.impl.internal.store.offheap.portability.AssertingOffHeapValueHolderPortability; +import org.ehcache.impl.internal.store.offheap.portability.OffHeapValueHolderPortability; import org.ehcache.impl.internal.events.TestStoreEventDispatcher; import org.ehcache.impl.internal.executor.OnDemandExecutionService; import org.ehcache.impl.internal.persistence.TestLocalPersistenceService; @@ -88,7 +90,12 @@ protected OffHeapDiskStore createAndInitStore(final TimeSource t new OnDemandExecutionService(), null, 1, storeConfiguration, timeSource, new TestStoreEventDispatcher(), - MemoryUnit.MB.toBytes(1)); + MemoryUnit.MB.toBytes(1)) { + @Override + protected OffHeapValueHolderPortability createValuePortability(Serializer serializer) { + return new AssertingOffHeapValueHolderPortability<>(serializer); + } + }; OffHeapDiskStore.Provider.init(offHeapStore); return offHeapStore; } catch (UnsupportedTypeException e) { @@ -111,7 +118,12 @@ protected OffHeapDiskStore createAndInitStore(TimeSource timeSou new OnDemandExecutionService(), null, 1, storeConfiguration, timeSource, new TestStoreEventDispatcher(), - MemoryUnit.MB.toBytes(1)); + MemoryUnit.MB.toBytes(1)) { + @Override + protected OffHeapValueHolderPortability createValuePortability(Serializer serializer) { + return new AssertingOffHeapValueHolderPortability<>(serializer); + } + }; OffHeapDiskStore.Provider.init(offHeapStore); return offHeapStore; } catch (UnsupportedTypeException e) { diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java index ff356be7b8..4a28dae4b0 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java @@ -119,6 +119,7 @@ public void testGetAndRemoveExpiredElementReturnsNull() throws Exception { offHeapStore.setInvalidationListener(new CachingTier.InvalidationListener() { @Override public void onInvalidation(String key, Store.ValueHolder valueHolder) { + valueHolder.value(); invalidated.set(valueHolder); } }); @@ -200,6 +201,7 @@ public void testInvalidateKeyPresent() throws Exception { offHeapStore.setInvalidationListener(new CachingTier.InvalidationListener() { @Override public void onInvalidation(String key, Store.ValueHolder valueHolder) { + valueHolder.value(); invalidated.set(valueHolder); } }); @@ -256,6 +258,7 @@ public void testInvalidateWithFunctionKeyPresent() throws Exception { offHeapStore.setInvalidationListener(new CachingTier.InvalidationListener() { @Override public void onInvalidation(String key, Store.ValueHolder valueHolder) { + valueHolder.value(); invalidated.set(valueHolder); } }); diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolder.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolder.java new file mode 100644 index 0000000000..821bd5704b --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolder.java @@ -0,0 +1,187 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.internal.store.offheap; + +import org.ehcache.spi.serialization.Serializer; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.InstructionAdapter; +import org.objectweb.asm.commons.Method; +import org.terracotta.offheapstore.storage.portability.WriteContext; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.NavigableMap; +import java.util.TreeMap; +import java.util.concurrent.locks.Lock; +import java.util.function.Predicate; + +import static java.util.Arrays.asList; +import static java.util.Arrays.stream; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; +import static org.objectweb.asm.Opcodes.ASM5; +import static org.objectweb.asm.Type.getObjectType; +import static org.objectweb.asm.Type.getType; +import static org.objectweb.asm.commons.Method.getMethod; + +public class AssertingOffHeapValueHolder extends OffHeapValueHolder { + + /** + * This is a set of 'patterns' that capture a subset of the lock scopes that the `OffHeapValueHolder` can be + * called from. You might end up looking at these patterns for one of three reasons: + * + * 1. (Most Likely) You introduced new code or new testing that access a pre-existing lock scope that is not listed + * here. Find the lock scope in the stack trace of the thrown exception and add an appropriate stanza here. + * 2. (Less Likely) You introduced a new call path that leaks a still serialized, attached value holder that someone + * else tried to access later (outside lock scope). In this case you must locate the source of the value holder + * and either force deserialization or detach the value under the pre-existing lock scope. + * 3. (Least Likely) You introduced a new method to OffHeapStore that needs locking properly. + */ + private static final Collection> LOCK_SCOPES = asList( + className("org.terracotta.offheapstore.AbstractLockedOffHeapHashMap").methodName("shrink"), + className("org.terracotta.offheapstore.AbstractLockedOffHeapHashMap").methodName("computeWithMetadata"), + className("org.terracotta.offheapstore.AbstractLockedOffHeapHashMap").methodName("computeIfPresentWithMetadata"), + className("org.ehcache.impl.internal.store.offheap.factories.EhcacheSegmentFactory$EhcacheSegment").methodName("computeIfPresentAndPin"), + className("org.ehcache.impl.internal.store.disk.factories.EhcachePersistentSegmentFactory$EhcachePersistentSegment").methodName("computeIfPresentAndPin"), + className("org.ehcache.impl.internal.store.offheap.factories.EhcacheSegmentFactory$EhcacheSegment$EntrySet").methodName("iterator"), + className("org.ehcache.impl.internal.store.disk.factories.EhcachePersistentSegmentFactory$EhcachePersistentSegment$EntrySet").methodName("iterator"), + className("org.terracotta.offheapstore.AbstractLockedOffHeapHashMap$LockedEntryIterator").methodName("next") + ); + + private static void assertStackTraceContainsLockScope() { + assertThat(stream(Thread.currentThread().getStackTrace()).filter(ste -> LOCK_SCOPES.stream().anyMatch(p -> p.test(ste))).anyMatch(ste -> isLockedInFrame(ste)), is(true)); + } + + private static StePredicateBuilderOne className(String className) { + return new StePredicateBuilderOne() { + @Override + public Predicate methodName(String methodName) { + StePredicateBuilderOne outer = this; + return ste -> outer.test(ste) && methodName.equals(ste.getMethodName()); + } + + @Override + public boolean test(StackTraceElement ste) { + return className.equals(ste.getClassName()); + } + }; + } + + interface StePredicateBuilderOne extends Predicate { + + Predicate methodName(String computeIfPresentWithMetadata); + } + + public AssertingOffHeapValueHolder(long id, ByteBuffer binaryValue, Serializer serializer, long creationTime, long expireTime, long lastAccessTime, long hits, WriteContext writeContext) { + super(id, binaryValue, serializer, creationTime, expireTime, lastAccessTime, hits, writeContext); + } + + @Override + void writeBack() { + assertStackTraceContainsLockScope(); + super.writeBack(); + } + + @Override + V deserialize() { + assertStackTraceContainsLockScope(); + return super.deserialize(); + } + + @Override + void prepareForDelayedDeserialization() { + assertStackTraceContainsLockScope(); + super.prepareForDelayedDeserialization(); + } + + private static final Type LOCK_CLASS; + private static final Method LOCK_METHOD; + private static final Method UNLOCK_METHOD; + + static { + try { + LOCK_CLASS = getType(Lock.class); + LOCK_METHOD = getMethod(Lock.class.getMethod("lock")); + UNLOCK_METHOD = getMethod(Lock.class.getMethod("unlock")); + } catch (NoSuchMethodException e) { + throw new AssertionError(e); + } + } + + private static boolean isLockedInFrame(StackTraceElement ste) { + try { + ClassReader reader = new ClassReader(ste.getClassName()); + + NavigableMap lockLevels = new TreeMap<>(); + + reader.accept(new ClassVisitor(ASM5) { + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + if (ste.getMethodName().equals(name)) { + return new InstructionAdapter(ASM5, new MethodVisitor(ASM5) {}) { + + private final Map levels = new HashMap<>(); + + private int lockLevel; + + @Override + public void invokeinterface(String owner, String name, String descriptor) { + if (LOCK_CLASS.equals(getObjectType(owner))) { + if (LOCK_METHOD.equals(new Method(name, descriptor))) { + lockLevel++; + } else if (UNLOCK_METHOD.equals(new Method(name, descriptor))) { + lockLevel--; + } + } + } + + @Override + public void visitJumpInsn(int opcode, Label label) { + levels.merge(label, lockLevel, Integer::max); + } + + @Override + public void visitLabel(Label label) { + lockLevel = levels.merge(label, lockLevel, Integer::max); + } + + @Override + public void visitLineNumber(int line, Label start) { + lockLevels.merge(line, levels.get(start), Integer::max); + } + }; + } else { + return null; + } + } + }, 0); + + Map.Entry entry = lockLevels.floorEntry(ste.getLineNumber()); + + return entry.getValue() > 0; + } catch (IOException e) { + throw new AssertionError(e); + } + } +} diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolderTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolderTest.java new file mode 100644 index 0000000000..c56f0e691a --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolderTest.java @@ -0,0 +1,62 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.internal.store.offheap; + +import org.ehcache.spi.serialization.Serializer; +import org.junit.Test; +import org.terracotta.offheapstore.storage.portability.WriteContext; + +import java.nio.ByteBuffer; + +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; + +public class AssertingOffHeapValueHolderTest { + + @Test @SuppressWarnings("unchecked") + public void testLockingAssertionsOnPrepareForDelayedDeserialization() { + OffHeapValueHolder valueHolder = new AssertingOffHeapValueHolder<>(1L, ByteBuffer.allocate(1), mock(Serializer.class), 10L, 20L, 15L, 0L, mock(WriteContext.class)); + try { + valueHolder.prepareForDelayedDeserialization(); + fail("Expected AssertionError"); + } catch (AssertionError e) { + //expected + } + } + + @Test @SuppressWarnings("unchecked") + public void testLockingAssertionsOnForceDeserialize() { + OffHeapValueHolder valueHolder = new AssertingOffHeapValueHolder<>(1L, ByteBuffer.allocate(1), mock(Serializer.class), 10L, 20L, 15L, 0L, mock(WriteContext.class)); + try { + valueHolder.forceDeserialization(); + fail("Expected AssertionError"); + } catch (AssertionError e) { + //expected + } + } + + @Test @SuppressWarnings("unchecked") + public void testLockingAssertionsOnWriteBack() { + OffHeapValueHolder valueHolder = new AssertingOffHeapValueHolder<>(1L, ByteBuffer.allocate(1), mock(Serializer.class), 10L, 20L, 15L, 0L, mock(WriteContext.class)); + try { + valueHolder.writeBack(); + fail("Expected AssertionError"); + } catch (AssertionError e) { + //expected + } + } +} diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java index ba5f2f8f5b..f1b5d7c61c 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java @@ -23,6 +23,8 @@ import org.ehcache.impl.internal.events.TestStoreEventDispatcher; import org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider; import org.ehcache.core.spi.time.TimeSource; +import org.ehcache.impl.internal.store.offheap.portability.AssertingOffHeapValueHolderPortability; +import org.ehcache.impl.internal.store.offheap.portability.OffHeapValueHolderPortability; import org.ehcache.spi.serialization.SerializationProvider; import org.ehcache.spi.serialization.Serializer; import org.ehcache.spi.serialization.UnsupportedTypeException; @@ -41,7 +43,12 @@ protected OffHeapStore createAndInitStore(TimeSource timeSource, Serializer valueSerializer = serializationProvider.createValueSerializer(String.class, classLoader); StoreConfigurationImpl storeConfiguration = new StoreConfigurationImpl(String.class, String.class, null, classLoader, expiry, null, 0, keySerializer, valueSerializer); - OffHeapStore offHeapStore = new OffHeapStore(storeConfiguration, timeSource, new TestStoreEventDispatcher(), MemoryUnit.MB.toBytes(1)); + OffHeapStore offHeapStore = new OffHeapStore(storeConfiguration, timeSource, new TestStoreEventDispatcher(), MemoryUnit.MB.toBytes(1)) { + @Override + protected OffHeapValueHolderPortability createValuePortability(Serializer serializer) { + return new AssertingOffHeapValueHolderPortability<>(serializer); + } + }; OffHeapStore.Provider.init(offHeapStore); return offHeapStore; } catch (UnsupportedTypeException e) { @@ -59,7 +66,12 @@ protected OffHeapStore createAndInitStore(TimeSource timeSource, Serializer valueSerializer = serializationProvider.createValueSerializer(byte[].class, classLoader); StoreConfigurationImpl storeConfiguration = new StoreConfigurationImpl(String.class, byte[].class, evictionVeto, getClass().getClassLoader(), expiry, null, 0, keySerializer, valueSerializer); - OffHeapStore offHeapStore = new OffHeapStore(storeConfiguration, timeSource, new TestStoreEventDispatcher(),MemoryUnit.MB.toBytes(1)); + OffHeapStore offHeapStore = new OffHeapStore(storeConfiguration, timeSource, new TestStoreEventDispatcher(),MemoryUnit.MB.toBytes(1)) { + @Override + protected OffHeapValueHolderPortability createValuePortability(Serializer serializer) { + return new AssertingOffHeapValueHolderPortability<>(serializer); + } + }; OffHeapStore.Provider.init(offHeapStore); return offHeapStore; } catch (UnsupportedTypeException e) { diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/portability/AssertingOffHeapValueHolderPortability.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/portability/AssertingOffHeapValueHolderPortability.java new file mode 100644 index 0000000000..0b72d3dfde --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/portability/AssertingOffHeapValueHolderPortability.java @@ -0,0 +1,36 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.internal.store.offheap.portability; + +import org.ehcache.impl.internal.store.offheap.AssertingOffHeapValueHolder; +import org.ehcache.impl.internal.store.offheap.OffHeapValueHolder; +import org.ehcache.spi.serialization.Serializer; +import org.terracotta.offheapstore.storage.portability.WriteContext; + +import java.nio.ByteBuffer; + +public class AssertingOffHeapValueHolderPortability extends OffHeapValueHolderPortability { + + public AssertingOffHeapValueHolderPortability(Serializer serializer) { + super(serializer); + } + + @Override + protected OffHeapValueHolder createLazyOffHeapValueHolder(long id, ByteBuffer byteBuffer, Serializer serializer, long creationTime, long expireTime, long lastAccessTime, long hits, WriteContext writeContext) { + return new AssertingOffHeapValueHolder<>(id, byteBuffer, serializer, creationTime, expireTime, lastAccessTime, hits, writeContext); + } +} From 715f06c4ef60b24cb67a2cb1b693669a248d8d7d Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 14 Feb 2019 13:36:42 -0500 Subject: [PATCH 102/372] Remove cross module test dependency --- 107/build.gradle | 1 - .../org/ehcache/jsr107/Jsr107CacheParserIT.java | 3 +-- build.gradle | 1 - clustered/client/build.gradle | 3 ++- .../ClusteredCacheConfigurationParserIT.java | 7 ++----- ...lusteredResourceConfigurationParserTest.java | 14 ++++++++++---- ...heManagerServiceConfigurationParserTest.java | 17 +++++++++++------ ...ringCacheServiceConfigurationParserTest.java | 8 ++++++-- management/build.gradle | 3 ++- ...entRegistryServiceConfigurationParserIT.java | 7 ++----- ...tRegistryServiceConfigurationParserTest.java | 11 ++++++++--- transactions/build.gradle | 3 ++- .../TransactionalCacheParserIT.java | 6 ++---- ...heManagerServiceConfigurationParserTest.java | 8 ++++++-- .../TxCacheServiceConfigurationParserTest.java | 8 ++++++-- .../xml/ConfigurationParserTestHelper.java | 3 --- .../org/ehcache/xml/XmlConfigurationTest.java | 3 +-- 17 files changed, 61 insertions(+), 45 deletions(-) diff --git a/107/build.gradle b/107/build.gradle index 047379815a..3f035728b2 100644 --- a/107/build.gradle +++ b/107/build.gradle @@ -45,7 +45,6 @@ dependencies { tckTestClasses("javax.cache:cache-tests:$jcacheTckVersion:tests") { transitive = false } - testCompile project(path: ':xml', configuration: 'testArchives') } javadoc { diff --git a/107/src/test/java/org/ehcache/jsr107/Jsr107CacheParserIT.java b/107/src/test/java/org/ehcache/jsr107/Jsr107CacheParserIT.java index b825f6ed69..131d328e3a 100644 --- a/107/src/test/java/org/ehcache/jsr107/Jsr107CacheParserIT.java +++ b/107/src/test/java/org/ehcache/jsr107/Jsr107CacheParserIT.java @@ -17,7 +17,6 @@ import org.ehcache.config.Configuration; import org.ehcache.xml.XmlConfiguration; -import org.ehcache.xml.XmlConfigurationTest; import org.ehcache.xml.exceptions.XmlConfigurationException; import org.junit.Test; @@ -30,7 +29,7 @@ public class Jsr107CacheParserIT { @Test(expected = XmlConfigurationException.class) public void testJsr107CacheXmlTranslationToString() { - URL resource = XmlConfigurationTest.class.getResource("/ehcache-107.xml"); + URL resource = Jsr107CacheParserIT.class.getResource("/ehcache-107.xml"); Configuration config = new XmlConfiguration(resource); XmlConfiguration xmlConfig = new XmlConfiguration(config); } diff --git a/build.gradle b/build.gradle index 58e4011050..071720ff88 100644 --- a/build.gradle +++ b/build.gradle @@ -128,7 +128,6 @@ subprojects { testImplementation "org.assertj:assertj-core:$assertjVersion" testImplementation "org.hamcrest:hamcrest-library:$hamcrestVersion" testImplementation "org.mockito:mockito-core:$mockitoVersion" - testCompile 'org.xmlunit:xmlunit-core:2.6.0', 'org.xmlunit:xmlunit-matchers:2.6.0' testRuntimeOnly "org.slf4j:slf4j-simple:$parent.slf4jVersion" } diff --git a/clustered/client/build.gradle b/clustered/client/build.gradle index 05c60a3242..86a9a108d1 100644 --- a/clustered/client/build.gradle +++ b/clustered/client/build.gradle @@ -43,7 +43,8 @@ dependencies { testImplementation (group: 'org.codehaus.btm', name: 'btm', version: '2.1.4') { exclude group:'org.slf4j', module:'slf4j-api' } - testCompile project(path: ':xml', configuration: 'testArchives') + testImplementation 'org.xmlunit:xmlunit-core:2.6.0' + testImplementation 'org.xmlunit:xmlunit-matchers:2.6.0' } test { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java index f501af949d..04e4123caa 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java @@ -17,9 +17,7 @@ import org.ehcache.config.Configuration; import org.ehcache.xml.XmlConfiguration; -import org.ehcache.xml.XmlConfigurationTest; import org.junit.Test; -import org.xmlunit.builder.Input; import org.xmlunit.diff.DefaultNodeMatcher; import org.xmlunit.diff.ElementSelectors; @@ -35,11 +33,10 @@ public class ClusteredCacheConfigurationParserIT { @Test public void testClusteredCacheXmlTranslationToString() { - URL resource = XmlConfigurationTest.class.getResource("/configs/clustered-cache.xml"); + URL resource = ClusteredCacheConfigurationParserIT.class.getResource("/configs/clustered-cache.xml"); Configuration config = new XmlConfiguration(resource); XmlConfiguration xmlConfig = new XmlConfiguration(config); - assertThat(xmlConfig.toString(), isSimilarTo(Input.from(resource)).ignoreComments() - .ignoreWhitespace() + assertThat(xmlConfig.toString(), isSimilarTo(resource).ignoreComments().ignoreWhitespace() .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndAllAttributes))); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java index 2b490639bc..8f3b782ac0 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java @@ -21,8 +21,11 @@ import org.ehcache.config.units.MemoryUnit; import org.junit.Test; import org.w3c.dom.Node; +import org.xmlunit.diff.DefaultNodeMatcher; +import org.xmlunit.diff.ElementSelectors; -import static org.ehcache.xml.ConfigurationParserTestHelper.assertElement; +import static org.junit.Assert.assertThat; +import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** * ClusteredResourceConfigurationParserTest @@ -35,7 +38,8 @@ public void testTranslateClusteredResourcePoolConfiguration() { ClusteredResourcePoolImpl clusteredResourcePool = new ClusteredResourcePoolImpl(); Node retElement = configTranslator.unparseResourcePool(clusteredResourcePool); String inputString = ""; - assertElement(inputString, retElement); + assertThat(retElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } @Test @@ -45,7 +49,8 @@ public void testTranslateDedicatedResourcePoolConfiguration() { Node retElement = configTranslator.unparseResourcePool(dedicatedClusteredResourcePool); String inputString = "12"; - assertElement(inputString, retElement); + assertThat(retElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } @Test @@ -55,7 +60,8 @@ public void testTranslateSharedResourcePoolConfiguration() { Node retElement = configTranslator.unparseResourcePool(sharedResourcePool); String inputString = ""; - assertElement(inputString, retElement); + assertThat(retElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java index 4a786e4995..5fcfe3cc4a 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java @@ -37,6 +37,8 @@ import org.junit.rules.TestName; import org.w3c.dom.Attr; import org.w3c.dom.Element; +import org.xmlunit.diff.DefaultNodeMatcher; +import org.xmlunit.diff.ElementSelectors; import java.io.File; import java.io.FileOutputStream; @@ -60,7 +62,6 @@ import static java.time.temporal.ChronoUnit.MINUTES; import static java.util.Spliterators.spliterator; import static java.util.stream.StreamSupport.stream; -import static org.ehcache.xml.ConfigurationParserTestHelper.assertElement; import static org.ehcache.xml.XmlModel.convertToJavaTimeUnit; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -71,6 +72,7 @@ import static org.hamcrest.core.IsCollectionContaining.hasItem; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; +import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; public class ClusteringCacheManagerServiceConfigurationParserTest { @@ -441,8 +443,8 @@ public void testTranslateServiceCreationConfiguration() throws Exception { "5368709120" + "10737418240" + ""; - assertElement(inputString, returnElement); - + assertThat(returnElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } @Test @@ -466,7 +468,8 @@ public void testTranslateServiceCreationConfigurationWithNoResourcePoolAndAutoCr "" + "" + ""; - assertElement(inputString, returnElement); + assertThat(returnElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } @Test @@ -486,7 +489,8 @@ public void testTranslateServiceCreationConfigurationWithNoServerSideConfig() th "150" + "" + ""; - assertElement(inputString, returnElement); + assertThat(returnElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } @Test @@ -516,7 +520,8 @@ public void testTranslateServiceCreationConfigurationWithInetSocketAddress() { "5" + "150" + ""; - assertElement(inputString, returnElement); + assertThat(returnElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } /** diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java index 50f0335940..9604112616 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java @@ -19,8 +19,11 @@ import org.ehcache.clustered.common.Consistency; import org.junit.Test; import org.w3c.dom.Node; +import org.xmlunit.diff.DefaultNodeMatcher; +import org.xmlunit.diff.ElementSelectors; -import static org.ehcache.xml.ConfigurationParserTestHelper.assertElement; +import static org.junit.Assert.assertThat; +import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; public class ClusteringCacheServiceConfigurationParserTest { @@ -33,6 +36,7 @@ public void testTranslateServiceStoreConfiguration() { String inputString = ""; - assertElement(inputString, retNode); + assertThat(retNode, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } } diff --git a/management/build.gradle b/management/build.gradle index 3742560078..b2c608d35b 100644 --- a/management/build.gradle +++ b/management/build.gradle @@ -32,7 +32,8 @@ dependencies { testImplementation project(':xml') testImplementation project(':impl') testImplementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" - testCompile project(path: ':xml', configuration: 'testArchives') + testImplementation 'org.xmlunit:xmlunit-core:2.6.0' + testImplementation 'org.xmlunit:xmlunit-matchers:2.6.0' } test { diff --git a/management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java b/management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java index f30d6969ef..c1e7bc65b2 100644 --- a/management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java +++ b/management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java @@ -17,9 +17,7 @@ import org.ehcache.config.Configuration; import org.ehcache.xml.XmlConfiguration; -import org.ehcache.xml.XmlConfigurationTest; import org.junit.Test; -import org.xmlunit.builder.Input; import org.xmlunit.diff.DefaultNodeMatcher; import org.xmlunit.diff.ElementSelectors; @@ -35,11 +33,10 @@ public class ManagementRegistryServiceConfigurationParserIT { @Test public void testManagementRegistryXmlTranslationToString() { - URL resource = XmlConfigurationTest.class.getResource("/ehcache-management.xml"); + URL resource = ManagementRegistryServiceConfigurationParserIT.class.getResource("/ehcache-management.xml"); Configuration config = new XmlConfiguration(resource); XmlConfiguration xmlConfig = new XmlConfiguration(config); - assertThat(xmlConfig.toString(), isSimilarTo(Input.from(resource)).ignoreComments() - .ignoreWhitespace() + assertThat(xmlConfig.toString(), isSimilarTo(resource).ignoreComments().ignoreWhitespace() .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } } diff --git a/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java b/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java index 8ab0af7726..5c5d08ca9c 100644 --- a/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java +++ b/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java @@ -17,8 +17,11 @@ import org.junit.Test; import org.w3c.dom.Node; +import org.xmlunit.diff.DefaultNodeMatcher; +import org.xmlunit.diff.ElementSelectors; -import static org.ehcache.xml.ConfigurationParserTestHelper.assertElement; +import static org.junit.Assert.assertThat; +import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** * ManagementRegistryServiceConfigurationParserTest @@ -37,7 +40,8 @@ public void testTranslateServiceCreationConfiguration() { String inputString = "" + "tag1tag2"; - assertElement(inputString, retElement); + assertThat(retElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } @Test @@ -51,7 +55,8 @@ public void testTranslateServiceCreationConfigurationWithoutTags() { Node retElement = configTranslator.unparseServiceCreationConfiguration(defaultManagementRegistryConfiguration); String inputString = ""; - assertElement(inputString, retElement); + assertThat(retElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } } diff --git a/transactions/build.gradle b/transactions/build.gradle index e3f34ad07a..625980fd9d 100644 --- a/transactions/build.gradle +++ b/transactions/build.gradle @@ -31,7 +31,8 @@ dependencies { } compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':core-spi-test') - testCompile project(path: ':xml', configuration: 'testArchives') + testImplementation 'org.xmlunit:xmlunit-core:2.6.0' + testImplementation 'org.xmlunit:xmlunit-matchers:2.6.0' } // For EhPomMangle diff --git a/transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java b/transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java index 28bb8f247f..99662a1b83 100644 --- a/transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java +++ b/transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java @@ -17,9 +17,7 @@ import org.ehcache.config.Configuration; import org.ehcache.xml.XmlConfiguration; -import org.ehcache.xml.XmlConfigurationTest; import org.junit.Test; -import org.xmlunit.builder.Input; import org.xmlunit.diff.DefaultNodeMatcher; import org.xmlunit.diff.ElementSelectors; @@ -35,10 +33,10 @@ public class TransactionalCacheParserIT { @Test public void testTransactionalCacheXmlTranslationToString() { - URL resource = XmlConfigurationTest.class.getResource("/configs/transactional-cache.xml"); + URL resource = TransactionalCacheParserIT.class.getResource("/configs/transactional-cache.xml"); Configuration config = new XmlConfiguration(resource); XmlConfiguration xmlConfig = new XmlConfiguration(config); - assertThat(xmlConfig.toString(), isSimilarTo(Input.from(resource)).ignoreComments() + assertThat(xmlConfig.toString(), isSimilarTo(resource).ignoreComments() .ignoreWhitespace() .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java index 2c0a8291cd..b52d0c9cbe 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java @@ -19,9 +19,12 @@ import org.ehcache.transactions.xa.txmgr.provider.LookupTransactionManagerProviderConfiguration; import org.junit.Test; import org.w3c.dom.Node; +import org.xmlunit.diff.DefaultNodeMatcher; +import org.xmlunit.diff.ElementSelectors; -import static org.ehcache.xml.ConfigurationParserTestHelper.assertElement; +import static org.junit.Assert.assertThat; +import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** * TxCacheManagerServiceConfigurationParserTest @@ -38,7 +41,8 @@ public void testTranslateServiceCreationConfiguration() { String inputString = ""; - assertElement(inputString, retElement); + assertThat(retElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndAllAttributes))); } } diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java index 4136512cf6..9cd5276ef8 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java @@ -18,8 +18,11 @@ import org.ehcache.transactions.xa.configuration.XAStoreConfiguration; import org.junit.Test; import org.w3c.dom.Node; +import org.xmlunit.diff.DefaultNodeMatcher; +import org.xmlunit.diff.ElementSelectors; -import static org.ehcache.xml.ConfigurationParserTestHelper.assertElement; +import static org.junit.Assert.assertThat; +import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** * TxCacheServiceConfigurationParserTest @@ -34,7 +37,8 @@ public void testTranslateServiceConfiguration() { Node retElement = configTranslator.unparseServiceConfiguration(storeConfiguration); String inputString = ""; - assertElement(inputString, retElement); + assertThat(retElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndAllAttributes))); } } diff --git a/xml/src/test/java/org/ehcache/xml/ConfigurationParserTestHelper.java b/xml/src/test/java/org/ehcache/xml/ConfigurationParserTestHelper.java index 45d40ae19e..4a75ddd7f2 100644 --- a/xml/src/test/java/org/ehcache/xml/ConfigurationParserTestHelper.java +++ b/xml/src/test/java/org/ehcache/xml/ConfigurationParserTestHelper.java @@ -28,8 +28,5 @@ */ public class ConfigurationParserTestHelper { public static void assertElement(String inputString, Node rootElement) { - assertThat(Input.from(rootElement), isSimilarTo(Input.from(inputString)).ignoreComments() - .ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } } diff --git a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java index 1cfba1940f..69845b8f38 100644 --- a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java @@ -55,7 +55,6 @@ import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXParseException; -import org.xmlunit.builder.Input; import org.xmlunit.diff.DefaultNodeMatcher; import org.xmlunit.diff.ElementSelectors; @@ -772,7 +771,7 @@ public void testCompleteXmlToString() { URL resource = XmlConfigurationTest.class.getResource("/configs/ehcache-complete.xml"); Configuration config = new XmlConfiguration(resource); XmlConfiguration xmlConfig = new XmlConfiguration(config); - assertThat(xmlConfig.toString(), isSimilarTo(Input.from(resource)).ignoreComments().ignoreWhitespace().withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(xmlConfig.toString(), isSimilarTo(resource).ignoreComments().ignoreWhitespace().withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } private void checkListenerConfigurationExists(Collection configuration) { From ee9616d2efe18215673ad2cc1a81fa97d7d13e43 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 14 Feb 2019 13:37:17 -0500 Subject: [PATCH 103/372] Support Java 11 for testing --- 107/build.gradle | 6 ----- clustered/client/build.gradle | 6 ----- clustered/integration-test/build.gradle | 7 ++++-- clustered/osgi-test/build.gradle | 11 +++++--- .../java/org/ehcache/osgi/OsgiTestUtils.java | 25 ++++++++++++++----- dist/build.gradle | 4 ++- gradle.properties | 5 ++-- impl/build.gradle | 2 +- integration-test/build.gradle | 6 ----- management/build.gradle | 6 ----- osgi-test/build.gradle | 11 ++++++-- .../java/org/ehcache/osgi/OsgiTestUtils.java | 6 +++++ transactions/build.gradle | 6 ----- xml/build.gradle | 8 ++---- 14 files changed, 56 insertions(+), 53 deletions(-) diff --git a/107/build.gradle b/107/build.gradle index 3f035728b2..f21d19d20e 100644 --- a/107/build.gradle +++ b/107/build.gradle @@ -59,12 +59,6 @@ jar { ) } -test { - if (testJava.javaVersion.isJava9Compatible()) { - jvmArgs += ['--add-modules', 'java.xml.bind'] - } -} - task unpackTckTests(type: Copy) { from { configurations.tckTestClasses.collect {zipTree(it)} diff --git a/clustered/client/build.gradle b/clustered/client/build.gradle index 86a9a108d1..941c7151ea 100644 --- a/clustered/client/build.gradle +++ b/clustered/client/build.gradle @@ -46,9 +46,3 @@ dependencies { testImplementation 'org.xmlunit:xmlunit-core:2.6.0' testImplementation 'org.xmlunit:xmlunit-matchers:2.6.0' } - -test { - if (testJava.javaVersion.isJava9Compatible()) { - jvmArgs += ['--add-modules', 'java.xml.bind'] - } -} diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index ae1c06ee55..56b51ca55a 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -19,7 +19,7 @@ configurations { } dependencies { - // not required by gradle but required by the IDE because 'dist' do not has any transitive dependencies + // not required by gradle but required by the IDE because 'dist' does not have any transitive dependencies testCompileOnly project(':clustered:client') testCompileOnly project(':clustered:common') testCompileOnly project(':impl') @@ -35,6 +35,8 @@ dependencies { testRuntimeOnly project(':clustered:clustered-dist') testRuntimeOnly project(':dist') + testRuntimeOnly "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" + testImplementation (group:'org.terracotta.internal', name:'galvan-support', version: terracottaCoreVersion) testImplementation (group:'com.google.code.tempus-fugit', name:'tempus-fugit', version:'1.1') { exclude group:'junit', module:'junit' @@ -63,12 +65,13 @@ test { dependsOn copyServerLibs environment 'JAVA_HOME', testJava.javaHome if (testJava.javaVersion.isJava9Compatible()) { - jvmArgs += ['--add-modules', 'java.xml.bind'] environment 'JAVA_OPTS', '--add-modules java.xml.bind' } //If this directory does not exist, tests will fail with a cryptic assert failure systemProperty 'kitInstallationPath', "$unzipKit.destinationDir/${project(':clustered:clustered-dist').archivesBaseName}-$project.version-kit" // Uncomment to include client logging in console output // testLogging.showStandardStreams = true +}.doFirst { + if (testJava.javaVersion.isJava11Compatible()) throw new StopExecutionException("Clustered Tests Not Working in Java 11") } diff --git a/clustered/osgi-test/build.gradle b/clustered/osgi-test/build.gradle index f16d5fffa1..d05ea6ff6f 100644 --- a/clustered/osgi-test/build.gradle +++ b/clustered/osgi-test/build.gradle @@ -81,11 +81,16 @@ task unzipKit(type: Copy) { test { dependsOn unzipKit - if (testJava.javaVersion.isJava9Compatible()) throw new StopExecutionException("OSGi Tests Not Working in Java 9") - - environment 'JAVA_HOME', testJava.javaHome + if (testJava.javaVersion.isJava9Compatible()) { + //Deploying the jaxb-runtime as an OSGi module is currently impossible - don't ask... sigh. + jvmArgs += ['--add-modules', 'java.xml.bind'] + //Servers need JAXB too. + jvmArgs += ['-Dtc-server-opts=--add-modules java.xml.bind'] + } systemProperty 'kitInstallationPath', "$unzipKit.destinationDir/${project(':clustered:clustered-dist').archivesBaseName}-$project.version-kit" }.doFirst { + if (testJava.javaVersion.isJava11Compatible()) throw new StopExecutionException("OSGi Tests Not Working in Java 11") + configurations.osgiModule.resolvedConfiguration.resolvedArtifacts.forEach({ systemProperty "$it.moduleVersion.id.module:osgi-path", it.file }) diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java index f8ee55a22f..bb347f3af1 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -36,12 +36,14 @@ import static java.lang.String.join; import static java.nio.file.Files.find; import static java.nio.file.Files.isRegularFile; +import static java.util.Arrays.asList; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.joining; import static org.ops4j.pax.exam.CoreOptions.bundle; import static org.ops4j.pax.exam.CoreOptions.cleanCaches; import static org.ops4j.pax.exam.CoreOptions.composite; import static org.ops4j.pax.exam.CoreOptions.junitBundles; +import static org.ops4j.pax.exam.CoreOptions.systemPackages; import static org.ops4j.pax.exam.CoreOptions.systemProperty; import static org.ops4j.pax.exam.CoreOptions.workingDirectory; import static org.ops4j.pax.exam.CoreOptions.wrappedBundle; @@ -54,6 +56,11 @@ public static Option baseConfiguration(String ... path) { gradleBundle("org.slf4j:slf4j-simple").noStart(), gradleBundle("org.apache.felix:org.apache.felix.scr"), systemProperty("pax.exam.osgi.unresolved.fail").value("true"), + systemPackages( + "javax.xml.bind;version=2.3.0", + "javax.xml.bind.annotation;version=2.3.0", + "javax.xml.bind.annotation.adapters;version=2.3.0" + ), cleanCaches(true), workingDirectory(join(File.separator, "build", "osgi-container", join(File.separator, path))), junitBundles() @@ -123,12 +130,18 @@ public static Cluster startServer(Path serverDirectory) throws IOException { ProcessBuilder serverProcess = new ProcessBuilder() .directory(serverDirectory.toFile()) .command(Paths.get(System.getProperty("java.home")).resolve("bin") - .resolve(System.getProperty("os.name").contains("Windows") ? "java.exe" : "java").toString(), - "-Dtc.install-root=" + serverDir, - "-cp", serverDir.resolve("lib").resolve("tc.jar") + File.pathSeparator + pluginClasspath, - "com.tc.server.TCServerMain", - "-f", configFile.toString()) - .inheritIO(); + .resolve(System.getProperty("os.name").contains("Windows") ? "java.exe" : "java").toString()); + + String tcServerOptions = System.getProperty("tc-server-opts"); + if (tcServerOptions != null) { + serverProcess.command().addAll(asList(tcServerOptions.split("\\s"))); + } + serverProcess.command().addAll(asList( + "-Dtc.install-root=" + serverDir, + "-cp", serverDir.resolve("lib").resolve("tc.jar") + File.pathSeparator + pluginClasspath, + "com.tc.server.TCServerMain", + "-f", configFile.toString())); + serverProcess.inheritIO(); return new Cluster(serverProcess.start(), URI.create("terracotta://localhost:" + tsaPort), serverDirectory); } diff --git a/dist/build.gradle b/dist/build.gradle index a00ef74888..d33cec4345 100644 --- a/dist/build.gradle +++ b/dist/build.gradle @@ -29,6 +29,8 @@ apply plugin: EhDistribute dependencies { shadowCompile "org.slf4j:slf4j-api:$parent.slf4jVersion" + shadowCompile "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" + shadowProvided "javax.cache:cache-api:$parent.jcacheVersion" } jar { @@ -39,6 +41,6 @@ jar { 'Bundle-Activator': 'org.ehcache.core.osgi.EhcacheActivator', 'Export-Package': '!org.ehcache.jsr107.tck, !org.ehcache.*.internal.*, org.ehcache.*, org.terracotta.statistics.*, org.terracotta.context', - 'Import-Package': 'javax.cache.*;resolution:=optional, !sun.misc, *' + 'Import-Package': 'javax.cache.*;resolution:=optional, !javax.annotation, !sun.misc, *' ) } diff --git a/gradle.properties b/gradle.properties index 59aad6f84e..a480cf212e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,6 +7,7 @@ statisticVersion = 2.1 jcacheVersion = 1.1.0 slf4jVersion = 1.7.25 sizeofVersion = 0.3.0 +jaxbVersion = 2.3.1 # Terracotta clustered terracottaPlatformVersion = 5.6.0-pre10 @@ -18,14 +19,14 @@ terracottaPassthroughTestingVersion = 1.6.0-pre3 junitVersion = 4.12 assertjVersion = 3.9.0 hamcrestVersion = 1.3 -mockitoVersion = 2.13.0 +mockitoVersion = 2.23.4 jacksonVersion = 2.7.5 jcacheTckVersion = 1.1.0 # Tools spotbugsVersion = 3.1.3 checkstyleVersion = 5.9 -jacocoVersion = 0.8.1 +jacocoVersion = 0.8.3 sonatypeUser = OVERRIDE_ME sonatypePwd = OVERRIDE_ME diff --git a/impl/build.gradle b/impl/build.gradle index c7429bd6f8..6cef711075 100644 --- a/impl/build.gradle +++ b/impl/build.gradle @@ -36,7 +36,7 @@ jar { bnd ( 'Export-Package': '!org.ehcache.impl.internal.*, org.ehcache.impl.*, org.ehcache.config.builders, ' + 'org.ehcache.impl.internal.spi.loaderwriter', //ugly 107 induced internal export wart - 'Import-Package': '!sun.misc, *', + 'Import-Package': '!sun.misc, !javax.annotation, *', 'Service-Component': 'OSGI-INF/*.xml' ) } diff --git a/integration-test/build.gradle b/integration-test/build.gradle index c210ed9d51..13d536b828 100644 --- a/integration-test/build.gradle +++ b/integration-test/build.gradle @@ -24,9 +24,3 @@ dependencies { } testImplementation "org.terracotta:statistics:$parent.statisticVersion" } - -test { - if (testJava.javaVersion.isJava9Compatible()) { - jvmArgs += ['--add-modules', 'java.xml.bind'] - } -} diff --git a/management/build.gradle b/management/build.gradle index b2c608d35b..c1cb9330c0 100644 --- a/management/build.gradle +++ b/management/build.gradle @@ -35,9 +35,3 @@ dependencies { testImplementation 'org.xmlunit:xmlunit-core:2.6.0' testImplementation 'org.xmlunit:xmlunit-matchers:2.6.0' } - -test { - if (testJava.javaVersion.isJava9Compatible()) { - jvmArgs += ['--add-modules', 'java.xml.bind'] - } -} diff --git a/osgi-test/build.gradle b/osgi-test/build.gradle index eca61490de..ad9dc637c7 100644 --- a/osgi-test/build.gradle +++ b/osgi-test/build.gradle @@ -74,8 +74,15 @@ configurations.osgiModule.dependencies.withType(ProjectDependency).forEach { test.dependsOn it.dependencyProject.tasks.jar } -test.doFirst { - if (testJava.javaVersion.isJava9Compatible()) throw new StopExecutionException("OSGi Tests Not Working in Java 9") +test { + if (testJava.javaVersion.isJava9Compatible()) { + //Deploying the jaxb-runtime as an OSGi module is currently impossible - don't ask... sigh. + jvmArgs += ['--add-modules', 'java.xml.bind'] + //https://issues.apache.org/jira/browse/FELIX-5727 - framework extensions in Java 9 are ugly + jvmArgs += ['--add-opens=java.base/jdk.internal.loader=ALL-UNNAMED'] + } +}.doFirst { + if (testJava.javaVersion.isJava11Compatible()) throw new StopExecutionException("OSGi Tests Not Working in Java 11") configurations.osgiModule.resolvedConfiguration.resolvedArtifacts.forEach({ systemProperty "$it.moduleVersion.id.module:osgi-path", it.file diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java index b017d13227..476d2efc41 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -31,6 +31,7 @@ import static org.ops4j.pax.exam.CoreOptions.cleanCaches; import static org.ops4j.pax.exam.CoreOptions.composite; import static org.ops4j.pax.exam.CoreOptions.junitBundles; +import static org.ops4j.pax.exam.CoreOptions.systemPackages; import static org.ops4j.pax.exam.CoreOptions.systemProperty; import static org.ops4j.pax.exam.CoreOptions.workingDirectory; import static org.ops4j.pax.exam.CoreOptions.wrappedBundle; @@ -43,6 +44,11 @@ public static Option baseConfiguration(String ... path) { gradleBundle("org.slf4j:slf4j-simple").noStart(), gradleBundle("org.apache.felix:org.apache.felix.scr"), systemProperty("pax.exam.osgi.unresolved.fail").value("true"), + systemPackages( + "javax.xml.bind;version=2.3.0", + "javax.xml.bind.annotation;version=2.3.0", + "javax.xml.bind.annotation.adapters;version=2.3.0" + ), cleanCaches(true), workingDirectory(join(File.separator, "build", "osgi-container", join(File.separator, path))), junitBundles() diff --git a/transactions/build.gradle b/transactions/build.gradle index 625980fd9d..57d682cff6 100644 --- a/transactions/build.gradle +++ b/transactions/build.gradle @@ -41,12 +41,6 @@ dependencies { pomOnlyProvided 'javax.transaction:jta:1.1', 'org.codehaus.btm:btm:2.1.4' } -test { - if (testJava.javaVersion.isJava9Compatible()) { - jvmArgs += ['--add-modules', 'java.xml.bind'] - } -} - jar { bnd ( 'Bundle-SymbolicName': 'org.ehcache.transactions', diff --git a/xml/build.gradle b/xml/build.gradle index c46743f1f3..abdda0b208 100644 --- a/xml/build.gradle +++ b/xml/build.gradle @@ -27,17 +27,13 @@ dependencies { api project(':api') implementation project(':core') implementation project(':impl') + implementation "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" + testImplementation 'org.xmlunit:xmlunit-core:2.6.0', 'org.xmlunit:xmlunit-matchers:2.6.0' xjcClasspath 'org.jvnet.jaxb2_commons:jaxb2-fluent-api:3.0' xjcClasspath 'org.jvnet.jaxb2_commons:jaxb2-basics-annotate:1.1.0' } -test { - if (testJava.javaVersion.isJava9Compatible()) { - jvmArgs += ['--add-modules', 'java.xml.bind'] - } -} - jar { bnd ( 'Export-Package': 'org.ehcache.xml, org.ehcache.xml.exceptions, org.ehcache.xml.model', From 2c1695bd05fdec61e4a87658a3a1096b19af89b8 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 15 Feb 2019 17:02:11 -0500 Subject: [PATCH 104/372] Fixes #2345 : Allow Java Language style syntax for arrays, primitives and inner classes --- .../ehcache/core/util/ClassLoadingTest.java | 51 +++++++----- .../org/ehcache/xml/XmlConfiguration.java | 81 ++++++++++++++++++- .../org/ehcache/xml/XmlConfigurationTest.java | 76 +++++++++++++++++ .../resources/configs/pretty-typed-caches.xml | 45 +++++++++++ 4 files changed, 227 insertions(+), 26 deletions(-) create mode 100644 xml/src/test/resources/configs/pretty-typed-caches.xml diff --git a/core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java b/core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java index 94370a415d..cf8a9216f8 100644 --- a/core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java +++ b/core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java @@ -17,6 +17,7 @@ package org.ehcache.core.util; import static java.util.Collections.list; +import static org.ehcache.core.util.ClassLoading.getDefaultClassLoader; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; import static org.hamcrest.core.Is.is; import static org.junit.Assert.*; @@ -26,6 +27,7 @@ import java.io.InputStream; import java.net.URL; import java.util.Enumeration; +import java.util.Map; import java.util.Vector; import org.junit.Test; @@ -34,28 +36,33 @@ public class ClassLoadingTest { @Test public void testDefaultClassLoader() throws Exception { - String resource = getClass().getName().replace('.', '/').concat(".class"); - ClassLoader thisLoader = getClass().getClassLoader(); - ClassLoader defaultClassLoader = ClassLoading.getDefaultClassLoader(); - - Thread.currentThread().setContextClassLoader(null); - assertSame(thisLoader.loadClass(getClass().getName()), defaultClassLoader.loadClass(getClass().getName())); - assertEquals(thisLoader.getResource(resource), defaultClassLoader.getResource(resource)); - assertThat(list(defaultClassLoader.getResources(resource)), is(list(thisLoader.getResources(resource)))); - - Thread.currentThread().setContextClassLoader(new FindNothingLoader()); - assertSame(thisLoader.loadClass(getClass().getName()), defaultClassLoader.loadClass(getClass().getName())); - assertEquals(thisLoader.getResource(resource), defaultClassLoader.getResource(resource)); - assertThat(list(defaultClassLoader.getResources(resource)), is(list(thisLoader.getResources(resource)))); - - URL url = new URL("file:///tmp"); - ClassLoader tc = new TestClassLoader(url); - Thread.currentThread().setContextClassLoader(tc); - Class c = defaultClassLoader.loadClass(getClass().getName()); - assertNotSame(getClass(), c); - assertSame(tc, c.getClassLoader()); - assertEquals(url, defaultClassLoader.getResource(resource)); - assertThat(list(defaultClassLoader.getResources(resource)), contains(url, thisLoader.getResource(resource))); + ClassLoader originalTccl = Thread.currentThread().getContextClassLoader(); + try { + String resource = getClass().getName().replace('.', '/').concat(".class"); + ClassLoader thisLoader = getClass().getClassLoader(); + ClassLoader defaultClassLoader = getDefaultClassLoader(); + + Thread.currentThread().setContextClassLoader(null); + assertSame(thisLoader.loadClass(getClass().getName()), defaultClassLoader.loadClass(getClass().getName())); + assertEquals(thisLoader.getResource(resource), defaultClassLoader.getResource(resource)); + assertThat(list(defaultClassLoader.getResources(resource)), is(list(thisLoader.getResources(resource)))); + + Thread.currentThread().setContextClassLoader(new FindNothingLoader()); + assertSame(thisLoader.loadClass(getClass().getName()), defaultClassLoader.loadClass(getClass().getName())); + assertEquals(thisLoader.getResource(resource), defaultClassLoader.getResource(resource)); + assertThat(list(defaultClassLoader.getResources(resource)), is(list(thisLoader.getResources(resource)))); + + URL url = new URL("file:///tmp"); + ClassLoader tc = new TestClassLoader(url); + Thread.currentThread().setContextClassLoader(tc); + Class c = defaultClassLoader.loadClass(getClass().getName()); + assertNotSame(getClass(), c); + assertSame(tc, c.getClassLoader()); + assertEquals(url, defaultClassLoader.getResource(resource)); + assertThat(list(defaultClassLoader.getResources(resource)), contains(url, thisLoader.getResource(resource))); + } finally { + Thread.currentThread().setContextClassLoader(originalTccl); + } } @SafeVarargs diff --git a/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java b/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java index ac99366163..7feac9be08 100644 --- a/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java +++ b/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java @@ -26,14 +26,20 @@ import org.ehcache.xml.exceptions.XmlConfigurationException; import org.w3c.dom.Document; +import java.lang.reflect.Array; import java.net.URL; import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.function.Predicate; +import static java.lang.Class.forName; +import static java.util.Arrays.asList; import static java.util.Collections.emptyMap; import static java.util.Objects.requireNonNull; import static org.ehcache.xml.ConfigurationParser.documentToText; +import static org.ehcache.xml.XmlConfiguration.PrettyClassFormat.when; /** * Exposes {@link org.ehcache.config.Configuration} and {@link CacheConfigurationBuilder} expressed @@ -335,10 +341,6 @@ public CacheConfigurationBuilder newCacheConfigurationBuilderFromTe return newCacheConfigurationBuilderFromTemplate(name, keyType, valueType, resourcePoolsBuilder.build()); } - public static Class getClassForName(String name, ClassLoader classLoader) throws ClassNotFoundException { - return Class.forName(name, true, classLoader); - } - @Override public Map> getCacheConfigurations() { return configuration.getCacheConfigurations(); @@ -357,4 +359,75 @@ public ClassLoader getClassLoader() { public interface Template { CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resourcePools) throws ClassNotFoundException, InstantiationException, IllegalAccessException; } + + public static Class getClassForName(String name, ClassLoader classLoader) throws ClassNotFoundException { + return PRETTY_FORMATS.stream().filter(p -> p.applies().test(name)).findFirst().map(PrettyClassFormat::lookup).orElseThrow(AssertionError::new).lookup(name, classLoader); + } + + private static final List PRETTY_FORMATS = asList( + //Primitive Types + when("boolean"::equals).then((n, l) -> Boolean.TYPE), + when("byte"::equals).then((n, l) -> Byte.TYPE), + when("short"::equals).then((n, l) -> Short.TYPE), + when("int"::equals).then((n, l) -> Integer.TYPE), + when("long"::equals).then((n, l) -> Long.TYPE), + when("char"::equals).then((n, l) -> Character.TYPE), + when("float"::equals).then((n, l) -> Float.TYPE), + when("double"::equals).then((n, l) -> Double.TYPE), + + //Java Language Array Syntax + when(n -> n.endsWith("[]")).then((n, l) -> { + String component = n.split("(\\[\\])+$", 2)[0]; + int dimensions = (n.length() - component.length()) >> 1; + return Array.newInstance(getClassForName(component, l), new int[dimensions]).getClass(); + }), + + //Inner Classes + when(n -> n.contains(".")).then((n, l) -> { + try { + return forName(n, false, l); + } catch (ClassNotFoundException e) { + int innerSeperator = n.lastIndexOf("."); + if (innerSeperator == -1) { + throw e; + } else { + return forName(n.substring(0, innerSeperator) + "$" + n.substring(innerSeperator + 1), false, l); + } + } + }), + + //Everything Else + when(n -> true).then((n, l) -> forName(n, false, l)) + ); + + interface PrettyClassFormat { + + static Builder when(Predicate predicate) { + return lookup -> new PrettyClassFormat() { + @Override + public Predicate applies() { + return predicate; + } + + @Override + public Lookup lookup() { + return lookup; + } + }; + } + + Predicate applies(); + + Lookup lookup(); + + interface Builder { + PrettyClassFormat then(Lookup lookup); + } + } + + private interface Lookup { + + Class lookup(String name, ClassLoader loader) throws ClassNotFoundException; + } + } diff --git a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java index 69845b8f38..f94638e6c1 100644 --- a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java @@ -47,6 +47,7 @@ import org.hamcrest.CoreMatchers; import org.hamcrest.Matchers; import org.hamcrest.core.IsCollectionContaining; +import org.hamcrest.core.IsEqual; import org.hamcrest.core.IsNull; import org.junit.Rule; import org.junit.Test; @@ -92,6 +93,8 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; +import static org.ehcache.core.util.ClassLoading.getDefaultClassLoader; +import static org.ehcache.xml.XmlConfiguration.getClassForName; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; @@ -774,6 +777,79 @@ public void testCompleteXmlToString() { assertThat(xmlConfig.toString(), isSimilarTo(resource).ignoreComments().ignoreWhitespace().withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } + @Test + public void testPrettyTypeNames() { + URL resource = XmlConfigurationTest.class.getResource("/configs/pretty-typed-caches.xml"); + Configuration config = new XmlConfiguration(new XmlConfiguration(resource)); + + CacheConfiguration byteArray = config.getCacheConfigurations().get("byte-array"); + assertThat(byteArray.getValueType(), equalTo(byte[].class)); + + CacheConfiguration stringArray = config.getCacheConfigurations().get("string-array"); + assertThat(stringArray.getValueType(), equalTo(String[].class)); + + CacheConfiguration string2dArray = config.getCacheConfigurations().get("string-2d-array"); + assertThat(string2dArray.getValueType(), equalTo(String[][].class)); + + CacheConfiguration mapEntry = config.getCacheConfigurations().get("map-entry"); + assertThat(mapEntry.getValueType(), equalTo(Map.Entry.class)); + } + + @Test + public void testPrimitiveNameConversion() throws ClassNotFoundException { + assertThat(getClassForName("boolean", getDefaultClassLoader()), IsEqual.equalTo(Boolean.TYPE)); + assertThat(getClassForName("byte", getDefaultClassLoader()), IsEqual.equalTo(Byte.TYPE)); + assertThat(getClassForName("short", getDefaultClassLoader()), IsEqual.equalTo(Short.TYPE)); + assertThat(getClassForName("int", getDefaultClassLoader()), IsEqual.equalTo(Integer.TYPE)); + assertThat(getClassForName("long", getDefaultClassLoader()), IsEqual.equalTo(Long.TYPE)); + assertThat(getClassForName("char", getDefaultClassLoader()), IsEqual.equalTo(Character.TYPE)); + assertThat(getClassForName("float", getDefaultClassLoader()), IsEqual.equalTo(Float.TYPE)); + assertThat(getClassForName("double", getDefaultClassLoader()), IsEqual.equalTo(Double.TYPE)); + } + + @Test + public void testPrimitiveArrayClassNameConversion() throws ClassNotFoundException { + assertThat(getClassForName("boolean[]", getDefaultClassLoader()), IsEqual.equalTo(boolean[].class)); + assertThat(getClassForName("byte[]", getDefaultClassLoader()), IsEqual.equalTo(byte[].class)); + assertThat(getClassForName("short[]", getDefaultClassLoader()), IsEqual.equalTo(short[].class)); + assertThat(getClassForName("int[]", getDefaultClassLoader()), IsEqual.equalTo(int[].class)); + assertThat(getClassForName("long[]", getDefaultClassLoader()), IsEqual.equalTo(long[].class)); + assertThat(getClassForName("char[]", getDefaultClassLoader()), IsEqual.equalTo(char[].class)); + assertThat(getClassForName("float[]", getDefaultClassLoader()), IsEqual.equalTo(float[].class)); + assertThat(getClassForName("double[]", getDefaultClassLoader()), IsEqual.equalTo(double[].class)); + } + + @Test + public void testMultiDimensionPrimitiveArrayClassNameConversion() throws ClassNotFoundException { + assertThat(getClassForName("byte[][][][]", getDefaultClassLoader()), IsEqual.equalTo(byte[][][][].class)); + assertThat(getClassForName("short[][][][]", getDefaultClassLoader()), IsEqual.equalTo(short[][][][].class)); + assertThat(getClassForName("int[][][][]", getDefaultClassLoader()), IsEqual.equalTo(int[][][][].class)); + assertThat(getClassForName("long[][][][]", getDefaultClassLoader()), IsEqual.equalTo(long[][][][].class)); + assertThat(getClassForName("char[][][][]", getDefaultClassLoader()), IsEqual.equalTo(char[][][][].class)); + assertThat(getClassForName("float[][][][]", getDefaultClassLoader()), IsEqual.equalTo(float[][][][].class)); + assertThat(getClassForName("double[][][][]", getDefaultClassLoader()), IsEqual.equalTo(double[][][][].class)); + } + + @Test + public void testArrayClassNameConversion() throws ClassNotFoundException { + assertThat(getClassForName("java.lang.String[]", getDefaultClassLoader()), IsEqual.equalTo(String[].class)); + } + + @Test + public void testMultiDimensionArrayClassNameConversion() throws ClassNotFoundException { + assertThat(getClassForName("java.lang.String[][][][]", getDefaultClassLoader()), IsEqual.equalTo(String[][][][].class)); + } + + @Test + public void testInnerClassNameConversion() throws ClassNotFoundException { + assertThat(getClassForName("java.util.Map.Entry", getDefaultClassLoader()), IsEqual.equalTo(Map.Entry.class)); + } + + @Test + public void testInnerClassNameArrayConversion() throws ClassNotFoundException { + assertThat(getClassForName("java.util.Map.Entry[]", getDefaultClassLoader()), IsEqual.equalTo(Map.Entry[].class)); + } + private void checkListenerConfigurationExists(Collection configuration) { int count = 0; for (Object o : configuration) { diff --git a/xml/src/test/resources/configs/pretty-typed-caches.xml b/xml/src/test/resources/configs/pretty-typed-caches.xml new file mode 100644 index 0000000000..39f4f41045 --- /dev/null +++ b/xml/src/test/resources/configs/pretty-typed-caches.xml @@ -0,0 +1,45 @@ + + + + + + java.lang.Integer + byte[] + 5 + + + + java.lang.String + java.lang.String[] + 5 + + + + java.lang.String + java.lang.String[][] + 5 + + + + java.lang.String + java.util.Map.Entry + 5 + + From dff689dc20840473c0eb62d53567528b0e5d4583 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 22 Feb 2019 14:05:43 -0500 Subject: [PATCH 105/372] Issue #2296 : Passive sync related messages must be loaded by the component loader --- .../server/internal/messages/EhcacheMessageTrackerMessage.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java b/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java index ac50a4ca2d..6dbe39f15b 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java @@ -16,6 +16,7 @@ package org.ehcache.clustered.server.internal.messages; +import com.tc.classloader.CommonComponent; import org.ehcache.clustered.common.internal.messages.EhcacheEntityMessage; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse; import org.terracotta.client.message.tracker.OOOMessageHandler; @@ -29,6 +30,7 @@ * Message sending messages that are tracked for duplication. If a passive becoming active receives * a duplicate, it needs to discard it. */ +@CommonComponent public class EhcacheMessageTrackerMessage extends EhcacheSyncMessage { private final Map> trackedMessages; From aa61233f6c6478f72be1a9faf969b3124a6b99a5 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 22 Feb 2019 14:02:53 -0500 Subject: [PATCH 106/372] Issue #2296 : Passive sync related messages must be loaded by the component loader --- .../BasicClusteredCacheOpsReplicationMultiThreadedTest.java | 3 +++ .../server/internal/messages/EhcacheStateRepoSyncMessage.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index a7cd8dca36..17f4c16dc6 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -121,6 +121,9 @@ public void startServers() throws Exception { @After public void tearDown() throws Exception { + CLUSTER.getClusterControl().startAllServers(); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); + CACHE_MANAGER1.close(); CACHE_MANAGER2.close(); CACHE_MANAGER2.destroy(); diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java b/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java index ddaed046c0..35afc90552 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java @@ -16,11 +16,14 @@ package org.ehcache.clustered.server.internal.messages; +import com.tc.classloader.CommonComponent; + import java.util.concurrent.ConcurrentMap; /** * EhcacheStateRepoSyncMessage */ +@CommonComponent public class EhcacheStateRepoSyncMessage extends EhcacheSyncMessage { private final String cacheId; From 123319cc6b42238e7a006c12aef9732f40d45dda Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 22 Feb 2019 23:36:18 -0500 Subject: [PATCH 107/372] Issue #2588 : Use HTTPS for the Terracotta Maven repository --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index cbc475838a..de6e4ac186 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,7 @@ subprojects { repositories { mavenLocal() mavenCentral() - maven { url "http://repo.terracotta.org/maven2" } + maven { url "https://repo.terracotta.org/maven2" } } sourceSets { From 4f85312388a1ef9b1367875f76f5fda8268b26d3 Mon Sep 17 00:00:00 2001 From: Abhilash Date: Mon, 25 Feb 2019 15:26:03 +0530 Subject: [PATCH 108/372] Clustered Caching supports write-behind #2458 --- docs/src/docs/asciidoc/user/writers.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/docs/asciidoc/user/writers.adoc b/docs/src/docs/asciidoc/user/writers.adoc index 4284dc45cb..393032a99b 100644 --- a/docs/src/docs/asciidoc/user/writers.adoc +++ b/docs/src/docs/asciidoc/user/writers.adoc @@ -12,8 +12,6 @@ endif::notBuildingForSite[] [[introduction]] == Introduction to Cache Loaders and Writers -NOTE: Ehcache clustering is not yet compatible with _cache-through_. - This section documents the specifics behind the cache-through implementation in Ehcache. Refer to the section <> if you are not familiar with terms like _cache-through_, _read-through_, _write-through_ or _system of record_. @@ -98,3 +96,5 @@ include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[t <5> Define the concurrency level of write-behind queue(s). This indicates how many writer threads work in parallel to update the underlying system of record asynchronously. <6> Enable the write coalescing behavior, which ensures that only one update per key per batch reaches the underlying system of record. + +NOTE: `BatchedWriteBehindConfigurationBuilder` configurations are not honoured by clustered caches. From 659ce95eb99ca85cc1340d51fcebfb4b0ac92a86 Mon Sep 17 00:00:00 2001 From: Anthony Dahanne Date: Mon, 25 Feb 2019 15:25:52 -0500 Subject: [PATCH 109/372] Upgrade to final versions --- gradle.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 307fae0bac..7f8b36cb45 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,10 +9,10 @@ slf4jVersion = 1.7.25 sizeofVersion = 0.3.0 # Terracotta clustered -terracottaPlatformVersion = 5.6.0-pre10 -terracottaApisVersion = 1.6.0-pre3 -terracottaCoreVersion = 5.6.0-pre12 -terracottaPassthroughTestingVersion = 1.6.0-pre3 +terracottaPlatformVersion = 5.6.0 +terracottaApisVersion = 1.6.0 +terracottaCoreVersion = 5.6.0 +terracottaPassthroughTestingVersion = 1.6.0 # Test lib versions junitVersion = 4.12 From 0d53a0d3ff4690d1d5d0d6a499a41d969edec775 Mon Sep 17 00:00:00 2001 From: Anthony Dahanne Date: Mon, 25 Feb 2019 19:49:04 -0500 Subject: [PATCH 110/372] Update readme --- README.adoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.adoc b/README.adoc index f9de4e9bb5..14bf9f4f29 100644 --- a/README.adoc +++ b/README.adoc @@ -12,16 +12,16 @@ For samples, documentation, and usage information, please see http://ehcache.org == Current release -We released 3.6.1 on September 21st 2018. +We released 3.7.0 on February 25th 2019. -The https://github.com/ehcache/ehcache3/releases/tag/v3.6.1[release notes] contain the links to the artifacts and the documentation to help you get started. +The https://github.com/ehcache/ehcache3/releases/tag/v3.7.0[release notes] contain the links to the artifacts and the documentation to help you get started. -You should consider upgrading to 3.6.x as it does all previous 3.x do and more with a fully compatible API. +You should consider upgrading to 3.7.x as it does all previous 3.x do and more with a fully compatible API. The only thing to note compared to 3.0.x is that transactional support has been moved to a separate jar. == Current development & next release -We are still working on the missing features of the clustering tier of Ehcache 3 which will be included in upcoming releases. +We released the missing features of the clustering tier of Ehcache 3 in 3.7.0. Starting with version 3.5, Ehcache only supports Java 8 and later. From 9e450d09df4e95cce7e4e13d371b711a61d24d94 Mon Sep 17 00:00:00 2001 From: Abhilash Date: Fri, 8 Feb 2019 18:28:13 +0530 Subject: [PATCH 111/372] Don't wrap ServerStoreProxyException in RuntimeException #2552 --- .../store/StrongServerStoreProxy.java | 6 +++ .../store/StrongServerStoreProxyTest.java | 40 ++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java index 1ecc5cc694..a8a515dd7a 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java @@ -121,6 +121,9 @@ private T performWaitingForHashInvalidation(long key, Callable c, Duratio if (ex instanceof TimeoutException) { throw (TimeoutException)ex; } + if (ex instanceof ServerStoreProxyException) { + throw (ServerStoreProxyException)ex; + } throw new RuntimeException(ex); } } @@ -156,6 +159,9 @@ private T performWaitingForAllInvalidation(Callable c, Duration timeout) if (ex instanceof TimeoutException) { throw (TimeoutException)ex; } + if (ex instanceof ServerStoreProxyException) { + throw (ServerStoreProxyException)ex; + } throw new RuntimeException(ex); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java index 2b85a3b2ea..f1ff660355 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java @@ -16,6 +16,7 @@ package org.ehcache.clustered.client.internal.store; import org.ehcache.clustered.client.config.ClusteredResourcePool; +import org.ehcache.clustered.client.config.Timeouts; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.internal.store.ServerStoreProxy.ServerCallback; import org.ehcache.clustered.common.Consistency; @@ -25,6 +26,7 @@ import org.ehcache.impl.serialization.LongSerializer; import org.junit.Ignore; import org.junit.Test; +import org.terracotta.exception.ConnectionClosedException; import java.util.List; import java.util.concurrent.Callable; @@ -44,7 +46,8 @@ import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; public class StrongServerStoreProxyTest extends AbstractServerStoreProxyTest { @@ -385,4 +388,39 @@ public Chain compact(Chain chain) { assertThat(re.getCause(), instanceOf(IllegalStateException.class)); } } + + @Test + public void testAppendThrowsConnectionClosedExceptionDuringHashInvalidation() throws Exception { + SimpleClusterTierClientEntity clientEntity1 = mock(SimpleClusterTierClientEntity.class); + StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testAppendThrowsConnectionClosedExceptionDuringHashInvalidation", clientEntity1, mock(ServerCallback.class)); + doThrow(new ConnectionClosedException("Test")).when(clientEntity1).invokeAndWaitForReceive(any(), anyBoolean()); + when(clientEntity1.getTimeouts()).thenReturn(Timeouts.DEFAULT); + when(clientEntity1.isConnected()).thenReturn(true); + try { + serverStoreProxy1.append(1L, createPayload(1L)); + fail("Expected ServerStoreProxyException"); + } catch (ServerStoreProxyException e) { + assertThat(e.getCause(), instanceOf(ConnectionClosedException.class)); + } catch (RuntimeException e) { + fail("Expected ServerStoreProxyException"); + } + } + + @Test + public void testClearThrowsConnectionClosedExceptionDuringAllInvaildation() throws Exception { + SimpleClusterTierClientEntity clientEntity1 = mock(SimpleClusterTierClientEntity.class); + StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testClearThrowsConnectionClosedExceptionDuringAllInvaildation", clientEntity1, mock(ServerCallback.class)); + doThrow(new ConnectionClosedException("Test")).when(clientEntity1).invokeAndWaitForRetired(any(), anyBoolean()); + when(clientEntity1.getTimeouts()).thenReturn(Timeouts.DEFAULT); + when(clientEntity1.isConnected()).thenReturn(true); + try { + serverStoreProxy1.clear(); + fail("Expected ServerStoreProxyException"); + } catch (ServerStoreProxyException e) { + assertThat(e.getCause(), instanceOf(ConnectionClosedException.class)); + } catch (RuntimeException e) { + fail("Expected ServerStoreProxyException"); + } + } + } From 5ca09e387bcacd449a0902ac6361dbd0b43a6d47 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 4 Mar 2019 08:58:48 -0500 Subject: [PATCH 112/372] Upgrade to org.jayware.osgi-ds 0.5.6 to pick up fix for jayware/gradle-osgi-ds#6 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e798721546..4ef869626d 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ plugins { // Declare spotbugs at the top id 'com.github.spotbugs' version '1.6.5' apply false // Declare osgi-ds at the top - id 'org.jayware.osgi-ds' version '0.5.5' apply false + id 'org.jayware.osgi-ds' version '0.5.6' apply false } wrapper { From ac9823c45ad2404ef5d33b9f67decefc83be9c2e Mon Sep 17 00:00:00 2001 From: Anthony Dahanne Date: Mon, 4 Mar 2019 13:26:02 -0500 Subject: [PATCH 113/372] Fix 3.7.0 release documentation --- .../src/assemble/server/conf/tc-config.xml | 3 ++ deploy.sh | 2 +- docs/src/docs/asciidoc/user/107.adoc | 24 +++++++-------- .../asciidoc/user/cache-event-listeners.adoc | 10 +++---- .../docs/asciidoc/user/caching-concepts.adoc | 4 +-- .../docs/asciidoc/user/caching-patterns.adoc | 4 +-- .../src/docs/asciidoc/user/caching-terms.adoc | 4 +-- .../src/docs/asciidoc/user/class-loading.adoc | 4 +-- .../docs/asciidoc/user/clustered-cache.adoc | 22 +++++++------- docs/src/docs/asciidoc/user/common.adoc | 6 ++-- .../docs/asciidoc/user/eviction-advisor.adoc | 6 ++-- docs/src/docs/asciidoc/user/examples.adoc | 6 ++-- docs/src/docs/asciidoc/user/expiry.adoc | 14 ++++----- .../docs/asciidoc/user/getting-started.adoc | 20 ++++++------- docs/src/docs/asciidoc/user/index.adoc | 10 +++---- docs/src/docs/asciidoc/user/management.adoc | 12 ++++---- .../docs/asciidoc/user/migration-guide.adoc | 6 ++-- docs/src/docs/asciidoc/user/osgi.adoc | 4 +-- docs/src/docs/asciidoc/user/resilience.adoc | 6 ++-- .../asciidoc/user/serializers-copiers.adoc | 8 ++--- docs/src/docs/asciidoc/user/thread-pools.adoc | 12 ++++---- docs/src/docs/asciidoc/user/tiering.adoc | 24 +++++++-------- docs/src/docs/asciidoc/user/usermanaged.adoc | 14 ++++----- docs/src/docs/asciidoc/user/writers.adoc | 8 ++--- docs/src/docs/asciidoc/user/xa.adoc | 18 +++++------ docs/src/docs/asciidoc/user/xml.adoc | 30 +++++++++---------- docs/src/docs/asciidoc/user/xsds.adoc | 12 ++++---- 27 files changed, 148 insertions(+), 145 deletions(-) diff --git a/clustered/clustered-dist/src/assemble/server/conf/tc-config.xml b/clustered/clustered-dist/src/assemble/server/conf/tc-config.xml index 731ef5efcf..a342215c9f 100644 --- a/clustered/clustered-dist/src/assemble/server/conf/tc-config.xml +++ b/clustered/clustered-dist/src/assemble/server/conf/tc-config.xml @@ -55,4 +55,7 @@ --> 120 + + + diff --git a/deploy.sh b/deploy.sh index 88f53dda29..322399b46e 100755 --- a/deploy.sh +++ b/deploy.sh @@ -208,7 +208,7 @@ if [ $is_major ]; then echo " layout: \"docs35_page\"" >> _config.yml echo " ehc_version: \"${major_version}\"" >> _config.yml echo " ehc_javadoc_version: \"${version}\"" >> _config.yml - echo " ehc_checkout_dir_var: \"sourcedir36\"" >> _config.yml + echo " ehc_checkout_dir_var: \"sourcedir37\"" >> _config.yml sed -i '' "s/#needle\_for\_sourcedir/ - sourcedir${short_major_version}=\/_eh${short_major_version}\\ #needle_for_sourcedir/" _config.yml diff --git a/docs/src/docs/asciidoc/user/107.adoc b/docs/src/docs/asciidoc/user/107.adoc index 96b9189634..d398beef2e 100644 --- a/docs/src/docs/asciidoc/user/107.adoc +++ b/docs/src/docs/asciidoc/user/107.adoc @@ -1,9 +1,9 @@ --- --- = The Ehcache 3.x JSR-107 Provider -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -59,7 +59,7 @@ Here is a code sample that demonstrates the usage of the basic JCache configurat [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=basicConfigurationExample] +include::{sourcedir37}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=basicConfigurationExample] ---- <1> Retrieves the default CachingProvider implementation from the application's classpath. @@ -91,7 +91,7 @@ you can still get to the underlying Ehcache `CacheRuntimeConfiguration`: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=mutableConfigurationExample] +include::{sourcedir37}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=mutableConfigurationExample] ---- <1> Create a JCache cache using the `MutableConfiguration` interface from the JCache specification. @@ -109,7 +109,7 @@ The way you do this is as follows: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheCacheManagerConfigurationExample] +include::{sourcedir37}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheCacheManagerConfigurationExample] ---- <1> Cast the `CachingProvider` into the Ehcache specific implementation `org.ehcache.jsr107.EhcacheCachingProvider`, <2> Create a configuration using the specific Ehcache `DefaultConfiguration` and pass it some `CacheManager` level configurations, @@ -122,7 +122,7 @@ When using this mechanism, no JCache `CompleteConfiguration` is used and so you [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheBasedConfigurationExample] +include::{sourcedir37}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheBasedConfigurationExample] ---- <1> Create an Ehcache `CacheConfiguration`. @@ -142,14 +142,14 @@ The following is an example of an XML configuration: [source%nowrap,xml,indent=0] ---- -include::{sourcedir36}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml[] +include::{sourcedir37}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml[] ---- Here is an example of how to access the XML configuration using JCache: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107UsingXMLConfigExample] +include::{sourcedir37}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107UsingXMLConfigExample] ---- <1> Invoke `javax.cache.spi.CachingProvider.getCacheManager(java.net.URI, java.lang.ClassLoader)` @@ -179,7 +179,7 @@ You can do this at two different levels: [source%nowrap,xml,indent=0] ---- -include::{sourcedir36}/107/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml[lines=17..-1] +include::{sourcedir37}/107/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml[lines=17..-1] ---- <1> Using the JCache service extension, you can enable MBeans by default. @@ -201,7 +201,7 @@ To do this, add a `jsr107` service in your XML configuration file: [source%nowrap,xml,indent=0] ---- -include::{sourcedir36}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml[] +include::{sourcedir37}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml[] ---- <1> First, declare a namespace for the JCache extension, e.g. `jsr107`. @@ -218,7 +218,7 @@ Using the above configuration, you can not only supplement but also override the [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107SupplementWithTemplatesExample] +include::{sourcedir37}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107SupplementWithTemplatesExample] ---- <1> Assume existing JCache configuration code, which is store-by-value by default @@ -283,5 +283,5 @@ If you need _Ehcache through JCache_ behaviour, the following shows the relevant [source%nowrap,xml,indent=0] ---- -include::{sourcedir36}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml[tag=cacheThroughCAS] +include::{sourcedir37}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml[tag=cacheThroughCAS] ---- diff --git a/docs/src/docs/asciidoc/user/cache-event-listeners.adoc b/docs/src/docs/asciidoc/user/cache-event-listeners.adoc index c3f1e7c897..31fc3fe051 100644 --- a/docs/src/docs/asciidoc/user/cache-event-listeners.adoc +++ b/docs/src/docs/asciidoc/user/cache-event-listeners.adoc @@ -1,9 +1,9 @@ --- --- = Cache Event Listeners -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -20,7 +20,7 @@ Listeners are registered at the cache level - and therefore only receive events [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEventListener] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEventListener] ---- <1> Create a `CacheEventListenerConfiguration` using the builder indicating the listener and the events to receive (in this case create and update events) @@ -59,7 +59,7 @@ Cache event listeners may also be added and removed while the cache is being use [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=registerListenerAtRuntime] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=registerListenerAtRuntime] ---- <1> Create a `CacheEventListener` implementation instance. @@ -75,7 +75,7 @@ Advanced users may want to tune the level of concurrency which may be used for d [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=configuringEventProcessingQueues] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=configuringEventProcessingQueues] ---- <1> Indicate the level of concurrency desired diff --git a/docs/src/docs/asciidoc/user/caching-concepts.adoc b/docs/src/docs/asciidoc/user/caching-concepts.adoc index 31c1182cf6..e1fdfcfcaa 100644 --- a/docs/src/docs/asciidoc/user/caching-concepts.adoc +++ b/docs/src/docs/asciidoc/user/caching-concepts.adoc @@ -1,9 +1,9 @@ --- --- = Concepts Related to Caching -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/caching-patterns.adoc b/docs/src/docs/asciidoc/user/caching-patterns.adoc index 860d2c5df3..9331c3d04e 100644 --- a/docs/src/docs/asciidoc/user/caching-patterns.adoc +++ b/docs/src/docs/asciidoc/user/caching-patterns.adoc @@ -1,9 +1,9 @@ --- --- = Cache Usage Patterns -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/caching-terms.adoc b/docs/src/docs/asciidoc/user/caching-terms.adoc index 2d9c3cae2c..51b856a2a8 100644 --- a/docs/src/docs/asciidoc/user/caching-terms.adoc +++ b/docs/src/docs/asciidoc/user/caching-terms.adoc @@ -1,9 +1,9 @@ --- --- = Terms Related to Caching -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/class-loading.adoc b/docs/src/docs/asciidoc/user/class-loading.adoc index b9a4db8e78..119ec0a151 100644 --- a/docs/src/docs/asciidoc/user/class-loading.adoc +++ b/docs/src/docs/asciidoc/user/class-loading.adoc @@ -1,9 +1,9 @@ --- --- = Class loading -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/clustered-cache.adoc b/docs/src/docs/asciidoc/user/clustered-cache.adoc index 3a0150a3ca..4fa2f3e61b 100644 --- a/docs/src/docs/asciidoc/user/clustered-cache.adoc +++ b/docs/src/docs/asciidoc/user/clustered-cache.adoc @@ -1,9 +1,9 @@ --- --- = Clustered Cache -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -68,7 +68,7 @@ It contains the bare minimum configuration required for the samples in the rest [source,xml,indent=0] ---- -include::{sourcedir36}/clustered/client/src/test/resources/configs/docs/tc-config.xml[] +include::{sourcedir37}/clustered/client/src/test/resources/configs/docs/tc-config.xml[] ---- The above configuration defines two named server off-heap resources: @@ -109,7 +109,7 @@ Here is a code sample that shows how to configure a cache manager with clusterin [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] +include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] ---- <1> Returns the `org.ehcache.config.builders.CacheManagerBuilder` instance. @@ -126,7 +126,7 @@ This code sample demonstrates the usage of the concepts explained in the previou [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerWithServerSideConfigExample] +include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerWithServerSideConfigExample] ---- <1> `defaultServerResource(String)` on `ClusteringServiceConfigurationBuilder` instance sets the default server off-heap resource for the cache manager. @@ -153,7 +153,7 @@ When configuring a cache manager to connect to a cluster tier manager there are [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerLifecycle] +include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerLifecycle] ---- <1> In auto-create mode if no cluster tier manager exists then one is created with the supplied configuration. @@ -171,7 +171,7 @@ If it does not exist then the cache manager will fail to initialize. [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheTieredExample] +include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheTieredExample] ---- <1> Configuring the heap tier for cache. @@ -181,7 +181,7 @@ The equivalent XML configuration is as follows: [source%nowrap,xml,indent=0] ---- -include::{sourcedir36}/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=tieringSample] +include::{sourcedir37}/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=tieringSample] ---- <1> Specify the heap tier for cache. @@ -204,7 +204,7 @@ This comes with a latency penalty on the write operation required to give this g [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheConsistency] +include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheConsistency] ---- <1> Specify the consistency level through the use of additional service configuration, using _strong_ consistency here. @@ -214,7 +214,7 @@ The equivalent XML configuration is as follows: [source%nowrap,xml,indent=0] ---- -include::{sourcedir36}/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=consistencySample] +include::{sourcedir37}/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=consistencySample] ---- <1> Specify the consistency level through a custom service configuration from the `clustered` namespace. @@ -244,7 +244,7 @@ The example code below shows how this can be implemented. [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=unspecifiedClusteredCacheExample] +include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=unspecifiedClusteredCacheExample] ---- <1> Configure the first cache manager with auto create diff --git a/docs/src/docs/asciidoc/user/common.adoc b/docs/src/docs/asciidoc/user/common.adoc index 27131afdbb..93311263e2 100644 --- a/docs/src/docs/asciidoc/user/common.adoc +++ b/docs/src/docs/asciidoc/user/common.adoc @@ -1,6 +1,6 @@ --- --- -ifndef::sourcedir36[] +ifndef::sourcedir37[] :notBuildingForSite: true ifdef::basebackend-html[:outfilesuffix: .html] :source-highlighter: coderay @@ -10,9 +10,9 @@ ifdef::basebackend-html[:outfilesuffix: .html] :icons: font :iconfont-remote!: :iconfont-name: font-awesome.min -:sourcedir36: ../../../../../ +:sourcedir37: ../../../../../ :imagesdir: images :sectanchors: :idprefix: :idseparator: - -endif::sourcedir36[] +endif::sourcedir37[] diff --git a/docs/src/docs/asciidoc/user/eviction-advisor.adoc b/docs/src/docs/asciidoc/user/eviction-advisor.adoc index 6a8782a44d..56a33d88cc 100644 --- a/docs/src/docs/asciidoc/user/eviction-advisor.adoc +++ b/docs/src/docs/asciidoc/user/eviction-advisor.adoc @@ -1,9 +1,9 @@ --- --- = Eviction Advisor -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -29,7 +29,7 @@ If the eviction is advised against, Ehcache will try to honor the preference of [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEvictionAdvisor] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEvictionAdvisor] ---- <1> Configure a constrained heap, as the eviction advisor is only relevant when mappings get evicted from the cache. diff --git a/docs/src/docs/asciidoc/user/examples.adoc b/docs/src/docs/asciidoc/user/examples.adoc index 3ed6feab0d..c8260b4dcc 100644 --- a/docs/src/docs/asciidoc/user/examples.adoc +++ b/docs/src/docs/asciidoc/user/examples.adoc @@ -1,9 +1,9 @@ --- --- = Examples -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -102,5 +102,5 @@ Note the presence of the +Filling cache with peeps+, +Clearing peeps cache+, and [source,xml,indent=0] ---- -include::{sourcedir36}/107/src/test/resources/ehcache-example.xml[] +include::{sourcedir37}/107/src/test/resources/ehcache-example.xml[] ---- diff --git a/docs/src/docs/asciidoc/user/expiry.adoc b/docs/src/docs/asciidoc/user/expiry.adoc index 7ad3366e60..d154e14d3c 100644 --- a/docs/src/docs/asciidoc/user/expiry.adoc +++ b/docs/src/docs/asciidoc/user/expiry.adoc @@ -1,9 +1,9 @@ --- --- = Expiry -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -20,7 +20,7 @@ Expiry is configured at the cache level, in Java or in XML: [source,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] ---- <1> Expiry policy is configured at the cache level, so start by defining a cache configuration, @@ -28,7 +28,7 @@ include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[t [source,xml,indent=0] ---- -include::{sourcedir36}/xml/src/test/resources/configs/docs/expiry.xml[tags=expiry] +include::{sourcedir37}/xml/src/test/resources/configs/docs/expiry.xml[tags=expiry] ---- <1> At the cache level, using the predefined _time-to-live_ again. @@ -50,7 +50,7 @@ Supporting your own expiration scheme simply means implementing the `ExpiryPolic [source,java,indent=0] ---- -include::{sourcedir36}/api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java[lines=21..-1] +include::{sourcedir37}/api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java[lines=21..-1] ---- The main points to remember on the return value from these methods: @@ -71,7 +71,7 @@ In Java: [source,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=customExpiry] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=customExpiry] ---- <1> Simply pass your custom expiry instance into the cache builder. @@ -80,7 +80,7 @@ In XML: [source,xml,indent=0] ---- -include::{sourcedir36}/xml/src/test/resources/configs/docs/expiry.xml[tags=customExpiry] +include::{sourcedir37}/xml/src/test/resources/configs/docs/expiry.xml[tags=customExpiry] ---- <1> Simply pass the fully qualified class name of your custom expiry. diff --git a/docs/src/docs/asciidoc/user/getting-started.adoc b/docs/src/docs/asciidoc/user/getting-started.adoc index 77d8a48578..7e0d5e9e45 100644 --- a/docs/src/docs/asciidoc/user/getting-started.adoc +++ b/docs/src/docs/asciidoc/user/getting-started.adoc @@ -1,10 +1,10 @@ --- -version: 3.6 +version: 3.7 --- -= Ehcache {{page.version}} Documentation -ifndef::sourcedir36[] += Ehcache 3.7 Documentation +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] We feel that the Ehcache 3.x API is a great improvement over the Ehcache 2.x API that has been used by millions of developers. We hope you enjoy this new generation of Ehcache! ifdef::notBuildingForSite[] @@ -28,7 +28,7 @@ As with the previous versions of Ehcache, the canonical way of dealing with `Cac [source,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cachemanagerExample] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cachemanagerExample] ---- <1> The static method `org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder` returns a new `org.ehcache.config.builders.CacheManagerBuilder` instance. @@ -63,7 +63,7 @@ Here is a shorter version featuring 3 important things: [source,java,indent=0] ---- -include::{sourcedir36}/integration-test/src/test/java/org/ehcache/docs/GettingStartedWithStaticImports.java[tag=java7Example] +include::{sourcedir37}/integration-test/src/test/java/org/ehcache/docs/GettingStartedWithStaticImports.java[tag=java7Example] ---- <1> A `CacheManager` implements `Closeable` so can be closed automatically by a try-with-resources. A `CacheManager` must be closed cleanly. In a `finally` block, with a `try-with-resources` or (more frequent for normal applications) in some shutdown hook. @@ -77,7 +77,7 @@ You can create an XML file to configure a `CacheManager`. [source,xml,indent=0] ---- -include::{sourcedir36}/xml/src/test/resources/configs/docs/getting-started.xml[tags=gettingStarted] +include::{sourcedir37}/xml/src/test/resources/configs/docs/getting-started.xml[tags=gettingStarted] ---- <1> Declares a `Cache` aliased to `foo`. @@ -111,7 +111,7 @@ In addition, for creating the cache manager with clustering support, you will ne [source,java,indent=0] ---- -include::{sourcedir36}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] +include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] ---- <1> Returns the `org.ehcache.config.builders.CacheManagerBuilder` instance; @@ -140,7 +140,7 @@ A classical example would be using 3 tiers with a persistent disk storage. [source,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=threeTiersCacheManager] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=threeTiersCacheManager] ---- <1> If you wish to use disk storage (like for persistent `Cache` instances), you'll have to provide a @@ -159,7 +159,7 @@ The following illustrates how to configure a _time-to-live_ expiry. [source,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] ---- <1> Expiry is configured at the cache level, so start by defining a cache configuration, diff --git a/docs/src/docs/asciidoc/user/index.adoc b/docs/src/docs/asciidoc/user/index.adoc index 5d86bd231e..78fb564d27 100644 --- a/docs/src/docs/asciidoc/user/index.adoc +++ b/docs/src/docs/asciidoc/user/index.adoc @@ -1,10 +1,10 @@ --- -version: 3.6 +version: 3.7 --- -= Ehcache {{page.version}} Documentation Overview -ifndef::sourcedir36[] += Ehcache 3.7 Documentation Overview +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -12,7 +12,7 @@ endif::notBuildingForSite[] == Table of Contents -The Table of Contents provides an overview of the Ehcache {{page.version}} documentation on this site. +The Table of Contents provides an overview of the Ehcache 3.7 documentation on this site. Each topic below corresponds to a menu item at the left. === Basic Topics diff --git a/docs/src/docs/asciidoc/user/management.adoc b/docs/src/docs/asciidoc/user/management.adoc index d5b7182f15..7859e685f5 100644 --- a/docs/src/docs/asciidoc/user/management.adoc +++ b/docs/src/docs/asciidoc/user/management.adoc @@ -1,9 +1,9 @@ --- --- = Management and Monitoring -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -30,7 +30,7 @@ cache manager builder as a service: [source,java,indent=0] ---- -include::{sourcedir36}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=usingManagementRegistry] +include::{sourcedir37}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=usingManagementRegistry] ---- <1> Optional: give a name to your cache manager by using a custom configuration <2> Create an instance of `org.ehcache.management.registry.DefaultManagementRegistryService`. This is only required because the service is used below. @@ -50,7 +50,7 @@ and a cache name to uniquely identify the cache on which you want to query stats [source,java,indent=0] ---- -include::{sourcedir36}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=capabilitiesAndContexts] +include::{sourcedir37}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=capabilitiesAndContexts] ---- <1> Query the `ManagementRegistry` for the registered managed objects' capabilities. <2> Each capability has a unique name you will need to refer to it. @@ -74,7 +74,7 @@ a managed object. Examples of actions could be: clear caches, get their configur [source,java,indent=0] ---- -include::{sourcedir36}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=actionCall] +include::{sourcedir37}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=actionCall] ---- <1> Put something in a cache. <2> Call the 'clear' action on the managed cache. Refer to the descriptors of the provider to get the exact list of @@ -92,7 +92,7 @@ manager by default, but sometimes you may want one `ManagementRegistry` to manag [source,java,indent=0] ---- -include::{sourcedir36}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=managingMultipleCacheManagers] +include::{sourcedir37}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=managingMultipleCacheManagers] ---- <1> Create an instance of `org.ehcache.management.SharedManagementService` <2> Pass it as a service to the first cache manager diff --git a/docs/src/docs/asciidoc/user/migration-guide.adoc b/docs/src/docs/asciidoc/user/migration-guide.adoc index 4046156251..6eb67107fd 100644 --- a/docs/src/docs/asciidoc/user/migration-guide.adoc +++ b/docs/src/docs/asciidoc/user/migration-guide.adoc @@ -1,9 +1,9 @@ --- --- = Migration Guide -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -65,7 +65,7 @@ having dedicated logic in the methods called during the lifecycle of added and u [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/Ehcache3.java[tag=CustomExpiryEhcache3] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Ehcache3.java[tag=CustomExpiryEhcache3] ---- <1> Defining custom expiry to be called during the lifecycle of added mappings. diff --git a/docs/src/docs/asciidoc/user/osgi.adoc b/docs/src/docs/asciidoc/user/osgi.adoc index 2bb9849e45..261bdeb0e9 100644 --- a/docs/src/docs/asciidoc/user/osgi.adoc +++ b/docs/src/docs/asciidoc/user/osgi.adoc @@ -1,9 +1,9 @@ --- --- = OSGi Deployment -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/resilience.adoc b/docs/src/docs/asciidoc/user/resilience.adoc index 1784e7451f..cd141f8568 100644 --- a/docs/src/docs/asciidoc/user/resilience.adoc +++ b/docs/src/docs/asciidoc/user/resilience.adoc @@ -1,9 +1,9 @@ --- --- = Resilience -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -64,7 +64,7 @@ Timeouts can be configured using a dedicated builder or in XML. [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java[tag=timeoutsExample] +include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java[tag=timeoutsExample] ---- <1> Start setting timeouts using the build diff --git a/docs/src/docs/asciidoc/user/serializers-copiers.adoc b/docs/src/docs/asciidoc/user/serializers-copiers.adoc index e8639b60de..f96d1b087c 100644 --- a/docs/src/docs/asciidoc/user/serializers-copiers.adoc +++ b/docs/src/docs/asciidoc/user/serializers-copiers.adoc @@ -1,9 +1,9 @@ --- --- = Serializers and Copiers -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -119,7 +119,7 @@ Implement the following interface, from package `org.ehcache.spi.serialization`: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/api/src/main/java/org/ehcache/spi/serialization/Serializer.java[lines=20..-1] +include::{sourcedir37}/api/src/main/java/org/ehcache/spi/serialization/Serializer.java[lines=20..-1] ---- As the Javadoc states, there are some constructor rules, see the section <> for that. @@ -256,7 +256,7 @@ Implement the following interface: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/api/src/main/java/org/ehcache/spi/copy/Copier.java[lines=19..-1] +include::{sourcedir37}/api/src/main/java/org/ehcache/spi/copy/Copier.java[lines=19..-1] ---- * `T copyForRead(T obj)` is invoked when a copy must be made upon a read operation (like a cache `get()`), diff --git a/docs/src/docs/asciidoc/user/thread-pools.adoc b/docs/src/docs/asciidoc/user/thread-pools.adoc index 5e6e4df6dd..ed9bcfd48e 100644 --- a/docs/src/docs/asciidoc/user/thread-pools.adoc +++ b/docs/src/docs/asciidoc/user/thread-pools.adoc @@ -1,9 +1,9 @@ --- --- = Thread Pools -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -88,7 +88,7 @@ Following are examples of describing how to configure the thread pools the diffe [source%nowrap,java] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=diskStore] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=diskStore] ---- <1> Configure the thread pools. Note that the default one (`dflt`) is required for the events even when no event listener is configured. @@ -99,7 +99,7 @@ include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag= [source%nowrap,java] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=writeBehind] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=writeBehind] ---- <1> Configure the thread pools. Note that the default one (`dflt`) is required for the events even when no event listener is configured. @@ -110,7 +110,7 @@ include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag= [source%nowrap,java] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=events] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=events] ---- <1> Configure the thread pools. Note that there is no default one so all thread-using services must be configured with explicit defaults. @@ -124,7 +124,7 @@ Following is an example describing how to configure the thread pools the differe [source%nowrap,xml] ---- -include::{sourcedir36}/xml/src/test/resources/configs/docs/thread-pools.xml[tags=threadPools] +include::{sourcedir37}/xml/src/test/resources/configs/docs/thread-pools.xml[tags=threadPools] ---- <1> Configure the thread pools. Note that there is no default one. diff --git a/docs/src/docs/asciidoc/user/tiering.adoc b/docs/src/docs/asciidoc/user/tiering.adoc index 0b0a1dfc71..c952cf6a19 100644 --- a/docs/src/docs/asciidoc/user/tiering.adoc +++ b/docs/src/docs/asciidoc/user/tiering.adoc @@ -1,9 +1,9 @@ --- --- = Ehcache Tiering Options -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -48,7 +48,7 @@ For this, simply define the single resource in the cache configuration: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheapOnly] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheapOnly] ---- <1> Start with defining the key and value type in the configuration builder. @@ -65,7 +65,7 @@ A heap tier can be sized by entries or by size. [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=heap] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=heap] ---- <1> Only 10 entries allowed on heap. Eviction will occur when full. @@ -83,7 +83,7 @@ NOTE: Byte sizing has a runtime performance impact that depends on the size and [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=byteSizedTieredCache] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=byteSizedTieredCache] ---- <1> This will limit the amount of memory used by the heap tier for storing key-value pairs. @@ -103,7 +103,7 @@ If you wish to use off-heap, you'll have to define a resource pool, giving the m [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheap] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheap] ---- <1> Only 10 MB allowed off-heap. @@ -126,7 +126,7 @@ The faster and more dedicated the disk is, the faster accessing the data will be [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=persistentCacheManager] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=persistentCacheManager] ---- <1> To obtain a `PersistentCacheManager` which is a normal `CacheManager` but with the ability to @@ -166,7 +166,7 @@ In some cases, you might want to reduce the concurrency and save resources by re [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=diskSegments] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=diskSegments] ---- <1> Define an `OffHeapDiskStoreConfiguration` instance specifying the required number of segments. @@ -220,7 +220,7 @@ Here is an example using heap, offheap and clustered. [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java[tag=threeTiersCacheManager] +include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java[tag=threeTiersCacheManager] ---- <1> Clustered specific information telling how to connect to the Terracotta cluster @@ -239,7 +239,7 @@ Let's revisit an example used earlier: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=threeTiersCacheManager] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=threeTiersCacheManager] ---- This is a cache using 3 tiers (heap, offheap, disk). @@ -253,7 +253,7 @@ Consider for instance this code: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=notShared] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=notShared] ---- You will end up with two caches that can contain 10 entries each. @@ -270,7 +270,7 @@ Thus you can't change the sizing of off-heap or disk tiers. [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=updateResourcesAtRuntime] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=updateResourcesAtRuntime] ---- <1> You will need to create a new `ResourcePools` object with resources of the required size, using `ResourcePoolsBuilder`. diff --git a/docs/src/docs/asciidoc/user/usermanaged.adoc b/docs/src/docs/asciidoc/user/usermanaged.adoc index 463ebe28f5..0bbd39a845 100644 --- a/docs/src/docs/asciidoc/user/usermanaged.adoc +++ b/docs/src/docs/asciidoc/user/usermanaged.adoc @@ -1,9 +1,9 @@ --- --- = User managed caches -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -44,7 +44,7 @@ The interface definition is shown in this code: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/api/src/main/java/org/ehcache/UserManagedCache.java[lines=17..-1] +include::{sourcedir37}/api/src/main/java/org/ehcache/UserManagedCache.java[lines=17..-1] ---- === User Managed Persistent Cache @@ -63,7 +63,7 @@ The interface definition is shown in this code: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/api/src/main/java/org/ehcache/PersistentUserManagedCache.java[lines=17..-1] +include::{sourcedir37}/api/src/main/java/org/ehcache/PersistentUserManagedCache.java[lines=17..-1] ---- [[code-examples]] @@ -75,7 +75,7 @@ Here is a simple example showing a basic lifecycle of a user managed cache: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=userManagedCacheExample] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=userManagedCacheExample] ---- <1> Create a `UserManagedCache` instance. You can either pass `true` to have the builder `init()` it for you, @@ -102,7 +102,7 @@ If you want to use disk persistent cache, you will need to create and lifecycle [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=persistentUserManagedCache] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=persistentUserManagedCache] ---- <1> Create the persistence service to be used by the cache for storing data on disk. @@ -125,7 +125,7 @@ For more information on cache event listeners, see the section < Provide the `ExecutorService` for ordered and unordered event delivery. diff --git a/docs/src/docs/asciidoc/user/writers.adoc b/docs/src/docs/asciidoc/user/writers.adoc index 393032a99b..bbb04bcb59 100644 --- a/docs/src/docs/asciidoc/user/writers.adoc +++ b/docs/src/docs/asciidoc/user/writers.adoc @@ -1,9 +1,9 @@ --- --- = Cache Loaders and Writers -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -74,7 +74,7 @@ After this time has elapsed, the batch is processed even if incomplete. [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeThroughCache] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeThroughCache] ---- <1> We register a sample `CacheLoaderWriter` that knows about the mapping ("41L" maps to "zero"). @@ -86,7 +86,7 @@ The returned mapping will populate the cache and be returned to the caller. [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeBehindCache] +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeBehindCache] ---- <1> For write-behind you need a configured `CacheLoaderWriter`. diff --git a/docs/src/docs/asciidoc/user/xa.adoc b/docs/src/docs/asciidoc/user/xa.adoc index 16e3a74cc4..a3325b9935 100644 --- a/docs/src/docs/asciidoc/user/xa.adoc +++ b/docs/src/docs/asciidoc/user/xa.adoc @@ -1,9 +1,9 @@ --- --- = XA transactional caches -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -65,7 +65,7 @@ Here is an example: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testSimpleXACache] +include::{sourcedir37}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testSimpleXACache] ---- <1> First start the Bitronix transaction manager. By default, Ehcache will auto-detect it but will throw an exception during the cache manager initialization if BTM isn't started. @@ -96,7 +96,7 @@ Nothing special needs to be configured for this to happen, just ensure that the [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithWriteThrough] +include::{sourcedir37}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithWriteThrough] ---- <1> First start the Bitronix transaction manager. @@ -122,7 +122,7 @@ Any attempt to access one outside of such context will result in `XACacheExcepti [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testNonTransactionalAccess] +include::{sourcedir37}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testNonTransactionalAccess] ---- <1> First start the Bitronix transaction manager. @@ -151,7 +151,7 @@ Here is an example: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithThreeTiers] +include::{sourcedir37}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithThreeTiers] ---- <1> First start the Bitronix transaction manager. @@ -174,7 +174,7 @@ You can create a XML file to configure a `CacheManager`, lookup a specific trans [source%nowrap,xml,indent=0] ---- -include::{sourcedir36}/transactions/src/test/resources/docs/configs/xa-getting-started.xml[tags=gettingStarted] +include::{sourcedir37}/transactions/src/test/resources/docs/configs/xa-getting-started.xml[tags=gettingStarted] ---- <1> Declare a `TransactionManagerLookup` that will lookup your transaction manager. @@ -185,7 +185,7 @@ In order to parse an XML configuration, you can use the XmlConfiguration type: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithXMLConfig] +include::{sourcedir37}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithXMLConfig] ---- <1> The Bitronix transaction manager must be started before the cache manager is initialized. @@ -198,7 +198,7 @@ And here is what the BitronixTransactionManagerLookup implementation looks like: [source%nowrap,java,indent=0] ---- -include::{sourcedir36}/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixTransactionManagerLookup.java[tag=BitronixLookup] +include::{sourcedir37}/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixTransactionManagerLookup.java[tag=BitronixLookup] ---- <1> The `TransactionManagerLookup` interface must be implemented and the offer a `no-arg` constructor. diff --git a/docs/src/docs/asciidoc/user/xml.adoc b/docs/src/docs/asciidoc/user/xml.adoc index a967952f0f..3bf794c2bd 100644 --- a/docs/src/docs/asciidoc/user/xml.adoc +++ b/docs/src/docs/asciidoc/user/xml.adoc @@ -1,9 +1,9 @@ --- --- = XML Configuration -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -108,7 +108,7 @@ NOTE: If you are obtaining your `CacheManager` through the JSR-107 API, what fol [source,java,indent=0] ---- -include::{sourcedir36}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlConfig] +include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlConfig] ---- <1> Obtain a `URL` to your XML file's location <2> Instantiate an `XmlConfiguration` passing the XML file's URL to it @@ -121,14 +121,14 @@ to use a `` element from an XML file, e.g. the `/my-config.xml` [source,xml,indent=0] ---- -include::{sourcedir36}/xml/src/test/resources/configs/docs/template-sample.xml[tag=templateSample] +include::{sourcedir37}/xml/src/test/resources/configs/docs/template-sample.xml[tag=templateSample] ---- Creating a `CacheConfigurationBuilder` of that `example` `` element, would be done as follows: [source,java,indent=0] ---- -include::{sourcedir36}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] +include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] ---- <1> Creates a builder, inheriting the capacity constraint of 200 entries <2> The inherent properties can be overridden by simply providing a different value prior to building the `CacheConfiguration` @@ -141,14 +141,14 @@ and the string representation of that object will give you the XML equivalent of [source,java,indent=0] ---- -include::{sourcedir36}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] +include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] ---- <1> Creates a builder, inheriting the capacity constraint of 200 entries <2> The inherent properties can be overridden by simply providing a different value prior to building the `CacheConfiguration` [source,java,indent=0] ---- -include::{sourcedir36}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTranslation] +include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTranslation] ---- <1> Instantiate an `XmlConfiguration` passing the cache manager `Configuration` <2> Retrieve the XML representation using the `toString` method. @@ -176,7 +176,7 @@ The simplest use of the multi-configuration features is to embed multiple cache file: [source,xml,indent=0] ---- -include::{sourcedir36}/xml/src/test/resources/configs/docs/multi/multiple-managers.xml[] +include::{sourcedir37}/xml/src/test/resources/configs/docs/multi/multiple-managers.xml[] ---- <1> A top-level `` container with namespace declarations for the `multi` and core schemas <2> Each Ehcache configuration is embedded inside a `configuration` tag with a required (unique) `identity` attribute @@ -184,7 +184,7 @@ include::{sourcedir36}/xml/src/test/resources/configs/docs/multi/multiple-manage These embedded configurations can then be retrieved via an `XmlMultiConfiguration` instance built from the XML document. [source,java,indent=0] ---- -include::{sourcedir36}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleManagers] +include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleManagers] ---- <1> The `XmlMultiConfiguration` is assembled from the XML resource. <2> Once assembled the configuration is built. @@ -196,13 +196,13 @@ Multiple variant configurations for a given manager can be provided by including with a required `type` attribute: [source,xml,indent=0] ---- -include::{sourcedir36}/xml/src/test/resources/configs/docs/multi/multiple-variants.xml[tag=variants] +include::{sourcedir37}/xml/src/test/resources/configs/docs/multi/multiple-variants.xml[tag=variants] ---- A specific cache configuration can then be retrieved by choosing both a variant and an identity explicitly on retrieval. [source,java,indent=0] ---- -include::{sourcedir36}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleVariants] +include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleVariants] ---- The samples above are just samples, variant types can be used to represent any kind of variation: development vs production, clustered vs unclustered, red vs blue, etc. @@ -218,7 +218,7 @@ Multiple cache managers can be retrieved from an `XmlMultiConfiguration` by iter `identities()`: [source,java,indent=0] ---- -include::{sourcedir36}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleRetrieval] +include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleRetrieval] ---- <1> From a stream over the set of identities in a mult-configuration. <2> Map each identity to it's unique (non-varianted) configuration. @@ -232,7 +232,7 @@ of parsing XML multi-configuration documents are all just simple invocations of Configurations can be built from scratch as show below: [source,java,indent=0] ---- -include::{sourcedir36}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=building] +include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=building] ---- <1> Starting with an initially empty set of configurations. <2> Add a configuration without variants. @@ -242,7 +242,7 @@ include::{sourcedir36}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.ja They can also be built from existing configurations: [source,java,indent=0] ---- -include::{sourcedir36}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=modifying] +include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=modifying] ---- <1> Starting with an existing `XmlMultiConfiguration`. <2> Remove the configuration with identity `"foo"`. @@ -250,7 +250,7 @@ include::{sourcedir36}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.ja Once built a multi-configuration can be retrieved in XML form: [source,java,indent=0] ---- -include::{sourcedir36}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=rendering] +include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=rendering] ---- <1> Retrieving the XML as a rendered string. <2> Retrieving the XML as a DOM (`org.w3c.Document`). diff --git a/docs/src/docs/asciidoc/user/xsds.adoc b/docs/src/docs/asciidoc/user/xsds.adoc index 7a31a282ee..76ff465751 100644 --- a/docs/src/docs/asciidoc/user/xsds.adoc +++ b/docs/src/docs/asciidoc/user/xsds.adoc @@ -1,9 +1,9 @@ --- --- = Ehcache XSDs -ifndef::sourcedir36[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir36[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -51,7 +51,7 @@ endif::notBuildingForSite[] [source,xml,indent=0] ---- -include::{sourcedir36}/107/src/test/resources/org/ehcache/docs/public-xsds-location.xml[tag=xsdLocations] +include::{sourcedir37}/107/src/test/resources/org/ehcache/docs/public-xsds-location.xml[tag=xsdLocations] ---- [[core]] @@ -59,7 +59,7 @@ include::{sourcedir36}/107/src/test/resources/org/ehcache/docs/public-xsds-locat [source,xsd,indent=0] ---- -include::{sourcedir36}/xml/src/main/resources/ehcache-core.xsd[lines=18..-1] +include::{sourcedir37}/xml/src/main/resources/ehcache-core.xsd[lines=18..-1] ---- [[jsr-107-extension]] @@ -67,12 +67,12 @@ include::{sourcedir36}/xml/src/main/resources/ehcache-core.xsd[lines=18..-1] [source,xsd,indent=0] ---- -include::{sourcedir36}/107/src/main/resources/ehcache-107-ext.xsd[lines=18..-1] +include::{sourcedir37}/107/src/main/resources/ehcache-107-ext.xsd[lines=18..-1] ---- == XA transactions extension [source,xsd,indent=0] ---- -include::{sourcedir36}/transactions/src/main/resources/ehcache-tx-ext.xsd[lines=18..-1] +include::{sourcedir37}/transactions/src/main/resources/ehcache-tx-ext.xsd[lines=18..-1] ---- From e7273a7a2ab1649de88463b0a4038b5c45bd6aa4 Mon Sep 17 00:00:00 2001 From: Venkata Sairam Madduri Date: Tue, 5 Mar 2019 15:17:43 +0530 Subject: [PATCH 114/372] Bump versions --- .../server/ClusterTierManagerActiveEntityTest.java | 5 +++++ .../server/ClusterTierManagerPassiveEntityTest.java | 5 +++++ .../server/store/ClusterTierActiveEntityTest.java | 5 +++++ .../server/store/ClusterTierPassiveEntityTest.java | 5 +++++ gradle.properties | 8 ++++---- 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java index 89856b2326..b299335a02 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java @@ -665,6 +665,11 @@ public long capacity() { return capacity; } + @Override + public boolean setCapacity(long size) throws IllegalArgumentException { + throw new UnsupportedOperationException("Not supported"); + } + private long getUsed() { return used; } diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java index 25a340b5a9..4823b90f3d 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java @@ -429,6 +429,11 @@ public long capacity() { return capacity; } + @Override + public boolean setCapacity(long size) throws IllegalArgumentException { + throw new UnsupportedOperationException("Not supported"); + } + private long getUsed() { return used; } diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index 4090cd5e84..debc505a56 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -1364,6 +1364,11 @@ public long capacity() { return capacity; } + @Override + public boolean setCapacity(long size) throws IllegalArgumentException { + throw new UnsupportedOperationException("Not supported"); + } + private long getUsed() { return used; } diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java index 566bb4db4a..dd59b77477 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java @@ -413,6 +413,11 @@ public long capacity() { return capacity; } + @Override + public boolean setCapacity(long size) throws IllegalArgumentException { + throw new UnsupportedOperationException("Not supported"); + } + private long getUsed() { return used; } diff --git a/gradle.properties b/gradle.properties index f34e469e38..a2ab874e7b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,10 +10,10 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.6.0 -terracottaApisVersion = 1.6.0 -terracottaCoreVersion = 5.6.0 -terracottaPassthroughTestingVersion = 1.6.0 +terracottaPlatformVersion = 5.7.0-pre2 +terracottaApisVersion = 1.6.1-pre1 +terracottaCoreVersion = 5.6.1-pre6 +terracottaPassthroughTestingVersion = 1.6.1-pre1 # Test lib versions junitVersion = 4.12 From e95229839b1bba6a52ef02b364fa22e094b746d3 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Wed, 6 Mar 2019 13:34:41 -0800 Subject: [PATCH 115/372] Bump dependencies. --- gradle.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index a2ab874e7b..d0cf0ed020 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ ehcacheVersion = 3.7-SNAPSHOT # Terracotta third parties -offheapVersion = 2.4.2 +offheapVersion = 2.4.3 statisticVersion = 2.1 jcacheVersion = 1.1.0 slf4jVersion = 1.7.25 @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.0-pre2 +terracottaPlatformVersion = 5.7.0-pre3 terracottaApisVersion = 1.6.1-pre1 -terracottaCoreVersion = 5.6.1-pre6 +terracottaCoreVersion = 5.6.1-pre7 terracottaPassthroughTestingVersion = 1.6.1-pre1 # Test lib versions From b28e68f5f31df16ae1b851a8d2b683aa2caf6413 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Tue, 13 Feb 2018 15:40:18 -0500 Subject: [PATCH 116/372] Put classes using unsafe in a dedicated sourceSet to allow using -Werror on impl --- impl/build.gradle | 21 ++++++++++++++++++- .../internal/store/disk/OffHeapDiskStore.java | 2 +- .../org/ehcache/impl/store/BaseStore.java | 1 - .../concurrent/ConcurrentHashMap.java | 0 .../concurrent/EvictingConcurrentMap.java | 0 .../concurrent/ThreadLocalRandomUtil.java | 0 .../internal/concurrent/package-info.java | 0 7 files changed, 21 insertions(+), 3 deletions(-) rename impl/src/{main => unsafe}/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java (100%) rename impl/src/{main => unsafe}/java/org/ehcache/impl/internal/concurrent/EvictingConcurrentMap.java (100%) rename impl/src/{main => unsafe}/java/org/ehcache/impl/internal/concurrent/ThreadLocalRandomUtil.java (100%) rename impl/src/{main => unsafe}/java/org/ehcache/impl/internal/concurrent/package-info.java (100%) diff --git a/impl/build.gradle b/impl/build.gradle index 6cef711075..74a879d012 100644 --- a/impl/build.gradle +++ b/impl/build.gradle @@ -18,6 +18,14 @@ apply plugin: EhDeploy apply plugin: 'biz.aQute.bnd.builder' apply plugin: 'osgi-ds' +sourceSets { + unsafe { + java { + srcDir 'src/unsafe/java' + } + } +} + dependencies { api project(':core') implementation group: 'org.terracotta', name: 'offheap-store', version: parent.offheapVersion @@ -29,9 +37,16 @@ dependencies { testImplementation project(':core-spi-test') testImplementation 'org.ow2.asm:asm:6.2' testImplementation 'org.ow2.asm:asm-commons:6.2' + + unsafeImplementation project(':api') + unsafeCompileOnly "com.github.spotbugs:spotbugs-annotations:$parent.spotbugsVersion" + api files(sourceSets.unsafe.output.classesDirs) { + builtBy compileUnsafeJava + } } jar { + from sourceSets.unsafe.output from "$rootDir/NOTICE" bnd ( 'Export-Package': '!org.ehcache.impl.internal.*, org.ehcache.impl.*, org.ehcache.config.builders, ' + @@ -41,7 +56,11 @@ jar { ) } -compileJava { +sourceJar { + from sourceSets.unsafe.allSource +} + +compileUnsafeJava { //no -Werror due to unsafe options.compilerArgs = ['-Xlint:all'] } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java index 3f2715f559..7c7b275866 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java @@ -498,7 +498,7 @@ public static PersistentPortability persistent(final Portability norma } proxyInterfaces.add(PersistentPortability.class); - return (PersistentPortability) Proxy.newProxyInstance(normal.getClass().getClassLoader(), proxyInterfaces.toArray(new Class[0]), (o, method, os) -> { + return (PersistentPortability) Proxy.newProxyInstance(normal.getClass().getClassLoader(), proxyInterfaces.toArray(new Class[0]), (o, method, os) -> { if (method.getDeclaringClass().equals(Persistent.class)) { return null; } else { diff --git a/impl/src/main/java/org/ehcache/impl/store/BaseStore.java b/impl/src/main/java/org/ehcache/impl/store/BaseStore.java index 4acb762ff8..a2198dbcc6 100644 --- a/impl/src/main/java/org/ehcache/impl/store/BaseStore.java +++ b/impl/src/main/java/org/ehcache/impl/store/BaseStore.java @@ -26,7 +26,6 @@ import org.terracotta.statistics.StatisticsManager; import org.terracotta.statistics.ZeroOperationStatistic; import org.terracotta.statistics.observer.OperationObserver; -import sun.security.krb5.Config; import java.io.Serializable; import java.util.Map; diff --git a/impl/src/main/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java b/impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java rename to impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/concurrent/EvictingConcurrentMap.java b/impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/EvictingConcurrentMap.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/concurrent/EvictingConcurrentMap.java rename to impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/EvictingConcurrentMap.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/concurrent/ThreadLocalRandomUtil.java b/impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ThreadLocalRandomUtil.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/concurrent/ThreadLocalRandomUtil.java rename to impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ThreadLocalRandomUtil.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/concurrent/package-info.java b/impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/concurrent/package-info.java rename to impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/package-info.java From 2122ea89da538ba188d1ad931e78fff456a7df00 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 6 Mar 2019 10:54:22 -0500 Subject: [PATCH 117/372] Run baseline task on check for 'api' only. Hack up versions to appease OSGi/BND --- api/build.gradle | 2 ++ build.gradle | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/api/build.gradle b/api/build.gradle index 5c5512d3f4..002ef43993 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -27,3 +27,5 @@ jar { 'Import-Package': '*' ) } + +check.dependsOn(baseline) diff --git a/build.gradle b/build.gradle index 527976c59f..75809cbb98 100644 --- a/build.gradle +++ b/build.gradle @@ -231,6 +231,15 @@ subprojects { } plugins.withType(aQute.bnd.gradle.BndBuilderPlugin) { + /* + * The bnd gradle plugin does not handle our 2-digit snapshot versioning scheme very well. It maps `x.y-SNAPSHOT` + * to `x.y.0.SNAPSHOT`. This is bad since `x.y.0.SNAPSHOT` is considered to be less than *all* `x.y.z`. This means + * the baseline version range expression `(,x.y.0.SNAPSHOT[` will always pick the last release from the previous + * minor line. To fix this we manually map to a 3-digit snapshot version where the 3rd digit is a number chosen + * to be higher than we would ever release ('All the worlds a VAX'). + */ + def fixedVersion = project.version.asType(String).replaceAll(/^(\d+.\d+)-SNAPSHOT$/, "\$1.999-SNAPSHOT") + jar { bnd( 'Bundle-Name': project.properties.subPomName, @@ -240,9 +249,15 @@ subprojects { 'Bundle-License': 'LICENSE', 'Bundle-Vendor': 'Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.', 'Bundle-RequiredExecutionEnvironment': 'JavaSE-1.8', + 'Bundle-Version': fixedVersion ) } - check.dependsOn(baseline) + dependencies { + baseline(group: group, name: jar.baseName, version: "(,${fixedVersion}[") { + force = true + transitive = false + } + } } } From c0886170996609a6ac38a85de8dd304557d11f43 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 13 Mar 2019 10:27:32 -0400 Subject: [PATCH 118/372] Upgrade Asciidoctor Pipeline and move to generated diagrams --- docs/build.gradle | 27 ++-- docs/images/design/basics/Faulting.png | Bin 31138 -> 0 bytes docs/images/design/basics/baseTypes.png | Bin 16881 -> 0 bytes docs/images/design/basics/cacheStore.png | Bin 39841 -> 0 bytes docs/images/design/basics/config.png | Bin 43921 -> 0 bytes .../basics/persistentStateTransitions.jpg | Bin 65144 -> 0 bytes .../images/design/basics/stateTransitions.png | Bin 22090 -> 0 bytes .../images/design/basics/userManagedCache.png | Bin 8735 -> 0 bytes .../design/clustered/putIfAbsentUml.png | Bin 89005 -> 0 bytes .../asciidoc/developer/design.basics.adoc | 136 +++++++++++++++++- .../asciidoc/developer/design.tiering.adoc | 28 ++-- .../asciidoc/developer/module.clustering.adoc | 5 +- .../docs/asciidoc/user/caching-concepts.adoc | 66 ++++++++- .../docs/asciidoc/user/clustered-cache.adoc | 70 ++++++++- .../user/images/ClusteredEhcacheTopology.png | Bin 111099 -> 0 bytes .../user/images/EhcacheTerminology.png | Bin 72715 -> 0 bytes docs/src/docs/asciidoc/user/images/Get.png | Bin 18932 -> 0 bytes docs/src/docs/asciidoc/user/images/Put.png | Bin 5565 -> 0 bytes .../asciidoc/user/images/StoragePools.png | Bin 38159 -> 0 bytes .../asciidoc/user/images/TiersHierarchy.png | Bin 28915 -> 0 bytes docs/src/docs/asciidoc/user/performance.adoc | 6 +- docs/src/docs/asciidoc/user/tiering.adoc | 38 +++-- 22 files changed, 321 insertions(+), 55 deletions(-) delete mode 100644 docs/images/design/basics/Faulting.png delete mode 100644 docs/images/design/basics/baseTypes.png delete mode 100644 docs/images/design/basics/cacheStore.png delete mode 100644 docs/images/design/basics/config.png delete mode 100644 docs/images/design/basics/persistentStateTransitions.jpg delete mode 100644 docs/images/design/basics/stateTransitions.png delete mode 100644 docs/images/design/basics/userManagedCache.png delete mode 100644 docs/images/design/clustered/putIfAbsentUml.png delete mode 100644 docs/src/docs/asciidoc/user/images/ClusteredEhcacheTopology.png delete mode 100644 docs/src/docs/asciidoc/user/images/EhcacheTerminology.png delete mode 100644 docs/src/docs/asciidoc/user/images/Get.png delete mode 100644 docs/src/docs/asciidoc/user/images/Put.png delete mode 100644 docs/src/docs/asciidoc/user/images/StoragePools.png delete mode 100644 docs/src/docs/asciidoc/user/images/TiersHierarchy.png diff --git a/docs/build.gradle b/docs/build.gradle index 363aab12f1..bd7880b24b 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -15,18 +15,21 @@ */ plugins { - // Use 1.5.9.1 for now and wait for 1.5.9.3. The 1.5.9.2 prints annoying false warnings - id 'org.asciidoctor.convert' version '1.5.9.1' + id 'org.asciidoctor.convert' version '1.6.0' id 'org.kordamp.gradle.livereload' version '0.2.1' id 'com.github.jruby-gradle.base' version '1.6.0' } dependencies { - gems 'rubygems:asciidoctor-diagram:1.5.11' + gems 'rubygems:asciidoctor-diagram:1.5.15' } -configurations.asciidoctor.dependencies.matching({it.group == 'org.asciidoctor' && it.name == 'asciidoctorj-groovy-dsl'}).all { - exclude group:'org.asciidoctor', module:'asciidoctorj' +configurations.asciidoctor { + resolutionStrategy { + force 'com.github.jnr:jnr-enxio:0.19' + force 'com.github.jnr:jnr-posix:3.0.49' + force 'com.github.jnr:jnr-constants:0.9.12' + } } task copyCSS(type: Copy) { @@ -36,18 +39,7 @@ task copyCSS(type: Copy) { into("${buildDir}/asciidoc/user/css") } -task copyImages(type: Copy) { - from('src/docs/asciidoc/user/images') { - include '**' - } - into("${buildDir}/asciidoc/user/images") -} - -asciidoctor.dependsOn copyCSS, copyImages - -asciidoctorj { - version = '1.5.8.1' -} +asciidoctor.dependsOn copyCSS asciidoctor { dependsOn jrubyPrepare @@ -71,3 +63,4 @@ liveReload { dependencyCheck { skip = true } + diff --git a/docs/images/design/basics/Faulting.png b/docs/images/design/basics/Faulting.png deleted file mode 100644 index 21adaa36d92597465daa32de4bfc8e8c9b9aceb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31138 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 diff --git a/docs/images/design/basics/baseTypes.png b/docs/images/design/basics/baseTypes.png deleted file mode 100644 index 41d1511efec6b23d35a7503f0d4329c48076bf17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16881 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 diff --git a/docs/images/design/basics/cacheStore.png b/docs/images/design/basics/cacheStore.png deleted file mode 100644 index dfb4520b355201f3916ad66ba15a28e37e9046bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39841 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 zÂgmb&dtwh1bg1wZiwmJBB2~W0P=qrzL$?iF?@) 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 P_(xq?OQ}@BEad+OWg;d} diff --git a/docs/images/design/basics/config.png b/docs/images/design/basics/config.png deleted file mode 100644 index 9b80a5f59a078902947046374f5b47d1667785b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43921 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 diff --git a/docs/images/design/basics/persistentStateTransitions.jpg b/docs/images/design/basics/persistentStateTransitions.jpg deleted file mode 100644 index 79d04ad686d33362f31fb5081845b1ec92adc6be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65144 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%0DgiYu2su%3~T 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 z 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 QF&mqqo~dr0&MzT<0Kt8%p#T5? diff --git a/docs/src/docs/asciidoc/developer/design.basics.adoc b/docs/src/docs/asciidoc/developer/design.basics.adoc index 3c4fe6d94e..1721682d14 100644 --- a/docs/src/docs/asciidoc/developer/design.basics.adoc +++ b/docs/src/docs/asciidoc/developer/design.basics.adoc @@ -17,7 +17,23 @@ means fulfilling a couple of roles: This diagram tries to summarize the different roles: -image::https://raw.githubusercontent.com/ehcache/ehcache3/master/docs/images/design/basics/baseTypes.png[Base Types] +[plantuml] +.... +@startuml +interface CacheManager +interface Cache +interface Service +interface ServiceProvider + +CacheManager ..> Cache : <> +Cache ..> Service : <> +CacheManager ..> Service : <> +CacheManager ..> ServiceProvider : <> +ServiceProvider ..> Service : <> + +hide members +@enduml +.... A user will only mostly interact with the `CacheManager` and `Cache` API types... He may need to configure specific `Service` types for his `Cache` instances to use. See <> @@ -43,7 +59,32 @@ on the `CacheConfiguration` used to configure the given `Cache`. That indirectio be loaded by the `ServiceProvider`, should none be explicitly provided. That in turn will resolve the required `Store` instance to be provided to the `Cache` being created. -image::https://raw.githubusercontent.com/ehcache/ehcache3/master/docs/images/design/basics/cacheStore.png[Cache's Store] +[plantuml] +.... +@startuml +interface Cache +interface Store + +Cache *--> Store +Store <|-- OnHeapStore +Store <|-- OffHeapStore + +package "on createCache()" <> { + interface CacheManager + interface ServiceProvider + interface Service + interface Store.Provider + + CacheManager ..> Cache : <> + CacheManager ..> ServiceProvider : <> + CacheManager ..> Store.Provider : <> + Service "*" <--* ServiceProvider + Service <|-- Store.Provider +} + +hide members +@enduml +.... The `Cache` also tries to never _fails_ on operations invoked, e.g. a get shouldn't result in throwing an exception if the `Store` that backs it up uses serialization and fails to retrieve the mapping. Instead, Ehcache tries to be resilient and @@ -66,7 +107,19 @@ As the user manages that instance himself, he needs to provide all `Service` ins Also he'll need to invoke lifecycle methods on it (see <>) and finally keep a reference to it, as it won't available in any `CacheManager`. -image::https://raw.githubusercontent.com/ehcache/ehcache3/master/docs/images/design/basics/userManagedCache.png[UserManagedCache] +[plantuml] +.... +@startuml +interface Cache +interface UserManagedCache +interface Service + +UserManagedCache --|> Cache +UserManagedCache ..> Service : <> + +hide members +@enduml +.... == State transitions @@ -78,7 +131,21 @@ A lifecycled instance, e.g. a `CacheManager` or a `UserManagedCache`, has three operations can be performed on the instance; . `AVAILABLE`: The operational state of the instance, all operations can be performed by any amount of threads. -image::https://raw.githubusercontent.com/ehcache/ehcache3/master/docs/images/design/basics/stateTransitions.png[Statuses & transitions] +[plantuml] +.... +@startuml +[*] --> UNINITIALIZED + +UNINITIALIZED --> UNINITIALIZED : transition failure + +UNINITIALIZED --> AVAILABLE : init() +UNINITIALIZED --> MAINTENANCE : toMaintenance() + +AVAILABLE --> UNINITIALIZED : shutdown() +MAINTENANCE --> UNINITIALIZED : shutdown() +hide empty description +@enduml +.... State should only be maintained at the _higher_ user-visible API instance, e.g. a concrete `Cache` instance like `Ehcache`. That means that it is the warrant for blocking operations during state transitions or on an _illegal state_. No need for @@ -103,7 +170,35 @@ immutable. Instances of these types are used to configure some part of the syste configuration_ is introduced, e.g. `RuntimeCacheConfiguration`. That type will expose additional mutative methods for attributes that are mutable. Internally it will also let consumers of the type register listener for these attributes. -image::https://raw.githubusercontent.com/ehcache/ehcache3/master/docs/images/design/basics/config.png[Configuration types] +[plantuml] +.... +@startuml +interface CacheManagerBuilder +interface Configuration +interface CacheConfiguration +interface ServiceConfiguration +interface ServiceCreationConfiguration + +CacheManagerBuilder ..> Configuration : <> +Configuration *--> "*" ServiceCreationConfiguration +Configuration *--> "*" CacheConfiguration +CacheConfiguration *--> "*" ServiceConfiguration +hide members + +package runtime <> { + interface CacheManager + interface Service + interface RuntimeCacheConfiguration + interface Cache + + CacheManager <.. CacheManagerBuilder : <> + CacheManager ..> Service : <> + Cache ..> Service : <> + Cache <.. CacheManager : <> + Cache ..> RuntimeCacheConfiguration : <> +} +@enduml +.... ==== Services creation, `ServiceCreationConfiguration`, `ServiceProvider` and `ServiceConfiguration` @@ -192,7 +287,36 @@ datastructures on disk to store. We think of states of those structures in these . Online: the datastructures are present (with or without any data), referenced by the `Store` and the `Cache` is usable; . Offline: the datastructures are present (with or without data), not referenced by any `Store` and nothing accesses it. -image::https://raw.githubusercontent.com/ehcache/ehcache3/master/docs/images/design/basics/persistentStateTransitions.jpg[Persistence and statuses & their transitions] +[plantuml] +.... +@startuml +state store { +[*] --> UNINITIALIZED + +UNINITIALIZED --> UNINITIALIZED : transition failure + +UNINITIALIZED --> AVAILABLE : init +UNINITIALIZED --> MAINTENANCE : toMaintenance + +AVAILABLE --> UNINITIALIZED : shutdown +MAINTENANCE --> UNINITIALIZED : shutdown + +MAINTENANCE --> MAINTENANCE : destroy +MAINTENANCE --> MAINTENANCE : create +} + +state data { + [*] --> ONLINE : create + ONLINE --> [*] : destroy + + OFFLINE --> ONLINE : init + ONLINE --> OFFLINE : shutdown + OFFLINE --> [*] : destroy + OFFLINE --> OFFLINE : transition failure +} +hide empty description +@enduml +.... The user can fallback to the maintenance mode and the `Maintainable` instance returned when transitioning to the maintenance state. That `Maintainable` can be used to: diff --git a/docs/src/docs/asciidoc/developer/design.tiering.adoc b/docs/src/docs/asciidoc/developer/design.tiering.adoc index 5954e9dc71..4210177572 100644 --- a/docs/src/docs/asciidoc/developer/design.tiering.adoc +++ b/docs/src/docs/asciidoc/developer/design.tiering.adoc @@ -47,19 +47,21 @@ entry is expired/evicted from caching tier, it flushes that information to autho using invalidation listener. All the flushed entries are now marked as evictable in authority. -image::https://raw.githubusercontent.com/ehcache/ehcache3/master/docs/images/design/basics/Faulting.png[Faulting & Flushing] - - . All writes directly go to the Authoritative tier.This tier has all the data such that caching tier always has a subset of authority - - . On return, the mapping in the caching tier is invalidated. - - . On eviction or expiry in the caching tier, the mapping is flushed to the authority. - - . Any reading thread tries to get data from the caching tier and returns - - . If the key is not found in caching tier, it is faulted from authority - - . On return, the mapping faulted from the authority is installed in the caching tier. The install may fail under heavy contention to preserve correctness. +[plantuml] +.... +include::../../uml/put.puml[] +.... + * All writes directly go to the Authoritative tier.This tier has all the data such that caching tier always has a subset of authority + * On return, the mapping in the caching tier is invalidated. + * On eviction or expiry in the caching tier, the mapping is flushed to the authority. + +[plantuml] +.... +include::../../uml/get.puml[] +.... + * Any reading thread tries to get data from the caching tier and returns + * If the key is not found in caching tier, it is faulted from authority + * On return, the mapping faulted from the authority is installed in the caching tier. The install may fail under heavy contention to preserve correctness. diff --git a/docs/src/docs/asciidoc/developer/module.clustering.adoc b/docs/src/docs/asciidoc/developer/module.clustering.adoc index fa41460323..4632aa2cb2 100644 --- a/docs/src/docs/asciidoc/developer/module.clustering.adoc +++ b/docs/src/docs/asciidoc/developer/module.clustering.adoc @@ -66,4 +66,7 @@ _HA_? ==== putIfAbsent -image::https://github.com/ehcache/ehcache3/blob/master/docs/images/design/clustered/putIfAbsentUml.png[putIfAbsent sequence] +[plantuml] +.... +include::../../uml/putIfAbsentUml.puml[] +.... diff --git a/docs/src/docs/asciidoc/user/caching-concepts.adoc b/docs/src/docs/asciidoc/user/caching-concepts.adoc index e1fdfcfcaa..4984cf88f9 100644 --- a/docs/src/docs/asciidoc/user/caching-concepts.adoc +++ b/docs/src/docs/asciidoc/user/caching-concepts.adoc @@ -61,7 +61,29 @@ The remote server may optionally have a failover server providing improved high Since clustered storage comes with performance penalties due to such factors as network latency as well as for establishing client/server consistency, this tier, by nature, is slower than local off-heap storage. -image::EhcacheTerminology.png[] +[ditaa] +.... + +-----------------------------------+ + |cBE7 Application | + | | + | +-------------------------------+ | + | |c7DE Cache Manager | | Applications may have one or + | | | | more Cache Managers + | | +-------------------------+ | | + | | |c7AE Cache | | | A Cache Manager can manage + | | |+-----------------------+| | | many Caches + | | ||cFA4 Heap Tier || | | + | | |+-----------------------+| | | + | | || || | | Caches are configured to utilize + | | ||cFA4 Off Heap Tier || | | one or more Tiers for storing + | | || || | | cache entries + | | |+-----------------------+| | | + | | ||cA8D Disk Tier || | | Ehcache keeps the hotter data + | | |+-----------------------+| | | in faster tiers + | | +-------------------------+ | | + | +-------------------------------+ | + +-----------------------------------+ +.... == Topology Types @@ -78,7 +100,47 @@ This topology offers offers a selection of consistency options. A distributed topology is the recommended approach in a clustered or scaled-out application environment. It provides the best combination of performance, availability, and scalability. -image::ClusteredEhcacheTopology.png[] +[ditaa] +.... ++------------------------------+ +------------------------------+ +| Application | | Application | +| cBE7| | cBE7| +|+----------------------------+| |+----------------------------+| +|| Cache Manager c7DE|| || Cache Manager c7DE|| +||+--------------------------+|| ||+--------------------------+|| +||| Cache c7AE||| ||| Cache c7AE||| +|||+------------------------+||| |||+------------------------+||| +|||| Heap Tier cFA4|||| |||| Heap Tier cFA4|||| +|||+------------------------+||| |||+------------------------+||| +|||| |||| |||| |||| +|||| Off Heap Tier |||| |||| Off Heap Tier |||| +|||| cFA4|||| |||| cFA4|||| +|||+------------------------+||| |||+------------------------+||| +|||| Clustered Tier cA8D||||<--+ +-->|||| Clustered Tier cA8D|||| +|||+------------------------+||| | | |||+------------------------+||| +||+--------------------------+|| | | ||+--------------------------+|| +|+----------------------------+| | | |+----------------------------+| ++------------------------------+ | | +------------------------------+ + | | + V V + +------------------------------+ + | Terracotta Server | + | c7AE| + |+----------------------------+| + || Cache Clustered || + || Tier Manager cF55|| + |+----------------------------+| + || || + || Off Heap || + || Data Storage || + || cFA4|| + |+----------------------------+| + +------------------------------+ +.... +* Hot data is cached locally, hotter data in faster tiers +* Data cached by one application instance is available to all cluster members. +* Full data is available in the cluster. +* One or more mirror servers may be deployed to provide HA It is common for many production applications to be deployed in clusters of multiple instances for availability and scalability. However, without a distributed cache, application clusters exhibit a number of undesirable behaviors, such as: diff --git a/docs/src/docs/asciidoc/user/clustered-cache.adoc b/docs/src/docs/asciidoc/user/clustered-cache.adoc index 4fa2f3e61b..df5f02c8f7 100644 --- a/docs/src/docs/asciidoc/user/clustered-cache.adoc +++ b/docs/src/docs/asciidoc/user/clustered-cache.adoc @@ -13,7 +13,47 @@ endif::notBuildingForSite[] Distributed caching allows you to harness additional benefits of horizontal scale-out, without losing on low latency offered by local on-heap tiers. -image::ClusteredEhcacheTopology.png[] +[ditaa] +.... ++------------------------------+ +------------------------------+ +| Application | | Application | +| cBE7| | cBE7| +|+----------------------------+| |+----------------------------+| +|| Cache Manager c7DE|| || Cache Manager c7DE|| +||+--------------------------+|| ||+--------------------------+|| +||| Cache c7AE||| ||| Cache c7AE||| +|||+------------------------+||| |||+------------------------+||| +|||| Heap Tier cFA4|||| |||| Heap Tier cFA4|||| +|||+------------------------+||| |||+------------------------+||| +|||| |||| |||| |||| +|||| Off Heap Tier |||| |||| Off Heap Tier |||| +|||| cFA4|||| |||| cFA4|||| +|||+------------------------+||| |||+------------------------+||| +|||| Clustered Tier cA8D||||<--+ +-->|||| Clustered Tier cA8D|||| +|||+------------------------+||| | | |||+------------------------+||| +||+--------------------------+|| | | ||+--------------------------+|| +|+----------------------------+| | | |+----------------------------+| ++------------------------------+ | | +------------------------------+ + | | + V V + +------------------------------+ + | Terracotta Server | + | c7AE| + |+----------------------------+| + || Cache Clustered || + || Tier Manager cF55|| + |+----------------------------+| + || || + || Off Heap || + || Data Storage || + || cFA4|| + |+----------------------------+| + +------------------------------+ +.... + * Hot data is cached locally, hotter data in faster tiers + * Data cached by one application instance is available to all cluster members. + * Full data is available in the cluster. + * One or more mirror servers may be deployed to provide HA To enable clustering with Terracotta, you will have to deploy a Terracotta server configured with clustered cache storage. For convenience Ehcache 3.1 introduced a downloadable kit that contains the Terracotta Server and also the required client libraries. @@ -58,7 +98,33 @@ Consequently, when resource capacity is reached and triggers eviction, the evict Here is a pictorial representation of the concepts explained above: -image::StoragePools.png[] +[ditaa] +.... ++-----------------------------------------+ +| Primary Server Resource | +| (196 GB) | +| | +| /---------------\ /---------------\ | +| | Shared Pool A | | Shared Pool B | | +| | (32 GB)cBEC| | (24 GB)cBEC| | +| \---------------/ \---------------/ | +| | +| /---------------\ /---------------\ | +| | Fixed Pool C | | Fixed Pool D | | +| | (32 GB)cA8D| | (16 GB)cA8D| | +| \---------------/ \---------------/ | +| cFAA| ++-----------------------------------------+ +| Secondary Server Resource | +| (96 GB) | +| | +| /---------------\ /---------------\ | +| | Shared Pool E | | Fixed Pool F | | +| | (28 GB)cBEC| | (12 GB)cA8D| | +| \---------------/ \---------------/ | +| cF55| ++-----------------------------------------+ +.... [[starting-server]] == Starting the Terracotta Server diff --git a/docs/src/docs/asciidoc/user/images/ClusteredEhcacheTopology.png b/docs/src/docs/asciidoc/user/images/ClusteredEhcacheTopology.png deleted file mode 100644 index 4bcdb053c2496e3b3dcae7998d68a82c54882729..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111099 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 z 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 diff --git a/docs/src/docs/asciidoc/user/images/EhcacheTerminology.png b/docs/src/docs/asciidoc/user/images/EhcacheTerminology.png deleted file mode 100644 index 2b8d5e1829af9921e9a93b217f8e73e2dd28260e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72715 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 kwSs6P2OlMJ>2@~t$dv7< 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 D_Y%Qo diff --git a/docs/src/docs/asciidoc/user/images/Put.png b/docs/src/docs/asciidoc/user/images/Put.png deleted file mode 100644 index 37b9552222ee22af9d0efa3eec260fcaa0a0024e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5565 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 brPYaIl)s|Z`b_WdvMfj)qoq=L-2(qFX$ma} diff --git a/docs/src/docs/asciidoc/user/images/StoragePools.png b/docs/src/docs/asciidoc/user/images/StoragePools.png deleted file mode 100644 index 66df0bbf3b14e37174be50f74dcb774cd8853f3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38159 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 S@$#Qpw2Fd;e6{S?pZ^1ckMZpQ diff --git a/docs/src/docs/asciidoc/user/performance.adoc b/docs/src/docs/asciidoc/user/performance.adoc index 6d6ea37e5c..14c784055c 100644 --- a/docs/src/docs/asciidoc/user/performance.adoc +++ b/docs/src/docs/asciidoc/user/performance.adoc @@ -1,9 +1,9 @@ --- --- = Performance Tuning -ifndef::sourcedir35[] +ifndef::sourcedir37[] include::common.adoc[] -endif::sourcedir35[] +endif::sourcedir37[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -115,7 +115,7 @@ For instance, let's say you define an expiry policy like this. [source,java,indent=0] ---- -include::{sourcedir35}/integration-test/src/test/java/org/ehcache/docs/Performance.java[tag=expiryAllocation] +include::{sourcedir37}/integration-test/src/test/java/org/ehcache/docs/Performance.java[tag=expiryAllocation] ---- <1> Will instantiate a `Duration` every time an entry is accessed diff --git a/docs/src/docs/asciidoc/user/tiering.adoc b/docs/src/docs/asciidoc/user/tiering.adoc index c952cf6a19..d6ca14416c 100644 --- a/docs/src/docs/asciidoc/user/tiering.adoc +++ b/docs/src/docs/asciidoc/user/tiering.adoc @@ -202,8 +202,22 @@ This leads to the typical pyramid shape for a multi-tiered setup. -- [.left] .Tiers hierarchy -image::TiersHierarchy.png[Tiers hierarchy] - +[ditaa] +.... + +-------------------+ + |cBE7 Heap Tier | + +-+-------------------+-+ + |cFA4 | + | Off Heap Tier | + | | ++-+-----------------------+-+ +|cA8D | +| | +| Disk Tier | +| | +| | ++---------------------------+ +.... Ehcache requires the size of the heap tier to be smaller than the size of the offheap tier, and the size of the offheap tier to be smaller than the size of the disk tier. While Ehcache cannot verify at configuration time that a count-based sizing for heap will be smaller than a byte-based sizing for another tier, you should make sure that is the case during testing. -- @@ -297,19 +311,21 @@ This method destroys a given cache. The cache shouldn't be in use by another cac [[multi-tier-sequence-flow]] == Sequence Flow for Cache Operations with Multiple Tiers - -In order to understand what happens for different cache operations when using multiple tiers, here are examples of _Put_ and _Get_ operations. -The sequence diagrams are oversimplified but still show the main points. - -[.float-group] +[.right] -- -[.left] .Multiple tiers using Put -image::Put.png[Put] -[.left] +[plantuml] +.... +include::../../uml/put.puml[] +.... .Multiple tiers using Get -image::Get.png[Get] +[plantuml] +.... +include::../../uml/get.puml[] +.... -- +In order to understand what happens for different cache operations when using multiple tiers, here are examples of _Put_ and _Get_ operations. +The sequence diagrams are oversimplified but still show the main points. You should then notice the following: From d72ee063ee5c66b8c39c1417e11848ac39c8ab18 Mon Sep 17 00:00:00 2001 From: Abhilash Date: Mon, 8 Apr 2019 18:24:30 +0530 Subject: [PATCH 119/372] Bump up tc platform version --- .../clustered/server/store/ClusterTierActiveEntity.java | 1 + .../clustered/server/store/ClusterTierPassiveEntity.java | 1 + .../clustered/server/store/ClusterTierActiveEntityTest.java | 4 ++-- .../clustered/server/store/ClusterTierPassiveEntityTest.java | 2 +- gradle.properties | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java b/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java index 860e00fe7e..5220dfa788 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java @@ -907,6 +907,7 @@ public void destroy() { } catch (ClusterException e) { LOGGER.error("Failed to destroy server store - does not exist", e); } + messageHandler.destroy(); management.close(); } diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java b/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java index 50a7428a39..80bcfff72f 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java @@ -306,6 +306,7 @@ public void destroy() { throw new AssertionError(e); } management.close(); + messageHandler.destroy(); } @Override diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index debc505a56..8b11cd6c71 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -1133,7 +1133,7 @@ public T getService(final ServiceConfiguration configuration) { } else if (serviceType.isAssignableFrom(EntityManagementRegistry.class)) { return (T) entityManagementRegistry; } else if (serviceType.isAssignableFrom(OOOMessageHandler.class)) { - return (T) new OOOMessageHandlerImpl<>(message -> true, 1, message -> 0); + return (T) new OOOMessageHandlerImpl<>(message -> true, 1, message -> 0, () -> {}); } throw new AssertionError("Unknown service configuration of type: " + serviceType); } @@ -1309,7 +1309,7 @@ public OffHeapResource getOffHeapResource(OffHeapResourceIdentifier identifier) } else if(serviceConfiguration instanceof OOOMessageHandlerConfiguration) { OOOMessageHandlerConfiguration oooMessageHandlerConfiguration = (OOOMessageHandlerConfiguration) serviceConfiguration; return (T) new OOOMessageHandlerImpl<>(oooMessageHandlerConfiguration.getTrackerPolicy(), - oooMessageHandlerConfiguration.getSegments(), oooMessageHandlerConfiguration.getSegmentationStrategy()); + oooMessageHandlerConfiguration.getSegments(), oooMessageHandlerConfiguration.getSegmentationStrategy(), () -> {}); } throw new UnsupportedOperationException("Registry.getService does not support " + serviceConfiguration.getClass().getName()); diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java index dd59b77477..f418e2855b 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java @@ -358,7 +358,7 @@ public OffHeapResource getOffHeapResource(OffHeapResourceIdentifier identifier) } else if(serviceConfiguration instanceof OOOMessageHandlerConfiguration) { OOOMessageHandlerConfiguration oooMessageHandlerConfiguration = (OOOMessageHandlerConfiguration) serviceConfiguration; return (T) new OOOMessageHandlerImpl<>(oooMessageHandlerConfiguration.getTrackerPolicy(), - oooMessageHandlerConfiguration.getSegments(), oooMessageHandlerConfiguration.getSegmentationStrategy()); + oooMessageHandlerConfiguration.getSegments(), oooMessageHandlerConfiguration.getSegmentationStrategy(), () -> {}); } throw new UnsupportedOperationException("Registry.getService does not support " + serviceConfiguration.getClass().getName()); diff --git a/gradle.properties b/gradle.properties index d0cf0ed020..58be7f383f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.0-pre3 +terracottaPlatformVersion = 5.7.0-pre4 terracottaApisVersion = 1.6.1-pre1 terracottaCoreVersion = 5.6.1-pre7 terracottaPassthroughTestingVersion = 1.6.1-pre1 From 90e0020ca587811f8eb71c32f085f5a85583653d Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 8 Mar 2019 15:44:11 -0500 Subject: [PATCH 120/372] OSGi Manifest/Bnd Cleanup --- 107/build.gradle | 1 - build.gradle | 8 ++++---- buildSrc/src/main/groovy/EhDistribute.groovy | 7 ------- impl/build.gradle | 1 - transactions/build.gradle | 1 - 5 files changed, 4 insertions(+), 14 deletions(-) diff --git a/107/build.gradle b/107/build.gradle index f21d19d20e..b7c07985e2 100644 --- a/107/build.gradle +++ b/107/build.gradle @@ -55,7 +55,6 @@ jar { bnd( 'Export-Package': '!org.ehcache.jsr107.tck, !org.ehcache.jsr107.internal.*, org.ehcache.jsr107.*', 'Import-Package': 'javax.cache.*;resolution:=optional, *', - 'Service-Component': 'OSGI-INF/*.xml' ) } diff --git a/build.gradle b/build.gradle index 75809cbb98..ecef70bec5 100644 --- a/build.gradle +++ b/build.gradle @@ -230,7 +230,7 @@ subprojects { } } - plugins.withType(aQute.bnd.gradle.BndBuilderPlugin) { + plugins.withId('biz.aQute.bnd.builder') { /* * The bnd gradle plugin does not handle our 2-digit snapshot versioning scheme very well. It maps `x.y-SNAPSHOT` * to `x.y.0.SNAPSHOT`. This is bad since `x.y.0.SNAPSHOT` is considered to be less than *all* `x.y.z`. This means @@ -248,12 +248,12 @@ subprojects { 'Bundle-DocURL': 'http://ehcache.org', 'Bundle-License': 'LICENSE', 'Bundle-Vendor': 'Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.', - 'Bundle-RequiredExecutionEnvironment': 'JavaSE-1.8', - 'Bundle-Version': fixedVersion + 'Bundle-Version': fixedVersion, + 'Service-Component': 'OSGI-INF/*.xml' ) } dependencies { - baseline(group: group, name: jar.baseName, version: "(,${fixedVersion}[") { + baseline(group: group, name: jar.archiveBaseName.get(), version: "(,${fixedVersion}[") { force = true transitive = false } diff --git a/buildSrc/src/main/groovy/EhDistribute.groovy b/buildSrc/src/main/groovy/EhDistribute.groovy index 2b016b97cc..6850a414ed 100644 --- a/buildSrc/src/main/groovy/EhDistribute.groovy +++ b/buildSrc/src/main/groovy/EhDistribute.groovy @@ -64,13 +64,6 @@ class EhDistribute implements Plugin { duplicatesStrategy = 'exclude' classpath = project.files(project.configurations.shadowCompile, project.configurations.shadowProvided) - bnd( - 'Bundle-DocURL': 'http://ehcache.org', - 'Bundle-License': 'LICENSE', - 'Bundle-Vendor': 'Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.', - 'Bundle-RequiredExecutionEnvironment': 'JavaSE-1.8', - 'Service-Component': 'OSGI-INF/*.xml' - ) utils.fillManifest(manifest, project.archivesBaseName) } diff --git a/impl/build.gradle b/impl/build.gradle index 74a879d012..0808a31050 100644 --- a/impl/build.gradle +++ b/impl/build.gradle @@ -52,7 +52,6 @@ jar { 'Export-Package': '!org.ehcache.impl.internal.*, org.ehcache.impl.*, org.ehcache.config.builders, ' + 'org.ehcache.impl.internal.spi.loaderwriter', //ugly 107 induced internal export wart 'Import-Package': '!sun.misc, !javax.annotation, *', - 'Service-Component': 'OSGI-INF/*.xml' ) } diff --git a/transactions/build.gradle b/transactions/build.gradle index 57d682cff6..1b6ea31bb8 100644 --- a/transactions/build.gradle +++ b/transactions/build.gradle @@ -46,7 +46,6 @@ jar { 'Bundle-SymbolicName': 'org.ehcache.transactions', 'Export-Package': 'org.ehcache.transactions.xa.*', 'Import-Package': 'bitronix.tm.*;resolution:=optional, javax.transaction.*;resolution:=optional, org.ehcache.xml.*;resolution:=optional, *', - 'Service-Component': 'OSGI-INF/*.xml' ) } From 967d2d55d3de72c65645e8dfd08128cfef679a50 Mon Sep 17 00:00:00 2001 From: Anthony Dahanne Date: Tue, 9 Apr 2019 15:59:36 -0400 Subject: [PATCH 121/372] Upgrade dependencies to stable versions --- gradle.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 58be7f383f..68111ca8f4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,10 +10,10 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.0-pre4 -terracottaApisVersion = 1.6.1-pre1 -terracottaCoreVersion = 5.6.1-pre7 -terracottaPassthroughTestingVersion = 1.6.1-pre1 +terracottaPlatformVersion = 5.7.1 +terracottaApisVersion = 1.6.1 +terracottaCoreVersion = 5.6.2 +terracottaPassthroughTestingVersion = 1.6.1 # Test lib versions junitVersion = 4.12 From 6d01492dd8937345b6d3d85bdce2b5fa94779348 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 10 Apr 2019 09:55:57 -0400 Subject: [PATCH 122/372] Fixes #2634 : Reject internal releases as baseline candidates --- build.gradle | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 75809cbb98..035ffee2da 100644 --- a/build.gradle +++ b/build.gradle @@ -253,7 +253,11 @@ subprojects { ) } dependencies { - baseline(group: group, name: jar.baseName, version: "(,${fixedVersion}[") { + baseline(group: group, name: jar.baseName) { + version { + require "(,${fixedVersion}[" + reject "${fixedVersion}-internal+" + } force = true transitive = false } From 4682799665b61dcfb3f73a94d8c7167c817fd864 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 10 Apr 2019 12:45:31 -0400 Subject: [PATCH 123/372] Always use sourceDir for includes to avoid breaking org-site generation --- docs/src/docs/asciidoc/user/tiering.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/docs/asciidoc/user/tiering.adoc b/docs/src/docs/asciidoc/user/tiering.adoc index d6ca14416c..9decf0c2d9 100644 --- a/docs/src/docs/asciidoc/user/tiering.adoc +++ b/docs/src/docs/asciidoc/user/tiering.adoc @@ -316,12 +316,12 @@ This method destroys a given cache. The cache shouldn't be in use by another cac .Multiple tiers using Put [plantuml] .... -include::../../uml/put.puml[] +include::{sourcedir37}/docs/src/docs/uml/put.puml[] .... .Multiple tiers using Get [plantuml] .... -include::../../uml/get.puml[] +include::{sourcedir37}/docs/src/docs/uml/get.puml[] .... -- In order to understand what happens for different cache operations when using multiple tiers, here are examples of _Put_ and _Get_ operations. From fc08d3b5a14cfc30c5854ae5a8d363efb9f7cbef Mon Sep 17 00:00:00 2001 From: Anthony Dahanne Date: Wed, 10 Apr 2019 19:21:36 -0400 Subject: [PATCH 124/372] Fix release doc and script --- deploy.sh | 2 +- dist/templates/github-release-issue.md | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/deploy.sh b/deploy.sh index 322399b46e..3921828d43 100755 --- a/deploy.sh +++ b/deploy.sh @@ -117,7 +117,7 @@ else echo git checkout -b release-${version} echo git add gradle.properties dist/templates/github-release.md echo git commit -m "Version ${version}" - echo git tag -m ":ship: Release ${version}" -v${version} + echo git tag -m ":ship: Release ${version}" v${version} echo git push $git_origin v${version} fi diff --git a/dist/templates/github-release-issue.md b/dist/templates/github-release-issue.md index f11d907566..3abcc705c2 100644 --- a/dist/templates/github-release-issue.md +++ b/dist/templates/github-release-issue.md @@ -1,11 +1,11 @@ -- [] Tag release -- [] Build and verify release +- [ ] Tag release +- [ ] Build and verify release - includes checking javadoc and source jars -- [] Prepare release on GitHub -- [] Prepare website update +- [ ] Prepare release on GitHub +- [ ] Prepare website update - includes checking XSDs -- [] Publish jars to Maven Central -- [] Publish release on GitHub -- [] Publish website -- [] Update readme / bump version on release branch -- [] Email announcement +- [ ] Publish jars to Maven Central +- [ ] Publish release on GitHub +- [ ] Publish website +- [ ] Update readme / bump version on release branch +- [ ] Email announcement From cfbb7e263a3c54cdbc00c849b09c4b0eab6df358 Mon Sep 17 00:00:00 2001 From: Anthony Dahanne Date: Wed, 10 Apr 2019 21:26:09 -0400 Subject: [PATCH 125/372] Use latest core and platform --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 68111ca8f4..6853c57ee2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.1 +terracottaPlatformVersion = 5.7.2 terracottaApisVersion = 1.6.1 -terracottaCoreVersion = 5.6.2 +terracottaCoreVersion = 5.6.3 terracottaPassthroughTestingVersion = 1.6.1 # Test lib versions From ca76ab3d17a545853cb0bc92ba078925467ed9e9 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 15 Apr 2019 10:15:25 -0400 Subject: [PATCH 126/372] Issue #2626 : Test to expose #2626 --- .../store/operations/ChainResolverTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/operations/ChainResolverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/operations/ChainResolverTest.java index 92ee8a5043..dcdaf91e4a 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/operations/ChainResolverTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/operations/ChainResolverTest.java @@ -22,6 +22,7 @@ import org.ehcache.clustered.common.store.Chain; import org.ehcache.clustered.common.store.Element; import org.ehcache.core.spi.time.SystemTimeSource; +import org.ehcache.expiry.Duration; import org.ehcache.expiry.Expirations; import org.ehcache.impl.serialization.LongSerializer; import org.ehcache.impl.serialization.StringSerializer; @@ -30,8 +31,12 @@ import org.junit.Test; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.concurrent.TimeUnit; +import static java.util.Arrays.asList; +import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.*; public class ChainResolverTest { @@ -211,6 +216,20 @@ public void testResolvePutIfAbsentSucceeds() throws Exception { assertEquals(expected, result); } + @Test + public void testResolveExpiresUsingOperationTime() { + Chain chain = getChainFromOperations(asList( + new PutOperation(1L, "Albin", 0), + new PutIfAbsentOperation(1L, "Chris", 900) + )); + + ChainResolver resolver = new ChainResolver(codec, Expirations.timeToLiveExpiration(Duration.of(1, TimeUnit.SECONDS))); + + ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 1500); + Result result = resolvedChain.getResolvedResult(1L); + assertThat(result.getValue(), nullValue()); + } + private Chain getChainFromOperations(List> operations) { ChainBuilder chainBuilder = new ChainBuilder(); for(Operation operation: operations) { From 9457d207f2bd12d5e1b258c9e2d6786ba713585a Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 4 Apr 2019 15:26:07 -0400 Subject: [PATCH 127/372] Fixes #2626 : Timestamp chains to allow consistent expiry implementation --- .../ClusteredLoaderWriterStore.java | 68 ++- .../writebehind/ClusteredWriteBehind.java | 8 +- .../ClusteredWriteBehindStore.java | 81 ++-- .../service/DefaultClusteringService.java | 8 +- .../client/internal/store/ClusteredStore.java | 120 ++--- .../store/CommonServerStoreProxy.java | 51 ++- .../store/EventualServerStoreProxy.java | 4 +- .../store/ReconnectingServerStoreProxy.java | 87 +++- .../client/internal/store/ResolvedChain.java | 100 ---- .../internal/store/ServerStoreProxy.java | 80 +++- .../store/StrongServerStoreProxy.java | 4 +- .../internal/store/lock/LockManager.java | 71 ++- .../internal/store/lock/LockManagerImpl.java | 85 ---- .../store/lock/LockingServerStoreProxy.java | 72 +-- .../lock/LockingServerStoreProxyImpl.java | 111 +++++ .../store/operations/ChainResolver.java | 130 ++++-- .../operations/EternalChainResolver.java | 34 +- .../store/operations/ExpiryChainResolver.java | 54 ++- .../ClusteredLoaderWriterStoreTest.java | 118 +++-- .../writebehind/ClusteredWriteBehindTest.java | 33 +- .../internal/store/ClusteredStoreTest.java | 358 +-------------- .../store/CommonServerStoreProxyTest.java | 13 +- .../store/EventualServerStoreProxyTest.java | 11 +- ...ltiThreadedStrongServerStoreProxyTest.java | 3 +- .../store/StrongServerStoreProxyTest.java | 24 +- ...agerImplTest.java => LockManagerTest.java} | 10 +- .../operations/AbstractChainResolverTest.java | 427 ++++++++++-------- .../operations/ExpiryChainResolverTest.java | 124 ++--- .../operations/TimestampOperationTest.java | 97 ++++ ...icClusteredWriteBehindPassthroughTest.java | 7 +- .../store/operations/OperationCode.java | 8 + .../store/operations/TimestampOperation.java | 138 ++++++ .../common/internal/util/ChainBuilder.java | 4 + .../ClusteredStatisticsCountTest.java | 2 +- 34 files changed, 1314 insertions(+), 1231 deletions(-) delete mode 100644 clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ResolvedChain.java delete mode 100644 clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImpl.java create mode 100644 clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java rename clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/{LockManagerImplTest.java => LockManagerTest.java} (93%) create mode 100644 clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperationTest.java create mode 100644 clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperation.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java index d08126d3ac..dc6fc6b221 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java @@ -17,9 +17,8 @@ import org.ehcache.clustered.client.internal.store.ClusteredStore; import org.ehcache.clustered.client.internal.store.ClusteredValueHolder; -import org.ehcache.clustered.client.internal.store.ResolvedChain; import org.ehcache.clustered.client.internal.store.ServerStoreProxy; -import org.ehcache.clustered.client.internal.store.lock.LockManager; +import org.ehcache.clustered.client.internal.store.lock.LockingServerStoreProxy; import org.ehcache.clustered.client.internal.store.operations.ChainResolver; import org.ehcache.clustered.client.internal.store.operations.EternalChainResolver; import org.ehcache.clustered.common.internal.store.operations.ConditionalRemoveOperation; @@ -28,10 +27,8 @@ import org.ehcache.clustered.common.internal.store.operations.PutOperation; import org.ehcache.clustered.common.internal.store.operations.RemoveOperation; import org.ehcache.clustered.common.internal.store.operations.ReplaceOperation; -import org.ehcache.clustered.common.internal.store.operations.Result; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; import org.ehcache.clustered.client.service.ClusteringService; -import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.config.ResourceType; import org.ehcache.core.exceptions.StorePassThroughException; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; @@ -50,7 +47,6 @@ import java.util.concurrent.TimeoutException; import static org.ehcache.core.exceptions.ExceptionFactory.newCacheLoadingException; -import static org.ehcache.core.exceptions.ExceptionFactory.newCacheWritingException; import static org.ehcache.core.exceptions.StorePassThroughException.handleException; public class ClusteredLoaderWriterStore extends ClusteredStore implements AuthoritativeTier { @@ -75,8 +71,8 @@ public ClusteredLoaderWriterStore(Configuration config, OperationsCodec getInternal(K key) throws StoreAccessException, Timeout boolean unlocked = false; getProxy().lock(hash); try { - V value = null; + V value; try { value = cacheLoaderWriter.load(key); } catch (Exception e) { @@ -143,17 +139,12 @@ protected boolean silentRemove(K key) throws StoreAccessException { boolean unlocked = false; RemoveOperation operation = new RemoveOperation<>(key, timeSource.getTimeMillis()); ByteBuffer payLoad = codec.encode(operation); - Chain chain = getProxy().lock(hash); + ServerStoreProxy.ChainEntry chain = getProxy().lock(hash); try { cacheLoaderWriter.delete(key); storeProxy.append(hash, payLoad); unlocked = true; - ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); - if (resolvedChain.getResolvedResult(key) != null) { - return true; - } else { - return false; - } + return resolver.resolve(chain, key, timeSource.getTimeMillis()) != null; } finally { getProxy().unlock(hash, unlocked); } @@ -163,15 +154,13 @@ protected boolean silentRemove(K key) throws StoreAccessException { } @Override - protected V silentPutIfAbsent(K key, V value) throws StoreAccessException { + protected ValueHolder silentPutIfAbsent(K key, V value) throws StoreAccessException { try { long hash = extractLongKey(key); boolean unlocked = false; - Chain existing = getProxy().lock(hash); + ServerStoreProxy.ChainEntry existing = getProxy().lock(hash); try { - ResolvedChain resolvedChain = resolver.resolve(existing, key, timeSource.getTimeMillis()); - Result result = resolvedChain.getResolvedResult(key); - V existingVal = result == null ? null : result.getValue(); + ValueHolder existingVal = resolver.resolve(existing, key, timeSource.getTimeMillis()); if (existingVal != null) { return existingVal; } else { @@ -194,15 +183,13 @@ protected V silentPutIfAbsent(K key, V value) throws StoreAccessException { } @Override - protected V silentReplace(K key, V value) throws StoreAccessException { + protected ValueHolder silentReplace(K key, V value) throws StoreAccessException { try { long hash = extractLongKey(key); boolean unlocked = false; - Chain existing = getProxy().lock(hash); + ServerStoreProxy.ChainEntry existing = getProxy().lock(hash); try { - ResolvedChain resolvedChain = resolver.resolve(existing, key, timeSource.getTimeMillis()); - Result result = resolvedChain.getResolvedResult(key); - V existingVal = result == null ? null : result.getValue(); + ValueHolder existingVal = resolver.resolve(existing, key, timeSource.getTimeMillis()); if (existingVal != null) { cacheLoaderWriter.write(key, value); ReplaceOperation operation = new ReplaceOperation<>(key, value, timeSource.getTimeMillis()); @@ -211,7 +198,7 @@ protected V silentReplace(K key, V value) throws StoreAccessException { unlocked = true; return existingVal; } else { - V inCache = loadFromLoaderWriter(key); + ValueHolder inCache = loadFromLoaderWriter(key); if (inCache != null) { cacheLoaderWriter.write(key, value); ReplaceOperation operation = new ReplaceOperation<>(key, value, timeSource.getTimeMillis()); @@ -232,19 +219,17 @@ protected V silentReplace(K key, V value) throws StoreAccessException { } @Override - protected V silentRemove(K key, V value) throws StoreAccessException { + protected ValueHolder silentRemove(K key, V value) throws StoreAccessException { try { long hash = extractLongKey(key); boolean unlocked = false; - Chain existing = getProxy().lock(hash); + ServerStoreProxy.ChainEntry existing = getProxy().lock(hash); try { - ResolvedChain resolvedChain = resolver.resolve(existing, key, timeSource.getTimeMillis()); - Result result = resolvedChain.getResolvedResult(key); - V existingVal = result == null ? null : result.getValue(); + ValueHolder existingVal = resolver.resolve(existing, key, timeSource.getTimeMillis()); if (existingVal == null) { existingVal = loadFromLoaderWriter(key); } - if (value.equals(existingVal)) { + if (existingVal != null && value.equals(existingVal.get())) { cacheLoaderWriter.delete(key); ConditionalRemoveOperation operation = new ConditionalRemoveOperation<>(key, value, timeSource.getTimeMillis()); ByteBuffer payLoad = codec.encode(operation); @@ -261,19 +246,17 @@ protected V silentRemove(K key, V value) throws StoreAccessException { } @Override - protected V silentReplace(K key, V oldValue, V newValue) throws StoreAccessException { + protected ValueHolder silentReplace(K key, V oldValue, V newValue) throws StoreAccessException { try { long hash = extractLongKey(key); boolean unlocked = false; - Chain existing = getProxy().lock(hash); + ServerStoreProxy.ChainEntry existing = getProxy().lock(hash); try { - ResolvedChain resolvedChain = resolver.resolve(existing, key, timeSource.getTimeMillis()); - Result result = resolvedChain.getResolvedResult(key); - V existingVal = result == null ? null : result.getValue(); + ValueHolder existingVal = resolver.resolve(existing, key, timeSource.getTimeMillis()); if (existingVal == null) { existingVal = loadFromLoaderWriter(key); } - if (oldValue.equals(existingVal)) { + if (existingVal != null && oldValue.equals(existingVal.get())) { cacheLoaderWriter.write(key, newValue); ConditionalReplaceOperation operation = new ConditionalReplaceOperation<>(key, oldValue, newValue, timeSource.getTimeMillis()); ByteBuffer payLoad = codec.encode(operation); @@ -289,10 +272,15 @@ protected V silentReplace(K key, V oldValue, V newValue) throws StoreAccessExcep } } - private V loadFromLoaderWriter(K key) { + private ValueHolder loadFromLoaderWriter(K key) { if (useLoaderInAtomics) { try { - return cacheLoaderWriter.load(key); + V loaded = cacheLoaderWriter.load(key); + if (loaded == null) { + return null; + } else { + return new ClusteredValueHolder<>(loaded); + } } catch (Exception e) { throw new StorePassThroughException(newCacheLoadingException(e)); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java index 6ab6de747d..852f0ff3e1 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java @@ -24,12 +24,10 @@ import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.Element; -import org.ehcache.core.spi.time.TimeSource; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import java.nio.ByteBuffer; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeoutException; @@ -40,11 +38,9 @@ class ClusteredWriteBehind { private final CacheLoaderWriter cacheLoaderWriter; private final OperationsCodec codec; private final ChainResolver resolver; - private final TimeSource timeSource; ClusteredWriteBehind(ClusteredWriteBehindStore clusteredWriteBehindStore, ExecutorService executorService, - TimeSource timeSource, ChainResolver resolver, CacheLoaderWriter cacheLoaderWriter, OperationsCodec codec) { @@ -53,7 +49,6 @@ class ClusteredWriteBehind { this.resolver = resolver; this.cacheLoaderWriter = cacheLoaderWriter; this.codec = codec; - this.timeSource = timeSource; } void flushWriteBehindQueue(Chain ignored, long hash) { @@ -69,8 +64,7 @@ void flushWriteBehindQueue(Chain ignored, long hash) { K key = operation.getKey(); PutOperation result = resolver.applyOperation(key, currentState.get(key), - operation, - timeSource.getTimeMillis()); + operation); try { if (result != null) { if (result != currentState.get(key) && !(operation instanceof PutOperation)) { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java index 1f288b709c..9d5c19f41d 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java @@ -18,9 +18,8 @@ import org.ehcache.clustered.client.internal.loaderwriter.ClusteredLoaderWriterStore; import org.ehcache.clustered.client.internal.store.ClusteredStore; import org.ehcache.clustered.client.internal.store.ClusteredValueHolder; -import org.ehcache.clustered.client.internal.store.ResolvedChain; import org.ehcache.clustered.client.internal.store.ServerStoreProxy; -import org.ehcache.clustered.client.internal.store.lock.LockManager; +import org.ehcache.clustered.client.internal.store.lock.LockingServerStoreProxy; import org.ehcache.clustered.client.internal.store.operations.ChainResolver; import org.ehcache.clustered.common.internal.store.operations.ConditionalRemoveOperation; import org.ehcache.clustered.common.internal.store.operations.ConditionalReplaceOperation; @@ -29,7 +28,6 @@ import org.ehcache.clustered.common.internal.store.operations.PutWithWriterOperation; import org.ehcache.clustered.common.internal.store.operations.RemoveOperation; import org.ehcache.clustered.common.internal.store.operations.ReplaceOperation; -import org.ehcache.clustered.common.internal.store.operations.Result; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; import org.ehcache.clustered.client.service.ClusteringService; import org.ehcache.clustered.common.internal.store.Chain; @@ -67,19 +65,18 @@ private ClusteredWriteBehindStore(Configuration config, super(config, codec, resolver, timeSource); this.cacheLoaderWriter = loaderWriter; this.clusteredWriteBehind = new ClusteredWriteBehind<>(this, executorService, - timeSource, resolver, this.cacheLoaderWriter, codec); } - Chain lock(long hash) throws TimeoutException { - return ((LockManager) storeProxy).lock(hash); + ServerStoreProxy.ChainEntry lock(long hash) throws TimeoutException { + return ((LockingServerStoreProxy) storeProxy).lock(hash); } void unlock(long hash, boolean localOnly) throws TimeoutException { - ((LockManager) storeProxy).unlock(hash, localOnly); + ((LockingServerStoreProxy) storeProxy).unlock(hash, localOnly); } void replaceAtHead(long key, Chain expected, Chain replacement) { @@ -89,21 +86,14 @@ void replaceAtHead(long key, Chain expected, Chain replacement) { @Override protected ValueHolder getInternal(K key) throws StoreAccessException, TimeoutException { try { - Chain chain = storeProxy.get(extractLongKey(key)); + ServerStoreProxy.ChainEntry chain = storeProxy.get(extractLongKey(key)); + /* + * XXX : This condition is wrong... it should be "are there any entries for this key in the chain" + * Most sensible fix I can think of right now would be to push the cacheLoaderWriter access in to the chain + * resolver. + */ if (!chain.isEmpty()) { - ClusteredValueHolder holder = null; - ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); - Result resolvedResult = resolvedChain.getResolvedResult(key); - if (resolvedResult != null) { - V value = resolvedResult.getValue(); - long expirationTime = resolvedChain.getExpirationTime(); - if (expirationTime == Long.MAX_VALUE) { - holder = new ClusteredValueHolder<>(value); - } else { - holder = new ClusteredValueHolder<>(value, expirationTime); - } - } - return holder; + return resolver.resolve(chain, key, timeSource.getTimeMillis(), Integer.MAX_VALUE); } else { long hash = extractLongKey(key); lock(hash); @@ -149,16 +139,13 @@ protected PutStatus silentPut(final K key, final V value) throws StoreAccessExce } @Override - protected V silentPutIfAbsent(K key, V value) throws StoreAccessException { + protected ValueHolder silentPutIfAbsent(K key, V value) throws StoreAccessException { try { PutIfAbsentOperation operation = new PutIfAbsentOperation<>(key, value, timeSource.getTimeMillis()); ByteBuffer payload = codec.encode(operation); long extractedKey = extractLongKey(key); - Chain chain = storeProxy.getAndAppend(extractedKey, payload); - ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); - - Result result = resolvedChain.getResolvedResult(key); - return result == null ? null : result.getValue(); + ServerStoreProxy.ChainEntry chain = storeProxy.getAndAppend(extractedKey, payload); + return resolver.resolve(chain, key, timeSource.getTimeMillis(), Integer.MAX_VALUE); } catch (Exception re) { throw handleException(re); } @@ -170,58 +157,47 @@ protected boolean silentRemove(K key) throws StoreAccessException { RemoveOperation operation = new RemoveOperation<>(key, timeSource.getTimeMillis()); ByteBuffer payload = codec.encode(operation); long extractedKey = extractLongKey(key); - Chain chain = storeProxy.getAndAppend(extractedKey, payload); - ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); - - return resolvedChain.getResolvedResult(key) != null; + ServerStoreProxy.ChainEntry chain = storeProxy.getAndAppend(extractedKey, payload); + return resolver.resolve(chain, key, timeSource.getTimeMillis(), Integer.MAX_VALUE) != null; } catch (Exception re) { throw handleException(re); } } @Override - protected V silentRemove(K key, V value) throws StoreAccessException { + protected ValueHolder silentRemove(K key, V value) throws StoreAccessException { try { ConditionalRemoveOperation operation = new ConditionalRemoveOperation<>(key, value, timeSource.getTimeMillis()); ByteBuffer payload = codec.encode(operation); long extractedKey = extractLongKey(key); - Chain chain = storeProxy.getAndAppend(extractedKey, payload); - ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); - - Result result = resolvedChain.getResolvedResult(key); - return result == null ? null : result.getValue(); + ServerStoreProxy.ChainEntry chain = storeProxy.getAndAppend(extractedKey, payload); + return resolver.resolve(chain, key, timeSource.getTimeMillis(), Integer.MAX_VALUE); } catch (Exception re) { throw handleException(re); } } @Override - protected V silentReplace(K key, V value) throws StoreAccessException { + protected ValueHolder silentReplace(K key, V value) throws StoreAccessException { try { ReplaceOperation operation = new ReplaceOperation<>(key, value, timeSource.getTimeMillis()); ByteBuffer payload = codec.encode(operation); long extractedKey = extractLongKey(key); - Chain chain = storeProxy.getAndAppend(extractedKey, payload); - ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); - - Result result = resolvedChain.getResolvedResult(key); - return result == null ? null : result.getValue(); + ServerStoreProxy.ChainEntry chain = storeProxy.getAndAppend(extractedKey, payload); + return resolver.resolve(chain, key, timeSource.getTimeMillis(), Integer.MAX_VALUE); } catch (Exception re) { throw handleException(re); } } - protected V silentReplace(K key, V oldValue, V newValue) throws StoreAccessException { + protected ValueHolder silentReplace(K key, V oldValue, V newValue) throws StoreAccessException { try { ConditionalReplaceOperation operation = new ConditionalReplaceOperation<>(key, oldValue, newValue, timeSource .getTimeMillis()); ByteBuffer payload = codec.encode(operation); long extractedKey = extractLongKey(key); - Chain chain = storeProxy.getAndAppend(extractedKey, payload); - ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); - - Result result = resolvedChain.getResolvedResult(key); - return result == null ? null : result.getValue(); + ServerStoreProxy.ChainEntry chain = storeProxy.getAndAppend(extractedKey, payload); + return resolver.resolve(chain, key, timeSource.getTimeMillis(), Integer.MAX_VALUE); } catch (Exception re) { throw handleException(re); } @@ -246,14 +222,13 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { - return this.delegate.compact(chain); + public void compact(ServerStoreProxy.ChainEntry chain) { + this.delegate.compact(chain); } @Override - public Chain compact(Chain chain, long hash) { + public void compact(ServerStoreProxy.ChainEntry chain, long hash) { clusteredWriteBehind.flushWriteBehindQueue(chain, hash); - return null; } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java index 1d7a71b9b7..fe8ac2bd4b 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java @@ -27,8 +27,7 @@ import org.ehcache.clustered.client.internal.store.ServerStoreProxy.ServerCallback; import org.ehcache.clustered.client.internal.store.StrongServerStoreProxy; import org.ehcache.clustered.client.internal.store.lock.LockManager; -import org.ehcache.clustered.client.internal.store.lock.LockManagerImpl; -import org.ehcache.clustered.client.internal.store.lock.LockingServerStoreProxy; +import org.ehcache.clustered.client.internal.store.lock.LockingServerStoreProxyImpl; import org.ehcache.clustered.client.service.ClientEntityFactory; import org.ehcache.clustered.client.service.ClusteringService; import org.ehcache.clustered.client.service.EntityService; @@ -37,7 +36,6 @@ import org.ehcache.config.CacheConfiguration; import org.ehcache.config.ResourceType; import org.ehcache.core.spi.store.Store; -import org.ehcache.spi.loaderwriter.WriteBehindProvider; import org.ehcache.spi.persistence.StateRepository; import org.ehcache.spi.service.MaintainableService; import org.ehcache.spi.service.Service; @@ -285,8 +283,8 @@ public ServerStoreProxy getServerStoreProxy(ClusteredCacheIdentifier cach } if (storeConfig.getCacheLoaderWriter() != null) { - LockManager lockManager = new LockManagerImpl(storeClientEntity); - serverStoreProxy = new LockingServerStoreProxy(serverStoreProxy, lockManager); + LockManager lockManager = new LockManager(storeClientEntity); + serverStoreProxy = new LockingServerStoreProxyImpl(serverStoreProxy, lockManager); } return serverStoreProxy; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index eb09daf760..fa5c0788c4 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -31,7 +31,6 @@ import org.ehcache.clustered.common.internal.store.operations.PutOperation; import org.ehcache.clustered.common.internal.store.operations.RemoveOperation; import org.ehcache.clustered.common.internal.store.operations.ReplaceOperation; -import org.ehcache.clustered.common.internal.store.operations.Result; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; import org.ehcache.clustered.client.service.ClusteringService; import org.ehcache.clustered.client.service.ClusteringService.ClusteredCacheIdentifier; @@ -175,32 +174,12 @@ public ValueHolder get(final K key) throws StoreAccessException { } protected ValueHolder getInternal(K key) throws StoreAccessException, TimeoutException { - ClusteredValueHolder holder = null; try { - Chain chain = storeProxy.get(extractLongKey(key)); - if(!chain.isEmpty()) { - ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); - - if (resolvedChain.isCompacted()) { - Chain compactedChain = resolvedChain.getCompactedChain(); - storeProxy.replaceAtHead(extractLongKey(key), chain, compactedChain); - } - - Result resolvedResult = resolvedChain.getResolvedResult(key); - if (resolvedResult != null) { - V value = resolvedResult.getValue(); - long expirationTime = resolvedChain.getExpirationTime(); - if (expirationTime == Long.MAX_VALUE) { - holder = new ClusteredValueHolder<>(value); - } else { - holder = new ClusteredValueHolder<>(value, expirationTime); - } - } - } + ServerStoreProxy.ChainEntry entry = storeProxy.get(extractLongKey(key)); + return resolver.resolve(entry, key, timeSource.getTimeMillis()); } catch (RuntimeException re) { throw handleException(re); } - return holder; } protected long extractLongKey(K key) { @@ -248,31 +227,23 @@ protected PutStatus silentPut(final K key, final V value) throws StoreAccessExce @Override public ValueHolder putIfAbsent(final K key, final V value, Consumer put) throws StoreAccessException { putIfAbsentObserver.begin(); - V result = silentPutIfAbsent(key, value); + ValueHolder result = silentPutIfAbsent(key, value); if(result == null) { putIfAbsentObserver.end(StoreOperationOutcomes.PutIfAbsentOutcome.PUT); return null; } else { putIfAbsentObserver.end(StoreOperationOutcomes.PutIfAbsentOutcome.HIT); - return new ClusteredValueHolder<>(result); + return result; } } - protected V silentPutIfAbsent(K key, V value) throws StoreAccessException { + protected ValueHolder silentPutIfAbsent(K key, V value) throws StoreAccessException { try { PutIfAbsentOperation operation = new PutIfAbsentOperation<>(key, value, timeSource.getTimeMillis()); ByteBuffer payload = codec.encode(operation); long extractedKey = extractLongKey(key); - Chain chain = storeProxy.getAndAppend(extractedKey, payload); - ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); - - if (resolvedChain.getCompactionCount() > chainCompactionLimit) { - Chain compactedChain = resolvedChain.getCompactedChain(); - storeProxy.replaceAtHead(extractedKey, chain, compactedChain); - } - - Result result = resolvedChain.getResolvedResult(key); - return result == null ? null : result.getValue(); + ServerStoreProxy.ChainEntry chain = storeProxy.getAndAppend(extractedKey, payload); + return resolver.resolve(chain, key, timeSource.getTimeMillis(), chainCompactionLimit); } catch (Exception re) { throw handleException(re); } @@ -295,33 +266,20 @@ protected boolean silentRemove(K key) throws StoreAccessException { RemoveOperation operation = new RemoveOperation<>(key, timeSource.getTimeMillis()); ByteBuffer payload = codec.encode(operation); long extractedKey = extractLongKey(key); - Chain chain = storeProxy.getAndAppend(extractedKey, payload); - ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); - - if(resolvedChain.getResolvedResult(key) != null) { - storeProxy.replaceAtHead(extractedKey, chain, resolvedChain.getCompactedChain()); - return true; - } else { - return false; - } + ServerStoreProxy.ChainEntry chain = storeProxy.getAndAppend(extractedKey, payload); + return resolver.resolve(chain, key, timeSource.getTimeMillis()) != null; } catch (Exception re) { throw handleException(re); } } - protected V silentRemove(K key, V value) throws StoreAccessException { + protected ValueHolder silentRemove(K key, V value) throws StoreAccessException { try { ConditionalRemoveOperation operation = new ConditionalRemoveOperation<>(key, value, timeSource.getTimeMillis()); ByteBuffer payload = codec.encode(operation); long extractedKey = extractLongKey(key); - Chain chain = storeProxy.getAndAppend(extractedKey, payload); - ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); - - Result result = resolvedChain.getResolvedResult(key); - if (result != null && value.equals(result.getValue())) { - storeProxy.replaceAtHead(extractedKey, chain, resolvedChain.getCompactedChain()); - } - return result == null ? null : result.getValue(); + ServerStoreProxy.ChainEntry chain = storeProxy.getAndAppend(extractedKey, payload); + return resolver.resolve(chain, key, timeSource.getTimeMillis()); } catch (Exception re) { throw handleException(re); } @@ -330,9 +288,9 @@ protected V silentRemove(K key, V value) throws StoreAccessException { @Override public RemoveStatus remove(final K key, final V value) throws StoreAccessException { conditionalRemoveObserver.begin(); - V result = silentRemove(key, value); + ValueHolder result = silentRemove(key, value); if(result != null) { - if(value.equals(result)) { + if(value.equals(result.get())) { conditionalRemoveObserver.end(StoreOperationOutcomes.ConditionalRemoveOutcome.REMOVED); return RemoveStatus.REMOVED; } else { @@ -349,52 +307,36 @@ public RemoveStatus remove(final K key, final V value) throws StoreAccessExcepti public ValueHolder replace(final K key, final V value) throws StoreAccessException { replaceObserver.begin(); - V result = silentReplace(key, value); + ValueHolder result = silentReplace(key, value); if(result == null) { replaceObserver.end(StoreOperationOutcomes.ReplaceOutcome.MISS); return null; } else { replaceObserver.end(StoreOperationOutcomes.ReplaceOutcome.REPLACED); - return new ClusteredValueHolder<>(result); + return result; } } - protected V silentReplace(K key, V value) throws StoreAccessException { + protected ValueHolder silentReplace(K key, V value) throws StoreAccessException { try { ReplaceOperation operation = new ReplaceOperation<>(key, value, timeSource.getTimeMillis()); ByteBuffer payload = codec.encode(operation); long extractedKey = extractLongKey(key); - Chain chain = storeProxy.getAndAppend(extractedKey, payload); - ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); - - if (resolvedChain.getCompactionCount() > chainCompactionLimit) { - Chain compactedChain = resolvedChain.getCompactedChain(); - storeProxy.replaceAtHead(extractedKey, chain, compactedChain); - } - - Result result = resolvedChain.getResolvedResult(key); - return result == null ? null : result.getValue(); + ServerStoreProxy.ChainEntry chain = storeProxy.getAndAppend(extractedKey, payload); + return resolver.resolve(chain, key, timeSource.getTimeMillis(), chainCompactionLimit); } catch (Exception re) { throw handleException(re); } } - protected V silentReplace(K key, V oldValue, V newValue) throws StoreAccessException { + protected ValueHolder silentReplace(K key, V oldValue, V newValue) throws StoreAccessException { try { ConditionalReplaceOperation operation = new ConditionalReplaceOperation<>(key, oldValue, newValue, timeSource .getTimeMillis()); ByteBuffer payload = codec.encode(operation); long extractedKey = extractLongKey(key); - Chain chain = storeProxy.getAndAppend(extractedKey, payload); - ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); - - if (resolvedChain.getCompactionCount() > chainCompactionLimit) { - Chain compactedChain = resolvedChain.getCompactedChain(); - storeProxy.replaceAtHead(extractedKey, chain, compactedChain); - } - - Result result = resolvedChain.getResolvedResult(key); - return result == null ? null : result.getValue(); + ServerStoreProxy.ChainEntry chain = storeProxy.getAndAppend(extractedKey, payload); + return resolver.resolve(chain, key, timeSource.getTimeMillis(), chainCompactionLimit); } catch (Exception re) { throw handleException(re); } @@ -403,9 +345,9 @@ protected V silentReplace(K key, V oldValue, V newValue) throws StoreAccessExcep @Override public ReplaceStatus replace(final K key, final V oldValue, final V newValue) throws StoreAccessException { conditionalReplaceObserver.begin(); - V result = silentReplace(key, oldValue, newValue); + ValueHolder result = silentReplace(key, oldValue, newValue); if(result != null) { - if(oldValue.equals(result)) { + if(oldValue.equals(result.get())) { conditionalReplaceObserver.end(StoreOperationOutcomes.ConditionalReplaceOutcome.REPLACED); return ReplaceStatus.HIT; } else { @@ -459,18 +401,12 @@ public Cache.Entry> next() { private java.util.Iterator>> nextChain() { try { while (true) { - Map> chainContents = resolver.resolveChain(chainIterator.next(), timeSource.getTimeMillis()); + Map> chainContents = resolver.resolveAll(chainIterator.next(), timeSource.getTimeMillis()); if (!chainContents.isEmpty()) { return chainContents.entrySet().stream().map(entry -> { K key = entry.getKey(); - PutOperation operation = entry.getValue(); - ValueHolder valueHolder; - if (operation.isExpiryAvailable()) { - valueHolder = new ClusteredValueHolder<>(operation.getValue(), operation.expirationTime()); - } else { - valueHolder = new ClusteredValueHolder<>(operation.getValue()); - } + ValueHolder valueHolder = entry.getValue(); return new Cache.Entry>() { @Override @@ -846,8 +782,8 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { - return clusteredStore.resolver.compactChain(chain, clusteredStore.timeSource.getTimeMillis()); + public void compact(ServerStoreProxy.ChainEntry chain) { + clusteredStore.resolver.compact(chain); } }; } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java index 2dcce719c3..b1e6ebbbd0 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java @@ -30,6 +30,7 @@ import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.GetMessage; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.ReplaceAtHeadMessage; import org.ehcache.clustered.common.internal.store.Chain; +import org.ehcache.clustered.common.internal.store.Element; import org.ehcache.config.units.MemoryUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -96,11 +97,7 @@ class CommonServerStoreProxy implements ServerStoreProxy { } }); entity.addResponseListener(EhcacheEntityResponse.ResolveRequest.class, response -> { - Chain incoming = response.getChain(); - Chain compacted = invalidation.compact(incoming, response.getKey()); - if (compacted != null) { - replaceAtHead(response.getKey(), incoming, compacted); - } + invalidation.compact(new SimpleEntry(response.getKey(), response.getChain()), response.getKey()); }); } @@ -120,7 +117,7 @@ public void close() { } @Override - public Chain get(long key) throws TimeoutException { + public ChainEntry get(long key) throws TimeoutException { EhcacheEntityResponse response; try { response = entity.invokeAndWaitForComplete(new GetMessage(key), false); @@ -130,7 +127,7 @@ public Chain get(long key) throws TimeoutException { throw new ServerStoreProxyException(e); } if (response != null && response.getResponseType() == EhcacheResponseType.GET_RESPONSE) { - return ((EhcacheEntityResponse.GetResponse)response).getChain(); + return new SimpleEntry(key, ((EhcacheEntityResponse.GetResponse)response).getChain()); } else { throw new ServerStoreProxyException("Response for get operation was invalid : " + (response != null ? response.getResponseType() : "null message")); @@ -147,7 +144,7 @@ public void append(long key, ByteBuffer payLoad) { } @Override - public Chain getAndAppend(long key, ByteBuffer payLoad) throws TimeoutException { + public ChainEntry getAndAppend(long key, ByteBuffer payLoad) throws TimeoutException { EhcacheEntityResponse response; try { response = entity.invokeAndWaitForRetired(new GetAndAppendMessage(key, payLoad), true); @@ -157,7 +154,7 @@ public Chain getAndAppend(long key, ByteBuffer payLoad) throws TimeoutException throw new ServerStoreProxyException(e); } if (response != null && response.getResponseType() == EhcacheResponseType.GET_RESPONSE) { - return ((EhcacheEntityResponse.GetResponse)response).getChain(); + return new SimpleEntry(key, ((EhcacheEntityResponse.GetResponse)response).getChain()); } else { throw new ServerStoreProxyException("Response for getAndAppend operation was invalid : " + (response != null ? response.getResponseType() : "null message")); @@ -252,4 +249,40 @@ private EhcacheEntityResponse.IteratorBatch fetchBatch(EhcacheOperationMessage m (response != null ? response.getResponseType() : "null message")); } } + + private class SimpleEntry implements ChainEntry { + + private final long key; + private final Chain chain; + + public SimpleEntry(long key, Chain chain) { + this.key = key; + this.chain = chain; + } + + @Override + public void append(ByteBuffer payLoad) throws TimeoutException { + CommonServerStoreProxy.this.append(key, payLoad); + } + + @Override + public void replaceAtHead(Chain equivalent) { + CommonServerStoreProxy.this.replaceAtHead(key, chain, equivalent); + } + + @Override + public boolean isEmpty() { + return chain.isEmpty(); + } + + @Override + public int length() { + return chain.length(); + } + + @Override + public Iterator iterator() { + return chain.iterator(); + } + } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java index 4a38399e43..f174e79da4 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java @@ -40,7 +40,7 @@ public void close() { } @Override - public Chain get(long key) throws TimeoutException { + public ChainEntry get(long key) throws TimeoutException { return delegate.get(key); } @@ -50,7 +50,7 @@ public void append(final long key, final ByteBuffer payLoad) throws TimeoutExcep } @Override - public Chain getAndAppend(final long key, final ByteBuffer payLoad) throws TimeoutException { + public ChainEntry getAndAppend(final long key, final ByteBuffer payLoad) throws TimeoutException { return delegate.getAndAppend(key, payLoad); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java index 54c1420386..b996517c41 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java @@ -15,8 +15,8 @@ */ package org.ehcache.clustered.client.internal.store; -import org.ehcache.clustered.client.internal.store.lock.LockManager; import org.ehcache.clustered.client.internal.store.lock.LockingServerStoreProxy; +import org.ehcache.clustered.client.internal.store.lock.LockingServerStoreProxyImpl; import org.ehcache.clustered.common.internal.store.Chain; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,7 +28,7 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; -public class ReconnectingServerStoreProxy implements ServerStoreProxy, LockManager { +public class ReconnectingServerStoreProxy implements LockingServerStoreProxy { private static final Logger LOGGER = LoggerFactory.getLogger(ReconnectingServerStoreProxy.class); @@ -39,7 +39,7 @@ public ReconnectingServerStoreProxy(ServerStoreProxy serverStoreProxy, Runnable if (serverStoreProxy instanceof LockingServerStoreProxy) { this.delegateRef = new AtomicReference<>((LockingServerStoreProxy) serverStoreProxy); } else { - this.delegateRef = new AtomicReference<>(new LockingServerStoreProxy(serverStoreProxy, new UnSupportedLockManager())); + this.delegateRef = new AtomicReference<>(unsupportedLocking(serverStoreProxy)); } this.onReconnect = onReconnect; } @@ -59,7 +59,7 @@ public void close() { } @Override - public Chain get(long key) throws TimeoutException { + public ChainEntry get(long key) throws TimeoutException { return onStoreProxy(serverStoreProxy -> serverStoreProxy.get(key)); } @@ -72,7 +72,7 @@ public void append(long key, ByteBuffer payLoad) throws TimeoutException { } @Override - public Chain getAndAppend(long key, ByteBuffer payLoad) throws TimeoutException { + public ChainEntry getAndAppend(long key, ByteBuffer payLoad) throws TimeoutException { return onStoreProxy(serverStoreProxy -> serverStoreProxy.getAndAppend(key, payLoad)); } @@ -122,14 +122,14 @@ private T onStoreProxy(TimeoutExceptionFunction } @Override - public Chain lock(long hash) throws TimeoutException { - return onStoreProxy(lockingServerStoreProxy -> lockingServerStoreProxy.lock(hash)); + public ChainEntry lock(long key) throws TimeoutException { + return onStoreProxy(lockingServerStoreProxy -> lockingServerStoreProxy.lock(key)); } @Override - public void unlock(long hash, boolean localonly) throws TimeoutException { + public void unlock(long key, boolean localonly) throws TimeoutException { onStoreProxy(lockingServerStoreProxy -> { - lockingServerStoreProxy.unlock(hash, localonly); + lockingServerStoreProxy.unlock(key, localonly); return null; }); } @@ -139,7 +139,7 @@ private interface TimeoutExceptionFunction { V apply(U u) throws TimeoutException; } - private static class ReconnectInProgressProxy extends LockingServerStoreProxy { + private static class ReconnectInProgressProxy extends LockingServerStoreProxyImpl { private final String cacheId; @@ -159,7 +159,7 @@ public void close() { } @Override - public Chain get(long key) { + public ChainEntry get(long key) { throw new ReconnectInProgressException(); } @@ -169,7 +169,7 @@ public void append(long key, ByteBuffer payLoad) { } @Override - public Chain getAndAppend(long key, ByteBuffer payLoad) { + public ChainEntry getAndAppend(long key, ByteBuffer payLoad) { throw new ReconnectInProgressException(); } @@ -189,26 +189,67 @@ public Iterator iterator() { } @Override - public Chain lock(long hash) { + public ChainEntry lock(long key) { throw new ReconnectInProgressException(); } @Override - public void unlock(long hash, boolean localonly) { + public void unlock(long key, boolean localonly) { throw new ReconnectInProgressException(); } } - private static class UnSupportedLockManager implements LockManager { + private LockingServerStoreProxy unsupportedLocking(ServerStoreProxy serverStoreProxy) { + return new LockingServerStoreProxy() { + @Override + public ChainEntry lock(long hash) throws TimeoutException { + throw new UnsupportedOperationException("Lock ops are not supported"); + } - @Override - public Chain lock(long hash) { - throw new UnsupportedOperationException("Lock ops are not supported"); - } + @Override + public void unlock(long hash, boolean localonly) throws TimeoutException { + throw new UnsupportedOperationException("Lock ops are not supported"); + } - @Override - public void unlock(long hash, boolean localonly) { - throw new UnsupportedOperationException("Lock ops are not supported"); - } + @Override + public ChainEntry get(long key) throws TimeoutException { + return serverStoreProxy.get(key); + } + + @Override + public ChainEntry getAndAppend(long key, ByteBuffer payLoad) throws TimeoutException { + return serverStoreProxy.getAndAppend(key, payLoad); + } + + @Override + public String getCacheId() { + return serverStoreProxy.getCacheId(); + } + + @Override + public void close() { + serverStoreProxy.close(); + } + + @Override + public void append(long key, ByteBuffer payLoad) throws TimeoutException { + serverStoreProxy.append(key, payLoad); + } + + @Override + public void replaceAtHead(long key, Chain expect, Chain update) { + serverStoreProxy.replaceAtHead(key, expect, update); + } + + @Override + public void clear() throws TimeoutException { + serverStoreProxy.clear(); + } + + @Override + public Iterator iterator() throws TimeoutException { + return serverStoreProxy.iterator(); + } + }; } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ResolvedChain.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ResolvedChain.java deleted file mode 100644 index 8c8a76473b..0000000000 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ResolvedChain.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.ehcache.clustered.client.internal.store; - -import org.ehcache.clustered.common.internal.store.operations.Result; -import org.ehcache.clustered.common.internal.store.Chain; - -import java.util.Collections; -import java.util.Map; - -/** - * Represents the result of a {@link Chain} resolution. - * Implementors would be wrappers over the compacted chain and the resolved operations. - * A resolver may or may not have resolved all the different keys in a chain. - * - * @param the Key type - */ -public interface ResolvedChain { - - Chain getCompactedChain(); - - Result getResolvedResult(K key); - - /** - * Indicates whether the {@link #getCompactedChain()} is effectively compacted - * compared to the original chain it was built from. - * - * @return {@code true} if the chain has been compacted during resolution, {@code false} otherwise - */ - boolean isCompacted(); - - /** - * @return the number of chain elements that were compacted if there was any compaction - */ - int getCompactionCount(); - - /** - * @return the unix epoch at which the entry should expire - */ - long getExpirationTime(); - - /** - * Represents the {@link ResolvedChain} result of a resolver that resolves - * all the keys in a {@link Chain} - */ - class Impl implements ResolvedChain { - - private final Chain compactedChain; - private final Map> resolvedOperations; - private final int compactionCount; - private final long expirationTime; - - public Impl(Chain compactedChain, Map> resolvedOperations, int compactionCount, long expirationTime) { - this.compactedChain = compactedChain; - this.resolvedOperations = resolvedOperations; - this.compactionCount = compactionCount; - this.expirationTime = expirationTime; - } - - public Impl(Chain compactedChain, K key, Result result, int compactedSize, long expirationTime) { - this(compactedChain, Collections.singletonMap(key, result), compactedSize, expirationTime); - } - - public Chain getCompactedChain() { - return this.compactedChain; - } - - public Result getResolvedResult(K key) { - return resolvedOperations.get(key); - } - - @Override - public boolean isCompacted() { - return compactionCount > 0; - } - - public int getCompactionCount() { - return compactionCount; - } - - @Override - public long getExpirationTime() { - return expirationTime; - } - } -} diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxy.java index b77c884cdd..1a531ebdfe 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxy.java @@ -16,13 +16,37 @@ package org.ehcache.clustered.client.internal.store; import org.ehcache.clustered.common.internal.store.Chain; +import org.ehcache.clustered.common.internal.store.Element; import org.ehcache.clustered.common.internal.store.ServerStore; +import java.nio.ByteBuffer; +import java.util.concurrent.TimeoutException; + /** * @author Ludovic Orban */ public interface ServerStoreProxy extends ServerStore { + /** + * {@inheritDoc} + *

+ * {@code ServerStoreProxy} instances return {@link ChainEntry} instances that support mutation of the associated store. + * + * @return the associated chain entry + */ + @Override + ChainEntry get(long key) throws TimeoutException; + + /** + * {@inheritDoc} + *

+ * {@code ServerStoreProxy} instances return {@link ChainEntry} instances that support mutation of the associated store. + * + * @return the associated chain entry + */ + @Override + ChainEntry getAndAppend(long key, ByteBuffer payLoad) throws TimeoutException; + /** * The invalidation listener */ @@ -39,10 +63,10 @@ interface ServerCallback { */ void onInvalidateAll(); - Chain compact(Chain chain); + void compact(ChainEntry chain); - default Chain compact(Chain chain, long hash) { - return compact(chain); + default void compact(ChainEntry chain, long hash) { + compact(chain); } } @@ -58,4 +82,54 @@ default Chain compact(Chain chain, long hash) { */ void close(); + interface ChainEntry extends Chain { + + /** + * Appends the provided binary to this Chain + * While appending, the payLoad is stored in {@link Element}. + * Note that the {@code payLoad}'s position and limit are left untouched. + * + * @param payLoad to be appended + * + * @throws TimeoutException if the append exceeds the timeout configured for write operations + */ + void append(ByteBuffer payLoad) throws TimeoutException; + + + /** + * Replaces the provided Chain with the equivalent Chain present at the head. + * This operation is not guaranteed to succeed. + * The replaceAtHead is successful iff the Chain associated with the key has + * a sub-sequence of elements present as expected.. + * + * If below mapping is present: + * + * hash -> |payLoadA| - |payLoadB| - |payLoadC| + * + * And replaceAtHead(hash, |payLoadA| - |payLoadB| - |payLoadC|, |payLoadC'|) is invoked + * then this operation will succeed & the final mapping would be: + * + * hash -> |payLoadC'| + * + * The same operation will also succeed if the mapping was modified by the time replace was invoked to + * + * hash -> |payLoadA| - |payLoadB| - |payLoadC| - |payLoadD| + * + * Though the final mapping would be: + * + * hash -> |payLoadC'| - |payLoadD| + * + * Failure case: + * + * But before replaceAtHead if it was modified to : + * + * hash -> |payLoadC"| - |payLoadD| + * + * then replaceAtHead(hash, |payLoadA| - |payLoadB| - |payLoadC|, |payLoadC'|) will be ignored. + * Note that the payload's position and limit of all elements of both chains are left untouched. + * + * @param equivalent the new Chain to be replaced + */ + void replaceAtHead(Chain equivalent); + } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java index f147e65fa5..46063087f0 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java @@ -204,7 +204,7 @@ public void close() { } @Override - public Chain get(long key) throws TimeoutException { + public ChainEntry get(long key) throws TimeoutException { return delegate.get(key); } @@ -217,7 +217,7 @@ public void append(final long key, final ByteBuffer payLoad) throws TimeoutExcep } @Override - public Chain getAndAppend(final long key, final ByteBuffer payLoad) throws TimeoutException { + public ChainEntry getAndAppend(final long key, final ByteBuffer payLoad) throws TimeoutException { return performWaitingForHashInvalidation(key, () -> delegate.getAndAppend(key, payLoad), entity.getTimeouts().getWriteOperationTimeout()); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManager.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManager.java index 53e3e59b33..220ac6ee66 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManager.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManager.java @@ -15,22 +15,69 @@ */ package org.ehcache.clustered.client.internal.store.lock; +import org.ehcache.clustered.client.internal.store.ClusterTierClientEntity; +import org.ehcache.clustered.client.internal.store.ServerStoreProxyException; +import org.ehcache.clustered.common.internal.messages.ClusterTierReconnectMessage; +import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse; +import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.LockSuccess; +import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.LockMessage; +import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.UnlockMessage; import org.ehcache.clustered.common.internal.store.Chain; +import java.util.Collections; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeoutException; -public interface LockManager { - /** - * - * @param hash - */ - Chain lock(long hash) throws TimeoutException; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.LOCK_FAILURE; - /** - * - * @param hash - * @param localonly - */ - void unlock(long hash, boolean localonly) throws TimeoutException; +public class LockManager { + private final ClusterTierClientEntity clientEntity; + private final Set locksHeld = Collections.newSetFromMap(new ConcurrentHashMap<>()); + + public LockManager(ClusterTierClientEntity clientEntity) { + this.clientEntity = clientEntity; + clientEntity.addReconnectListener(this::reconnectListener); + } + + void reconnectListener(ClusterTierReconnectMessage reconnectMessage) { + reconnectMessage.addLocksHeld(locksHeld); + } + + public Chain lock(long hash) throws TimeoutException { + LockSuccess response = getlockResponse(hash); + locksHeld.add(hash); + return response.getChain(); + } + + private LockSuccess getlockResponse(long hash) throws TimeoutException { + EhcacheEntityResponse response; + do { + try { + response = clientEntity.invokeAndWaitForComplete(new LockMessage(hash), false); + } catch (TimeoutException tme) { + throw tme; + } catch (Exception e) { + throw new ServerStoreProxyException(e); + } + if (response == null) { + throw new ServerStoreProxyException("Response for acquiring lock was invalid null message"); + } + } while (response.getResponseType() == LOCK_FAILURE); + return (LockSuccess) response; + } + + public void unlock(long hash, boolean localonly) throws TimeoutException { + try { + if (!localonly) { + clientEntity.invokeAndWaitForComplete(new UnlockMessage(hash), false); + } + locksHeld.remove(hash); + } catch (TimeoutException tme) { + throw tme; + } catch (Exception e) { + throw new ServerStoreProxyException(e); + } + } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImpl.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImpl.java deleted file mode 100644 index 7fa2121ec0..0000000000 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImpl.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.ehcache.clustered.client.internal.store.lock; - -import org.ehcache.clustered.client.internal.store.ClusterTierClientEntity; -import org.ehcache.clustered.client.internal.store.ServerStoreProxyException; -import org.ehcache.clustered.common.internal.messages.ClusterTierReconnectMessage; -import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse; -import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.LockSuccess; -import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.LockMessage; -import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.UnlockMessage; -import org.ehcache.clustered.common.internal.store.Chain; - -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeoutException; - -import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.LOCK_FAILURE; - -public class LockManagerImpl implements LockManager { - - private final ClusterTierClientEntity clientEntity; - private final Set locksHeld = Collections.newSetFromMap(new ConcurrentHashMap<>()); - - public LockManagerImpl(ClusterTierClientEntity clientEntity) { - this.clientEntity = clientEntity; - clientEntity.addReconnectListener(this::reconnectListener); - } - - void reconnectListener(ClusterTierReconnectMessage reconnectMessage) { - reconnectMessage.addLocksHeld(locksHeld); - } - - @Override - public Chain lock(long hash) throws TimeoutException { - LockSuccess response = getlockResponse(hash); - locksHeld.add(hash); - return response.getChain(); - } - - private LockSuccess getlockResponse(long hash) throws TimeoutException { - EhcacheEntityResponse response; - do { - try { - response = clientEntity.invokeAndWaitForComplete(new LockMessage(hash), false); - } catch (TimeoutException tme) { - throw tme; - } catch (Exception e) { - throw new ServerStoreProxyException(e); - } - if (response == null) { - throw new ServerStoreProxyException("Response for acquiring lock was invalid null message"); - } - } while (response.getResponseType() == LOCK_FAILURE); - return (LockSuccess) response; - } - - @Override - public void unlock(long hash, boolean localonly) throws TimeoutException { - try { - if (!localonly) { - clientEntity.invokeAndWaitForComplete(new UnlockMessage(hash), false); - } - locksHeld.remove(hash); - } catch (TimeoutException tme) { - throw tme; - } catch (Exception e) { - throw new ServerStoreProxyException(e); - } - } -} diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java index 3d68efdbfa..588ea8e768 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java @@ -16,69 +16,21 @@ package org.ehcache.clustered.client.internal.store.lock; import org.ehcache.clustered.client.internal.store.ServerStoreProxy; -import org.ehcache.clustered.common.internal.store.Chain; -import java.nio.ByteBuffer; -import java.util.Iterator; import java.util.concurrent.TimeoutException; -public class LockingServerStoreProxy implements ServerStoreProxy, LockManager { +public interface LockingServerStoreProxy extends ServerStoreProxy { - private final ServerStoreProxy storeProxy; - private final LockManager lockManager; + /** + * + * @param hash + */ + ChainEntry lock(long hash) throws TimeoutException; - public LockingServerStoreProxy(ServerStoreProxy storeProxy, LockManager lockManager) { - this.storeProxy = storeProxy; - this.lockManager = lockManager; - } - - @Override - public String getCacheId() { - return storeProxy.getCacheId(); - } - - @Override - public void close() { - storeProxy.close(); - } - - @Override - public Chain lock(long hash) throws TimeoutException { - return lockManager.lock(hash); - } - - @Override - public void unlock(long hash, boolean localonly) throws TimeoutException { - lockManager.unlock(hash, localonly); - } - - @Override - public Chain get(long key) throws TimeoutException { - return storeProxy.get(key); - } - - @Override - public void append(long key, ByteBuffer payLoad) throws TimeoutException { - storeProxy.append(key, payLoad); - } - - @Override - public Chain getAndAppend(long key, ByteBuffer payLoad) throws TimeoutException { - return storeProxy.getAndAppend(key, payLoad); - } - - @Override - public void replaceAtHead(long key, Chain expect, Chain update) { - storeProxy.replaceAtHead(key, expect, update); - } - - @Override - public void clear() throws TimeoutException { - storeProxy.clear(); - } - - @Override - public Iterator iterator() throws TimeoutException { - return storeProxy.iterator(); - } + /** + * + * @param hash + * @param localonly + */ + void unlock(long hash, boolean localonly) throws TimeoutException; } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java new file mode 100644 index 0000000000..eb289a20dd --- /dev/null +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java @@ -0,0 +1,111 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered.client.internal.store.lock; + +import org.ehcache.clustered.client.internal.store.ServerStoreProxy; +import org.ehcache.clustered.common.internal.store.Chain; +import org.ehcache.clustered.common.internal.store.Element; + +import java.nio.ByteBuffer; +import java.util.Iterator; +import java.util.concurrent.TimeoutException; + +public class LockingServerStoreProxyImpl implements LockingServerStoreProxy { + + private final ServerStoreProxy storeProxy; + private final LockManager lockManager; + + public LockingServerStoreProxyImpl(ServerStoreProxy storeProxy, LockManager lockManager) { + this.storeProxy = storeProxy; + this.lockManager = lockManager; + } + + @Override + public String getCacheId() { + return storeProxy.getCacheId(); + } + + @Override + public void close() { + storeProxy.close(); + } + + @Override + public ChainEntry lock(long key) throws TimeoutException { + Chain chain = lockManager.lock(key); + return new ChainEntry() { + @Override + public void append(ByteBuffer payLoad) throws TimeoutException { + LockingServerStoreProxyImpl.this.append(key, payLoad); + } + + @Override + public void replaceAtHead(Chain equivalent) { + LockingServerStoreProxyImpl.this.replaceAtHead(key, chain, equivalent); + } + + @Override + public boolean isEmpty() { + return chain.isEmpty(); + } + + @Override + public int length() { + return chain.length(); + } + + @Override + public Iterator iterator() { + return chain.iterator(); + } + }; + } + + @Override + public void unlock(long key, boolean localonly) throws TimeoutException { + lockManager.unlock(key, localonly); + } + + @Override + public ChainEntry get(long key) throws TimeoutException { + return storeProxy.get(key); + } + + @Override + public void append(long key, ByteBuffer payLoad) throws TimeoutException { + storeProxy.append(key, payLoad); + } + + @Override + public ChainEntry getAndAppend(long key, ByteBuffer payLoad) throws TimeoutException { + return storeProxy.getAndAppend(key, payLoad); + } + + @Override + public void replaceAtHead(long key, Chain expect, Chain update) { + storeProxy.replaceAtHead(key, expect, update); + } + + @Override + public void clear() throws TimeoutException { + storeProxy.clear(); + } + + @Override + public Iterator iterator() throws TimeoutException { + return storeProxy.iterator(); + } +} diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java index a1bd911646..7bcdbe7f08 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java @@ -16,13 +16,14 @@ package org.ehcache.clustered.client.internal.store.operations; +import org.ehcache.clustered.client.internal.store.ServerStoreProxy; import org.ehcache.clustered.common.internal.util.ChainBuilder; -import org.ehcache.clustered.client.internal.store.ResolvedChain; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.Element; import org.ehcache.clustered.common.internal.store.operations.Operation; import org.ehcache.clustered.common.internal.store.operations.PutOperation; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; +import org.ehcache.core.spi.store.Store.ValueHolder; import java.nio.ByteBuffer; import java.util.HashMap; @@ -47,89 +48,118 @@ public ChainResolver(final OperationsCodec codec) { } /** - * Extract the {@code Element}s from the provided {@code Chain} that are not associated with the provided key - * and create a new {@code Chain} + * Resolves the given key within the given chain entry to its current value with a specific compaction threshold. + *

+ * If the resultant chain has shrunk by more than {@code threshold} elements then an attempt is made to perform the + * equivalent compaction on the server. * - * Separate the {@code Element}s from the provided {@code Chain} that are associated and not associated with - * the provided key. Create a new chain with the unassociated {@code Element}s. Resolve the associated elements - * and append the resolved {@code Element} to the newly created chain. + * @param entry target chain entry + * @param key target key + * @param now current time + * @param threshold compaction threshold + * @return the current value + */ + public abstract ValueHolder resolve(ServerStoreProxy.ChainEntry entry, K key, long now, int threshold); + + /** + * Resolves the given key within the given chain entry to its current value. + *

+ * This is exactly equivalent to calling {@link #resolve(ServerStoreProxy.ChainEntry, Object, long, int)} with a zero + * compaction threshold. + * + * @param entry target chain entry + * @param key target key + * @param now current time + * @return the current value + */ + public ValueHolder resolve(ServerStoreProxy.ChainEntry entry, K key, long now) { + return resolve(entry, key, now, 0); + } + + /** + * Resolves all keys within the given chain to their current values. * - * @param chain a heterogeneous {@code Chain} - * @param key a key - * @param now time when the chain is being resolved - * @return a resolved chain, result of resolution of chain provided + * @param chain target chain + * @param now current time + * @return a map of current values */ - public ResolvedChain resolve(Chain chain, K key, long now) { + public abstract Map> resolveAll(Chain chain, long now); + + /** + * Compacts the given chain entry by resolving every key within. + * + * @param entry an uncompacted heterogenous {@link ServerStoreProxy.ChainEntry} + */ + public void compact(ServerStoreProxy.ChainEntry entry) { + ChainBuilder builder = new ChainBuilder(); + for (PutOperation operation : resolveAll(entry).values()) { + builder = builder.add(codec.encode(operation)); + } + Chain compacted = builder.build(); + if (compacted.length() < entry.length()) { + entry.replaceAtHead(compacted); + } + } + + /** + * Resolves the given key within the given chain entry to an equivalent put operation. + *

+ * If the resultant chain has shrunk by more than {@code threshold} elements then an attempt is made to perform the + * equivalent compaction on the server. + * + * @param entry target chain entry + * @param key target key + * @param threshold compaction threshold + * @return equivalent put operation + */ + protected PutOperation resolve(ServerStoreProxy.ChainEntry entry, K key, int threshold) { PutOperation result = null; - ChainBuilder newChainBuilder = new ChainBuilder(); - boolean matched = false; - for (Element element : chain) { + ChainBuilder resolvedChain = new ChainBuilder(); + for (Element element : entry) { ByteBuffer payload = element.getPayload(); Operation operation = codec.decode(payload); if(key.equals(operation.getKey())) { - matched = true; - result = applyOperation(key, result, operation, now); + result = applyOperation(key, result, operation); } else { payload.rewind(); - newChainBuilder = newChainBuilder.add(payload); + resolvedChain = resolvedChain.add(payload); } } - - if(result == null) { - if (matched) { - Chain newChain = newChainBuilder.build(); - return new ResolvedChain.Impl<>(newChain, key, null, chain.length() - newChain.length(), Long.MAX_VALUE); - } else { - return new ResolvedChain.Impl<>(chain, key, null, 0, Long.MAX_VALUE); - } - } else { - Chain newChain = newChainBuilder.add(codec.encode(result)).build(); - return new ResolvedChain.Impl<>(newChain, key, result, chain.length() - newChain.length(), result.expirationTime()); + if(result != null) { + resolvedChain = resolvedChain.add(codec.encode(result)); } - } - /** - * Compacts the given chain by resolving every key within. - * - * @param chain a compacted heterogenous {@code Chain} - * @param now time when the chain is being resolved - * @return a compacted chain - */ - public Chain compactChain(Chain chain, long now) { - ChainBuilder builder = new ChainBuilder(); - for (PutOperation operation : resolveChain(chain, now).values()) { - builder = builder.add(codec.encode(operation)); + if (entry.length() - resolvedChain.length() > threshold) { + entry.replaceAtHead(resolvedChain.build()); } - return builder.build(); + return result; } /** - * Resolves all keys within the given chain. + * Resolves all keys within the given chain to their equivalent put operations. * - * @param chain a compacted heterogenous {@code Chain} - * @param now time when the chain is being resolved - * @return a compacted chain + * @param chain target chain + * @return a map of equivalent put operations */ - public Map> resolveChain(Chain chain, long now) { + protected Map> resolveAll(Chain chain) { //absent hash-collisions this should always be a 1 entry map Map> compacted = new HashMap<>(2); for (Element element : chain) { ByteBuffer payload = element.getPayload(); Operation operation = codec.decode(payload); - compacted.compute(operation.getKey(), (k, v) -> applyOperation(k, v, operation, now)); + compacted.compute(operation.getKey(), (k, v) -> applyOperation(k, v, operation)); } return compacted; } /** - * Applies the given operation to the current state at the time specified. + * Applies the given operation to the current state. * * @param key cache key * @param existing current state * @param operation operation to apply - * @param now current time * @return an equivalent put operation */ - public abstract PutOperation applyOperation(K key, PutOperation existing, Operation operation, long now); + public abstract PutOperation applyOperation(K key, PutOperation existing, Operation operation); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/EternalChainResolver.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/EternalChainResolver.java index dd2cc6bf93..da73db546a 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/EternalChainResolver.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/EternalChainResolver.java @@ -16,10 +16,19 @@ package org.ehcache.clustered.client.internal.store.operations; +import org.ehcache.clustered.client.internal.store.ClusteredValueHolder; +import org.ehcache.clustered.client.internal.store.ServerStoreProxy; +import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.operations.Operation; import org.ehcache.clustered.common.internal.store.operations.PutOperation; import org.ehcache.clustered.common.internal.store.operations.Result; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; +import org.ehcache.core.spi.store.Store.ValueHolder; + +import java.util.HashMap; +import java.util.Map; + +import static java.util.Collections.unmodifiableMap; /** * A specialized chain resolver for eternal caches. @@ -35,16 +44,29 @@ public EternalChainResolver(final OperationsCodec codec) { super(codec); } + @Override + public ValueHolder resolve(ServerStoreProxy.ChainEntry entry, K key, long now, int threshold) { + PutOperation resolved = resolve(entry, key, threshold); + return resolved == null ? null : new ClusteredValueHolder<>(resolved.getValue()); + } + + @Override + public Map> resolveAll(Chain chain, long now) { + Map> resolved = resolveAll(chain); + + Map> values = new HashMap<>(resolved.size()); + for (Map.Entry> e : resolved.entrySet()) { + values.put(e.getKey(), new ClusteredValueHolder<>(e.getValue().getValue())); + } + return unmodifiableMap(values); + } + /** * Applies the given operation returning a result that never expires. * - * @param key cache key - * @param existing current state - * @param operation operation to apply - * @param now current time - * @return the equivalent put operation + * {@inheritDoc} */ - public PutOperation applyOperation(K key, PutOperation existing, Operation operation, long now) { + public PutOperation applyOperation(K key, PutOperation existing, Operation operation) { final Result newValue = operation.apply(existing); if (newValue == null) { return null; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java index f7f5e6b544..a37caa1015 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java @@ -16,17 +16,26 @@ package org.ehcache.clustered.client.internal.store.operations; +import org.ehcache.clustered.client.internal.store.ClusteredValueHolder; +import org.ehcache.clustered.client.internal.store.ServerStoreProxy; +import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.operations.Operation; import org.ehcache.clustered.common.internal.store.operations.PutOperation; import org.ehcache.clustered.common.internal.store.operations.Result; +import org.ehcache.clustered.common.internal.store.operations.TimestampOperation; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; import org.ehcache.core.config.ExpiryUtils; +import org.ehcache.core.spi.store.Store.ValueHolder; import org.ehcache.expiry.ExpiryPolicy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.time.Duration; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeoutException; +import static java.util.Collections.unmodifiableMap; import static java.util.Objects.requireNonNull; import static org.ehcache.core.config.ExpiryUtils.isExpiryDurationInfinite; @@ -53,6 +62,35 @@ public ExpiryChainResolver(final OperationsCodec codec, ExpiryPolicy resolve(ServerStoreProxy.ChainEntry entry, K key, long now, int threshold) { + PutOperation resolved = resolve(entry, key, threshold); + + if (resolved == null) { + return null; + } else if (now >= resolved.expirationTime()) { + try { + entry.append(codec.encode(new TimestampOperation<>(key, now))); + } catch (TimeoutException e) { + LOG.debug("Failed to append timestamp operation", e); + } + return null; + } else { + return new ClusteredValueHolder<>(resolved.getValue(), resolved.expirationTime()); + } + } + + @Override + public Map> resolveAll(Chain chain, long now) { + Map> resolved = resolveAll(chain); + + Map> values = new HashMap<>(resolved.size()); + for (Map.Entry> e : resolved.entrySet()) { + values.put(e.getKey(), new ClusteredValueHolder<>(e.getValue().getValue(), e.getValue().expirationTime())); + } + return unmodifiableMap(values); + } + /** * Applies the given operation returning a result with an expiry time determined by this resolvers expiry policy. *

@@ -65,18 +103,18 @@ public ExpiryChainResolver(final OperationsCodec codec, ExpiryPolicy applyOperation(K key, PutOperation existing, Operation operation, long now) { + public PutOperation applyOperation(K key, PutOperation existing, Operation operation) { + if (existing != null && operation.timeStamp() >= existing.expirationTime()) { + existing = null; + } + final Result newValue = operation.apply(existing); if (newValue == null) { return null; + } else if (newValue == existing) { + return existing; } else { - long expirationTime = calculateExpiryTime(key, existing, operation, newValue); - - if (now >= expirationTime) { - return null; - } else { - return newValue.asOperationExpiringAt(expirationTime); - } + return newValue.asOperationExpiringAt(calculateExpiryTime(key, existing, operation, newValue)); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java index ce6c14e85e..5eb1fc8781 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java @@ -16,8 +16,9 @@ package org.ehcache.clustered.client.internal.loaderwriter; import org.ehcache.clustered.client.internal.store.ServerStoreProxy; -import org.ehcache.clustered.client.internal.store.lock.LockingServerStoreProxy; +import org.ehcache.clustered.client.internal.store.lock.LockingServerStoreProxyImpl; import org.ehcache.clustered.client.internal.store.operations.EternalChainResolver; +import org.ehcache.clustered.common.internal.store.Element; import org.ehcache.clustered.common.internal.store.operations.PutOperation; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; import org.ehcache.clustered.common.internal.store.Chain; @@ -31,8 +32,9 @@ import org.mockito.ArgumentMatchers; import java.nio.ByteBuffer; +import java.util.Iterator; +import java.util.concurrent.TimeoutException; -import static java.util.Collections.emptyList; import static org.ehcache.clustered.ChainUtils.chainOf; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; @@ -57,9 +59,9 @@ public class ClusteredLoaderWriterStoreTest { @Test public void testGetValueAbsentInSOR() throws Exception { - ServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + ServerStoreProxy storeProxy = mock(LockingServerStoreProxyImpl.class); CacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.get(eq(1L))).thenReturn(chainOf()); + when(storeProxy.get(eq(1L))).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(store.get(1L), is(nullValue())); @@ -67,10 +69,10 @@ public void testGetValueAbsentInSOR() throws Exception { @Test public void testGetValuePresentInSOR() throws Exception { - ServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + ServerStoreProxy storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); loaderWriter.storeMap.put(1L, "one"); - when(storeProxy.get(eq(1L))).thenReturn(chainOf()); + when(storeProxy.get(eq(1L))).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(store.get(1L).get(), equalTo("one")); @@ -78,11 +80,11 @@ public void testGetValuePresentInSOR() throws Exception { @Test public void testGetValuePresentInCache() throws Exception { - ServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + ServerStoreProxy storeProxy = mock(LockingServerStoreProxyImpl.class); @SuppressWarnings("unchecked") CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); PutOperation operation = new PutOperation<>(1L, "one", System.currentTimeMillis()); - Chain toReturn = chainOf(codec.encode(operation)); + ServerStoreProxy.ChainEntry toReturn = entryOf(codec.encode(operation)); when(storeProxy.get(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); @@ -93,7 +95,7 @@ public void testGetValuePresentInCache() throws Exception { @Test public void testPut() throws Exception { - ServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + ServerStoreProxy storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); @@ -104,9 +106,9 @@ public void testPut() throws Exception { @Test public void testRemoveValueAbsentInCachePresentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(chainOf()); + when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); loaderWriter.storeMap.put(1L, "one"); @@ -116,10 +118,10 @@ public void testRemoveValueAbsentInCachePresentInSOR() throws Exception { @Test public void testRemoveValuePresentInCachePresentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); PutOperation operation = new PutOperation<>(1L, "one", System.currentTimeMillis()); - Chain toReturn = chainOf(codec.encode(operation)); + ServerStoreProxy.ChainEntry toReturn = entryOf(codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); when(storeProxy.get(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, @@ -132,10 +134,10 @@ public void testRemoveValuePresentInCachePresentInSOR() throws Exception { @Test public void testRemoveValueAbsentInCacheAbsentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); @SuppressWarnings("unchecked") CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); - when(storeProxy.lock(anyLong())).thenReturn(chainOf()); + when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(store.remove(1L), is(false)); @@ -144,9 +146,9 @@ public void testRemoveValueAbsentInCacheAbsentInSOR() throws Exception { @Test public void testPufIfAbsentValueAbsentInCacheAbsentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(chainOf()); + when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(loaderWriter.storeMap.isEmpty(), is(true)); @@ -156,9 +158,9 @@ public void testPufIfAbsentValueAbsentInCacheAbsentInSOR() throws Exception { @Test public void testPufIfAbsentValueAbsentInCachePresentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(chainOf()); + when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); loaderWriter.storeMap.put(1L, "one"); @@ -169,10 +171,10 @@ public void testPufIfAbsentValueAbsentInCachePresentInSOR() throws Exception { @Test public void testPufIfAbsentValuePresentInCachePresentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); PutOperation operation = new PutOperation<>(1L, "one", System.currentTimeMillis()); - Chain toReturn = chainOf(codec.encode(operation)); + ServerStoreProxy.ChainEntry toReturn = entryOf(codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); @@ -184,9 +186,9 @@ public void testPufIfAbsentValuePresentInCachePresentInSOR() throws Exception { @Test public void testReplaceValueAbsentInCacheAbsentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(chainOf()); + when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(loaderWriter.storeMap.isEmpty(), is(true)); @@ -197,9 +199,9 @@ public void testReplaceValueAbsentInCacheAbsentInSOR() throws Exception { @Test public void testReplaceValueAbsentInCachePresentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(chainOf()); + when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); loaderWriter.storeMap.put(1L, "one"); @@ -210,10 +212,10 @@ public void testReplaceValueAbsentInCachePresentInSOR() throws Exception { @Test public void testReplaceValuePresentInCachePresentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); PutOperation operation = new PutOperation<>(1L, "one", System.currentTimeMillis()); - Chain toReturn = chainOf(codec.encode(operation)); + ServerStoreProxy.ChainEntry toReturn = entryOf(codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); @@ -225,10 +227,10 @@ public void testReplaceValuePresentInCachePresentInSOR() throws Exception { @Test public void testRemove2ArgsValueAbsentInCacheAbsentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); @SuppressWarnings("unchecked") CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); - when(storeProxy.lock(anyLong())).thenReturn(chainOf()); + when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(store.remove(1L, "one"), is(Store.RemoveStatus.KEY_MISSING)); @@ -237,9 +239,9 @@ public void testRemove2ArgsValueAbsentInCacheAbsentInSOR() throws Exception { @Test public void testRemove2ArgsValueAbsentInCachePresentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(chainOf()); + when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); loaderWriter.storeMap.put(1L, "one"); @@ -250,11 +252,11 @@ public void testRemove2ArgsValueAbsentInCachePresentInSOR() throws Exception { @Test public void testRemove2ArgsValuePresentInCachePresentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); @SuppressWarnings("unchecked") CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); PutOperation operation = new PutOperation<>(1L, "one", System.currentTimeMillis()); - Chain toReturn = chainOf(codec.encode(operation)); + ServerStoreProxy.ChainEntry toReturn = entryOf(codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); @@ -266,9 +268,9 @@ public void testRemove2ArgsValuePresentInCachePresentInSOR() throws Exception { @Test public void testRemove2ArgsValueAbsentInCacheDiffValuePresentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(chainOf()); + when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); loaderWriter.storeMap.put(1L, "one"); @@ -279,10 +281,10 @@ public void testRemove2ArgsValueAbsentInCacheDiffValuePresentInSOR() throws Exce @Test public void testReplace2ArgsValueAbsentInCacheAbsentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); @SuppressWarnings("unchecked") CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); - when(storeProxy.lock(anyLong())).thenReturn(chainOf()); + when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(store.replace(1L, "one", "Again"), is(Store.ReplaceStatus.MISS_NOT_PRESENT)); @@ -293,9 +295,9 @@ public void testReplace2ArgsValueAbsentInCacheAbsentInSOR() throws Exception { @Test public void testReplace2ArgsValueAbsentInCachePresentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(chainOf()); + when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); loaderWriter.storeMap.put(1L, "one"); @@ -306,11 +308,11 @@ public void testReplace2ArgsValueAbsentInCachePresentInSOR() throws Exception { @Test public void testReplace2ArgsValuePresentInCachePresentInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); @SuppressWarnings("unchecked") CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); PutOperation operation = new PutOperation<>(1L, "one", System.currentTimeMillis()); - Chain toReturn = chainOf(codec.encode(operation)); + ServerStoreProxy.ChainEntry toReturn = entryOf(codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); @@ -322,9 +324,9 @@ public void testReplace2ArgsValuePresentInCachePresentInSOR() throws Exception { @Test public void testReplace2ArgsValueAbsentInCacheDiffValueInSOR() throws Exception { - LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + LockingServerStoreProxyImpl storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); - when(storeProxy.lock(anyLong())).thenReturn(chainOf()); + when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); loaderWriter.storeMap.put(1L, "one"); @@ -332,4 +334,34 @@ public void testReplace2ArgsValueAbsentInCacheDiffValueInSOR() throws Exception verify(storeProxy, times(0)).append(anyLong(), ArgumentMatchers.any(ByteBuffer.class)); assertThat(loaderWriter.storeMap.get(1L), equalTo("one")); } + + private static ServerStoreProxy.ChainEntry entryOf(ByteBuffer ... elements) { + Chain chain = chainOf(elements); + return new ServerStoreProxy.ChainEntry() { + @Override + public void append(ByteBuffer payLoad) throws TimeoutException { + throw new AssertionError(); + } + + @Override + public void replaceAtHead(Chain equivalent) { + throw new AssertionError(); + } + + @Override + public boolean isEmpty() { + return chain.isEmpty(); + } + + @Override + public int length() { + return chain.length(); + } + + @Override + public Iterator iterator() { + return chain.iterator(); + } + }; + } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java index 3e25e1f3c0..18656fb1a8 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java @@ -15,6 +15,7 @@ */ package org.ehcache.clustered.client.internal.loaderwriter.writebehind; +import org.ehcache.clustered.client.internal.store.ServerStoreProxy; import org.ehcache.clustered.common.internal.util.ChainBuilder; import org.ehcache.clustered.client.internal.store.operations.ChainResolver; import org.ehcache.clustered.client.internal.store.operations.ExpiryChainResolver; @@ -40,6 +41,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.AbstractExecutorService; @@ -156,13 +158,37 @@ private void verifyEvents(List expected, Map expectedCh ClusteredWriteBehind clusteredWriteBehind = new ClusteredWriteBehind<>(clusteredWriteBehindStore, executorService, - TIME_SOURCE, resolver, cacheLoaderWriter, operationCodec); Chain elements = makeChain(expected, operationCodec); - when(clusteredWriteBehindStore.lock(1L)).thenReturn(elements); + when(clusteredWriteBehindStore.lock(1L)).thenReturn(new ServerStoreProxy.ChainEntry() { + @Override + public void append(ByteBuffer payLoad) throws TimeoutException { + + } + + @Override + public void replaceAtHead(Chain equivalent) { + + } + + @Override + public boolean isEmpty() { + return elements.isEmpty(); + } + + @Override + public int length() { + return elements.length(); + } + + @Override + public Iterator iterator() { + return elements.iterator(); + } + }); ArgumentCaptor chainArgumentCaptor = ArgumentCaptor.forClass(Chain.class); @@ -199,8 +225,7 @@ private Map convert(Chain chain, OperationsCodec cod Long key = operation.getKey(); PutOperation opResult = resolver.applyOperation(key, null, - operation, - timeSource.getTimeMillis()); + operation); result.put(key, opResult.getValue()); } return result; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java index be8881520d..d736b58154 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java @@ -26,11 +26,9 @@ import org.ehcache.clustered.client.internal.UnitTestConnectionService; import org.ehcache.clustered.client.internal.store.ServerStoreProxy.ServerCallback; import org.ehcache.clustered.client.internal.store.operations.EternalChainResolver; -import org.ehcache.clustered.common.internal.store.operations.Result; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; import org.ehcache.clustered.common.ServerSideConfiguration; import org.ehcache.clustered.common.internal.ServerStoreConfiguration; -import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.config.EvictionAdvisor; import org.ehcache.config.ResourcePools; import org.ehcache.config.units.MemoryUnit; @@ -54,7 +52,6 @@ import org.terracotta.connection.Connection; import java.net.URI; -import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; @@ -67,8 +64,6 @@ import java.util.function.Function; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.ehcache.clustered.client.internal.store.ClusteredStore.DEFAULT_CHAIN_COMPACTION_THRESHOLD; -import static org.ehcache.clustered.client.internal.store.ClusteredStore.CHAIN_COMPACTION_THRESHOLD_PROP; import static org.ehcache.clustered.util.StatisticsTestUtils.validateStat; import static org.ehcache.clustered.util.StatisticsTestUtils.validateStats; import static org.ehcache.core.spi.store.Store.ValueHolder.NO_EXPIRE; @@ -79,12 +74,11 @@ import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.RETURNS_MOCKS; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; public class ClusteredStoreTest { @@ -239,55 +233,6 @@ public void testGetTimeout() throws Exception { validateStats(store, EnumSet.of(StoreOperationOutcomes.GetOutcome.TIMEOUT)); } - @Test - public void testGetThatCompactsInvokesReplace() throws Exception { - TestTimeSource timeSource = new TestTimeSource(); - timeSource.advanceTime(134556L); - long now = timeSource.getTimeMillis(); - @SuppressWarnings("unchecked") - OperationsCodec operationsCodec = new OperationsCodec<>(new LongSerializer(), new StringSerializer()); - @SuppressWarnings("unchecked") - EternalChainResolver chainResolver = mock(EternalChainResolver.class); - @SuppressWarnings("unchecked") - ResolvedChain resolvedChain = mock(ResolvedChain.class); - when(resolvedChain.isCompacted()).thenReturn(true); - when(chainResolver.resolve(any(Chain.class), eq(42L), eq(now))).thenReturn(resolvedChain); - ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); - Chain chain = mock(Chain.class); - when(chain.isEmpty()).thenReturn(false); - long longKey = HashUtils.intHashToLong(new Long(42L).hashCode()); - when(serverStoreProxy.get(longKey)).thenReturn(chain); - - ClusteredStore clusteredStore = new ClusteredStore<>(config, operationsCodec, chainResolver, - serverStoreProxy, timeSource); - clusteredStore.get(42L); - verify(serverStoreProxy).replaceAtHead(eq(longKey), eq(chain), isNull()); - } - - @Test - public void testGetThatDoesNotCompactsInvokesReplace() throws Exception { - TestTimeSource timeSource = new TestTimeSource(); - timeSource.advanceTime(134556L); - long now = timeSource.getTimeMillis(); - OperationsCodec operationsCodec = new OperationsCodec<>(new LongSerializer(), new StringSerializer()); - @SuppressWarnings("unchecked") - EternalChainResolver chainResolver = mock(EternalChainResolver.class); - @SuppressWarnings("unchecked") - ResolvedChain resolvedChain = mock(ResolvedChain.class); - when(resolvedChain.isCompacted()).thenReturn(false); - when(chainResolver.resolve(any(Chain.class), eq(42L), eq(now))).thenReturn(resolvedChain); - ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); - Chain chain = mock(Chain.class); - when(chain.isEmpty()).thenReturn(false); - long longKey = HashUtils.intHashToLong(new Long(42L).hashCode()); - when(serverStoreProxy.get(longKey)).thenReturn(chain); - - ClusteredStore clusteredStore = new ClusteredStore<>(config, operationsCodec, chainResolver, - serverStoreProxy, timeSource); - clusteredStore.get(42L); - verify(serverStoreProxy, never()).replaceAtHead(eq(longKey), eq(chain), any(Chain.class)); - } - @Test public void testContainsKey() throws Exception { assertThat(store.containsKey(1L), is(false)); @@ -407,7 +352,7 @@ public void testPutIfAbsentThrowsOnlySAE() throws Exception { @SuppressWarnings("unchecked") EternalChainResolver chainResolver = mock(EternalChainResolver.class); ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); - when(serverStoreProxy.get(anyLong())).thenThrow(new RuntimeException()); + when(serverStoreProxy.getAndAppend(anyLong(), any())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); store.putIfAbsent(1L, "one", b -> {}); @@ -444,7 +389,7 @@ public void testConditionalRemoveThrowsOnlySAE() throws Exception { @SuppressWarnings("unchecked") EternalChainResolver chainResolver = mock(EternalChainResolver.class); ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); - when(serverStoreProxy.get(anyLong())).thenThrow(new RuntimeException()); + when(serverStoreProxy.getAndAppend(anyLong(), any())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); store.remove(1L, "one"); @@ -478,7 +423,7 @@ public void testReplaceThrowsOnlySAE() throws Exception { @SuppressWarnings("unchecked") EternalChainResolver chainResolver = mock(EternalChainResolver.class); ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); - when(serverStoreProxy.get(anyLong())).thenThrow(new RuntimeException()); + when(serverStoreProxy.getAndAppend(anyLong(), any())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); store.replace(1L, "one"); @@ -516,7 +461,7 @@ public void testConditionalReplaceThrowsOnlySAE() throws Exception { @SuppressWarnings("unchecked") EternalChainResolver chainResolver = mock(EternalChainResolver.class); ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); - when(serverStoreProxy.get(anyLong())).thenThrow(new RuntimeException()); + when(serverStoreProxy.getAndAppend(anyLong(), any())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); store.replace(1L, "one", "another one"); @@ -597,284 +542,18 @@ public void testBulkComputeIfAbsentThrowsForGenericFunction() throws Exception { store.bulkComputeIfAbsent(new HashSet<>(Arrays.asList(1L, 2L)), mappingFunction); } - @Test - @SuppressWarnings("unchecked") - public void testPutIfAbsentReplacesChainOnlyOnCompressionThreshold() throws Exception { - Result result = mock(Result.class); - when(result.getValue()).thenReturn("one"); - - ResolvedChain resolvedChain = mock(ResolvedChain.class); - when(resolvedChain.getResolvedResult(anyLong())).thenReturn(result); - when(resolvedChain.getCompactedChain()).thenReturn(mock(Chain.class)); - - ServerStoreProxy proxy = mock(ServerStoreProxy.class); - when(proxy.getAndAppend(anyLong(), any(ByteBuffer.class))).thenReturn(mock(Chain.class)); - - EternalChainResolver resolver = mock(EternalChainResolver.class); - when(resolver.resolve(any(Chain.class), anyLong(), anyLong())).thenReturn(resolvedChain); - - OperationsCodec codec = mock(OperationsCodec.class); - when(codec.encode(any())).thenReturn(ByteBuffer.allocate(0)); - TimeSource timeSource = mock(TimeSource.class); - - ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource); - - when(resolvedChain.getCompactionCount()).thenReturn(DEFAULT_CHAIN_COMPACTION_THRESHOLD - 1); // less than the default threshold - store.putIfAbsent(1L, "one", b -> {}); - verify(proxy, never()).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - - when(resolvedChain.getCompactionCount()).thenReturn(DEFAULT_CHAIN_COMPACTION_THRESHOLD); // equal to the default threshold - store.putIfAbsent(1L, "one", b -> {}); - verify(proxy, never()).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - - when(resolvedChain.getCompactionCount()).thenReturn(DEFAULT_CHAIN_COMPACTION_THRESHOLD + 1); // greater than the default threshold - store.putIfAbsent(1L, "one", b -> {}); - verify(proxy).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - } - - @Test - @SuppressWarnings("unchecked") - public void testReplaceReplacesChainOnlyOnCompressionThreshold() throws Exception { - Result result = mock(Result.class); - when(result.getValue()).thenReturn("one"); - - ResolvedChain resolvedChain = mock(ResolvedChain.class); - when(resolvedChain.getResolvedResult(anyLong())).thenReturn(result); - when(resolvedChain.getCompactedChain()).thenReturn(mock(Chain.class)); - - ServerStoreProxy proxy = mock(ServerStoreProxy.class); - when(proxy.getAndAppend(anyLong(), any(ByteBuffer.class))).thenReturn(mock(Chain.class)); - - EternalChainResolver resolver = mock(EternalChainResolver.class); - when(resolver.resolve(any(Chain.class), anyLong(), anyLong())).thenReturn(resolvedChain); - - OperationsCodec codec = mock(OperationsCodec.class); - when(codec.encode(any())).thenReturn(ByteBuffer.allocate(0)); - TimeSource timeSource = mock(TimeSource.class); - - ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource); - - when(resolvedChain.getCompactionCount()).thenReturn(DEFAULT_CHAIN_COMPACTION_THRESHOLD - 1); // less than the default threshold - store.replace(1L, "one"); - verify(proxy, never()).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - - when(resolvedChain.getCompactionCount()).thenReturn(DEFAULT_CHAIN_COMPACTION_THRESHOLD); // equal to the default threshold - store.replace(1L, "one"); - verify(proxy, never()).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - - when(resolvedChain.getCompactionCount()).thenReturn(DEFAULT_CHAIN_COMPACTION_THRESHOLD + 1); // greater than the default threshold - store.replace(1L, "one"); - verify(proxy).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - } - - @Test - @SuppressWarnings("unchecked") - public void testConditionalReplaceReplacesChainOnlyOnCompressionThreshold() throws Exception { - ResolvedChain resolvedChain = mock(ResolvedChain.class); - when(resolvedChain.getResolvedResult(anyLong())).thenReturn(mock(Result.class)); - when(resolvedChain.getCompactedChain()).thenReturn(mock(Chain.class)); - - ServerStoreProxy proxy = mock(ServerStoreProxy.class); - when(proxy.getAndAppend(anyLong(), any(ByteBuffer.class))).thenReturn(mock(Chain.class)); - - EternalChainResolver resolver = mock(EternalChainResolver.class); - when(resolver.resolve(any(Chain.class), anyLong(), anyLong())).thenReturn(resolvedChain); - - OperationsCodec codec = mock(OperationsCodec.class); - when(codec.encode(any())).thenReturn(ByteBuffer.allocate(0)); - TimeSource timeSource = mock(TimeSource.class); - - ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource); - - when(resolvedChain.getCompactionCount()).thenReturn(DEFAULT_CHAIN_COMPACTION_THRESHOLD - 1); // less than the default threshold - store.replace(1L, "one", "anotherOne"); - verify(proxy, never()).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - - when(resolvedChain.getCompactionCount()).thenReturn(DEFAULT_CHAIN_COMPACTION_THRESHOLD); // equal to the default threshold - store.replace(1L, "one", "anotherOne"); - verify(proxy, never()).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - - when(resolvedChain.getCompactionCount()).thenReturn(DEFAULT_CHAIN_COMPACTION_THRESHOLD + 1); // greater than the default threshold - store.replace(1L, "one", "anotherOne"); - verify(proxy).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - } - - @Test - @SuppressWarnings("unchecked") - public void testCustomCompressionThreshold() throws Exception { - int customThreshold = 4; - try { - System.setProperty(CHAIN_COMPACTION_THRESHOLD_PROP, String.valueOf(customThreshold)); - - Result result = mock(Result.class); - when(result.getValue()).thenReturn("one"); - - ResolvedChain resolvedChain = mock(ResolvedChain.class); - when(resolvedChain.getResolvedResult(anyLong())).thenReturn(result); - when(resolvedChain.getCompactedChain()).thenReturn(mock(Chain.class)); - - ServerStoreProxy proxy = mock(ServerStoreProxy.class); - when(proxy.getAndAppend(anyLong(), any(ByteBuffer.class))).thenReturn(mock(Chain.class)); - - EternalChainResolver resolver = mock(EternalChainResolver.class); - when(resolver.resolve(any(Chain.class), anyLong(), anyLong())).thenReturn(resolvedChain); - - OperationsCodec codec = mock(OperationsCodec.class); - when(codec.encode(any())).thenReturn(ByteBuffer.allocate(0)); - TimeSource timeSource = mock(TimeSource.class); - - ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource); - - when(resolvedChain.getCompactionCount()).thenReturn(customThreshold - 1); // less than the custom threshold - store.putIfAbsent(1L, "one", b -> {}); - verify(proxy, never()).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - - when(resolvedChain.getCompactionCount()).thenReturn(customThreshold); // equal to the custom threshold - store.replace(1L, "one"); - verify(proxy, never()).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - - when(resolvedChain.getCompactionCount()).thenReturn(customThreshold + 1); // greater than the custom threshold - store.replace(1L, "one"); - verify(proxy).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - } finally { - System.clearProperty(CHAIN_COMPACTION_THRESHOLD_PROP); - } - } - - @Test - @SuppressWarnings("unchecked") - public void testRemoveReplacesChainOnHits() throws Exception { - ResolvedChain resolvedChain = mock(ResolvedChain.class); - when(resolvedChain.getCompactedChain()).thenReturn(mock(Chain.class)); - when(resolvedChain.getResolvedResult(anyLong())).thenReturn(mock(Result.class)); //simulate a key hit on chain resolution - when(resolvedChain.getCompactionCount()).thenReturn(1); - - ServerStoreProxy proxy = mock(ServerStoreProxy.class); - when(proxy.getAndAppend(anyLong(), any(ByteBuffer.class))).thenReturn(mock(Chain.class)); - - EternalChainResolver resolver = mock(EternalChainResolver.class); - when(resolver.resolve(any(Chain.class), anyLong(), anyLong())).thenReturn(resolvedChain); - - OperationsCodec codec = mock(OperationsCodec.class); - when(codec.encode(any())).thenReturn(ByteBuffer.allocate(0)); - TimeSource timeSource = mock(TimeSource.class); - - ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource); - - store.remove(1L); - verify(proxy).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - } - - @Test - @SuppressWarnings("unchecked") - public void testRemoveDoesNotReplaceChainOnMisses() throws Exception { - ResolvedChain resolvedChain = mock(ResolvedChain.class); - when(resolvedChain.getResolvedResult(anyLong())).thenReturn(null); //simulate a key miss on chain resolution - - EternalChainResolver resolver = mock(EternalChainResolver.class); - when(resolver.resolve(any(Chain.class), anyLong(), anyLong())).thenReturn(resolvedChain); - - OperationsCodec codec = mock(OperationsCodec.class); - when(codec.encode(any())).thenReturn(ByteBuffer.allocate(0)); - ServerStoreProxy proxy = mock(ServerStoreProxy.class); - when(proxy.getAndAppend(anyLong(), any(ByteBuffer.class))).thenReturn(mock(Chain.class)); - TimeSource timeSource = mock(TimeSource.class); - - ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource); - - store.remove(1L); - verify(proxy, never()).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - } - - @Test - @SuppressWarnings("unchecked") - public void testConditionalRemoveReplacesChainOnHits() throws Exception { - Result result = mock(Result.class); - when(result.getValue()).thenReturn("foo"); - - ResolvedChain resolvedChain = mock(ResolvedChain.class); - when(resolvedChain.getCompactedChain()).thenReturn(mock(Chain.class)); - when(resolvedChain.getResolvedResult(anyLong())).thenReturn(result); //simulate a key hit on chain resolution - when(resolvedChain.getCompactionCount()).thenReturn(1); - - ServerStoreProxy proxy = mock(ServerStoreProxy.class); - when(proxy.getAndAppend(anyLong(), any(ByteBuffer.class))).thenReturn(mock(Chain.class)); - - EternalChainResolver resolver = mock(EternalChainResolver.class); - when(resolver.resolve(any(Chain.class), anyLong(), anyLong())).thenReturn(resolvedChain); - - OperationsCodec codec = mock(OperationsCodec.class); - when(codec.encode(any())).thenReturn(ByteBuffer.allocate(0)); - TimeSource timeSource = mock(TimeSource.class); - - ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource); - - store.remove(1L, "foo"); - verify(proxy).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - } - - @Test - @SuppressWarnings("unchecked") - public void testConditionalRemoveDoesNotReplaceChainOnKeyMiss() throws Exception { - ResolvedChain resolvedChain = mock(ResolvedChain.class); - when(resolvedChain.getResolvedResult(anyLong())).thenReturn(null); //simulate a key miss on chain resolution - - EternalChainResolver resolver = mock(EternalChainResolver.class); - when(resolver.resolve(any(Chain.class), anyLong(), anyLong())).thenReturn(resolvedChain); - - OperationsCodec codec = mock(OperationsCodec.class); - when(codec.encode(any())).thenReturn(ByteBuffer.allocate(0)); - ServerStoreProxy proxy = mock(ServerStoreProxy.class); - when(proxy.getAndAppend(anyLong(), any(ByteBuffer.class))).thenReturn(mock(Chain.class)); - TimeSource timeSource = mock(TimeSource.class); - - ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource); - - store.remove(1L, "foo"); - verify(proxy, never()).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - } - - @Test - @SuppressWarnings("unchecked") - public void testConditionalRemoveDoesNotReplaceChainOnKeyHitValueMiss() throws Exception { - Result result = mock(Result.class); - ResolvedChain resolvedChain = mock(ResolvedChain.class); - when(resolvedChain.getResolvedResult(anyLong())).thenReturn(result); //simulate a key kit - when(result.getValue()).thenReturn("bar"); //but a value miss - - - EternalChainResolver resolver = mock(EternalChainResolver.class); - when(resolver.resolve(any(Chain.class), anyLong(), anyLong())).thenReturn(resolvedChain); - - OperationsCodec codec = mock(OperationsCodec.class); - when(codec.encode(any())).thenReturn(ByteBuffer.allocate(0)); - ServerStoreProxy proxy = mock(ServerStoreProxy.class); - when(proxy.getAndAppend(anyLong(), any(ByteBuffer.class))).thenReturn(mock(Chain.class)); - TimeSource timeSource = mock(TimeSource.class); - - ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource); - - store.remove(1L, "foo"); - verify(proxy, never()).replaceAtHead(anyLong(), any(Chain.class), any(Chain.class)); - } - @Test public void testExpirationIsSentToHigherTiers() throws Exception { @SuppressWarnings("unchecked") - Result result = mock(Result.class); - when(result.getValue()).thenReturn("bar"); - - @SuppressWarnings("unchecked") - ResolvedChain resolvedChain = mock(ResolvedChain.class); - when(resolvedChain.getResolvedResult(anyLong())).thenReturn(result); - when(resolvedChain.getExpirationTime()).thenReturn(1000L); + Store.ValueHolder valueHolder = mock(Store.ValueHolder.class, withSettings().defaultAnswer(RETURNS_MOCKS)); + when(valueHolder.get()).thenReturn("bar"); + when(valueHolder.expirationTime()).thenReturn(1000L); @SuppressWarnings("unchecked") EternalChainResolver resolver = mock(EternalChainResolver.class); - when(resolver.resolve(any(Chain.class), anyLong(), anyLong())).thenReturn(resolvedChain); + when(resolver.resolve(any(ServerStoreProxy.ChainEntry.class), anyLong(), anyLong())).thenReturn(valueHolder); - ServerStoreProxy proxy = mock(ServerStoreProxy.class); - when(proxy.get(anyLong())).thenReturn(mock(Chain.class)); + ServerStoreProxy proxy = mock(ServerStoreProxy.class, withSettings().defaultAnswer(RETURNS_MOCKS)); @SuppressWarnings("unchecked") OperationsCodec codec = mock(OperationsCodec.class); @@ -891,20 +570,15 @@ public void testExpirationIsSentToHigherTiers() throws Exception { @Test public void testNoExpireIsSentToHigherTiers() throws Exception { @SuppressWarnings("unchecked") - Result result = mock(Result.class); - when(result.getValue()).thenReturn("bar"); - - @SuppressWarnings("unchecked") - ResolvedChain resolvedChain = mock(ResolvedChain.class); - when(resolvedChain.getResolvedResult(anyLong())).thenReturn(result); - when(resolvedChain.getExpirationTime()).thenReturn(Long.MAX_VALUE); // no expire + Store.ValueHolder valueHolder = mock(Store.ValueHolder.class, withSettings().defaultAnswer(RETURNS_MOCKS)); + when(valueHolder.get()).thenReturn("bar"); + when(valueHolder.expirationTime()).thenReturn(NO_EXPIRE); @SuppressWarnings("unchecked") EternalChainResolver resolver = mock(EternalChainResolver.class); - when(resolver.resolve(any(Chain.class), anyLong(), anyLong())).thenReturn(resolvedChain); + when(resolver.resolve(any(ServerStoreProxy.ChainEntry.class), anyLong(), anyLong())).thenReturn(valueHolder); - ServerStoreProxy proxy = mock(ServerStoreProxy.class); - when(proxy.get(anyLong())).thenReturn(mock(Chain.class)); + ServerStoreProxy proxy = mock(ServerStoreProxy.class, withSettings().defaultAnswer(RETURNS_MOCKS)); @SuppressWarnings("unchecked") OperationsCodec codec = mock(OperationsCodec.class); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java index b6aad89406..e8e254b279 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java @@ -38,10 +38,10 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; public class CommonServerStoreProxyTest extends AbstractServerStoreProxyTest { @@ -165,18 +165,23 @@ public void testResolveRequestIsProcessedAtThreshold() throws Exception { ClusterTierClientEntity clientEntity = createClientEntity("testResolveRequestIsProcessed"); ServerCallback serverCallback = mock(ServerCallback.class); - when(serverCallback.compact(any(Chain.class), any(long.class))).thenReturn(chainOf(buffer.duplicate())); + doAnswer(inv -> { + ServerStoreProxy.ChainEntry entry = inv.getArgument(0); + entry.replaceAtHead(chainOf(buffer.duplicate())); + return null; + }).when(serverCallback).compact(any(ServerStoreProxy.ChainEntry.class), any(long.class)); + CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testResolveRequestIsProcessed", clientEntity, serverCallback); for (int i = 0; i < 8; i++) { serverStoreProxy.append(1L, buffer.duplicate()); } - verify(serverCallback, never()).compact(any(Chain.class)); + verify(serverCallback, never()).compact(any(ServerStoreProxy.ChainEntry.class)); assertThat(serverStoreProxy.get(1L), hasPayloads(42L, 42L, 42L, 42L, 42L, 42L, 42L, 42L)); //trigger compaction at > 8 entries serverStoreProxy.append(1L, buffer.duplicate()); - verify(serverCallback).compact(any(Chain.class), any(long.class)); + verify(serverCallback).compact(any(ServerStoreProxy.ChainEntry.class), any(long.class)); assertThat(serverStoreProxy.get(1L), hasPayloads(42L)); } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java index 6b0d0003ac..9c662f31c6 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java @@ -73,7 +73,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { + public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); } }); @@ -89,8 +89,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { - return chain; + public void compact(ServerStoreProxy.ChainEntry chain) { } }); @@ -144,7 +143,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { + public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); } }); @@ -179,7 +178,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { + public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); } }); @@ -213,7 +212,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { + public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); } }); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java index 0aee490af3..7e4e36c81d 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java @@ -20,7 +20,6 @@ import org.ehcache.clustered.client.internal.store.ServerStoreProxy.ServerCallback; import org.ehcache.clustered.common.Consistency; import org.ehcache.clustered.common.internal.ServerStoreConfiguration; -import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.config.units.MemoryUnit; import org.ehcache.impl.serialization.LongSerializer; import org.junit.Assert; @@ -77,7 +76,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { + public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); } }); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java index 6be27fdf30..be04af279c 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java @@ -44,7 +44,10 @@ import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class StrongServerStoreProxyTest extends AbstractServerStoreProxyTest { @@ -78,7 +81,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { + public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); } }); @@ -94,8 +97,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { - return chain; + public void compact(ServerStoreProxy.ChainEntry chain) { } }); @@ -145,7 +147,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { + public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); } }); @@ -184,7 +186,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { + public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); } }); @@ -228,7 +230,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { + public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); } }); @@ -258,7 +260,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { + public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); } }); @@ -298,7 +300,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { + public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); } }); @@ -340,7 +342,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { + public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); } }); @@ -371,7 +373,7 @@ public void onInvalidateAll() { } @Override - public Chain compact(Chain chain) { + public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); } }); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImplTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerTest.java similarity index 93% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImplTest.java rename to clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerTest.java index 5dbb8241e4..f5ddf3f6bd 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerImplTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerTest.java @@ -42,13 +42,13 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.*; -public class LockManagerImplTest { +public class LockManagerTest { @Test public void testLock() throws Exception { ClusterTierClientEntity clusterTierClientEntity = mock(ClusterTierClientEntity.class); - LockManagerImpl lockManager = new LockManagerImpl(clusterTierClientEntity); + LockManager lockManager = new LockManager(clusterTierClientEntity); LockSuccess lockSuccess = getLockSuccessResponse(); @@ -66,7 +66,7 @@ public void testLock() throws Exception { public void testLockWhenException() throws Exception { ClusterTierClientEntity clusterTierClientEntity = mock(ClusterTierClientEntity.class); - LockManagerImpl lockManager = new LockManagerImpl(clusterTierClientEntity); + LockManager lockManager = new LockManager(clusterTierClientEntity); when(clusterTierClientEntity.invokeAndWaitForComplete(any(LockMessage.class), anyBoolean())) .thenThrow(new UnknownClusterException(""), new TimeoutException("timed out test")); @@ -91,7 +91,7 @@ public void testLockWhenException() throws Exception { public void testLockWhenFailure() throws Exception { ClusterTierClientEntity clusterTierClientEntity = mock(ClusterTierClientEntity.class); - LockManagerImpl lockManager = new LockManagerImpl(clusterTierClientEntity); + LockManager lockManager = new LockManager(clusterTierClientEntity); LockSuccess lockSuccess = getLockSuccessResponse(); @@ -108,7 +108,7 @@ public void testLockWhenFailure() throws Exception { @Test public void testUnlockClearsLocksHeldState() throws Exception { ClusterTierClientEntity clusterTierClientEntity = mock(ClusterTierClientEntity.class); - LockManagerImpl lockManager = new LockManagerImpl(clusterTierClientEntity); + LockManager lockManager = new LockManager(clusterTierClientEntity); LockSuccess lockSuccess = getLockSuccessResponse(); when(clusterTierClientEntity.invokeAndWaitForComplete(any(LockMessage.class), anyBoolean())) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java index 1ecb50a87a..c8e13c12f1 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java @@ -16,13 +16,14 @@ package org.ehcache.clustered.common.internal.store.operations; +import org.ehcache.clustered.client.internal.store.ServerStoreProxy; import org.ehcache.clustered.common.internal.util.ChainBuilder; -import org.ehcache.clustered.client.internal.store.ResolvedChain; import org.ehcache.clustered.client.internal.store.operations.ChainResolver; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.Element; import org.ehcache.config.builders.ExpiryPolicyBuilder; +import org.ehcache.core.spi.store.Store; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.serialization.LongSerializer; import org.ehcache.impl.serialization.StringSerializer; @@ -30,24 +31,29 @@ import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; import org.junit.Test; +import org.mockito.ArgumentMatcher; +import org.mockito.ArgumentMatchers; import java.nio.ByteBuffer; import java.time.Duration; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import static java.util.Collections.emptyMap; import static org.hamcrest.Matchers.emptyIterable; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; -import static org.hamcrest.collection.IsMapContaining.hasEntry; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; public abstract class AbstractChainResolverTest { @@ -58,8 +64,8 @@ public abstract class AbstractChainResolverTest { @Test @SuppressWarnings("unchecked") public void testResolveMaintainsOtherKeysInOrder() { - Operation expected = new PutOperation<>(1L, "Suresh", 0L); - Chain chain = getChainFromOperations( + PutOperation expected = new PutOperation<>(1L, "Suresh", 0L); + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L), new PutOperation<>(2L, "Albin", 0L), expected, @@ -67,176 +73,151 @@ public void testResolveMaintainsOtherKeysInOrder() { new PutOperation<>(2L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(1)); - - Chain compactedChain = resolvedChain.getCompactedChain(); - assertThat(compactedChain, contains( //@SuppressWarnings("unchecked") + Store.ValueHolder valueHolder = resolver.resolve(chain, 1L, 0L); + assertThat(valueHolder.get(), is(expected.getValue())); + verify(chain).replaceAtHead(argThat(contains( operation(new PutOperation<>(2L, "Albin", 0L)), operation(new PutOperation<>(2L, "Suresh", 0L)), operation(new PutOperation<>(2L, "Matthew", 0L)), - operation(new PutOperation<>(1L, "Suresh", 0L)))); + operation(new PutOperation<>(1L, "Suresh", 0L))))); } @Test public void testResolveEmptyChain() { - Chain chain = getChainFromOperations(); + ServerStoreProxy.ChainEntry chain = getEntryFromOperations(); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertNull(result); - - assertThat(resolvedChain.isCompacted(), is(false)); - assertThat(resolvedChain.getCompactionCount(), is(0)); + Store.ValueHolder valueHolder = resolver.resolve(chain, 1L, 0L); + assertThat(valueHolder, nullValue()); + verify(chain, never()).replaceAtHead(any()); } @Test public void testResolveChainWithNonExistentKey() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L), new PutOperation<>(2L, "Suresh", 0L), new PutOperation<>(2L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 3L, 0L); - Result result = resolvedChain.getResolvedResult(3L); - assertNull(result); - assertThat(resolvedChain.isCompacted(), is(false)); - assertThat(resolvedChain.getCompactionCount(), is(0)); + Store.ValueHolder valueHolder = resolver.resolve(chain, 3L, 0L); + assertThat(valueHolder, nullValue()); + verify(chain, never()).replaceAtHead(any()); } @Test public void testResolveSinglePut() { - Operation expected = new PutOperation<>(1L, "Albin", 0L); - Chain chain = getChainFromOperations(expected); + PutOperation expected = new PutOperation<>(1L, "Albin", 0L); + ServerStoreProxy.ChainEntry chain = getEntryFromOperations(expected); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(false)); - assertThat(resolvedChain.getCompactionCount(), is(0)); + Store.ValueHolder valueHolder = resolver.resolve(chain, 1L, 0L); + assertThat(valueHolder.get(), is(expected.getValue())); + verify(chain, never()).replaceAtHead(any()); } @Test public void testResolvePutsOnly() { - Operation expected = new PutOperation<>(1L, "Matthew", 0L); + PutOperation expected = new PutOperation<>(1L, "Matthew", 0L); - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L), new PutOperation<>(1L, "Suresh", 0L), expected); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(2)); + Store.ValueHolder valueHolder = resolver.resolve(chain, 1L, 0L); + assertThat(valueHolder.get(), is(expected.getValue())); + verify(chain).replaceAtHead(argThat(contains(operation(expected)))); } @Test public void testResolveSingleRemove() { - Chain chain = getChainFromOperations(new RemoveOperation<>(1L, 0L)); + ServerStoreProxy.ChainEntry chain = getEntryFromOperations(new RemoveOperation<>(1L, 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertNull(result); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(1)); + Store.ValueHolder valueHolder = resolver.resolve(chain, 1L, 0L); + assertThat(valueHolder, nullValue()); + verify(chain).replaceAtHead(argThat(emptyIterable())); } @Test public void testResolveRemovesOnly() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new RemoveOperation<>(1L, 0L), new RemoveOperation<>(1L, 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertNull(result); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(2)); + Store.ValueHolder valueHolder = resolver.resolve(chain, 1L, 0L); + assertThat(valueHolder, nullValue()); + verify(chain).replaceAtHead(argThat(emptyIterable())); } @Test public void testPutAndRemove() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L), new RemoveOperation<>(1L, 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertNull(result); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(2)); + Store.ValueHolder valueHolder = resolver.resolve(chain, 1L, 0L); + assertThat(valueHolder, nullValue()); + verify(chain).replaceAtHead(argThat(emptyIterable())); } @Test public void testResolvePutIfAbsentOnly() { - Operation expected = new PutOperation<>(1L, "Matthew", 0L); - Chain chain = getChainFromOperations(new PutIfAbsentOperation<>(1L, "Matthew", 0L)); + PutOperation expected = new PutOperation<>(1L, "Matthew", 0L); + ServerStoreProxy.ChainEntry chain = getEntryFromOperations(new PutIfAbsentOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(false)); - assertThat(resolvedChain.getCompactionCount(), is(0)); + Store.ValueHolder valueHolder = resolver.resolve(chain, 1L, 0L); + assertThat(valueHolder.get(), is(expected.getValue())); + verify(chain, never()).replaceAtHead(any()); } @Test public void testResolvePutIfAbsentsOnly() { - Operation expected = new PutOperation<>(1L, "Albin", 0L); - Chain chain = getChainFromOperations( + PutOperation expected = new PutOperation<>(1L, "Albin", 0L); + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutIfAbsentOperation<>(1L, "Albin", 0L), new PutIfAbsentOperation<>(1L, "Suresh", 0L), new PutIfAbsentOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(2)); + Store.ValueHolder valueHolder = resolver.resolve(chain, 1L, 0L); + assertThat(valueHolder.get(), is(expected.getValue())); + verify(chain).replaceAtHead(argThat(contains(operation(expected)))); } @Test public void testResolvePutIfAbsentSucceeds() { - Operation expected = new PutOperation<>(1L, "Matthew", 0L); - Chain chain = getChainFromOperations( + PutOperation expected = new PutOperation<>(1L, "Matthew", 0L); + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L), new RemoveOperation<>(1L, 0L), new PutIfAbsentOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - Result result = resolvedChain.getResolvedResult(1L); - assertEquals(expected, result); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(2)); + Store.ValueHolder valueHolder = resolver.resolve(chain, 1L, 0L); + assertThat(valueHolder.get(), is(expected.getValue())); + verify(chain).replaceAtHead(argThat(contains(operation(expected)))); } @Test public void testResolveForSingleOperationDoesNotCompact() { - Chain chain = getChainFromOperations(new PutOperation<>(1L, "Albin", 0L)); + ServerStoreProxy.ChainEntry chain = getEntryFromOperations(new PutOperation<>(1L, "Albin", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - assertThat(resolvedChain.isCompacted(), is(false)); - assertThat(resolvedChain.getCompactionCount(), is(0)); + Store.ValueHolder valueHolder = resolver.resolve(chain, 1L, 0L); + assertThat(valueHolder.get(), is("Albin")); + verify(chain, never()).replaceAtHead(any()); } @Test + @SuppressWarnings("unchecked") public void testResolveForMultiplesOperationsAlwaysCompact() { //create a random mix of operations - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutIfAbsentOperation<>(1L, "Albin", 0L), new PutOperation<>(1L, "Suresh", 0L), new PutOperation<>(1L, "Matthew", 0L), @@ -250,14 +231,18 @@ public void testResolveForMultiplesOperationsAlwaysCompact() { new PutIfAbsentOperation<>(2L, "Albin", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 0L); - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(8)); + Store.ValueHolder valueHolder = resolver.resolve(chain, 1L, 0L); + assertThat(valueHolder, nullValue()); + verify(chain).replaceAtHead(argThat(contains( + operation(new PutOperation<>(2L, "Melvin", 0L)), + operation(new RemoveOperation<>(2L, 0L)), + operation(new PutIfAbsentOperation<>(2L, "Albin", 0L)) + ))); } @Test public void testResolveDoesNotDecodeOtherKeyOperationValues() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(2L, "Albin", 0L), new PutOperation<>(2L, "Suresh", 0L), new PutOperation<>(2L, "Matthew", 0L)); @@ -276,7 +261,7 @@ public void testResolveDoesNotDecodeOtherKeyOperationValues() { @Test public void testResolveDecodesOperationValueOnlyOnDemand() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 1), new PutOperation<>(1L, "Suresh", 2), new PutOperation<>(1L, "Matthew", 3)); @@ -288,7 +273,7 @@ public void testResolveDecodesOperationValueOnlyOnDemand() { resolver.resolve(chain, 1L, 0L); assertThat(keySerializer.decodeCount, is(3)); - assertThat(valueSerializer.decodeCount, is(0)); + assertThat(valueSerializer.decodeCount, is(1)); assertThat(valueSerializer.encodeCount, is(0)); assertThat(keySerializer.encodeCount, is(1)); //One encode from encoding the resolved operation's key } @@ -296,7 +281,7 @@ public void testResolveDecodesOperationValueOnlyOnDemand() { @Test @SuppressWarnings("unchecked") public void testCompactingTwoKeys() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L), new PutOperation<>(2L, "Albin", 0L), new PutOperation<>(1L, "Suresh", 0L), @@ -305,114 +290,114 @@ public void testCompactingTwoKeys() { ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.compactChain(chain, 0L); + resolver.compact(chain); - assertThat(compactedChain, containsInAnyOrder( //@SuppressWarnings("unchecked") + verify(chain).replaceAtHead(argThat(containsInAnyOrder( //@SuppressWarnings("unchecked") operation(new PutOperation<>(2L, "Matthew", 0L)), operation(new PutOperation<>(1L, "Suresh", 0L)) - )); + ))); } @Test public void testCompactEmptyChain() { - Chain chain = (new ChainBuilder()).build(); + ServerStoreProxy.ChainEntry chain = getEntryFromOperations(); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compacted = resolver.compactChain(chain, 0L); - assertThat(compacted, emptyIterable()); + resolver.compact(chain); + verify(chain, never()).replaceAtHead(any()); } @Test public void testCompactSinglePut() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L) ); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compacted = resolver.compactChain(chain, 0L); + resolver.compact(chain); - assertThat(compacted, contains(operation(new PutOperation<>(1L, "Albin", 0L)))); + verify(chain, never()).replaceAtHead(any()); } @Test public void testCompactMultiplePuts() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L), new PutOperation<>(1L, "Suresh", 0L), new PutOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.compactChain(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Matthew", 0L)))); + resolver.compact(chain); + verify(chain).replaceAtHead(argThat(contains(operation(new PutOperation<>(1L, "Matthew", 0L))))); } @Test public void testCompactSingleRemove() { - Chain chain = getChainFromOperations(new RemoveOperation<>(1L, 0L)); + ServerStoreProxy.ChainEntry chain = getEntryFromOperations(new RemoveOperation<>(1L, 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.compactChain(chain, 0L); - assertThat(compactedChain, emptyIterable()); + resolver.compact(chain); + verify(chain).replaceAtHead(argThat(emptyIterable())); } @Test public void testCompactMultipleRemoves() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new RemoveOperation<>(1L, 0L), new RemoveOperation<>(1L, 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.compactChain(chain, 0L); - assertThat(compactedChain, emptyIterable()); + resolver.compact(chain); + verify(chain).replaceAtHead(argThat(emptyIterable())); } @Test public void testCompactPutAndRemove() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L), new RemoveOperation<>(1L, 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.compactChain(chain, 0L); - assertThat(compactedChain, emptyIterable()); + resolver.compact(chain); + verify(chain).replaceAtHead(argThat(emptyIterable())); } @Test public void testCompactSinglePutIfAbsent() { - Chain chain = getChainFromOperations(new PutIfAbsentOperation<>(1L, "Matthew", 0L)); + ServerStoreProxy.ChainEntry chain = getEntryFromOperations(new PutIfAbsentOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.compactChain(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Matthew", 0L)))); + resolver.compact(chain); + verify(chain, never()).replaceAtHead(any()); } @Test public void testCompactMultiplePutIfAbsents() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutIfAbsentOperation<>(1L, "Albin", 0L), new PutIfAbsentOperation<>(1L, "Suresh", 0L), new PutIfAbsentOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.compactChain(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin", 0L)))); + resolver.compact(chain); + verify(chain).replaceAtHead(argThat(contains(operation(new PutOperation<>(1L, "Albin", 0L))))); } @Test public void testCompactPutIfAbsentAfterRemove() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L), new RemoveOperation<>(1L, 0L), new PutIfAbsentOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.compactChain(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Matthew", 0L)))); + resolver.compact(chain); + verify(chain).replaceAtHead(argThat(contains(operation(new PutOperation<>(1L, "Matthew", 0L))))); } @Test public void testCompactForMultipleKeysAndOperations() { //create a random mix of operations - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutIfAbsentOperation<>(1L, "Albin", 0L), new PutOperation<>(1L, "Suresh", 0L), new PutOperation<>(1L, "Matthew", 0L), @@ -426,27 +411,27 @@ public void testCompactForMultipleKeysAndOperations() { new PutIfAbsentOperation<>(2L, "Albin", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.compactChain(chain, 0L); - assertThat(compactedChain, contains(operation(new PutOperation<>(2L, "Albin", 0L)))); + resolver.compact(chain); + verify(chain).replaceAtHead(argThat(contains(operation(new PutOperation<>(2L, "Albin", 0L))))); } @Test public void testCompactHasCorrectTimeStamp() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0), new PutOperation<>(1L, "Albin", 1), new RemoveOperation<>(1L, 2), new PutOperation<>(1L, "Albin", 3)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Chain compactedChain = resolver.compactChain(chain, 3); + resolver.compact(chain); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin", 3)))); + verify(chain).replaceAtHead(argThat(contains(operation(new PutOperation<>(1L, "Albin", 3))))); } @Test public void testCompactDecodesOperationValueOnlyOnDemand() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 1), new PutOperation<>(1L, "Suresh", 2), new PutOperation<>(1L, "Matthew", 3)); @@ -455,7 +440,7 @@ public void testCompactDecodesOperationValueOnlyOnDemand() { CountingStringSerializer valueSerializer = new CountingStringSerializer(); OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration(), customCodec); - resolver.compactChain(chain, 0L); + resolver.compact(chain); assertThat(keySerializer.decodeCount, is(3)); //Three decodes: one for each operation assertThat(keySerializer.encodeCount, is(1)); //One encode from encoding the resolved operation's key @@ -467,7 +452,7 @@ public void testCompactDecodesOperationValueOnlyOnDemand() { @Test @SuppressWarnings("unchecked") public void testResolvingTwoKeys() { - Chain chain = getChainFromOperations( + Chain chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L), new PutOperation<>(2L, "Albin", 0L), new PutOperation<>(1L, "Suresh", 0L), @@ -476,112 +461,112 @@ public void testResolvingTwoKeys() { ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Map> resolved = resolver.resolveChain(chain, 0L); + Map> resolved = resolver.resolveAll(chain, 0L); - assertThat(resolved, hasEntry(2L, new PutOperation<>(2L, "Matthew", 0L))); - assertThat(resolved, hasEntry(1L, new PutOperation<>(1L, "Suresh", 0L))); + assertThat(resolved.get(1L).get(), is("Suresh")); + assertThat(resolved.get(2L).get(), is("Matthew")); } @Test public void testFullResolveEmptyChain() { Chain chain = (new ChainBuilder()).build(); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Map> resolved = resolver.resolveChain(chain, 0L); + Map> resolved = resolver.resolveAll(chain, 0L); assertThat(resolved, is(emptyMap())); } @Test public void testFullResolveSinglePut() { - Chain chain = getChainFromOperations( + Chain chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L) ); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Map> resolved = resolver.resolveChain(chain, 0L); + Map> resolved = resolver.resolveAll(chain, 0L); - assertThat(resolved, hasEntry(1L, new PutOperation<>(1L, "Albin", 0L))); + assertThat(resolved.get(1L).get(), is("Albin")); } @Test public void testFullResolveMultiplePuts() { - Chain chain = getChainFromOperations( + Chain chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L), new PutOperation<>(1L, "Suresh", 0L), new PutOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Map> resolved = resolver.resolveChain(chain, 0L); - assertThat(resolved, hasEntry(1L, new PutOperation<>(1L, "Matthew", 0L))); + Map> resolved = resolver.resolveAll(chain, 0L); + assertThat(resolved.get(1L).get(), is("Matthew")); } @Test public void testFullResolveSingleRemove() { - Chain chain = getChainFromOperations(new RemoveOperation<>(1L, 0L)); + Chain chain = getEntryFromOperations(new RemoveOperation<>(1L, 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Map> resolved = resolver.resolveChain(chain, 0L); + Map> resolved = resolver.resolveAll(chain, 0L); assertThat(resolved, is(emptyMap())); } @Test public void testFullResolveMultipleRemoves() { - Chain chain = getChainFromOperations( + Chain chain = getEntryFromOperations( new RemoveOperation<>(1L, 0L), new RemoveOperation<>(1L, 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Map> resolved = resolver.resolveChain(chain, 0L); + Map> resolved = resolver.resolveAll(chain, 0L); assertThat(resolved, is(emptyMap())); } @Test public void testFullResolvePutAndRemove() { - Chain chain = getChainFromOperations( + Chain chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L), new RemoveOperation<>(1L, 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Map> resolved = resolver.resolveChain(chain, 0L); + Map> resolved = resolver.resolveAll(chain, 0L); assertThat(resolved, is(emptyMap())); } @Test public void testFullResolveSinglePutIfAbsent() { - Chain chain = getChainFromOperations(new PutIfAbsentOperation<>(1L, "Matthew", 0L)); + Chain chain = getEntryFromOperations(new PutIfAbsentOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Map> resolved = resolver.resolveChain(chain, 0L); - assertThat(resolved, hasEntry(1L, new PutOperation<>(1L, "Matthew", 0L))); + Map> resolved = resolver.resolveAll(chain, 0L); + assertThat(resolved.get(1L).get(), is("Matthew")); } @Test public void testFullResolveMultiplePutIfAbsents() { - Chain chain = getChainFromOperations( + Chain chain = getEntryFromOperations( new PutIfAbsentOperation<>(1L, "Albin", 0L), new PutIfAbsentOperation<>(1L, "Suresh", 0L), new PutIfAbsentOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Map> resolved = resolver.resolveChain(chain, 0L); - assertThat(resolved, hasEntry(1L, new PutOperation<>(1L, "Albin", 0L))); + Map> resolved = resolver.resolveAll(chain, 0L); + assertThat(resolved.get(1L).get(), is("Albin")); } @Test public void testFullResolvePutIfAbsentAfterRemove() { - Chain chain = getChainFromOperations( + Chain chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0L), new RemoveOperation<>(1L, 0L), new PutIfAbsentOperation<>(1L, "Matthew", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Map> resolved = resolver.resolveChain(chain, 0L); - assertThat(resolved, hasEntry(1L, new PutOperation<>(1L, "Matthew", 0L))); + Map> resolved = resolver.resolveAll(chain, 0L); + assertThat(resolved.get(1L).get(), is("Matthew")); } @Test public void testFullResolveForMultipleKeysAndOperations() { //create a random mix of operations - Chain chain = getChainFromOperations( + Chain chain = getEntryFromOperations( new PutIfAbsentOperation<>(1L, "Albin", 0L), new PutOperation<>(1L, "Suresh", 0L), new PutOperation<>(1L, "Matthew", 0L), @@ -595,52 +580,41 @@ public void testFullResolveForMultipleKeysAndOperations() { new PutIfAbsentOperation<>(2L, "Albin", 0L)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Map> resolved = resolver.resolveChain(chain, 0L); - assertThat(resolved, hasEntry(2L, new PutOperation<>(2L, "Albin", 0L))); + Map> resolved = resolver.resolveAll(chain, 0L); + assertThat(resolved.get(2L).get(), is("Albin")); } @Test public void testFullResolveHasCorrectTimeStamp() { - Chain chain = getChainFromOperations( + Chain chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 0), new PutOperation<>(1L, "Albin", 1), new RemoveOperation<>(1L, 2), new PutOperation<>(1L, "Albin", 3)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); - Map> resolved = resolver.resolveChain(chain, 3); + Map> resolved = resolver.resolveAll(chain, 3); - assertThat(resolved, hasEntry(1L, new PutOperation<>(1L, "Albin", 3))); + assertThat(resolved.get(1L).get(), is("Albin")); } @Test public void testResolveForMultipleOperationHasCorrectIsFirstAndTimeStamp() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin1", 0), new PutOperation<>(1L, "Albin2", 1), new RemoveOperation<>(1L, 2), new PutOperation<>(1L, "AlbinAfterRemove", 3)); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofHours(1))); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 3); - - Operation operation = codec.decode(resolvedChain.getCompactedChain().iterator().next().getPayload()); - - assertThat(operation.isExpiryAvailable(), is(true)); - assertThat(operation.expirationTime(), is(TimeUnit.HOURS.toMillis(1) + 3)); - try { - operation.timeStamp(); - fail(); - } catch (Exception ex) { - assertThat(ex.getMessage(), is("Timestamp not available")); - } - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(3)); + Store.ValueHolder valueHolder = resolver.resolve(chain, 1L, 3); + assertThat(valueHolder.get(), is("AlbinAfterRemove")); + verify(chain).replaceAtHead(argThat(contains(operation(new PutOperation<>(1L, "AlbinAfterRemove", TimeUnit.HOURS.toMillis(1) + 3))))); } @Test public void testResolveForMultipleOperationHasCorrectIsFirstAndTimeStampWithExpiry() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin1", 0L), new PutOperation<>(1L, "Albin2", 1L), new PutOperation<>(1L, "Albin3", 2L), @@ -648,26 +622,15 @@ public void testResolveForMultipleOperationHasCorrectIsFirstAndTimeStampWithExpi ); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(1L))); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 3L); - - Operation operation = codec.decode(resolvedChain.getCompactedChain().iterator().next().getPayload()); + Store.ValueHolder valueHolder = resolver.resolve(chain, 1L, 3L); - assertThat(operation.isExpiryAvailable(), is(true)); - assertThat(operation.expirationTime(), is(4L)); - - try { - operation.timeStamp(); - fail(); - } catch (Exception ex) { - assertThat(ex.getMessage(), is("Timestamp not available")); - } - assertThat(resolvedChain.isCompacted(), is(true)); - assertThat(resolvedChain.getCompactionCount(), is(3)); + assertThat(valueHolder.get(), is("Albin4")); + verify(chain).replaceAtHead(argThat(contains(operation(new PutOperation<>(1L, "Albin4", 4L))))); } @Test public void testCompactHasCorrectWithExpiry() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin1", 0L), new PutOperation<>(1L, "Albin2", 1L), new PutOperation<>(1L, "Albin3", 2L), @@ -675,22 +638,63 @@ public void testCompactHasCorrectWithExpiry() { ); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(1L))); - Chain compactedChain = resolver.compactChain(chain, 3L); + resolver.compact(chain); - assertThat(compactedChain, contains(operation(new PutOperation<>(1L, "Albin4", 3L)))); + verify(chain).replaceAtHead(argThat(contains(operation(new PutOperation<>(1L, "Albin4", 3L))))); } protected ChainResolver createChainResolver(ExpiryPolicy expiryPolicy) { return createChainResolver(expiryPolicy, codec); } + @Test + public void testNonExpiringTimestampIsCleared() throws TimeoutException { + PutOperation expected = new PutOperation<>(1L, "Albin", 0L); + ServerStoreProxy.ChainEntry chain = getEntryFromOperations(expected, + new TimestampOperation<>(1L, 1L) + ); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration()); + + assertThat(resolver.resolve(chain, 1L, 2L).get(), is("Albin")); + verify(chain).replaceAtHead(argThat(contains(operation(expected)))); + } + + @SafeVarargs - protected final Chain getChainFromOperations(Operation ... operations) { + protected final ServerStoreProxy.ChainEntry getEntryFromOperations(Operation ... operations) { ChainBuilder chainBuilder = new ChainBuilder(); for(Operation operation: operations) { chainBuilder = chainBuilder.add(codec.encode(operation)); } - return chainBuilder.build(); + Chain chain = chainBuilder.build(); + return spy(new ServerStoreProxy.ChainEntry(){ + + @Override + public Iterator iterator() { + return chain.iterator(); + } + + @Override + public void append(ByteBuffer payLoad) throws TimeoutException { + //nothing + } + + @Override + public void replaceAtHead(Chain equivalent) { + //nothing + } + + @Override + public boolean isEmpty() { + return chain.isEmpty(); + } + + @Override + public int length() { + return chain.length(); + } + }); } protected List> getOperationsListFromChain(Chain chain) { @@ -702,7 +706,7 @@ protected List> getOperationsListFromChain(Chain chain) return list; } - private Matcher operation(Operation operation) { + protected Matcher operation(Operation operation) { return new TypeSafeMatcher() { @Override protected boolean matchesSafely(Element item) { @@ -716,6 +720,20 @@ public void describeTo(Description description) { }; } + protected Matcher binaryOperation(Operation operation) { + return new TypeSafeMatcher() { + @Override + protected boolean matchesSafely(ByteBuffer item) { + return operation.equals(codec.decode(item.duplicate())); + } + + @Override + public void describeTo(Description description) { + description.appendText("is ").appendValue(operation); + } + }; + } + protected static class CountingLongSerializer extends LongSerializer { protected int encodeCount = 0; @@ -761,4 +779,13 @@ public boolean equals(final String object, final ByteBuffer binary) throws Class return super.equals(object, binary); } } + + T argThat(Matcher matches) { + return ArgumentMatchers.argThat(new ArgumentMatcher() { + @Override + public boolean matches(T argument) { + return matches.matches(argument); + } + }); + } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java index 93758290f2..a6d7ee5c10 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java @@ -17,33 +17,32 @@ package org.ehcache.clustered.common.internal.store.operations; import org.ehcache.clustered.client.TestTimeSource; -import org.ehcache.clustered.client.internal.store.ResolvedChain; +import org.ehcache.clustered.client.internal.store.ServerStoreProxy; import org.ehcache.clustered.client.internal.store.operations.ChainResolver; import org.ehcache.clustered.client.internal.store.operations.ExpiryChainResolver; -import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; import org.ehcache.config.builders.ExpiryPolicyBuilder; +import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.time.TimeSource; -import org.ehcache.expiry.Expirations; import org.ehcache.expiry.ExpiryPolicy; import org.junit.Test; import org.mockito.InOrder; -import java.time.Duration; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import static java.time.Duration.ofMillis; -import static java.util.Arrays.asList; import static org.ehcache.config.builders.ExpiryPolicyBuilder.timeToLiveExpiration; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.emptyIterable; import static org.hamcrest.Matchers.is; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -58,7 +57,7 @@ protected ChainResolver createChainResolver(ExpiryPolicy(1L, "Albin", 1), new PutOperation<>(1L, "Suresh", 2), new PutOperation<>(1L, "Matthew", 3)); @@ -67,7 +66,7 @@ public void testCompactDecodesOperationValueOnlyOnDemand() { CountingStringSerializer valueSerializer = new CountingStringSerializer(); OperationsCodec customCodec = new OperationsCodec<>(keySerializer, valueSerializer); ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.noExpiration(), customCodec); - resolver.compactChain(chain, 0L); + resolver.compact(chain); assertThat(keySerializer.decodeCount, is(3)); assertThat(valueSerializer.decodeCount, is(3)); @@ -77,7 +76,7 @@ public void testCompactDecodesOperationValueOnlyOnDemand() { @Test @Override public void testResolveDecodesOperationValueOnlyOnDemand() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Albin", 1), new PutOperation<>(1L, "Suresh", 2), new PutOperation<>(1L, "Matthew", 3)); @@ -104,18 +103,18 @@ public void testGetExpiryForAccessIsIgnored() { when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "One", timeSource.getTimeMillis()), new PutOperation<>(1L, "Second", timeSource.getTimeMillis()) ); - ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); + Store.ValueHolder valueHolder = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); verify(expiry, times(0)).getExpiryForAccess(anyLong(), any()); verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); verify(expiry, times(1)).getExpiryForUpdate(anyLong(), any(), anyString()); - assertThat(resolvedChain.isCompacted(), is(true)); + verify(chain).replaceAtHead(any()); } @Test @@ -127,21 +126,21 @@ public void testGetExpiryForCreationIsInvokedOnlyOnce() { when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "One", timeSource.getTimeMillis()), new PutOperation<>(1L, "Second", timeSource.getTimeMillis()), new PutOperation<>(1L, "Three", timeSource.getTimeMillis()), new PutOperation<>(1L, "Four", timeSource.getTimeMillis()) ); - ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); + Store.ValueHolder valueHolder = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); InOrder inOrder = inOrder(expiry); inOrder.verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); inOrder.verify(expiry, times(3)).getExpiryForUpdate(anyLong(), any(), anyString()); - assertThat(resolvedChain.isCompacted(), is(true)); + verify(chain).replaceAtHead(any()); } @Test @@ -154,18 +153,18 @@ public void testGetExpiryForCreationIsNotInvokedForReplacedChains() { when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Replaced", -10L), new PutOperation<>(1L, "SecondAfterReplace", timeSource.getTimeMillis()), new PutOperation<>(1L, "ThirdAfterReplace", timeSource.getTimeMillis()), new PutOperation<>(1L, "FourthAfterReplace", timeSource.getTimeMillis()) ); - ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); + Store.ValueHolder valueHolder = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); verify(expiry, times(0)).getExpiryForCreation(anyLong(), anyString()); verify(expiry, times(3)).getExpiryForUpdate(anyLong(), any(), anyString()); - assertThat(resolvedChain.isCompacted(), is(true)); + verify(chain).replaceAtHead(any()); } @Test @@ -178,14 +177,14 @@ public void testGetExpiryForCreationIsInvokedAfterRemoveOperations() { when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - Chain replacedChain = getChainFromOperations( + ServerStoreProxy.ChainEntry chainA = getEntryFromOperations( new PutOperation<>(1L, "Replaced", 10L), new PutOperation<>(1L, "SecondAfterReplace", 3L), new RemoveOperation<>(1L, 4L), new PutOperation<>(1L, "FourthAfterReplace", 5L) ); - ResolvedChain resolvedChain = chainResolver.resolve(replacedChain, 1L, timeSource.getTimeMillis()); + Store.ValueHolder valueHolder = chainResolver.resolve(chainA, 1L, timeSource.getTimeMillis()); InOrder inOrder = inOrder(expiry); @@ -194,21 +193,21 @@ public void testGetExpiryForCreationIsInvokedAfterRemoveOperations() { inOrder.verify(expiry, times(1)).getExpiryForUpdate(anyLong(), any(), anyString()); inOrder.verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); - assertThat(resolvedChain.isCompacted(), is(true)); + verify(chainA).replaceAtHead(any()); reset(expiry); when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(ExpiryPolicy.INFINITE); - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chainB = getEntryFromOperations( new PutOperation<>(1L, "One", timeSource.getTimeMillis()), new PutOperation<>(1L, "Second", timeSource.getTimeMillis()), new RemoveOperation<>(1L, timeSource.getTimeMillis()), new PutOperation<>(1L, "Four", timeSource.getTimeMillis()) ); - chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); + chainResolver.resolve(chainB, 1L, timeSource.getTimeMillis()); inOrder = inOrder(expiry); @@ -217,7 +216,7 @@ public void testGetExpiryForCreationIsInvokedAfterRemoveOperations() { inOrder.verify(expiry, times(1)).getExpiryForUpdate(anyLong(), any(), anyString()); inOrder.verify(expiry, times(1)).getExpiryForCreation(anyLong(), anyString()); - assertThat(resolvedChain.isCompacted(), is(true)); + verify(chainB).replaceAtHead(any()); } @Test @@ -229,12 +228,12 @@ public void testNullGetExpiryForCreation() { when(expiry.getExpiryForCreation(anyLong(), anyString())).thenReturn(null); - Chain chain = getChainFromOperations(new PutOperation<>(1L, "Replaced", 10L)); + ServerStoreProxy.ChainEntry chain = getEntryFromOperations(new PutOperation<>(1L, "Replaced", 10L)); - ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); + Store.ValueHolder valueHolder = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - assertTrue(resolvedChain.getCompactedChain().isEmpty()); - assertThat(resolvedChain.isCompacted(), is(true)); + assertThat(valueHolder, nullValue()); + verify(chain, never()).replaceAtHead(any()); } @Test @@ -246,17 +245,16 @@ public void testNullGetExpiryForUpdate() { when(expiry.getExpiryForUpdate(anyLong(), any(), anyString())).thenReturn(null); - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Replaced", -10L), new PutOperation<>(1L, "New", timeSource.getTimeMillis()) ); - ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); + Store.ValueHolder resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - assertThat(resolvedChain.getResolvedResult(1L).getValue(), is("New")); - assertTrue(getOperationsListFromChain(resolvedChain.getCompactedChain()).get(0).isExpiryAvailable()); - assertThat(getOperationsListFromChain(resolvedChain.getCompactedChain()).get(0).expirationTime(), is(10L)); - assertThat(resolvedChain.isCompacted(), is(true)); + assertThat(resolvedChain.get(), is("New")); + + verify(chain).replaceAtHead(argThat(contains(operation(new PutOperation<>(1L, "New", -10L))))); } @Test @@ -268,17 +266,15 @@ public void testGetExpiryForUpdateUpdatesExpirationTimeStamp() { when(expiry.getExpiryForUpdate(anyLong(), any(), anyString())).thenReturn(ofMillis(2L)); - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "Replaced", -10L), new PutOperation<>(1L, "New", timeSource.getTimeMillis()) ); - ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); + Store.ValueHolder valueHolder = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - assertThat(resolvedChain.getResolvedResult(1L).getValue(), is("New")); - assertTrue(getOperationsListFromChain(resolvedChain.getCompactedChain()).get(0).isExpiryAvailable()); - assertThat(getOperationsListFromChain(resolvedChain.getCompactedChain()).get(0).expirationTime(), is(2L)); - assertThat(resolvedChain.isCompacted(), is(true)); + assertThat(valueHolder.get(), is("New")); + verify(chain).replaceAtHead(argThat(contains(operation(new PutOperation<>(1L, "New", -2L))))); } @Test @@ -291,38 +287,62 @@ public void testExpiryThrowsException() { when(expiry.getExpiryForUpdate(anyLong(), any(), anyString())).thenThrow(new RuntimeException("Test Update Expiry")); when(expiry.getExpiryForCreation(anyLong(), anyString())).thenThrow(new RuntimeException("Test Create Expiry")); - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation<>(1L, "One", -10L), new PutOperation<>(1L, "Two", timeSource.getTimeMillis()) ); - ResolvedChain resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); + Store.ValueHolder valueHolder = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - assertThat(resolvedChain.getResolvedResult(1L), nullValue()); + assertThat(valueHolder, nullValue()); - chain = getChainFromOperations( + chain = getEntryFromOperations( new PutOperation<>(1L, "One", timeSource.getTimeMillis()), new PutOperation<>(1L, "Two", timeSource.getTimeMillis()) ); - resolvedChain = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); + valueHolder = chainResolver.resolve(chain, 1L, timeSource.getTimeMillis()); - assertThat(resolvedChain.getResolvedResult(1L), nullValue()); + assertThat(valueHolder, nullValue()); - assertThat(resolvedChain.isCompacted(), is(true)); + verify(chain).replaceAtHead(any()); } @Test public void testResolveExpiresUsingOperationTime() { - Chain chain = getChainFromOperations( + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( new PutOperation(1L, "Albin", 0), new PutIfAbsentOperation(1L, "Chris", 900) ); ChainResolver resolver = createChainResolver(timeToLiveExpiration(ofMillis(1000))); - ResolvedChain resolvedChain = resolver.resolve(chain, 1L, 1500); - Result result = resolvedChain.getResolvedResult(1L); - assertThat(result.getValue(), nullValue()); + Store.ValueHolder result = resolver.resolve(chain, 1L, 1500); + assertThat(result, nullValue()); + } + + @Test + public void testExpiredResolvedValueAddsTimestamp() throws TimeoutException { + ServerStoreProxy.ChainEntry chain = getEntryFromOperations(new PutOperation<>(1L, "Albin", 0L)); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.timeToLiveExpiration(ofMillis(1000))); + + assertThat(resolver.resolve(chain, 1L, 1001L), nullValue()); + verify(chain).append(argThat(binaryOperation(new TimestampOperation<>(1L, 1001L)))); + verify(chain, never()).replaceAtHead(any()); + + } + + @Test + public void testExpiredTimestampClearsChain() { + PutOperation expected = new PutOperation<>(1L, "Albin", 0L); + ServerStoreProxy.ChainEntry chain = getEntryFromOperations(expected, + new TimestampOperation<>(1L, 1000L) + ); + + ChainResolver resolver = createChainResolver(ExpiryPolicyBuilder.timeToLiveExpiration(ofMillis(1000))); + + assertThat(resolver.resolve(chain, 1L, 999L), nullValue()); + verify(chain).replaceAtHead(argThat(emptyIterable())); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperationTest.java new file mode 100644 index 0000000000..1b72b22d4f --- /dev/null +++ b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperationTest.java @@ -0,0 +1,97 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered.common.internal.store.operations; + +import org.ehcache.clustered.client.TestTimeSource; +import org.ehcache.impl.serialization.LongSerializer; +import org.ehcache.impl.serialization.StringSerializer; +import org.ehcache.spi.serialization.Serializer; +import org.junit.Test; + +import java.nio.ByteBuffer; + +import static org.ehcache.clustered.common.internal.store.operations.Operation.BYTE_SIZE_BYTES; +import static org.ehcache.clustered.common.internal.store.operations.Operation.LONG_SIZE_BYTES; +import static org.hamcrest.core.IsNull.nullValue; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; + +public class TimestampOperationTest { + + private static final Serializer keySerializer = new LongSerializer(); + private static final Serializer valueSerializer = new StringSerializer(); + + private static final TestTimeSource TIME_SOURCE = new TestTimeSource(); + + @Test + public void testEncode() throws Exception { + Long key = 12L; + TimestampOperation operation = new TimestampOperation<>(key, TIME_SOURCE.getTimeMillis()); + ByteBuffer byteBuffer = operation.encode(keySerializer, valueSerializer); + + ByteBuffer expected = ByteBuffer.allocate(BYTE_SIZE_BYTES + 2 * LONG_SIZE_BYTES); + expected.put(OperationCode.TIMESTAMP.getValue()); + expected.putLong(TIME_SOURCE.getTimeMillis()); + expected.putLong(key); + expected.flip(); + assertArrayEquals(expected.array(), byteBuffer.array()); + } + + @Test + public void testDecode() throws Exception { + Long key = 12L; + ByteBuffer blob = ByteBuffer.allocate(BYTE_SIZE_BYTES + 2 * LONG_SIZE_BYTES); + blob.put(OperationCode.TIMESTAMP.getValue()); + blob.putLong(TIME_SOURCE.getTimeMillis()); + blob.putLong(key); + blob.flip(); + + TimestampOperation operation = new TimestampOperation<>(blob, keySerializer); + assertEquals(key, operation.getKey()); + } + + @Test + public void testEncodeDecodeInvariant() throws Exception { + Long key = 12L; + TimestampOperation operation = new TimestampOperation<>(key, System.currentTimeMillis()); + + TimestampOperation decodedOperation = + new TimestampOperation<>(operation.encode(keySerializer, valueSerializer), keySerializer); + assertEquals(key, decodedOperation.getKey()); + } + + @Test(expected = IllegalArgumentException.class) + public void testDecodeThrowsOnInvalidType() throws Exception { + ByteBuffer buffer = ByteBuffer.wrap(new byte[] {10}); + new TimestampOperation(buffer, keySerializer); + } + + @Test + public void testApply() throws Exception { + TimestampOperation operation = new TimestampOperation<>(1L, System.currentTimeMillis()); + + Result result = operation.apply(null); + assertThat(result, nullValue()); + + PutOperation anotherOperation = new PutOperation<>(1L, "another one", System.currentTimeMillis()); + result = operation.apply(anotherOperation); + assertThat(result, sameInstance(anotherOperation)); + } +} diff --git a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java index 214fde795e..4777934eb2 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java @@ -78,11 +78,10 @@ public void testBasicClusteredWriteBehind() { try (PersistentCacheManager cacheManager = createCacheManager()) { Cache cache = cacheManager.getCache(CACHE_NAME, Long.class, String.class); - for (int i = 0; i < 10; i++) { - put(cache, String.valueOf(i)); - } + put(cache, String.valueOf(0)); + put(cache, String.valueOf(1)); - assertValue(cache, String.valueOf(9)); + assertValue(cache, String.valueOf(1)); verifyRecords(cache); cache.clear(); diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/OperationCode.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/OperationCode.java index 4ee3277644..7515a387b7 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/OperationCode.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/OperationCode.java @@ -68,6 +68,12 @@ public Operation decode(final ByteBuffer buffer, final Serializer Operation decode(ByteBuffer buffer, Serializer keySerializer, Serializer valueSerializer) { return new PutWithWriterOperation<>(buffer, keySerializer, valueSerializer); } + }, + TIMESTAMP((byte)8) { + @Override + public Operation decode(ByteBuffer buffer, Serializer keySerializer, Serializer valueSerializer) { + return new TimestampOperation<>(buffer, keySerializer); + } }; private final byte value; @@ -102,6 +108,8 @@ public static OperationCode valueOf(byte value) { return REPLACE_CONDITIONAL; case 7: return PUT_WITH_WRITER; + case 8: + return TIMESTAMP; default: throw new IllegalArgumentException("Operation undefined for the value " + value); } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperation.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperation.java new file mode 100644 index 0000000000..ad34af91b0 --- /dev/null +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperation.java @@ -0,0 +1,138 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered.common.internal.store.operations; + +import org.ehcache.clustered.common.internal.store.operations.codecs.CodecException; +import org.ehcache.spi.serialization.Serializer; + +import java.nio.ByteBuffer; + +import static java.util.Objects.requireNonNull; + +public class TimestampOperation implements Operation { + + private final K key; + private final long timeStamp; + + public TimestampOperation(final K key, final long timeStamp) { + this.key = requireNonNull(key); + this.timeStamp = timeStamp; + } + + TimestampOperation(final ByteBuffer buffer, final Serializer keySerializer) { + OperationCode opCode = OperationCode.valueOf(buffer.get()); + if (opCode != getOpCode()) { + throw new IllegalArgumentException("Invalid operation: " + opCode); + } + this.timeStamp = buffer.getLong(); + ByteBuffer keyBlob = buffer.slice(); + try { + this.key = keySerializer.read(keyBlob); + } catch (ClassNotFoundException e) { + throw new CodecException(e); + } + } + + public K getKey() { + return key; + } + + @Override + public OperationCode getOpCode() { + return OperationCode.TIMESTAMP; + } + + /** + * Timestamp operation is a no-op - it only exists to establish a wall-time in the chain. + */ + @Override + public Result apply(final Result previousOperation) { + return previousOperation; + } + + @Override + public ByteBuffer encode(final Serializer keySerializer, final Serializer valueSerializer) { + ByteBuffer keyBuf = keySerializer.serialize(key); + + int size = BYTE_SIZE_BYTES + // Operation type + LONG_SIZE_BYTES + // Size of expiration time stamp + keyBuf.remaining(); // the key payload itself + + ByteBuffer buffer = ByteBuffer.allocate(size); + buffer.put(getOpCode().getValue()); + buffer.putLong(this.timeStamp); + buffer.put(keyBuf); + buffer.flip(); + return buffer; + } + + @Override + public String toString() { + return "{" + getOpCode() + "# key: " + key + "}"; + } + + @Override + public boolean equals(final Object obj) { + if(obj == null) { + return false; + } + if(!(obj instanceof TimestampOperation)) { + return false; + } + + @SuppressWarnings("unchecked") + TimestampOperation other = (TimestampOperation) obj; + if(this.getOpCode() != other.getOpCode()) { + return false; + } + if(!this.getKey().equals(other.getKey())) { + return false; + } + return true; + } + + @Override + public int hashCode() { + int hash = getOpCode().hashCode(); + hash = hash * 31 + key.hashCode(); + return hash; + } + + @Override + public long timeStamp() { + if (!isExpiryAvailable()) { + return this.timeStamp; + } else { + throw new RuntimeException("Timestamp not available"); + } + } + + @Override + public boolean isExpiryAvailable() { + return timeStamp < 0; + } + + @Override + public long expirationTime() { + if (isExpiryAvailable()) { + return - this.timeStamp; + } else { + throw new RuntimeException("Expiry not available"); + } + } + +} diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/util/ChainBuilder.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/util/ChainBuilder.java index 8f614bac15..0dd9ff8f0a 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/util/ChainBuilder.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/util/ChainBuilder.java @@ -43,6 +43,10 @@ public Chain build() { return chainFromList(elements); } + public int length() { + return buffers.size(); + } + public static Chain chainFromList(List elements) { return new Chain() { @Override diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java index f27143201e..7e6be02a7c 100755 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java @@ -62,7 +62,7 @@ public void countTest() throws Exception { // please leave it there - it's really useful to see what's coming /*System.out.println("stats:"); - for (Map.Entry> entry : stat.getStatistics().entrySet()) { + for (Map.ChainEntry> entry : stat.getStatistics().entrySet()) { System.out.println(" - " + entry.getKey() + " : " + entry.getValue()); }*/ From 517ce3f0d79b7ecf38f90d8fe09f3e6124e64f40 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 17 Apr 2019 14:38:38 -0400 Subject: [PATCH 128/372] Fixes #2638 : Check for expiry correctly during resolveAll --- .../store/operations/ExpiryChainResolver.java | 4 +++- .../operations/ExpiryChainResolverTest.java | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java index a37caa1015..8683edbcc3 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java @@ -86,7 +86,9 @@ public Map> resolveAll(Chain chain, long now) { Map> values = new HashMap<>(resolved.size()); for (Map.Entry> e : resolved.entrySet()) { - values.put(e.getKey(), new ClusteredValueHolder<>(e.getValue().getValue(), e.getValue().expirationTime())); + if (now < e.getValue().expirationTime()) { + values.put(e.getKey(), new ClusteredValueHolder<>(e.getValue().getValue(), e.getValue().expirationTime())); + } } return unmodifiableMap(values); } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java index a6d7ee5c10..b734c4312f 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java @@ -28,9 +28,11 @@ import org.junit.Test; import org.mockito.InOrder; +import java.util.Map; import java.util.concurrent.TimeoutException; import static java.time.Duration.ofMillis; +import static java.util.Collections.emptyMap; import static org.ehcache.config.builders.ExpiryPolicyBuilder.timeToLiveExpiration; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.emptyIterable; @@ -321,6 +323,20 @@ public void testResolveExpiresUsingOperationTime() { assertThat(result, nullValue()); } + @Test + public void testResolveAllExpiresUsingOperationTime() { + ServerStoreProxy.ChainEntry chain = getEntryFromOperations( + new PutOperation<>(1L, "Albin", 0), + new PutIfAbsentOperation<>(1L, "Chris", 900) + ); + + ChainResolver resolver = createChainResolver(timeToLiveExpiration(ofMillis(1000))); + + Map> result = resolver.resolveAll(chain, 1500); + + assertThat(result, is(emptyMap())); + } + @Test public void testExpiredResolvedValueAddsTimestamp() throws TimeoutException { ServerStoreProxy.ChainEntry chain = getEntryFromOperations(new PutOperation<>(1L, "Albin", 0L)); From 754aab455f9c4734dd01491996dce6452d757d28 Mon Sep 17 00:00:00 2001 From: Venkata Sairam Madduri Date: Mon, 6 May 2019 15:34:26 +0530 Subject: [PATCH 129/372] version bump --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 6853c57ee2..616370f8f7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.2 +terracottaPlatformVersion = 5.7.3-pre1 terracottaApisVersion = 1.6.1 -terracottaCoreVersion = 5.6.3 +terracottaCoreVersion = 5.6.4-pre1 terracottaPassthroughTestingVersion = 1.6.1 # Test lib versions From 1ee5ac9339f9e30bf00f53104235ea9f59f4db3c Mon Sep 17 00:00:00 2001 From: Ludovic Orban Date: Thu, 4 Apr 2019 13:38:56 +0200 Subject: [PATCH 130/372] implement clustered events --- .../ClusteredLoaderWriterStore.java | 13 +- .../ClusteredWriteBehindStore.java | 22 +- .../store/ClusterTierClientEntity.java | 2 + .../client/internal/store/ClusteredStore.java | 187 ++++++++- .../store/CommonServerStoreProxy.java | 22 +- .../store/EventualServerStoreProxy.java | 5 + .../store/ReconnectingServerStoreProxy.java | 13 + .../internal/store/ServerStoreProxy.java | 17 +- .../store/SimpleClusterTierClientEntity.java | 14 +- .../store/StrongServerStoreProxy.java | 5 + .../lock/LockingServerStoreProxyImpl.java | 5 + .../store/operations/ChainResolver.java | 13 +- ...edCombinationsWithClusteredCacheTest.java} | 36 +- .../store/AbstractServerStoreProxyTest.java | 15 + .../store/ClusteredStoreEventsTest.java | 365 ++++++++++++++++++ .../internal/store/ClusteredStoreTest.java | 39 +- .../store/CommonServerStoreProxyTest.java | 248 ++++++++++-- .../store/EventualServerStoreProxyTest.java | 67 ++-- ...ltiThreadedStrongServerStoreProxyTest.java | 9 +- .../store/StrongServerStoreProxyTest.java | 111 ++++-- .../common/internal/messages/ChainCodec.java | 5 + .../messages/ClusterTierReconnectMessage.java | 11 +- .../messages/EhcacheEntityResponse.java | 42 +- .../internal/messages/EhcacheMessageType.java | 4 +- .../messages/EhcacheResponseType.java | 5 +- .../messages/ReconnectMessageCodec.java | 9 +- .../internal/messages/ResponseCodec.java | 90 +++-- .../internal/messages/ServerStoreOpCodec.java | 14 + .../messages/ServerStoreOpMessage.java | 18 + .../ConditionalReplaceOperation.java | 2 +- .../messages/ReconnectMessageCodecTest.java | 2 +- .../internal/messages/ResponseCodecTest.java | 30 +- .../messages/ServerStoreOpCodecTest.java | 10 + clustered/integration-test/build.gradle | 1 + .../clustered/EventsFailureBehaviorTest.java | 218 +++++++++++ .../reconnect/EventsReconnectTest.java | 179 +++++++++ .../server/ServerSideServerStore.java | 3 +- .../server/ServerStoreEventListener.java | 48 +++ .../server/ServerStoreEvictionListener.java | 30 -- .../clustered/server/ServerStoreImpl.java | 10 +- .../server/offheap/InternalChain.java | 2 + .../server/offheap/OffHeapChainMap.java | 4 +- .../server/offheap/OffHeapServerStore.java | 58 ++- .../server/store/ClusterTierActiveEntity.java | 93 ++++- .../offheap/OffHeapServerStoreTest.java | 119 ++++++ .../store/ClusterTierActiveEntityTest.java | 69 +++- .../asciidoc/developer/clustered-events.adoc | 82 ++++ .../events/AbstractStoreEventDispatcher.java | 7 +- .../impl/internal/store/heap/OnHeapStore.java | 6 +- .../DefaultStoreEventDispatcher.java} | 12 +- .../DefaultStoreEventDispatcherTest.java} | 18 +- 51 files changed, 2133 insertions(+), 276 deletions(-) rename clustered/client/src/test/java/org/ehcache/clustered/client/{UnSupportedCombinationsWIthClusteredCacheTest.java => UnSupportedCombinationsWithClusteredCacheTest.java} (77%) create mode 100644 clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java create mode 100644 clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java delete mode 100644 clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreEvictionListener.java create mode 100644 docs/src/docs/asciidoc/developer/clustered-events.adoc rename impl/src/main/java/org/ehcache/impl/{internal/events/ScopedStoreEventDispatcher.java => store/DefaultStoreEventDispatcher.java} (71%) rename impl/src/test/java/org/ehcache/impl/{internal/events/ScopedStoreEventDispatcherTest.java => store/DefaultStoreEventDispatcherTest.java} (89%) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java index dc6fc6b221..ed8c4505a2 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java @@ -21,6 +21,7 @@ import org.ehcache.clustered.client.internal.store.lock.LockingServerStoreProxy; import org.ehcache.clustered.client.internal.store.operations.ChainResolver; import org.ehcache.clustered.client.internal.store.operations.EternalChainResolver; +import org.ehcache.clustered.client.service.ClusteringService; import org.ehcache.clustered.common.internal.store.operations.ConditionalRemoveOperation; import org.ehcache.clustered.common.internal.store.operations.ConditionalReplaceOperation; import org.ehcache.clustered.common.internal.store.operations.PutIfAbsentOperation; @@ -28,12 +29,13 @@ import org.ehcache.clustered.common.internal.store.operations.RemoveOperation; import org.ehcache.clustered.common.internal.store.operations.ReplaceOperation; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; -import org.ehcache.clustered.client.service.ClusteringService; import org.ehcache.config.ResourceType; +import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.core.exceptions.StorePassThroughException; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.core.spi.time.TimeSourceService; +import org.ehcache.impl.store.DefaultStoreEventDispatcher; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.loaderwriter.CacheLoaderWriterConfiguration; import org.ehcache.spi.loaderwriter.CacheLoadingException; @@ -55,8 +57,8 @@ public class ClusteredLoaderWriterStore extends ClusteredStore imple private final boolean useLoaderInAtomics; public ClusteredLoaderWriterStore(Configuration config, OperationsCodec codec, ChainResolver resolver, TimeSource timeSource, - CacheLoaderWriter loaderWriter, boolean useLoaderInAtomics) { - super(config, codec, resolver, timeSource); + CacheLoaderWriter loaderWriter, boolean useLoaderInAtomics, StoreEventDispatcher storeEventDispatcher) { + super(config, codec, resolver, timeSource, storeEventDispatcher); this.cacheLoaderWriter = loaderWriter; this.useLoaderInAtomics = useLoaderInAtomics; } @@ -66,7 +68,7 @@ public ClusteredLoaderWriterStore(Configuration config, OperationsCodec config, OperationsCodec codec, EternalChainResolver resolver, ServerStoreProxy proxy, TimeSource timeSource, CacheLoaderWriter loaderWriter) { - super(config, codec, resolver, proxy, timeSource); + super(config, codec, resolver, proxy, timeSource, null); this.cacheLoaderWriter = loaderWriter; this.useLoaderInAtomics = true; } @@ -300,8 +302,9 @@ protected ClusteredStore createStore(Configuration storeConfi TimeSource timeSource, boolean useLoaderInAtomics, Object[] serviceConfigs) { + StoreEventDispatcher storeEventDispatcher = new DefaultStoreEventDispatcher<>(storeConfig.getDispatcherConcurrency()); return new ClusteredLoaderWriterStore<>(storeConfig, codec, resolver, timeSource, - storeConfig.getCacheLoaderWriter(), useLoaderInAtomics); + storeConfig.getCacheLoaderWriter(), useLoaderInAtomics, storeEventDispatcher); } @Override diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java index 9d5c19f41d..4f06701007 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java @@ -32,9 +32,11 @@ import org.ehcache.clustered.client.service.ClusteringService; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.config.ResourceType; +import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.core.spi.time.TimeSourceService; +import org.ehcache.impl.store.DefaultStoreEventDispatcher; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.loaderwriter.WriteBehindConfiguration; import org.ehcache.spi.resilience.StoreAccessException; @@ -61,8 +63,9 @@ private ClusteredWriteBehindStore(Configuration config, ChainResolver resolver, TimeSource timeSource, CacheLoaderWriter loaderWriter, - ExecutorService executorService) { - super(config, codec, resolver, timeSource); + ExecutorService executorService, + StoreEventDispatcher storeEventDispatcher) { + super(config, codec, resolver, timeSource, storeEventDispatcher); this.cacheLoaderWriter = loaderWriter; this.clusteredWriteBehind = new ClusteredWriteBehind<>(this, executorService, resolver, @@ -212,8 +215,8 @@ public class WriteBehindServerCallback implements ServerStoreProxy.ServerCallbac } @Override - public void onInvalidateHash(long hash) { - this.delegate.onInvalidateHash(hash); + public void onInvalidateHash(long hash, Chain evictedChain) { + this.delegate.onInvalidateHash(hash, evictedChain); } @Override @@ -221,6 +224,11 @@ public void onInvalidateAll() { this.delegate.onInvalidateAll(); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + this.delegate.onAppend(beforeAppend, appended); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { this.delegate.compact(chain); @@ -253,18 +261,20 @@ protected ClusteredStore createStore(Configuration storeConfi ExecutorService executorService = executionService.getOrderedExecutor(writeBehindConfiguration.getThreadPoolAlias(), new LinkedBlockingQueue<>()); + StoreEventDispatcher storeEventDispatcher = new DefaultStoreEventDispatcher<>(storeConfig.getDispatcherConcurrency()); return new ClusteredWriteBehindStore<>(storeConfig, codec, resolver, timeSource, storeConfig.getCacheLoaderWriter(), - executorService); + executorService, + storeEventDispatcher); } throw new AssertionError(); } @Override - protected ServerStoreProxy.ServerCallback getServerCallback(ClusteredStore clusteredStore) { + protected ServerStoreProxy.ServerCallback getServerCallback(ClusteredStore clusteredStore) { if (clusteredStore instanceof ClusteredWriteBehindStore) { return ((ClusteredWriteBehindStore)clusteredStore).getWriteBehindServerCallback(super.getServerCallback(clusteredStore)); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntity.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntity.java index 57f7b40463..b9b7b446fc 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntity.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntity.java @@ -55,6 +55,8 @@ public interface ClusterTierClientEntity extends Entity { void addReconnectListener(ReconnectListener reconnectListener); + void enableEvents(boolean enable) throws ClusterException, TimeoutException; + interface ResponseListener { void onResponse(T response); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index fa5c0788c4..0da2ae3234 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -25,29 +25,31 @@ import org.ehcache.clustered.client.internal.store.operations.ChainResolver; import org.ehcache.clustered.client.internal.store.operations.EternalChainResolver; import org.ehcache.clustered.client.internal.store.operations.ExpiryChainResolver; +import org.ehcache.clustered.client.service.ClusteringService; +import org.ehcache.clustered.client.service.ClusteringService.ClusteredCacheIdentifier; +import org.ehcache.clustered.common.Consistency; +import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.operations.ConditionalRemoveOperation; import org.ehcache.clustered.common.internal.store.operations.ConditionalReplaceOperation; +import org.ehcache.clustered.common.internal.store.operations.Operation; import org.ehcache.clustered.common.internal.store.operations.PutIfAbsentOperation; import org.ehcache.clustered.common.internal.store.operations.PutOperation; import org.ehcache.clustered.common.internal.store.operations.RemoveOperation; import org.ehcache.clustered.common.internal.store.operations.ReplaceOperation; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; -import org.ehcache.clustered.client.service.ClusteringService; -import org.ehcache.clustered.client.service.ClusteringService.ClusteredCacheIdentifier; -import org.ehcache.clustered.common.Consistency; -import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.config.ResourceType; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.core.CacheConfigurationChangeListener; import org.ehcache.core.Ehcache; import org.ehcache.core.collections.ConcurrentWeakIdentityHashMap; import org.ehcache.core.events.CacheEventListenerConfiguration; -import org.ehcache.core.events.NullStoreEventDispatcher; +import org.ehcache.core.events.StoreEventDispatcher; +import org.ehcache.core.events.StoreEventSink; import org.ehcache.core.spi.service.ExecutionService; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.spi.store.events.StoreEventFilter; +import org.ehcache.core.spi.store.events.StoreEventListener; import org.ehcache.core.spi.store.events.StoreEventSource; -import org.ehcache.impl.store.BaseStore; -import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.core.spi.time.TimeSourceService; @@ -55,9 +57,14 @@ import org.ehcache.core.statistics.StoreOperationOutcomes; import org.ehcache.core.statistics.StoreOperationOutcomes.EvictionOutcome; import org.ehcache.core.statistics.TierOperationOutcomes; +import org.ehcache.event.EventFiring; +import org.ehcache.event.EventOrdering; import org.ehcache.expiry.ExpiryPolicy; +import org.ehcache.impl.store.DefaultStoreEventDispatcher; +import org.ehcache.impl.store.BaseStore; import org.ehcache.impl.store.HashUtils; import org.ehcache.spi.persistence.StateRepository; +import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.spi.serialization.Serializer; import org.ehcache.spi.serialization.StatefulSerializer; import org.ehcache.spi.service.Service; @@ -106,6 +113,7 @@ public class ClusteredStore extends BaseStore implements Authoritati protected final ChainResolver resolver; protected final TimeSource timeSource; + private final DelegatingStoreEventDispatcher storeEventDispatcher; protected volatile ServerStoreProxy storeProxy; private volatile InvalidationValve invalidationValve; @@ -122,13 +130,14 @@ public class ClusteredStore extends BaseStore implements Authoritati private final OperationObserver getAndFaultObserver; - protected ClusteredStore(Configuration config, OperationsCodec codec, ChainResolver resolver, TimeSource timeSource) { + protected ClusteredStore(Configuration config, OperationsCodec codec, ChainResolver resolver, TimeSource timeSource, StoreEventDispatcher storeEventDispatcher) { super(config); this.chainCompactionLimit = Integer.getInteger(CHAIN_COMPACTION_THRESHOLD_PROP, DEFAULT_CHAIN_COMPACTION_THRESHOLD); this.codec = codec; this.resolver = resolver; this.timeSource = timeSource; + this.storeEventDispatcher = new DelegatingStoreEventDispatcher<>(storeEventDispatcher); this.getObserver = createObserver("get", StoreOperationOutcomes.GetOutcome.class, true); this.putObserver = createObserver("put", StoreOperationOutcomes.PutOutcome.class, true); @@ -144,8 +153,8 @@ protected ClusteredStore(Configuration config, OperationsCodec codec /** * For tests */ - protected ClusteredStore(Configuration config, OperationsCodec codec, EternalChainResolver resolver, ServerStoreProxy proxy, TimeSource timeSource) { - this(config, codec, resolver, timeSource); + protected ClusteredStore(Configuration config, OperationsCodec codec, ChainResolver resolver, ServerStoreProxy proxy, TimeSource timeSource, StoreEventDispatcher storeEventDispatcher) { + this(config, codec, resolver, timeSource, storeEventDispatcher); this.storeProxy = proxy; } @@ -371,8 +380,7 @@ public void clear() throws StoreAccessException { @Override public StoreEventSource getStoreEventSource() { - // TODO: Is there a StoreEventSource for a ServerStore? - return new NullStoreEventDispatcher<>(); + return storeEventDispatcher; } @Override @@ -615,10 +623,16 @@ public ClusteredStore createStore(Configuration storeConfig, private ClusteredStore createStoreInternal(Configuration storeConfig, Object[] serviceConfigs) { connectLock.lock(); try { - CacheEventListenerConfiguration eventListenerConfiguration = findSingletonAmongst(CacheEventListenerConfiguration.class, serviceConfigs); if (eventListenerConfiguration != null) { - throw new IllegalStateException("CacheEventListener is not supported with clustered tiers"); + if (eventListenerConfiguration.firingMode() == EventFiring.SYNCHRONOUS) { + // Forget it. Never. + throw new IllegalStateException("Synchronous CacheEventListener is not supported with clustered tiers"); + } + if (eventListenerConfiguration.orderingMode() == EventOrdering.ORDERED) { + // this could be supported, but at least expiration events would need to be reordered + throw new IllegalStateException("Ordered CacheEventListener is not supported with clustered tiers"); + } } if (clusteringService == null) { @@ -669,7 +683,8 @@ protected ClusteredStore createStore(Configuration storeConfi TimeSource timeSource, boolean useLoaderInAtomics, Object[] serviceConfigs) { - return new ClusteredStore<>(storeConfig, codec, resolver, timeSource); + StoreEventDispatcher storeEventDispatcher = new DefaultStoreEventDispatcher<>(storeConfig.getDispatcherConcurrency()); + return new ClusteredStore<>(storeConfig, codec, resolver, timeSource, storeEventDispatcher); } @Override @@ -718,7 +733,7 @@ public void initStore(Store resource) { }; CompletableFuture.runAsync(reconnectTask, executionService.getUnorderedExecutor(null, new LinkedBlockingQueue<>())); }); - clusteredStore.storeProxy = reconnectingServerStoreProxy; + clusteredStore.setStoreProxy(reconnectingServerStoreProxy); } catch (CachePersistenceException e) { throw new RuntimeException("Unable to create cluster tier proxy - " + cacheIdentifier, e); } @@ -749,10 +764,50 @@ public void initStore(Store resource) { } } - protected ServerCallback getServerCallback(ClusteredStore clusteredStore) { + protected ServerCallback getServerCallback(ClusteredStore clusteredStore) { return new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + StoreEventSink sink = clusteredStore.storeEventDispatcher.eventSink(); + try { + Operation operation = clusteredStore.codec.decode(appended); + K key = operation.getKey(); + + PutOperation resolvedBefore = clusteredStore.resolver.resolve(beforeAppend, key); + PutOperation resolvedAfter = clusteredStore.resolver.applyOperation(key, resolvedBefore, operation); + + if (resolvedBefore == null) { + if (resolvedAfter == null) { + //a non-event + } else { + sink.created(key, resolvedAfter.getValue()); + } + } else { + if (resolvedAfter != null) { + if (resolvedAfter == resolvedBefore) { + //non-event + } else { + sink.updated(key, resolvedBefore::getValue, resolvedAfter.getValue()); + } + } else { + switch (operation.getOpCode()) { + case TIMESTAMP: + sink.expired(key, resolvedBefore::getValue); + break; + default: + sink.removed(key, resolvedBefore::getValue); + } + } + } + clusteredStore.storeEventDispatcher.releaseEventSink(sink); + } catch (Exception e) { + clusteredStore.storeEventDispatcher.releaseEventSinkAfterFailure(sink, e); + LOGGER.warn("Error processing server append event", e); + } + } + + @Override + public void onInvalidateHash(long hash, Chain evictedChain) { EvictionOutcome result = EvictionOutcome.SUCCESS; clusteredStore.evictionObserver.begin(); if (clusteredStore.invalidationValve != null) { @@ -765,6 +820,16 @@ public void onInvalidateHash(long hash) { result = EvictionOutcome.FAILURE; } } + if (evictedChain != null) { + StoreEventSink sink = clusteredStore.storeEventDispatcher.eventSink(); + Map> operationMap = clusteredStore.resolver.resolveAll(evictedChain, clusteredStore.timeSource.getTimeMillis()); + for (Map.Entry> entry : operationMap.entrySet()) { + K key = entry.getKey(); + V value = entry.getValue() == null ? null : entry.getValue().get(); + sink.evicted(key, () -> value); + } + clusteredStore.storeEventDispatcher.releaseEventSink(sink); + } clusteredStore.evictionObserver.end(result); } @@ -853,6 +918,13 @@ public void initAuthoritativeTier(AuthoritativeTier resource) { } + private void setStoreProxy(ServerStoreProxy storeProxy) throws CachePersistenceException { + // don't change the order of the following two lines or you'll create a race condition that can + // make the server drop some event notifications during a client reconnection + this.storeEventDispatcher.setStoreProxy(storeProxy); + this.storeProxy = storeProxy; + } + private static class StoreConfig { private final ClusteredCacheIdentifier cacheIdentifier; @@ -877,4 +949,83 @@ public Consistency getConsistency() { return consistency; } } + + static class DelegatingStoreEventDispatcher implements StoreEventDispatcher { + private int listenerCounter; + private ServerStoreProxy storeProxy; // protected by synchronized blocks + private final StoreEventDispatcher delegate; + + DelegatingStoreEventDispatcher(StoreEventDispatcher delegate) { + this.delegate = delegate; + } + + synchronized void setStoreProxy(ServerStoreProxy storeProxy) throws CachePersistenceException { + if (storeProxy != null && listenerCounter > 0) { + try { + storeProxy.enableEvents(true); + } catch (TimeoutException te) { + throw new CachePersistenceException("Error enabling events", te); + } + } + this.storeProxy = storeProxy; + } + + @Override + public StoreEventSink eventSink() { + return delegate.eventSink(); + } + @Override + public void releaseEventSink(StoreEventSink eventSink) { + delegate.releaseEventSink(eventSink); + } + @Override + public void releaseEventSinkAfterFailure(StoreEventSink eventSink, Throwable throwable) { + delegate.releaseEventSinkAfterFailure(eventSink, throwable); + } + @Override + public void reset(StoreEventSink eventSink) { + delegate.reset(eventSink); + } + @Override + public synchronized void addEventListener(StoreEventListener eventListener) { + if (listenerCounter == 0 && storeProxy != null) { + try { + storeProxy.enableEvents(true); + } catch (TimeoutException te) { + throw new RuntimeException("Error enabling events", te); + } + } + if (listenerCounter < Integer.MAX_VALUE) { + listenerCounter++; + } + delegate.addEventListener(eventListener); + } + @Override + public synchronized void removeEventListener(StoreEventListener eventListener) { + if (listenerCounter == 1 && storeProxy != null) { + try { + storeProxy.enableEvents(false); + } catch (TimeoutException te) { + throw new RuntimeException("Error disabling events", te); + } + } + if (listenerCounter > 0) { + listenerCounter--; + } + delegate.removeEventListener(eventListener); + } + @Override + public void addEventFilter(StoreEventFilter eventFilter) { + delegate.addEventFilter(eventFilter); + } + @Override + public void setEventOrdering(boolean ordering) { + delegate.setEventOrdering(ordering); + } + @Override + public boolean isEventOrdering() { + return delegate.isEventOrdering(); + } + } + } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java index b1e6ebbbd0..2b90eac56d 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java @@ -19,6 +19,7 @@ import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.ClientInvalidateAll; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.ClientInvalidateHash; +import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.ServerAppend; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.ServerInvalidateHash; import org.ehcache.clustered.common.internal.messages.EhcacheOperationMessage; import org.ehcache.clustered.common.internal.messages.EhcacheResponseType; @@ -62,17 +63,23 @@ class CommonServerStoreProxy implements ServerStoreProxy { entity.addDisconnectionListener(invalidation::onInvalidateAll); + entity.addResponseListener(ServerAppend.class, response -> { + LOGGER.debug("CLIENT: on cache {}, server append notification", cacheId); + invalidation.onAppend(response.getBeforeAppend(), response.getAppended()); + }); entity.addResponseListener(ServerInvalidateHash.class, response -> { long key = response.getKey(); - LOGGER.debug("CLIENT: on cache {}, server requesting hash {} to be invalidated", cacheId, key); - invalidation.onInvalidateHash(key); + Chain evictedChain = response.getEvictedChain(); + LOGGER.debug("CLIENT: on cache {}, server requesting hash {} to be invalidated (evicted chain : {})", cacheId, key, evictedChain); + invalidation.onInvalidateHash(key, evictedChain); }); entity.addResponseListener(ClientInvalidateHash.class, response -> { long key = response.getKey(); int invalidationId = response.getInvalidationId(); LOGGER.debug("CLIENT: doing work to invalidate hash {} from cache {} (ID {})", key, cacheId, invalidationId); - invalidation.onInvalidateHash(key); + // evicted chain is always null: ClientInvalidateHash is fired when another client did an append, not when the server evicted + invalidation.onInvalidateHash(key, null); try { LOGGER.debug("CLIENT: ack'ing invalidation of hash {} from cache {} (ID {})", key, cacheId, invalidationId); @@ -161,6 +168,15 @@ public ChainEntry getAndAppend(long key, ByteBuffer payLoad) throws TimeoutExcep } } + @Override + public void enableEvents(boolean enable) { + try { + entity.enableEvents(enable); + } catch (Exception e) { + throw new ServerStoreProxyException(e); + } + } + @Override public void replaceAtHead(long key, Chain expect, Chain update) { // TODO: Optimize this method to just send sequences for expect Chain diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java index f174e79da4..093cf1aa6e 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java @@ -54,6 +54,11 @@ public ChainEntry getAndAppend(final long key, final ByteBuffer payLoad) throws return delegate.getAndAppend(key, payLoad); } + @Override + public void enableEvents(boolean enable) throws TimeoutException { + delegate.enableEvents(enable); + } + @Override public void replaceAtHead(long key, Chain expect, Chain update) { delegate.replaceAtHead(key, expect, update); diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java index b996517c41..7c1819df4d 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java @@ -76,6 +76,14 @@ public ChainEntry getAndAppend(long key, ByteBuffer payLoad) throws TimeoutExcep return onStoreProxy(serverStoreProxy -> serverStoreProxy.getAndAppend(key, payLoad)); } + @Override + public void enableEvents(boolean enable) throws TimeoutException { + onStoreProxy(serverStoreProxy -> { + serverStoreProxy.enableEvents(enable); + return null; + }); + } + @Override public void replaceAtHead(long key, Chain expect, Chain update) { try { @@ -221,6 +229,11 @@ public ChainEntry getAndAppend(long key, ByteBuffer payLoad) throws TimeoutExcep return serverStoreProxy.getAndAppend(key, payLoad); } + @Override + public void enableEvents(boolean enable) throws TimeoutException { + serverStoreProxy.enableEvents(enable); + } + @Override public String getCacheId() { return serverStoreProxy.getCacheId(); diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxy.java index 1a531ebdfe..2eacd7a92a 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxy.java @@ -55,21 +55,36 @@ interface ServerCallback { * Callback for invalidation of hash requests * * @param hash the hash of the keys to invalidate + * @param evictedChain the evicted chain, or null if it wasn't an eviction that triggered the invalidation but + * a change on a different client or when events are disabled. */ - void onInvalidateHash(long hash); + void onInvalidateHash(long hash, Chain evictedChain); /** * Callback for invalidation of all requests */ void onInvalidateAll(); + /** + * Callback append events + */ + void onAppend(Chain beforeAppend, ByteBuffer appended); + void compact(ChainEntry chain); default void compact(ChainEntry chain, long hash) { compact(chain); } + } + /** + * Enable or disable event firing from the server + * @param enable {@code true} to enable, {@code false} to disable + */ + void enableEvents(boolean enable) throws TimeoutException; + + /** * Gets the identifier linking a client-side cache to a {@code ServerStore} instance. * diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java index 1ab2e5a4f4..5d3d09b1fa 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java @@ -30,6 +30,7 @@ import org.ehcache.clustered.common.internal.messages.EhcacheResponseType; import org.ehcache.clustered.common.internal.messages.LifeCycleMessageFactory; import org.ehcache.clustered.common.internal.messages.ReconnectMessageCodec; +import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage; import org.ehcache.clustered.common.internal.messages.StateRepositoryOpMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -79,6 +80,7 @@ public class SimpleClusterTierClientEntity implements InternalClusterTierClientE private final List reconnectListeners = new CopyOnWriteArrayList<>(); private volatile boolean connected = true; + private volatile boolean eventsEnabled; public SimpleClusterTierClientEntity(EntityClientEndpoint endpoint, Timeouts timeouts, String storeIdentifier) { @@ -96,7 +98,7 @@ public void handleMessage(EhcacheEntityResponse messageFromServer) { @Override public byte[] createExtendedReconnectData() { synchronized (lock) { - ClusterTierReconnectMessage reconnectMessage = new ClusterTierReconnectMessage(); + ClusterTierReconnectMessage reconnectMessage = new ClusterTierReconnectMessage(eventsEnabled); reconnectListeners.forEach(reconnectListener -> reconnectListener.onHandleReconnect(reconnectMessage)); return reconnectMessageCodec.encode(reconnectMessage); } @@ -145,6 +147,16 @@ public void addReconnectListener(ReconnectListener reconnectListener) { this.reconnectListeners.add(reconnectListener); } + @Override + public void enableEvents(boolean enable) throws ClusterException, TimeoutException { + if (enable == this.eventsEnabled) { + return; + } + // make sure the server received and processed the message before returning + this.invokeAndWaitForComplete(new ServerStoreOpMessage.EnableEventListenerMessage(enable), true); + this.eventsEnabled = enable; + } + @Override public void addDisconnectionListener(DisconnectionListener disconnectionListener) { this.disconnectionListeners.add(disconnectionListener); diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java index 46063087f0..a98735b31b 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java @@ -221,6 +221,11 @@ public ChainEntry getAndAppend(final long key, final ByteBuffer payLoad) throws return performWaitingForHashInvalidation(key, () -> delegate.getAndAppend(key, payLoad), entity.getTimeouts().getWriteOperationTimeout()); } + @Override + public void enableEvents(boolean enable) { + delegate.enableEvents(enable); + } + @Override public void replaceAtHead(long key, Chain expect, Chain update) { delegate.replaceAtHead(key, expect, update); diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java index eb289a20dd..df8130aee7 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java @@ -94,6 +94,11 @@ public ChainEntry getAndAppend(long key, ByteBuffer payLoad) throws TimeoutExcep return storeProxy.getAndAppend(key, payLoad); } + @Override + public void enableEvents(boolean enable) throws TimeoutException { + storeProxy.enableEvents(enable); + } + @Override public void replaceAtHead(long key, Chain expect, Chain update) { storeProxy.replaceAtHead(key, expect, update); diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java index 7bcdbe7f08..b0d77e6b9d 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java @@ -17,12 +17,12 @@ package org.ehcache.clustered.client.internal.store.operations; import org.ehcache.clustered.client.internal.store.ServerStoreProxy; -import org.ehcache.clustered.common.internal.util.ChainBuilder; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.Element; import org.ehcache.clustered.common.internal.store.operations.Operation; import org.ehcache.clustered.common.internal.store.operations.PutOperation; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; +import org.ehcache.clustered.common.internal.util.ChainBuilder; import org.ehcache.core.spi.store.Store.ValueHolder; import java.nio.ByteBuffer; @@ -153,6 +153,17 @@ protected Map> resolveAll(Chain chain) { return compacted; } + /** + * Resolves a key within the given chain to its equivalent put operation. + * + * @param chain target chain + * @param key the key + * @return the equivalent put operation + */ + public PutOperation resolve(Chain chain, K key) { + return resolveAll(chain).get(key); + } + /** * Applies the given operation to the current state. * diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWIthClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java similarity index 77% rename from clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWIthClusteredCacheTest.java rename to clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java index 09c4352f61..87ec3b5126 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWIthClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java @@ -51,7 +51,7 @@ /** * This class should be removed as and when following features are done. */ -public class UnSupportedCombinationsWIthClusteredCacheTest { +public class UnSupportedCombinationsWithClusteredCacheTest { @Before public void resetPassthroughServer() throws Exception { @@ -68,11 +68,37 @@ public void removePassthroughServer() throws Exception { } @Test - public void testClusteredCacheWithEventListeners() { + public void testClusteredCacheWithOrderedEventListeners() { + CacheEventListenerConfigurationBuilder cacheEventListenerConfiguration = CacheEventListenerConfigurationBuilder + .newEventListenerConfiguration(new TestEventListener(), EventType.CREATED, EventType.UPDATED) + .ordered().asynchronous(); + + final CacheManagerBuilder clusteredCacheManagerBuilder + = CacheManagerBuilder.newCacheManagerBuilder() + .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) + .autoCreate()); + final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); + + try { + CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, + ResourcePoolsBuilder.newResourcePoolsBuilder() + .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) + .add(cacheEventListenerConfiguration) + .build(); + cacheManager.createCache("test", config); + fail("IllegalStateException expected"); + } catch (IllegalStateException e){ + assertThat(e.getCause().getMessage(), is("Ordered CacheEventListener is not supported with clustered tiers")); + } + cacheManager.close(); + } + + @Test + public void testClusteredCacheWithSynchronousEventListeners() { CacheEventListenerConfigurationBuilder cacheEventListenerConfiguration = CacheEventListenerConfigurationBuilder - .newEventListenerConfiguration(new TestEventListener(), EventType.CREATED, EventType.UPDATED) // <1> - .unordered().asynchronous(); // <2> + .newEventListenerConfiguration(new TestEventListener(), EventType.CREATED, EventType.UPDATED) + .unordered().synchronous(); final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() @@ -90,7 +116,7 @@ public void testClusteredCacheWithEventListeners() { cacheManager.createCache("test", config); fail("IllegalStateException expected"); } catch (IllegalStateException e){ - assertThat(e.getCause().getMessage(), is("CacheEventListener is not supported with clustered tiers")); + assertThat(e.getCause().getMessage(), is("Synchronous CacheEventListener is not supported with clustered tiers")); } cacheManager.close(); } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java index 7d93bf16d3..addbeabe78 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java @@ -15,18 +15,22 @@ */ package org.ehcache.clustered.client.internal.store; +import org.ehcache.clustered.client.config.ClusteredResourcePool; +import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntityFactory; import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntityService; import org.ehcache.clustered.client.internal.UnitTestConnectionService; import org.ehcache.clustered.client.internal.UnitTestConnectionService.PassthroughServerBuilder; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLockEntityClientService; +import org.ehcache.clustered.common.Consistency; import org.ehcache.clustered.common.ServerSideConfiguration; import org.ehcache.clustered.common.internal.ServerStoreConfiguration; import org.ehcache.clustered.lock.server.VoltronReadWriteLockServerEntityService; import org.ehcache.clustered.server.ClusterTierManagerServerEntityService; import org.ehcache.clustered.server.store.ObservableClusterTierServerEntityService; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.impl.serialization.LongSerializer; import org.junit.AfterClass; import org.junit.BeforeClass; import org.terracotta.connection.Connection; @@ -88,4 +92,15 @@ protected static SimpleClusterTierClientEntity createClientEntity(String name, return clientEntity; } + protected static SimpleClusterTierClientEntity createClientEntity(String name, Consistency consistency, boolean create) throws Exception { + ClusteredResourcePool resourcePool = ClusteredResourcePoolBuilder.clusteredDedicated(8L, MemoryUnit.MB); + + ServerStoreConfiguration serverStoreConfiguration = new ServerStoreConfiguration(resourcePool.getPoolAllocation(), Long.class + .getName(), + Long.class.getName(), LongSerializer.class.getName(), LongSerializer.class + .getName(), consistency, false); + + return createClientEntity(name, serverStoreConfiguration, create); + } + } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java new file mode 100644 index 0000000000..96e0a38079 --- /dev/null +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java @@ -0,0 +1,365 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered.client.internal.store; + +import org.ehcache.clustered.ChainUtils; +import org.ehcache.clustered.client.TestTimeSource; +import org.ehcache.clustered.client.config.ClusteredResourcePool; +import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; +import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntityFactory; +import org.ehcache.clustered.client.internal.UnitTestConnectionService; +import org.ehcache.clustered.client.internal.store.ServerStoreProxy.ServerCallback; +import org.ehcache.clustered.client.internal.store.operations.ChainResolver; +import org.ehcache.clustered.client.internal.store.operations.ExpiryChainResolver; +import org.ehcache.clustered.common.ServerSideConfiguration; +import org.ehcache.clustered.common.internal.ServerStoreConfiguration; +import org.ehcache.clustered.common.internal.store.Chain; +import org.ehcache.clustered.common.internal.store.operations.ConditionalRemoveOperation; +import org.ehcache.clustered.common.internal.store.operations.ConditionalReplaceOperation; +import org.ehcache.clustered.common.internal.store.operations.Operation; +import org.ehcache.clustered.common.internal.store.operations.PutIfAbsentOperation; +import org.ehcache.clustered.common.internal.store.operations.PutOperation; +import org.ehcache.clustered.common.internal.store.operations.RemoveOperation; +import org.ehcache.clustered.common.internal.store.operations.ReplaceOperation; +import org.ehcache.clustered.common.internal.store.operations.TimestampOperation; +import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; +import org.ehcache.config.EvictionAdvisor; +import org.ehcache.config.ResourcePools; +import org.ehcache.config.builders.ExpiryPolicyBuilder; +import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.events.StoreEventDispatcher; +import org.ehcache.core.events.StoreEventSink; +import org.ehcache.core.spi.store.Store; +import org.ehcache.expiry.ExpiryPolicy; +import org.ehcache.impl.serialization.LongSerializer; +import org.ehcache.impl.serialization.StringSerializer; +import org.ehcache.spi.loaderwriter.CacheLoaderWriter; +import org.ehcache.spi.serialization.Serializer; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.terracotta.connection.Connection; + +import java.net.URI; +import java.nio.ByteBuffer; +import java.time.Duration; +import java.util.Collections; +import java.util.Properties; +import java.util.function.Supplier; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +public class ClusteredStoreEventsTest { + + private static final String CACHE_IDENTIFIER = "testCache"; + private static final URI CLUSTER_URI = URI.create("terracotta://localhost"); + + private final Store.Configuration config = new Store.Configuration() { + + @Override + public Class getKeyType() { + return Long.class; + } + + @Override + public Class getValueType() { + return String.class; + } + + @Override + public EvictionAdvisor getEvictionAdvisor() { + return null; + } + + @Override + public ClassLoader getClassLoader() { + return null; + } + + @Override + public ExpiryPolicy getExpiry() { + return null; + } + + @Override + public ResourcePools getResourcePools() { + return null; + } + + @Override + public Serializer getKeySerializer() { + return null; + } + + @Override + public Serializer getValueSerializer() { + return null; + } + + @Override + public int getDispatcherConcurrency() { + return 0; + } + + @Override + public CacheLoaderWriter getCacheLoaderWriter() { + return null; + } + }; + private StoreEventSink storeEventSink; + private ServerCallback serverCallback; + private OperationsCodec codec; + private TestTimeSource testTimeSource; + + @SuppressWarnings("unchecked") + @Before + public void setup() throws Exception { + UnitTestConnectionService.add( + CLUSTER_URI, + new UnitTestConnectionService.PassthroughServerBuilder().resource("defaultResource", 8, MemoryUnit.MB).build() + ); + + Connection connection = new UnitTestConnectionService().connect(CLUSTER_URI, new Properties()); + ClusterTierManagerClientEntityFactory entityFactory = new ClusterTierManagerClientEntityFactory(connection); + + ServerSideConfiguration serverConfig = + new ServerSideConfiguration("defaultResource", Collections.emptyMap()); + entityFactory.create("TestCacheManager", serverConfig); + + ClusteredResourcePool resourcePool = ClusteredResourcePoolBuilder.clusteredDedicated(4, MemoryUnit.MB); + ServerStoreConfiguration serverStoreConfiguration = new ServerStoreConfiguration(resourcePool.getPoolAllocation(), + Long.class.getName(), String.class.getName(), LongSerializer.class.getName(), StringSerializer.class.getName(), null, false); + ClusterTierClientEntity clientEntity = entityFactory.fetchOrCreateClusteredStoreEntity("TestCacheManager", CACHE_IDENTIFIER, serverStoreConfiguration, true); + clientEntity.validate(serverStoreConfiguration); + ServerStoreProxy serverStoreProxy = new CommonServerStoreProxy(CACHE_IDENTIFIER, clientEntity, mock(ServerCallback.class)); + + testTimeSource = new TestTimeSource(); + + codec = new OperationsCodec<>(new LongSerializer(), new StringSerializer()); + ChainResolver resolver = new ExpiryChainResolver<>(codec, ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(1000))); + + StoreEventDispatcher storeEventDispatcher = mock(StoreEventDispatcher.class); + storeEventSink = mock(StoreEventSink.class); + when(storeEventDispatcher.eventSink()).thenReturn(storeEventSink); + + ClusteredStore store = new ClusteredStore<>(config, codec, resolver, serverStoreProxy, testTimeSource, storeEventDispatcher); + serverCallback = new ClusteredStore.Provider().getServerCallback(store); + } + + @After + public void tearDown() throws Exception { + UnitTestConnectionService.remove("terracotta://localhost/my-application"); + } + + private ByteBuffer op(Operation operation) { + return codec.encode(operation); + } + + + @Test + public void testOnAppend_PutAfterNothingFiresCreatedEvent() { + Chain beforeAppend = ChainUtils.chainOf(); + serverCallback.onAppend(beforeAppend, op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + + verify(storeEventSink).created(eq(1L), eq("one")); + verifyNoMoreInteractions(storeEventSink); + } + + @SuppressWarnings("unchecked") + @Test + public void testOnAppend_PutAfterPutFiresUpdatedEvent() { + Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + serverCallback.onAppend(beforeAppend, op(new PutOperation<>(1L, "one-bis", testTimeSource.getTimeMillis()))); + + ArgumentCaptor> supplierArgumentCaptor = ArgumentCaptor.forClass(Supplier.class); + verify(storeEventSink).updated(eq(1L), supplierArgumentCaptor.capture(), eq("one-bis")); + verifyNoMoreInteractions(storeEventSink); + assertThat(supplierArgumentCaptor.getValue().get(), is("one")); + } + + @SuppressWarnings("unchecked") + @Test + public void testOnAppend_RemoveAfterPutFiresRemovedEvent() { + Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + serverCallback.onAppend(beforeAppend, op(new RemoveOperation<>(1L, testTimeSource.getTimeMillis()))); + + ArgumentCaptor> supplierArgumentCaptor = ArgumentCaptor.forClass(Supplier.class); + verify(storeEventSink).removed(eq(1L), supplierArgumentCaptor.capture()); + verifyNoMoreInteractions(storeEventSink); + assertThat(supplierArgumentCaptor.getValue().get(), is("one")); + } + + @Test + public void testOnAppend_RemoveAfterNothingFiresNoEvent() { + Chain beforeAppend = ChainUtils.chainOf(); + serverCallback.onAppend(beforeAppend, op(new RemoveOperation<>(1L, testTimeSource.getTimeMillis()))); + + verifyNoMoreInteractions(storeEventSink); + } + + @SuppressWarnings("unchecked") + @Test + public void testOnAppend_ReplaceAfterPutFiresUpdatedEvent() { + Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + serverCallback.onAppend(beforeAppend, op(new ReplaceOperation<>(1L, "one-bis", testTimeSource.getTimeMillis()))); + + ArgumentCaptor> supplierArgumentCaptor = ArgumentCaptor.forClass(Supplier.class); + verify(storeEventSink).updated(eq(1L), supplierArgumentCaptor.capture(), eq("one-bis")); + verifyNoMoreInteractions(storeEventSink); + assertThat(supplierArgumentCaptor.getValue().get(), is("one")); + } + + @Test + public void testOnAppend_ReplaceAfterNothingFiresNoEvent() { + Chain beforeAppend = ChainUtils.chainOf(); + serverCallback.onAppend(beforeAppend, op(new ReplaceOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + + verifyNoMoreInteractions(storeEventSink); + } + + @Test + public void testOnAppend_PutIfAbsentAfterNothingFiresCreatedEvent() { + Chain beforeAppend = ChainUtils.chainOf(); + serverCallback.onAppend(beforeAppend, op(new PutIfAbsentOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + + verify(storeEventSink).created(eq(1L), eq("one")); + verifyNoMoreInteractions(storeEventSink); + } + + @Test + public void testOnAppend_PutIfAbsentAfterPutFiresNoEvent() { + Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + serverCallback.onAppend(beforeAppend, op(new PutIfAbsentOperation<>(1L, "one-bis", testTimeSource.getTimeMillis()))); + + verifyNoMoreInteractions(storeEventSink); + } + + @SuppressWarnings("unchecked") + @Test + public void testOnAppend_SuccessfulReplaceConditionalAfterPutFiresUpdatedEvent() { + Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + serverCallback.onAppend(beforeAppend, op(new ConditionalReplaceOperation<>(1L, "one", "one-bis", testTimeSource.getTimeMillis()))); + + ArgumentCaptor> supplierArgumentCaptor = ArgumentCaptor.forClass(Supplier.class); + verify(storeEventSink).updated(eq(1L), supplierArgumentCaptor.capture(), eq("one-bis")); + verifyNoMoreInteractions(storeEventSink); + assertThat(supplierArgumentCaptor.getValue().get(), is("one")); + } + + @Test + public void testOnAppend_FailingReplaceConditionalAfterPutFiresNoEvent() { + Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + serverCallback.onAppend(beforeAppend, op(new ConditionalReplaceOperation<>(1L, "un", "one-bis", testTimeSource.getTimeMillis()))); + + verifyNoMoreInteractions(storeEventSink); + } + + @Test + public void testOnAppend_ReplaceConditionalAfterNothingFiresNoEvent() { + Chain beforeAppend = ChainUtils.chainOf(); + serverCallback.onAppend(beforeAppend, op(new ConditionalReplaceOperation<>(1L, "one", "one-bis", testTimeSource.getTimeMillis()))); + + verifyNoMoreInteractions(storeEventSink); + } + + @SuppressWarnings("unchecked") + @Test + public void testOnAppend_SuccessfulRemoveConditionalAfterPutFiresUpdatedEvent() { + Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + serverCallback.onAppend(beforeAppend, op(new ConditionalRemoveOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + + ArgumentCaptor> supplierArgumentCaptor = ArgumentCaptor.forClass(Supplier.class); + verify(storeEventSink).removed(eq(1L), supplierArgumentCaptor.capture()); + verifyNoMoreInteractions(storeEventSink); + assertThat(supplierArgumentCaptor.getValue().get(), is("one")); + } + + @Test + public void testOnAppend_FailingRemoveConditionalAfterPutFiresNoEvent() { + Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + serverCallback.onAppend(beforeAppend, op(new ConditionalRemoveOperation<>(1L, "un", testTimeSource.getTimeMillis()))); + + verifyNoMoreInteractions(storeEventSink); + } + + @Test + public void testOnAppend_RemoveConditionalAfterNothingFiresNoEvent() { + Chain beforeAppend = ChainUtils.chainOf(); + serverCallback.onAppend(beforeAppend, op(new ConditionalRemoveOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + + verifyNoMoreInteractions(storeEventSink); + } + + @SuppressWarnings("unchecked") + @Test + public void testOnAppend_timestampAfterExpiryFiresExpiredEvent() { + Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "wrong-one", testTimeSource.getTimeMillis())), op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + testTimeSource.advanceTime(1100L); + serverCallback.onAppend(beforeAppend, op(new TimestampOperation<>(1L, testTimeSource.getTimeMillis()))); + + ArgumentCaptor> supplierArgumentCaptor = ArgumentCaptor.forClass(Supplier.class); + verify(storeEventSink).expired(eq(1L), supplierArgumentCaptor.capture()); + verifyNoMoreInteractions(storeEventSink); + assertThat(supplierArgumentCaptor.getValue().get(), is("one")); + } + + @Test + public void testOnAppend_timestampAfterNothingFiresNoEvent() { + Chain beforeAppend = ChainUtils.chainOf(); + serverCallback.onAppend(beforeAppend, op(new TimestampOperation<>(1L, testTimeSource.getTimeMillis()))); + + verifyNoMoreInteractions(storeEventSink); + } + + @Test + public void testOnAppend_timestampAfterNoExpiryFiresNoEvent() { + Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + testTimeSource.advanceTime(100L); + serverCallback.onAppend(beforeAppend, op(new TimestampOperation<>(1L, testTimeSource.getTimeMillis()))); + + verifyNoMoreInteractions(storeEventSink); + } + + @SuppressWarnings("unchecked") + @Test + public void testOnInvalidateHash_chainFiresEvictedEvents() { + Chain evictedChain = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis())), op(new PutOperation<>(2L, "two", testTimeSource.getTimeMillis()))); + serverCallback.onInvalidateHash(1L, evictedChain); + + ArgumentCaptor> supplierArgumentCaptor1 = ArgumentCaptor.forClass(Supplier.class); + ArgumentCaptor> supplierArgumentCaptor2 = ArgumentCaptor.forClass(Supplier.class); + verify(storeEventSink).evicted(eq(1L), supplierArgumentCaptor1.capture()); + verify(storeEventSink).evicted(eq(2L), supplierArgumentCaptor2.capture()); + verifyNoMoreInteractions(storeEventSink); + assertThat(supplierArgumentCaptor1.getValue().get(), is("one")); + assertThat(supplierArgumentCaptor2.getValue().get(), is("two")); + } + + @Test + public void testOnInvalidateHash_noChainFiresNoEvent() { + serverCallback.onInvalidateHash(1L, null); + + verifyNoMoreInteractions(storeEventSink); + } +} diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java index d736b58154..ad510ac903 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java @@ -35,6 +35,7 @@ import org.ehcache.core.Ehcache; import org.ehcache.core.spi.store.Store; import org.ehcache.expiry.ExpiryPolicy; +import org.ehcache.impl.store.DefaultStoreEventDispatcher; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.time.TimeSource; @@ -165,7 +166,7 @@ public void setup() throws Exception { OperationsCodec codec = new OperationsCodec<>(new LongSerializer(), new StringSerializer()); EternalChainResolver resolver = new EternalChainResolver<>(codec); - store = new ClusteredStore<>(config, codec, resolver, serverStoreProxy, testTimeSource); + store = new ClusteredStore<>(config, codec, resolver, serverStoreProxy, testTimeSource, new DefaultStoreEventDispatcher<>(8)); } @After @@ -195,7 +196,7 @@ public void testPutTimeout() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); doThrow(TimeoutException.class).when(proxy).append(anyLong(), isNull()); - ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null); assertTimeoutOccurred(() -> store.put(1L, "one")); } @@ -218,7 +219,7 @@ public void testGetThrowsOnlySAE() throws Exception { ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.get(anyLong())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); store.get(1L); } @@ -228,7 +229,7 @@ public void testGetTimeout() throws Exception { ServerStoreProxy proxy = mock(ServerStoreProxy.class); long longKey = HashUtils.intHashToLong(new Long(1L).hashCode()); when(proxy.get(longKey)).thenThrow(TimeoutException.class); - ClusteredStore store = new ClusteredStore<>(config,null, null, proxy, null); + ClusteredStore store = new ClusteredStore<>(config,null, null, proxy, null, null); assertThat(store.get(1L), nullValue()); validateStats(store, EnumSet.of(StoreOperationOutcomes.GetOutcome.TIMEOUT)); } @@ -251,7 +252,7 @@ public void testContainsKeyThrowsOnlySAE() throws Exception { ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.get(anyLong())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); store.containsKey(1L); } @@ -276,7 +277,7 @@ public void testRemoveThrowsOnlySAE() throws Exception { when(serverStoreProxy.getAndAppend(anyLong(), any())).thenThrow(theException); TestTimeSource testTimeSource = new TestTimeSource(); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); assertThatExceptionOfType(StoreAccessException.class) .isThrownBy(() -> store.remove(1L)) .withCause(theException); @@ -289,7 +290,7 @@ public void testRemoveTimeout() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); when(proxy.getAndAppend(anyLong(), isNull())).thenThrow(TimeoutException.class); - ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null); assertTimeoutOccurred(() -> store.remove(1L)); } @@ -321,7 +322,7 @@ public void testClearThrowsOnlySAE() throws Exception { ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); doThrow(new RuntimeException()).when(serverStoreProxy).clear(); TestTimeSource testTimeSource = mock(TestTimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); store.clear(); } @@ -332,7 +333,7 @@ public void testClearTimeout() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); doThrow(TimeoutException.class).when(proxy).clear(); - ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null); assertTimeoutOccurred(() -> store.clear()); } @@ -354,7 +355,7 @@ public void testPutIfAbsentThrowsOnlySAE() throws Exception { ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.getAndAppend(anyLong(), any())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); store.putIfAbsent(1L, "one", b -> {}); } @@ -365,7 +366,7 @@ public void testPutIfAbsentTimeout() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); when(proxy.getAndAppend(anyLong(), isNull())).thenThrow(TimeoutException.class); - ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null); assertTimeoutOccurred(() -> store.putIfAbsent(1L, "one", b -> {})); } @@ -391,7 +392,7 @@ public void testConditionalRemoveThrowsOnlySAE() throws Exception { ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.getAndAppend(anyLong(), any())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); store.remove(1L, "one"); } @@ -402,7 +403,7 @@ public void testConditionalRemoveTimeout() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); when(proxy.getAndAppend(anyLong(), isNull())).thenThrow(TimeoutException.class); - ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null); assertTimeoutOccurred(() -> store.remove(1L, "one")); } @@ -425,7 +426,7 @@ public void testReplaceThrowsOnlySAE() throws Exception { ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.getAndAppend(anyLong(), any())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); store.replace(1L, "one"); } @@ -436,7 +437,7 @@ public void testReplaceTimeout() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); when(proxy.getAndAppend(anyLong(), isNull())).thenThrow(TimeoutException.class); - ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null); assertTimeoutOccurred(() -> store.replace(1L, "one")); } @@ -463,7 +464,7 @@ public void testConditionalReplaceThrowsOnlySAE() throws Exception { ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.getAndAppend(anyLong(), any())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); store.replace(1L, "one", "another one"); } @@ -474,7 +475,7 @@ public void testConditionalReplaceTimeout() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); when(proxy.getAndAppend(anyLong(), isNull())).thenThrow(TimeoutException.class); - ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null); assertTimeoutOccurred(() -> store.replace(1L, "one", "another one")); } @@ -559,7 +560,7 @@ public void testExpirationIsSentToHigherTiers() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource, null); Store.ValueHolder vh = store.get(1L); @@ -584,7 +585,7 @@ public void testNoExpireIsSentToHigherTiers() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource); + ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource, null); Store.ValueHolder vh = store.get(1L); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java index e8e254b279..b5a9360a1d 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java @@ -15,25 +15,30 @@ */ package org.ehcache.clustered.client.internal.store; -import org.ehcache.clustered.client.config.ClusteredResourcePool; -import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; +import org.ehcache.clustered.Matchers; import org.ehcache.clustered.client.internal.store.ServerStoreProxy.ServerCallback; -import org.ehcache.clustered.common.internal.ServerStoreConfiguration; +import org.ehcache.clustered.common.Consistency; import org.ehcache.clustered.common.internal.store.Chain; -import org.ehcache.config.units.MemoryUnit; -import org.ehcache.impl.serialization.LongSerializer; +import org.ehcache.clustered.common.internal.store.Element; +import org.ehcache.clustered.server.store.ObservableClusterTierServerEntityService; import org.hamcrest.CoreMatchers; import org.hamcrest.Matcher; +import org.hamcrest.MatcherAssert; +import org.hamcrest.core.Is; import org.junit.Test; import java.nio.ByteBuffer; import java.util.Iterator; +import java.util.List; import java.util.NoSuchElementException; +import java.util.concurrent.CopyOnWriteArrayList; import static org.ehcache.clustered.ChainUtils.chainOf; import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.Matchers.hasPayloads; +import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.CombinableMatcher.either; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; @@ -45,21 +50,216 @@ public class CommonServerStoreProxyTest extends AbstractServerStoreProxyTest { - private static ClusterTierClientEntity createClientEntity(String name) throws Exception { - ClusteredResourcePool resourcePool = ClusteredResourcePoolBuilder.clusteredDedicated(8L, MemoryUnit.MB); + @Test + public void testInvalidationsContainChains() throws Exception { + SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testInvalidationsContainChains", Consistency.EVENTUAL, true); + SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testInvalidationsContainChains", Consistency.EVENTUAL, false); + + final List store1InvalidatedHashes = new CopyOnWriteArrayList<>(); + final List store1InvalidatedChains = new CopyOnWriteArrayList<>(); + final List store2InvalidatedHashes = new CopyOnWriteArrayList<>(); + final List store2InvalidatedChains = new CopyOnWriteArrayList<>(); + + EventualServerStoreProxy serverStoreProxy1 = new EventualServerStoreProxy("testInvalidationsContainChains", clientEntity1, new ServerCallback() { + @Override + public void onInvalidateHash(long hash, Chain evictedChain) { + store1InvalidatedHashes.add(hash); + if (evictedChain != null) { + // make sure the chain's elements' buffers are correctly sized + for (Element element : evictedChain) { + assertThat(element.getPayload().limit(), is(512 * 1024)); + } + store1InvalidatedChains.add(evictedChain); + } + } + + @Override + public void onInvalidateAll() { + fail("should not be called"); + } + + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + // make sure the appended buffer is correctly sized + assertThat(appended.limit(), is(512 * 1024)); + // make sure the chain's elements' buffers are correctly sized + for (Element element : beforeAppend) { + assertThat(element.getPayload().limit(), is(512 * 1024)); + } + } + + @Override + public void compact(ServerStoreProxy.ChainEntry chain) { + fail("should not be called"); + } + }); + serverStoreProxy1.enableEvents(true); + EventualServerStoreProxy serverStoreProxy2 = new EventualServerStoreProxy("testInvalidationsContainChains", clientEntity2, new ServerCallback() { + @Override + public void onInvalidateHash(long hash, Chain evictedChain) { + store2InvalidatedHashes.add(hash); + if (evictedChain != null) { + // make sure the chain's elements' buffers are correctly sized + for (Element element : evictedChain) { + assertThat(element.getPayload().limit(), is(512 * 1024)); + } + store2InvalidatedChains.add(evictedChain); + } + } + + @Override + public void onInvalidateAll() { + fail("should not be called"); + } + + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + // make sure the appended buffer is correctly sized + assertThat(appended.limit(), is(512 * 1024)); + // make sure the chain's elements' buffers are correctly sized + for (Element element : beforeAppend) { + assertThat(element.getPayload().limit(), is(512 * 1024)); + } + } + + @Override + public void compact(ServerStoreProxy.ChainEntry chain) { + fail("should not be called"); + } + }); + serverStoreProxy2.enableEvents(true); + + final int ITERATIONS = 40; + for (int i = 0; i < ITERATIONS; i++) { + serverStoreProxy1.append(i, createPayload(i, 512 * 1024)); + } - ServerStoreConfiguration serverStoreConfiguration = new ServerStoreConfiguration(resourcePool.getPoolAllocation(), Long.class - .getName(), - Long.class.getName(), LongSerializer.class.getName(), LongSerializer.class - .getName(), null, false); + int evictionCount = 0; + int entryCount = 0; + for (int i = 0; i < ITERATIONS; i++) { + Chain elements1 = serverStoreProxy1.get(i); + Chain elements2 = serverStoreProxy2.get(i); + MatcherAssert.assertThat(elements1, Matchers.matchesChain(elements2)); + if (!elements1.isEmpty()) { + entryCount++; + } else { + evictionCount++; + } + } - return createClientEntity(name, serverStoreConfiguration, true); + // there has to be server-side evictions, otherwise this test is useless + MatcherAssert.assertThat(store1InvalidatedHashes.size(), greaterThan(0)); + // test that each time the server evicted, the originating client got notified + MatcherAssert.assertThat(store1InvalidatedHashes.size(), Is.is(ITERATIONS - entryCount)); + // test that each time the server evicted, the other client got notified on top of normal invalidations + MatcherAssert.assertThat(store2InvalidatedHashes.size(), Is.is(ITERATIONS + evictionCount)); + // test that we got evicted chains + MatcherAssert.assertThat(store1InvalidatedChains.size(), greaterThan(0)); + MatcherAssert.assertThat(store2InvalidatedChains.size(), is(store1InvalidatedChains.size())); + + assertThatClientsWaitingForInvalidationIsEmpty("testInvalidationsContainChains"); + } + + @Test + public void testAppendFireEvents() throws Exception { + SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testAppendFireEvents", Consistency.EVENTUAL, true); + SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testAppendFireEvents", Consistency.EVENTUAL, false); + + final List store1AppendedBuffers = new CopyOnWriteArrayList<>(); + final List store1Chains = new CopyOnWriteArrayList<>(); + final List store2AppendedBuffers = new CopyOnWriteArrayList<>(); + final List store2Chains = new CopyOnWriteArrayList<>(); + + EventualServerStoreProxy serverStoreProxy1 = new EventualServerStoreProxy("testAppendFireEvents", clientEntity1, new ServerCallback() { + @Override + public void onInvalidateHash(long hash, Chain evictedChain) { + fail("should not be called"); + } + + @Override + public void onInvalidateAll() { + fail("should not be called"); + } + + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + // make sure the appended buffer is correctly sized + assertThat(appended.limit(), is(512)); + // make sure the chain's elements' buffers are correctly sized + for (Element element : beforeAppend) { + assertThat(element.getPayload().limit(), is(512)); + } + store1AppendedBuffers.add(appended); + store1Chains.add(beforeAppend); + } + + @Override + public void compact(ServerStoreProxy.ChainEntry chain) { + fail("should not be called"); + } + }); + serverStoreProxy1.enableEvents(true); + EventualServerStoreProxy serverStoreProxy2 = new EventualServerStoreProxy("testAppendFireEvents", clientEntity2, new ServerCallback() { + @Override + public void onInvalidateHash(long hash, Chain evictedChain) { + // make sure those only are cross-client invalidations and not server evictions + assertThat(evictedChain, is(nullValue())); + } + + @Override + public void onInvalidateAll() { + fail("should not be called"); + } + + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + // make sure the appended buffer is correctly sized + assertThat(appended.limit(), is(512)); + // make sure the chain's elements' buffers are correctly sized + for (Element element : beforeAppend) { + assertThat(element.getPayload().limit(), is(512)); + } + store2AppendedBuffers.add(appended); + store2Chains.add(beforeAppend); + } + + @Override + public void compact(ServerStoreProxy.ChainEntry chain) { + fail("should not be called"); + } + }); + serverStoreProxy2.enableEvents(true); + + serverStoreProxy1.append(1L, createPayload(1L, 512)); + Chain c = serverStoreProxy1.getAndAppend(1L, createPayload(2L, 512)); + assertThat(c.length(), is(1)); + + assertThatClientsWaitingForInvalidationIsEmpty("testAppendFireEvents"); + + assertThat(store1AppendedBuffers.size(), is(2)); + assertThat(store1AppendedBuffers.get(0).asLongBuffer().get(), is(1L)); + assertThat(store1AppendedBuffers.get(1).asLongBuffer().get(), is(2L)); + assertThat(store1Chains.size(), is(2)); + assertThat(store1Chains.get(0).length(), is(0)); + assertThat(store1Chains.get(1).length(), is(1)); + assertThat(store2AppendedBuffers.size(), is(2)); + assertThat(store2AppendedBuffers.get(0).asLongBuffer().get(), is(1L)); + assertThat(store2AppendedBuffers.get(1).asLongBuffer().get(), is(2L)); + assertThat(store2Chains.size(), is(2)); + assertThat(store2Chains.get(0).length(), is(0)); + assertThat(store2Chains.get(1).length(), is(1)); + } + private static void assertThatClientsWaitingForInvalidationIsEmpty(String name) throws Exception { + ObservableClusterTierServerEntityService.ObservableClusterTierActiveEntity activeEntity = observableClusterTierService.getServedActiveEntitiesFor(name).get(0); + long now = System.currentTimeMillis(); + while (System.currentTimeMillis() < now + 5000 && activeEntity.getClientsWaitingForInvalidation().size() != 0); + MatcherAssert.assertThat(activeEntity.getClientsWaitingForInvalidation().size(), Is.is(0)); } @Test public void testGetKeyNotPresent() throws Exception { - ClusterTierClientEntity clientEntity = createClientEntity("testGetKeyNotPresent"); + ClusterTierClientEntity clientEntity = createClientEntity("testGetKeyNotPresent", Consistency.EVENTUAL, true); CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testGetKeyNotPresent", clientEntity, mock(ServerCallback.class)); Chain chain = serverStoreProxy.get(1); @@ -69,7 +269,7 @@ public void testGetKeyNotPresent() throws Exception { @Test public void testAppendKeyNotPresent() throws Exception { - ClusterTierClientEntity clientEntity = createClientEntity("testAppendKeyNotPresent"); + ClusterTierClientEntity clientEntity = createClientEntity("testAppendKeyNotPresent", Consistency.EVENTUAL, true); CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testAppendKeyNotPresent", clientEntity, mock(ServerCallback.class)); serverStoreProxy.append(2, createPayload(2)); @@ -81,7 +281,7 @@ public void testAppendKeyNotPresent() throws Exception { @Test public void testGetAfterMultipleAppendsOnSameKey() throws Exception { - ClusterTierClientEntity clientEntity = createClientEntity("testGetAfterMultipleAppendsOnSameKey"); + ClusterTierClientEntity clientEntity = createClientEntity("testGetAfterMultipleAppendsOnSameKey", Consistency.EVENTUAL, true); CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testGetAfterMultipleAppendsOnSameKey", clientEntity, mock(ServerCallback.class)); serverStoreProxy.append(3L, createPayload(3L)); @@ -97,7 +297,7 @@ public void testGetAfterMultipleAppendsOnSameKey() throws Exception { @Test public void testGetAndAppendKeyNotPresent() throws Exception { - ClusterTierClientEntity clientEntity = createClientEntity("testGetAndAppendKeyNotPresent"); + ClusterTierClientEntity clientEntity = createClientEntity("testGetAndAppendKeyNotPresent", Consistency.EVENTUAL, true); CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testGetAndAppendKeyNotPresent", clientEntity, mock(ServerCallback.class)); Chain chain = serverStoreProxy.getAndAppend(4L, createPayload(4L)); @@ -111,7 +311,7 @@ public void testGetAndAppendKeyNotPresent() throws Exception { @Test public void testGetAndAppendMultipleTimesOnSameKey() throws Exception { - ClusterTierClientEntity clientEntity = createClientEntity("testGetAndAppendMultipleTimesOnSameKey"); + ClusterTierClientEntity clientEntity = createClientEntity("testGetAndAppendMultipleTimesOnSameKey", Consistency.EVENTUAL, true); CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testGetAndAppendMultipleTimesOnSameKey", clientEntity, mock(ServerCallback.class)); serverStoreProxy.getAndAppend(5L, createPayload(5L)); serverStoreProxy.getAndAppend(5L, createPayload(55L)); @@ -124,7 +324,7 @@ public void testGetAndAppendMultipleTimesOnSameKey() throws Exception { @Test public void testReplaceAtHeadSuccessFull() throws Exception { - ClusterTierClientEntity clientEntity = createClientEntity("testReplaceAtHeadSuccessFull"); + ClusterTierClientEntity clientEntity = createClientEntity("testReplaceAtHeadSuccessFull", Consistency.EVENTUAL, true); CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testReplaceAtHeadSuccessFull", clientEntity, mock(ServerCallback.class)); serverStoreProxy.append(20L, createPayload(200L)); serverStoreProxy.append(20L, createPayload(2000L)); @@ -150,7 +350,7 @@ public void testReplaceAtHeadSuccessFull() throws Exception { @Test public void testClear() throws Exception { - ClusterTierClientEntity clientEntity = createClientEntity("testClear"); + ClusterTierClientEntity clientEntity = createClientEntity("testClear", Consistency.EVENTUAL, true); CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testClear", clientEntity, mock(ServerCallback.class)); serverStoreProxy.append(1L, createPayload(100L)); @@ -163,7 +363,7 @@ public void testClear() throws Exception { public void testResolveRequestIsProcessedAtThreshold() throws Exception { ByteBuffer buffer = createPayload(42L); - ClusterTierClientEntity clientEntity = createClientEntity("testResolveRequestIsProcessed"); + ClusterTierClientEntity clientEntity = createClientEntity("testResolveRequestIsProcessed", Consistency.EVENTUAL, true); ServerCallback serverCallback = mock(ServerCallback.class); doAnswer(inv -> { ServerStoreProxy.ChainEntry entry = inv.getArgument(0); @@ -187,7 +387,7 @@ public void testResolveRequestIsProcessedAtThreshold() throws Exception { @Test public void testEmptyStoreIteratorIsEmpty() throws Exception { - ClusterTierClientEntity clientEntity = createClientEntity("testEmptyStoreIteratorIsEmpty"); + ClusterTierClientEntity clientEntity = createClientEntity("testEmptyStoreIteratorIsEmpty", Consistency.EVENTUAL, true); CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testEmptyStoreIteratorIsEmpty", clientEntity, mock(ServerCallback.class)); Iterator iterator = serverStoreProxy.iterator(); @@ -203,7 +403,7 @@ public void testEmptyStoreIteratorIsEmpty() throws Exception { @Test public void testSingleChainIterator() throws Exception { - ClusterTierClientEntity clientEntity = createClientEntity("testSingleChainIterator"); + ClusterTierClientEntity clientEntity = createClientEntity("testSingleChainIterator", Consistency.EVENTUAL, true); CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testSingleChainIterator", clientEntity, mock(ServerCallback.class)); serverStoreProxy.append(1L, createPayload(42L)); @@ -223,7 +423,7 @@ public void testSingleChainIterator() throws Exception { @Test public void testSingleChainMultipleElements() throws Exception { - ClusterTierClientEntity clientEntity = createClientEntity("testSingleChainMultipleElements"); + ClusterTierClientEntity clientEntity = createClientEntity("testSingleChainMultipleElements", Consistency.EVENTUAL, true); CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testSingleChainMultipleElements", clientEntity, mock(ServerCallback.class)); serverStoreProxy.append(1L, createPayload(42L)); @@ -244,7 +444,7 @@ public void testSingleChainMultipleElements() throws Exception { @Test public void testMultipleChains() throws Exception { - ClusterTierClientEntity clientEntity = createClientEntity("testMultipleChains"); + ClusterTierClientEntity clientEntity = createClientEntity("testMultipleChains", Consistency.EVENTUAL, true); CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testMultipleChains", clientEntity, mock(ServerCallback.class)); serverStoreProxy.append(1L, createPayload(42L)); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java index 9c662f31c6..8291a482c4 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java @@ -16,17 +16,13 @@ package org.ehcache.clustered.client.internal.store; import org.ehcache.clustered.Matchers; -import org.ehcache.clustered.client.config.ClusteredResourcePool; -import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.internal.store.ServerStoreProxy.ServerCallback; import org.ehcache.clustered.common.Consistency; -import org.ehcache.clustered.common.internal.ServerStoreConfiguration; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.server.store.ObservableClusterTierServerEntityService.ObservableClusterTierActiveEntity; -import org.ehcache.config.units.MemoryUnit; -import org.ehcache.impl.serialization.LongSerializer; import org.junit.Test; +import java.nio.ByteBuffer; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; @@ -43,27 +39,17 @@ public class EventualServerStoreProxyTest extends AbstractServerStoreProxyTest { - private static SimpleClusterTierClientEntity createClientEntity(String name, boolean create) throws Exception { - ClusteredResourcePool resourcePool = ClusteredResourcePoolBuilder.clusteredDedicated(8L, MemoryUnit.MB); - - ServerStoreConfiguration serverStoreConfiguration = new ServerStoreConfiguration(resourcePool.getPoolAllocation(), Long.class.getName(), - Long.class.getName(), LongSerializer.class.getName(), LongSerializer.class - .getName(), Consistency.EVENTUAL, false); - - return createClientEntity(name, serverStoreConfiguration, create); - } - @Test public void testServerSideEvictionFiresInvalidations() throws Exception { - SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testServerSideEvictionFiresInvalidations", true); - SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testServerSideEvictionFiresInvalidations", false); + SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testServerSideEvictionFiresInvalidations", Consistency.EVENTUAL, true); + SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testServerSideEvictionFiresInvalidations", Consistency.EVENTUAL, false); final List store1InvalidatedHashes = new CopyOnWriteArrayList<>(); final List store2InvalidatedHashes = new CopyOnWriteArrayList<>(); EventualServerStoreProxy serverStoreProxy1 = new EventualServerStoreProxy("testServerSideEvictionFiresInvalidations", clientEntity1, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { store1InvalidatedHashes.add(hash); } @@ -72,6 +58,11 @@ public void onInvalidateAll() { fail("should not be called"); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + fail("should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); @@ -79,7 +70,7 @@ public void compact(ServerStoreProxy.ChainEntry chain) { }); EventualServerStoreProxy serverStoreProxy2 = new EventualServerStoreProxy("testServerSideEvictionFiresInvalidations", clientEntity2, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { store2InvalidatedHashes.add(hash); } @@ -88,6 +79,11 @@ public void onInvalidateAll() { fail("should not be called"); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + fail("should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { } @@ -123,8 +119,8 @@ public void compact(ServerStoreProxy.ChainEntry chain) { @Test public void testHashInvalidationListenerWithAppend() throws Exception { - SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testHashInvalidationListenerWithAppend", true); - SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testHashInvalidationListenerWithAppend", false); + SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testHashInvalidationListenerWithAppend", Consistency.EVENTUAL, true); + SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testHashInvalidationListenerWithAppend", Consistency.EVENTUAL, false); final CountDownLatch latch = new CountDownLatch(1); final AtomicReference invalidatedHash = new AtomicReference<>(); @@ -132,7 +128,7 @@ public void testHashInvalidationListenerWithAppend() throws Exception { EventualServerStoreProxy serverStoreProxy1 = new EventualServerStoreProxy("testHashInvalidationListenerWithAppend", clientEntity1, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { invalidatedHash.set(hash); latch.countDown(); } @@ -142,6 +138,11 @@ public void onInvalidateAll() { throw new AssertionError("Should not be called"); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + fail("should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); @@ -158,8 +159,8 @@ public void compact(ServerStoreProxy.ChainEntry chain) { @Test public void testHashInvalidationListenerWithGetAndAppend() throws Exception { - SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testHashInvalidationListenerWithGetAndAppend", true); - SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testHashInvalidationListenerWithGetAndAppend", false); + SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testHashInvalidationListenerWithGetAndAppend", Consistency.EVENTUAL, true); + SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testHashInvalidationListenerWithGetAndAppend", Consistency.EVENTUAL, false); final CountDownLatch latch = new CountDownLatch(1); final AtomicReference invalidatedHash = new AtomicReference<>(); @@ -167,7 +168,7 @@ public void testHashInvalidationListenerWithGetAndAppend() throws Exception { EventualServerStoreProxy serverStoreProxy1 = new EventualServerStoreProxy("testHashInvalidationListenerWithGetAndAppend", clientEntity1, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { invalidatedHash.set(hash); latch.countDown(); } @@ -177,6 +178,11 @@ public void onInvalidateAll() { throw new AssertionError("Should not be called"); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + fail("should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); @@ -193,15 +199,15 @@ public void compact(ServerStoreProxy.ChainEntry chain) { @Test public void testAllInvalidationListener() throws Exception { - SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testAllInvalidationListener", true); - SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testAllInvalidationListener", false); + SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testAllInvalidationListener", Consistency.EVENTUAL, true); + SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testAllInvalidationListener", Consistency.EVENTUAL, false); final CountDownLatch latch = new CountDownLatch(1); final AtomicBoolean invalidatedAll = new AtomicBoolean(); EventualServerStoreProxy serverStoreProxy1 = new EventualServerStoreProxy("testAllInvalidationListener", clientEntity1, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { throw new AssertionError("Should not be called"); } @@ -211,6 +217,11 @@ public void onInvalidateAll() { latch.countDown(); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + fail("should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java index 7e4e36c81d..c03d933856 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java @@ -20,11 +20,13 @@ import org.ehcache.clustered.client.internal.store.ServerStoreProxy.ServerCallback; import org.ehcache.clustered.common.Consistency; import org.ehcache.clustered.common.internal.ServerStoreConfiguration; +import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.config.units.MemoryUnit; import org.ehcache.impl.serialization.LongSerializer; import org.junit.Assert; import org.junit.Test; +import java.nio.ByteBuffer; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -66,7 +68,7 @@ public void testConcurrentHashInvalidationListenerWithAppend() throws Exception SimpleClusterTierClientEntity clientEntity2 = createClientEntity(ENTITY_NAME, getServerStoreConfiguration(), false, false); StrongServerStoreProxy serverStoreProxy2 = new StrongServerStoreProxy(ENTITY_NAME, clientEntity2, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { invalidatedHash.set(hash); } @@ -75,6 +77,11 @@ public void onInvalidateAll() { throw new AssertionError("Should not be called"); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + throw new AssertionError("Should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java index be04af279c..0ecf4dae20 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java @@ -15,18 +15,14 @@ */ package org.ehcache.clustered.client.internal.store; -import org.ehcache.clustered.client.config.ClusteredResourcePool; import org.ehcache.clustered.client.config.Timeouts; -import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.internal.store.ServerStoreProxy.ServerCallback; import org.ehcache.clustered.common.Consistency; -import org.ehcache.clustered.common.internal.ServerStoreConfiguration; import org.ehcache.clustered.common.internal.store.Chain; -import org.ehcache.config.units.MemoryUnit; -import org.ehcache.impl.serialization.LongSerializer; import org.junit.Test; import org.terracotta.exception.ConnectionClosedException; +import java.nio.ByteBuffer; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; @@ -51,27 +47,17 @@ public class StrongServerStoreProxyTest extends AbstractServerStoreProxyTest { - private static SimpleClusterTierClientEntity createClientEntity(String name, boolean create) throws Exception { - ClusteredResourcePool resourcePool = ClusteredResourcePoolBuilder.clusteredDedicated(4L, MemoryUnit.MB); - - ServerStoreConfiguration serverStoreConfiguration = new ServerStoreConfiguration(resourcePool.getPoolAllocation(), Long.class.getName(), - Long.class.getName(), LongSerializer.class.getName(), LongSerializer.class - .getName(), Consistency.STRONG, false); - - return createClientEntity(name, serverStoreConfiguration, create); - } - @Test public void testServerSideEvictionFiresInvalidations() throws Exception { - SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testServerSideEvictionFiresInvalidations", true); - SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testServerSideEvictionFiresInvalidations", false); + SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testServerSideEvictionFiresInvalidations", Consistency.STRONG, true); + SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testServerSideEvictionFiresInvalidations", Consistency.STRONG, false); final List store1InvalidatedHashes = new CopyOnWriteArrayList<>(); final List store2InvalidatedHashes = new CopyOnWriteArrayList<>(); StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testServerSideEvictionFiresInvalidations", clientEntity1, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { store1InvalidatedHashes.add(hash); } @@ -80,6 +66,11 @@ public void onInvalidateAll() { fail("should not be called"); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + fail("should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); @@ -87,7 +78,7 @@ public void compact(ServerStoreProxy.ChainEntry chain) { }); StrongServerStoreProxy serverStoreProxy2 = new StrongServerStoreProxy("testServerSideEvictionFiresInvalidations", clientEntity2, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { store2InvalidatedHashes.add(hash); } @@ -96,6 +87,11 @@ public void onInvalidateAll() { fail("should not be called"); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + fail("should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { } @@ -129,15 +125,15 @@ public void compact(ServerStoreProxy.ChainEntry chain) { @Test public void testHashInvalidationListenerWithAppend() throws Exception { - SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testHashInvalidationListenerWithAppend", true); - SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testHashInvalidationListenerWithAppend", false); + SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testHashInvalidationListenerWithAppend", Consistency.STRONG, true); + SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testHashInvalidationListenerWithAppend", Consistency.STRONG, false); final AtomicReference invalidatedHash = new AtomicReference<>(); StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testHashInvalidationListenerWithAppend", clientEntity1, mock(ServerCallback.class)); StrongServerStoreProxy serverStoreProxy2 = new StrongServerStoreProxy("testHashInvalidationListenerWithAppend", clientEntity2, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { invalidatedHash.set(hash); } @@ -146,6 +142,11 @@ public void onInvalidateAll() { throw new AssertionError("Should not be called"); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + fail("should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); @@ -159,15 +160,15 @@ public void compact(ServerStoreProxy.ChainEntry chain) { @Test public void testConcurrentHashInvalidationListenerWithAppend() throws Exception { - SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testConcurrentHashInvalidationListenerWithAppend", true); - SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testConcurrentHashInvalidationListenerWithAppend", false); + SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testConcurrentHashInvalidationListenerWithAppend", Consistency.STRONG, true); + SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testConcurrentHashInvalidationListenerWithAppend", Consistency.STRONG, false); final AtomicBoolean invalidating = new AtomicBoolean(); final CountDownLatch latch = new CountDownLatch(2); StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testConcurrentHashInvalidationListenerWithAppend", clientEntity1, mock(ServerCallback.class)); StrongServerStoreProxy serverStoreProxy2 = new StrongServerStoreProxy("testConcurrentHashInvalidationListenerWithAppend", clientEntity2, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { if (!invalidating.compareAndSet(false, true)) { fail("Both threads entered the listener concurrently"); } @@ -185,6 +186,11 @@ public void onInvalidateAll() { throw new AssertionError("Should not be called"); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + fail("should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); @@ -212,15 +218,15 @@ public void compact(ServerStoreProxy.ChainEntry chain) { @Test public void testHashInvalidationListenerWithGetAndAppend() throws Exception { - SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testHashInvalidationListenerWithGetAndAppend", true); - SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testHashInvalidationListenerWithGetAndAppend", false); + SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testHashInvalidationListenerWithGetAndAppend", Consistency.STRONG, true); + SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testHashInvalidationListenerWithGetAndAppend", Consistency.STRONG, false); final AtomicReference invalidatedHash = new AtomicReference<>(); StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testHashInvalidationListenerWithGetAndAppend", clientEntity1, mock(ServerCallback.class)); StrongServerStoreProxy serverStoreProxy2 = new StrongServerStoreProxy("testHashInvalidationListenerWithGetAndAppend", clientEntity2, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { invalidatedHash.set(hash); } @@ -229,6 +235,11 @@ public void onInvalidateAll() { throw new AssertionError("Should not be called"); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + fail("should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); @@ -242,15 +253,15 @@ public void compact(ServerStoreProxy.ChainEntry chain) { @Test public void testAllInvalidationListener() throws Exception { - SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testAllInvalidationListener", true); - SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testAllInvalidationListener", false); + SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testAllInvalidationListener", Consistency.STRONG, true); + SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testAllInvalidationListener", Consistency.STRONG, false); final AtomicBoolean invalidatedAll = new AtomicBoolean(); StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testAllInvalidationListener", clientEntity1, mock(ServerCallback.class)); StrongServerStoreProxy serverStoreProxy2 = new StrongServerStoreProxy("testAllInvalidationListener", clientEntity2, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { throw new AssertionError("Should not be called"); } @@ -259,6 +270,11 @@ public void onInvalidateAll() { invalidatedAll.set(true); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + fail("should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); @@ -272,8 +288,8 @@ public void compact(ServerStoreProxy.ChainEntry chain) { @Test public void testConcurrentAllInvalidationListener() throws Exception { - SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testConcurrentAllInvalidationListener", true); - SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testConcurrentAllInvalidationListener", false); + SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testConcurrentAllInvalidationListener", Consistency.STRONG, true); + SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testConcurrentAllInvalidationListener", Consistency.STRONG, false); final AtomicBoolean invalidating = new AtomicBoolean(); final CountDownLatch latch = new CountDownLatch(2); @@ -281,7 +297,7 @@ public void testConcurrentAllInvalidationListener() throws Exception { StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testConcurrentAllInvalidationListener", clientEntity1, mock(ServerCallback.class)); StrongServerStoreProxy serverStoreProxy2 = new StrongServerStoreProxy("testConcurrentAllInvalidationListener", clientEntity2, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { throw new AssertionError("Should not be called"); } @@ -299,6 +315,11 @@ public void onInvalidateAll() { latch.countDown(); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + fail("should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); @@ -326,13 +347,13 @@ public void compact(ServerStoreProxy.ChainEntry chain) { @Test public void testAppendInvalidationUnblockedByDisconnection() throws Exception { - SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testAppendInvalidationUnblockedByDisconnection", true); - SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testAppendInvalidationUnblockedByDisconnection", false); + SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testAppendInvalidationUnblockedByDisconnection", Consistency.STRONG, true); + SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testAppendInvalidationUnblockedByDisconnection", Consistency.STRONG, false); StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testAppendInvalidationUnblockedByDisconnection", clientEntity1, mock(ServerCallback.class)); StrongServerStoreProxy serverStoreProxy2 = new StrongServerStoreProxy("testAppendInvalidationUnblockedByDisconnection", clientEntity2, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { clientEntity1.fireDisconnectionEvent(); } @@ -341,6 +362,11 @@ public void onInvalidateAll() { throw new AssertionError("Should not be called"); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + fail("should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); @@ -357,13 +383,13 @@ public void compact(ServerStoreProxy.ChainEntry chain) { @Test public void testClearInvalidationUnblockedByDisconnection() throws Exception { - SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testClearInvalidationUnblockedByDisconnection", true); - SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testClearInvalidationUnblockedByDisconnection", false); + SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testClearInvalidationUnblockedByDisconnection", Consistency.STRONG, true); + SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testClearInvalidationUnblockedByDisconnection", Consistency.STRONG, false); StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testClearInvalidationUnblockedByDisconnection", clientEntity1, mock(ServerCallback.class)); StrongServerStoreProxy serverStoreProxy2 = new StrongServerStoreProxy("testClearInvalidationUnblockedByDisconnection", clientEntity2, new ServerCallback() { @Override - public void onInvalidateHash(long hash) { + public void onInvalidateHash(long hash, Chain evictedChain) { throw new AssertionError("Should not be called"); } @@ -372,6 +398,11 @@ public void onInvalidateAll() { clientEntity1.fireDisconnectionEvent(); } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + fail("should not be called"); + } + @Override public void compact(ServerStoreProxy.ChainEntry chain) { throw new AssertionError(); diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java index a12775cfe3..606ec6e41a 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java @@ -97,6 +97,11 @@ public long getSequenceNumber() { public ByteBuffer getPayload() { return byteBuffer.asReadOnlyBuffer(); } + + @Override + public String toString() { + return "SequencedElement{sequence=" + sequence + " size=" + byteBuffer.capacity() + "}"; + } }); } } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ClusterTierReconnectMessage.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ClusterTierReconnectMessage.java index 49315a99d4..129cca97ea 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ClusterTierReconnectMessage.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ClusterTierReconnectMessage.java @@ -24,16 +24,19 @@ public class ClusterTierReconnectMessage { private final Set hashInvalidationsInProgress; private boolean clearInProgress = false; private final Set locksHeld; + private boolean eventsEnabled; - public ClusterTierReconnectMessage() { + public ClusterTierReconnectMessage(boolean eventsEnabled) { + this.eventsEnabled = eventsEnabled; hashInvalidationsInProgress = new HashSet<>(); locksHeld = new HashSet<>(); } - public ClusterTierReconnectMessage(Set hashInvalidationsInProgress, Set locksHeld, boolean clearInProgress) { + public ClusterTierReconnectMessage(Set hashInvalidationsInProgress, Set locksHeld, boolean clearInProgress, boolean eventsEnabled) { this.hashInvalidationsInProgress = hashInvalidationsInProgress; this.locksHeld = locksHeld; this.clearInProgress = clearInProgress; + this.eventsEnabled = eventsEnabled; } public void addInvalidationsInProgress(Set hashInvalidationsInProgress) { @@ -59,4 +62,8 @@ public boolean isClearInProgress() { public Set getLocksHeld() { return locksHeld; } + + public boolean isEventsEnabled() { + return eventsEnabled; + } } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java index dc4cb79056..08653adfca 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java @@ -21,6 +21,7 @@ import org.ehcache.clustered.common.internal.store.Chain; import org.terracotta.entity.EntityResponse; +import java.nio.ByteBuffer; import java.util.List; import java.util.Set; import java.util.UUID; @@ -127,21 +128,55 @@ public final EhcacheResponseType getResponseType() { } } - public static ServerInvalidateHash serverInvalidateHash(long key) { - return new ServerInvalidateHash(key); + public static ServerAppend serverAppend(ByteBuffer appended, Chain beforeAppend) { + return new ServerAppend(appended, beforeAppend); } + public static class ServerAppend extends EhcacheEntityResponse { + private final ByteBuffer appended; + private final Chain beforeAppend; + + ServerAppend(ByteBuffer appended, Chain beforeAppend) { + this.appended = appended; + this.beforeAppend = beforeAppend; + } + + public ByteBuffer getAppended() { + return appended; + } + + public Chain getBeforeAppend() { + return beforeAppend; + } + + @Override + public EhcacheResponseType getResponseType() { + return EhcacheResponseType.SERVER_APPEND; + } + } + + public static ServerInvalidateHash serverInvalidateHash(long key, Chain evictedChain) { + return new ServerInvalidateHash(key, evictedChain); + } + + // this is fired when the server evicts a chain public static class ServerInvalidateHash extends EhcacheEntityResponse { private final long key; + private final Chain evictedChain; - private ServerInvalidateHash(long key) { + private ServerInvalidateHash(long key, Chain evictedChain) { this.key = key; + this.evictedChain = evictedChain; } public long getKey() { return key; } + public Chain getEvictedChain() { + return evictedChain; + } + @Override public final EhcacheResponseType getResponseType() { return EhcacheResponseType.SERVER_INVALIDATE_HASH; @@ -152,6 +187,7 @@ public static ClientInvalidateHash clientInvalidateHash(long key, int invalidati return new ClientInvalidateHash(key, invalidationId); } + // this is fired when a client modifies a chain (i.e.: on append) public static class ClientInvalidateHash extends EhcacheEntityResponse { private final long key; private final int invalidationId; diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java index c1243b4ef0..5802e615ad 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java @@ -47,6 +47,7 @@ public enum EhcacheMessageType { ITERATOR_OPEN, ITERATOR_CLOSE, ITERATOR_ADVANCE, + ENABLE_EVENT_LISTENER, // StateRepository operation messages GET_STATE_REPO, @@ -77,6 +78,7 @@ public enum EhcacheMessageType { .mapping(ITERATOR_OPEN, 30) .mapping(ITERATOR_CLOSE, 31) .mapping(ITERATOR_ADVANCE, 32) + .mapping(ENABLE_EVENT_LISTENER, 33) .mapping(GET_STATE_REPO, 41) .mapping(PUT_IF_ABSENT, 42) @@ -93,7 +95,7 @@ public static boolean isLifecycleMessage(EhcacheMessageType value) { } public static final EnumSet STORE_OPERATION_MESSAGES = of(GET_AND_APPEND, APPEND, - REPLACE, CLIENT_INVALIDATION_ACK, CLIENT_INVALIDATION_ALL_ACK, CLEAR, GET_STORE, LOCK, UNLOCK, ITERATOR_OPEN, ITERATOR_CLOSE, ITERATOR_ADVANCE); + REPLACE, CLIENT_INVALIDATION_ACK, CLIENT_INVALIDATION_ALL_ACK, CLEAR, GET_STORE, LOCK, UNLOCK, ITERATOR_OPEN, ITERATOR_CLOSE, ITERATOR_ADVANCE, ENABLE_EVENT_LISTENER); public static boolean isStoreOperationMessage(EhcacheMessageType value) { return STORE_OPERATION_MESSAGES.contains(value); } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java index 6fa8c80e61..59cacfcc3a 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java @@ -37,7 +37,9 @@ public enum EhcacheResponseType { RESOLVE_REQUEST, LOCK_SUCCESS, LOCK_FAILURE, - ITERATOR_BATCH; + ITERATOR_BATCH, + SERVER_APPEND, + ; public static final String RESPONSE_TYPE_FIELD_NAME = "opCode"; @@ -57,5 +59,6 @@ public enum EhcacheResponseType { .mapping(EhcacheResponseType.LOCK_SUCCESS, 91) .mapping(EhcacheResponseType.LOCK_FAILURE, 92) .mapping(EhcacheResponseType.ITERATOR_BATCH, 93) + .mapping(EhcacheResponseType.SERVER_APPEND, 94) .build(); } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodec.java index b68a4ef661..d21fbb6ce6 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodec.java @@ -33,11 +33,13 @@ public class ReconnectMessageCodec { private static final String HASH_INVALIDATION_IN_PROGRESS_FIELD = "hashInvalidationInProgress"; private static final String CLEAR_IN_PROGRESS_FIELD = "clearInProgress"; private static final String LOCKS_HELD_FIELD = "locksHeld"; + private static final String EVENTS_ENABLED_FIELD = "eventsEnabled"; private static final Struct CLUSTER_TIER_RECONNECT_MESSAGE_STRUCT = newStructBuilder() .int64s(HASH_INVALIDATION_IN_PROGRESS_FIELD, 20) .bool(CLEAR_IN_PROGRESS_FIELD, 30) .int64s(LOCKS_HELD_FIELD, 40) + .bool(EVENTS_ENABLED_FIELD, 50) // added in 10.5.0 .build(); public byte[] encode(ClusterTierReconnectMessage reconnectMessage) { @@ -47,6 +49,7 @@ public byte[] encode(ClusterTierReconnectMessage reconnectMessage) { encoder.bool(CLEAR_IN_PROGRESS_FIELD, reconnectMessage.isClearInProgress()); ArrayEncoder> locksHeldEncoder = encoder.int64s(LOCKS_HELD_FIELD); reconnectMessage.getLocksHeld().forEach(locksHeldEncoder::value); + encoder.bool(EVENTS_ENABLED_FIELD, reconnectMessage.isEventsEnabled()); return encoder.encode().array(); } @@ -61,11 +64,9 @@ public ClusterTierReconnectMessage decode(byte[] payload) { ArrayDecoder> locksHeldDecoder = decoder.int64s(LOCKS_HELD_FIELD); Set locks = decodeLongs(locksHeldDecoder); - ClusterTierReconnectMessage message = new ClusterTierReconnectMessage(hashes, locks, clearInProgress != null ? clearInProgress : false); + Boolean eventsEnabled = decoder.bool(EVENTS_ENABLED_FIELD); - - - return message; + return new ClusterTierReconnectMessage(hashes, locks, clearInProgress != null ? clearInProgress : false, eventsEnabled != null ? eventsEnabled : false); } private static Set decodeLongs(ArrayDecoder> decoder) { diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java index bb08715a35..008b2fa3c5 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java @@ -39,12 +39,19 @@ import static java.nio.ByteBuffer.wrap; import static org.ehcache.clustered.common.internal.messages.ChainCodec.CHAIN_STRUCT; -import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.AllInvalidationDone; -import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.ClientInvalidateAll; -import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.ClientInvalidateHash; -import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.HashInvalidationDone; -import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.ServerInvalidateHash; -import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.MapValue; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.allInvalidationDone; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.clientInvalidateAll; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.clientInvalidateHash; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.failure; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.getResponse; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.hashInvalidationDone; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.lockFailure; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.mapValue; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.prepareForDestroy; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.resolveRequest; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.serverAppend; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.serverInvalidateHash; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.success; import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.EHCACHE_RESPONSE_TYPES_ENUM_MAPPING; import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.RESPONSE_TYPE_FIELD_INDEX; import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.RESPONSE_TYPE_FIELD_NAME; @@ -57,6 +64,7 @@ public class ResponseCodec { private static final String EXCEPTION_FIELD = "exception"; private static final String INVALIDATION_ID_FIELD = "invalidationId"; private static final String CHAIN_FIELD = "chain"; + private static final String APPENDED_FIELD = "appended"; private static final String MAP_VALUE_FIELD = "mapValue"; private static final String STORES_FIELD = "stores"; @@ -90,6 +98,12 @@ public class ResponseCodec { private static final Struct SERVER_INVALIDATE_HASH_RESPONSE_STRUCT = StructBuilder.newStructBuilder() .enm(RESPONSE_TYPE_FIELD_NAME, RESPONSE_TYPE_FIELD_INDEX, EHCACHE_RESPONSE_TYPES_ENUM_MAPPING) .int64(KEY_FIELD, 20) + .struct(CHAIN_FIELD, 30, CHAIN_STRUCT) // added in version 10.5.0 + .build(); + private static final Struct SERVER_APPEND_RESPONSE_STRUCT = StructBuilder.newStructBuilder() + .enm(RESPONSE_TYPE_FIELD_NAME, RESPONSE_TYPE_FIELD_INDEX, EHCACHE_RESPONSE_TYPES_ENUM_MAPPING) + .byteBuffer(APPENDED_FIELD, 20) + .struct(CHAIN_FIELD, 30, CHAIN_STRUCT) .build(); private static final Struct MAP_VALUE_RESPONSE_STRUCT = StructBuilder.newStructBuilder() .enm(RESPONSE_TYPE_FIELD_NAME, RESPONSE_TYPE_FIELD_INDEX, EHCACHE_RESPONSE_TYPES_ENUM_MAPPING) @@ -134,20 +148,20 @@ public byte[] encode(EhcacheEntityResponse response) { .struct(CHAIN_FIELD, getResponse.getChain(), ChainCodec::encode) .encode().array(); case HASH_INVALIDATION_DONE: { - HashInvalidationDone hashInvalidationDone = (HashInvalidationDone) response; + EhcacheEntityResponse.HashInvalidationDone hashInvalidationDone = (EhcacheEntityResponse.HashInvalidationDone) response; return HASH_INVALIDATION_DONE_RESPONSE_STRUCT.encoder() .enm(RESPONSE_TYPE_FIELD_NAME, hashInvalidationDone.getResponseType()) .int64(KEY_FIELD, hashInvalidationDone.getKey()) .encode().array(); } case ALL_INVALIDATION_DONE: { - AllInvalidationDone allInvalidationDone = (AllInvalidationDone) response; + EhcacheEntityResponse.AllInvalidationDone allInvalidationDone = (EhcacheEntityResponse.AllInvalidationDone) response; return ALL_INVALIDATION_DONE_RESPONSE_STRUCT.encoder() .enm(RESPONSE_TYPE_FIELD_NAME, allInvalidationDone.getResponseType()) .encode().array(); } case CLIENT_INVALIDATE_HASH: { - ClientInvalidateHash clientInvalidateHash = (ClientInvalidateHash) response; + EhcacheEntityResponse.ClientInvalidateHash clientInvalidateHash = (EhcacheEntityResponse.ClientInvalidateHash) response; return CLIENT_INVALIDATE_HASH_RESPONSE_STRUCT.encoder() .enm(RESPONSE_TYPE_FIELD_NAME, clientInvalidateHash.getResponseType()) .int64(KEY_FIELD, clientInvalidateHash.getKey()) @@ -155,21 +169,32 @@ public byte[] encode(EhcacheEntityResponse response) { .encode().array(); } case CLIENT_INVALIDATE_ALL: { - ClientInvalidateAll clientInvalidateAll = (ClientInvalidateAll) response; + EhcacheEntityResponse.ClientInvalidateAll clientInvalidateAll = (EhcacheEntityResponse.ClientInvalidateAll) response; return CLIENT_INVALIDATE_ALL_RESPONSE_STRUCT.encoder() .enm(RESPONSE_TYPE_FIELD_NAME, clientInvalidateAll.getResponseType()) .int32(INVALIDATION_ID_FIELD, clientInvalidateAll.getInvalidationId()) .encode().array(); } + case SERVER_APPEND: { + EhcacheEntityResponse.ServerAppend serverAppend = (EhcacheEntityResponse.ServerAppend) response; + return SERVER_APPEND_RESPONSE_STRUCT.encoder() + .enm(RESPONSE_TYPE_FIELD_NAME, serverAppend.getResponseType()) + .byteBuffer(APPENDED_FIELD, serverAppend.getAppended()) + .struct(CHAIN_FIELD, serverAppend.getBeforeAppend(), ChainCodec::encode) + .encode().array(); + } case SERVER_INVALIDATE_HASH: { - ServerInvalidateHash serverInvalidateHash = (ServerInvalidateHash) response; - return SERVER_INVALIDATE_HASH_RESPONSE_STRUCT.encoder() + EhcacheEntityResponse.ServerInvalidateHash serverInvalidateHash = (EhcacheEntityResponse.ServerInvalidateHash) response; + StructEncoder encoder = SERVER_INVALIDATE_HASH_RESPONSE_STRUCT.encoder() .enm(RESPONSE_TYPE_FIELD_NAME, serverInvalidateHash.getResponseType()) - .int64(KEY_FIELD, serverInvalidateHash.getKey()) - .encode().array(); + .int64(KEY_FIELD, serverInvalidateHash.getKey()); + if (serverInvalidateHash.getEvictedChain() != null) { + encoder.struct(CHAIN_FIELD, serverInvalidateHash.getEvictedChain(), ChainCodec::encode); + } + return encoder.encode().array(); } case MAP_VALUE: { - MapValue mapValue = (MapValue) response; + EhcacheEntityResponse.MapValue mapValue = (EhcacheEntityResponse.MapValue) response; byte[] encodedMapValue = Util.marshall(mapValue.getValue()); return MAP_VALUE_RESPONSE_STRUCT.encoder() .enm(RESPONSE_TYPE_FIELD_NAME, mapValue.getResponseType()) @@ -188,7 +213,7 @@ public byte[] encode(EhcacheEntityResponse response) { .encode().array(); } case RESOLVE_REQUEST: { - EhcacheEntityResponse.ResolveRequest resolve = (ResolveRequest) response; + ResolveRequest resolve = (ResolveRequest) response; return RESOLVE_REQUEST_RESPONSE_STRUCT.encoder() .enm(RESPONSE_TYPE_FIELD_NAME, resolve.getResponseType()) .int64(KEY_FIELD, resolve.getKey()) @@ -239,41 +264,50 @@ public EhcacheEntityResponse decode(byte[] payload) { buffer.rewind(); switch (opCode) { case SUCCESS: - return EhcacheEntityResponse.success(); + return success(); case FAILURE: decoder = FAILURE_RESPONSE_STRUCT.decoder(buffer); ClusterException exception = ExceptionCodec.decode(decoder.struct(EXCEPTION_FIELD)); - return EhcacheEntityResponse.failure(exception.withClientStackTrace()); + return failure(exception.withClientStackTrace()); case GET_RESPONSE: decoder = GET_RESPONSE_STRUCT.decoder(buffer); - return EhcacheEntityResponse.getResponse(ChainCodec.decode(decoder.struct(CHAIN_FIELD))); + return getResponse(ChainCodec.decode(decoder.struct(CHAIN_FIELD))); case HASH_INVALIDATION_DONE: { decoder = HASH_INVALIDATION_DONE_RESPONSE_STRUCT.decoder(buffer); long key = decoder.int64(KEY_FIELD); - return EhcacheEntityResponse.hashInvalidationDone(key); + return hashInvalidationDone(key); } case ALL_INVALIDATION_DONE: { - return EhcacheEntityResponse.allInvalidationDone(); + return allInvalidationDone(); + } + case SERVER_APPEND: { + decoder = SERVER_APPEND_RESPONSE_STRUCT.decoder(buffer); + ByteBuffer appended = decoder.byteBuffer(APPENDED_FIELD); + StructDecoder> chainDecoder = decoder.struct(CHAIN_FIELD); + Chain chain = chainDecoder == null ? null : ChainCodec.decode(chainDecoder); + return serverAppend(appended, chain); } case CLIENT_INVALIDATE_HASH: { decoder = CLIENT_INVALIDATE_HASH_RESPONSE_STRUCT.decoder(buffer); long key = decoder.int64(KEY_FIELD); int invalidationId = decoder.int32(INVALIDATION_ID_FIELD); - return EhcacheEntityResponse.clientInvalidateHash(key, invalidationId); + return clientInvalidateHash(key, invalidationId); } case CLIENT_INVALIDATE_ALL: { decoder = CLIENT_INVALIDATE_ALL_RESPONSE_STRUCT.decoder(buffer); int invalidationId = decoder.int32(INVALIDATION_ID_FIELD); - return EhcacheEntityResponse.clientInvalidateAll(invalidationId); + return clientInvalidateAll(invalidationId); } case SERVER_INVALIDATE_HASH: { decoder = SERVER_INVALIDATE_HASH_RESPONSE_STRUCT.decoder(buffer); long key = decoder.int64(KEY_FIELD); - return EhcacheEntityResponse.serverInvalidateHash(key); + StructDecoder> chainDecoder = decoder.struct(CHAIN_FIELD); + Chain evictedChain = chainDecoder == null ? null : ChainCodec.decode(chainDecoder); + return serverInvalidateHash(key, evictedChain); } case MAP_VALUE: { decoder = MAP_VALUE_RESPONSE_STRUCT.decoder(buffer); - return EhcacheEntityResponse.mapValue( + return mapValue( Util.unmarshall(decoder.byteBuffer(MAP_VALUE_FIELD), WHITELIST_PREDICATE)); } case PREPARE_FOR_DESTROY: { @@ -283,13 +317,13 @@ public EhcacheEntityResponse decode(byte[] payload) { for (int i = 0; i < storesDecoder.length(); i++) { stores.add(storesDecoder.value()); } - return EhcacheEntityResponse.prepareForDestroy(stores); + return prepareForDestroy(stores); } case RESOLVE_REQUEST: { decoder = RESOLVE_REQUEST_RESPONSE_STRUCT.decoder(buffer); long key = decoder.int64(KEY_FIELD); Chain chain = ChainCodec.decode(decoder.struct(CHAIN_FIELD)); - return EhcacheEntityResponse.resolveRequest(key, chain); + return resolveRequest(key, chain); } case LOCK_SUCCESS: { decoder = LOCK_RESPONSE_STRUCT.decoder(buffer); @@ -297,7 +331,7 @@ public EhcacheEntityResponse decode(byte[] payload) { return new EhcacheEntityResponse.LockSuccess(chain); } case LOCK_FAILURE: { - return EhcacheEntityResponse.lockFailure(); + return lockFailure(); } case ITERATOR_BATCH: { decoder = ITERATOR_BATCH_STRUCT.decoder(buffer); diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java index 6bb3a53242..a52ce3c9ab 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java @@ -100,6 +100,11 @@ public class ServerStoreOpCodec { .int32("batchSize", 30) .build(); + private static final Struct ENABLE_EVENT_LISTENER_STRUCT = newStructBuilder() + .enm(MESSAGE_TYPE_FIELD_NAME, MESSAGE_TYPE_FIELD_INDEX, EHCACHE_MESSAGE_TYPES_ENUM_MAPPING) + .bool("enable", 20) + .build(); + public byte[] encode(ServerStoreOpMessage message) { switch (message.getMessageType()) { case GET_STORE: @@ -163,6 +168,10 @@ public byte[] encode(ServerStoreOpMessage message) { .string("id", ((ServerStoreOpMessage.IteratorAdvanceMessage) message).getIdentity().toString()) .int32("batchSize", ((ServerStoreOpMessage.IteratorAdvanceMessage) message).getBatchSize()) .encode().array(); + case ENABLE_EVENT_LISTENER: + return encodeMandatoryFields(ENABLE_EVENT_LISTENER_STRUCT, message) + .bool("enable", ((ServerStoreOpMessage.EnableEventListenerMessage) message).isEnable()) + .encode().array(); default: throw new RuntimeException("Unhandled message operation : " + message.getMessageType()); } @@ -234,6 +243,11 @@ public EhcacheEntityMessage decode(EhcacheMessageType opCode, ByteBuffer message int batchSize = decoder.int32("batchSize"); return new ServerStoreOpMessage.IteratorAdvanceMessage(identity, batchSize); } + case ENABLE_EVENT_LISTENER: { + StructDecoder decoder = ENABLE_EVENT_LISTENER_STRUCT.decoder(messageBuffer); + Boolean enable = decoder.bool("enable"); + return new ServerStoreOpMessage.EnableEventListenerMessage(enable); + } default: throw new RuntimeException("Unhandled message operation : " + opCode); } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessage.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessage.java index 9096a59aa6..a0b459d590 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessage.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessage.java @@ -263,5 +263,23 @@ public EhcacheMessageType getMessageType() { return EhcacheMessageType.ITERATOR_ADVANCE; } } + + public static class EnableEventListenerMessage extends ServerStoreOpMessage { + private final boolean enable; + + public EnableEventListenerMessage(boolean enable) { + this.enable = enable; + } + + public boolean isEnable() { + return enable; + } + + @Override + public EhcacheMessageType getMessageType() { + return EhcacheMessageType.ENABLE_EVENT_LISTENER; + } + } + } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperation.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperation.java index e38cf833b0..caac548cca 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperation.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperation.java @@ -80,7 +80,7 @@ public K getKey() { return key; } - V getOldValue() { + public V getOldValue() { return this.oldValueHolder.getValue(); } diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodecTest.java index d1b336fd53..7c99c360be 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodecTest.java @@ -39,7 +39,7 @@ public void setUp() { @Test public void testClusterTierReconnectCodec() { - ClusterTierReconnectMessage reconnectMessage = new ClusterTierReconnectMessage(); + ClusterTierReconnectMessage reconnectMessage = new ClusterTierReconnectMessage(false); Set setToInvalidate = new HashSet<>(); setToInvalidate.add(1L); diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java index 4cf537c017..9da75e5bd6 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java @@ -43,6 +43,7 @@ import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.success; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; public class ResponseCodecTest { @@ -129,14 +130,27 @@ public void testClientInvalidateAll() throws Exception { } @Test - public void testServerInvalidateHash() throws Exception { - EhcacheEntityResponse.ServerInvalidateHash response = serverInvalidateHash(KEY); + public void testServerInvalidateHash_withEvictedChain() { + EhcacheEntityResponse.ServerInvalidateHash response = serverInvalidateHash(KEY, chainOf(createPayload(1L), createPayload(11L), createPayload(111L))); byte[] encoded = RESPONSE_CODEC.encode(response); EhcacheEntityResponse.ServerInvalidateHash decodedResponse = (EhcacheEntityResponse.ServerInvalidateHash) RESPONSE_CODEC.decode(encoded); assertThat(decodedResponse.getResponseType(), is(EhcacheResponseType.SERVER_INVALIDATE_HASH)); assertThat(decodedResponse.getKey(), is(KEY)); + assertThat(decodedResponse.getEvictedChain(), hasPayloads(1L, 11L, 111L)); + } + + @Test + public void testServerInvalidateHash_withoutEvictedChain() { + EhcacheEntityResponse.ServerInvalidateHash response = serverInvalidateHash(KEY, null); + + byte[] encoded = RESPONSE_CODEC.encode(response); + EhcacheEntityResponse.ServerInvalidateHash decodedResponse = (EhcacheEntityResponse.ServerInvalidateHash) RESPONSE_CODEC.decode(encoded); + + assertThat(decodedResponse.getResponseType(), is(EhcacheResponseType.SERVER_INVALIDATE_HASH)); + assertThat(decodedResponse.getKey(), is(KEY)); + assertThat(decodedResponse.getEvictedChain(), is(nullValue())); } @Test @@ -201,4 +215,16 @@ public void testIteratorBatchResponse() { assertThat(batchDecoded.getChains().get(1), hasPayloads(2L, 20L)); assertThat(batchDecoded.isLast(), is(true)); } + + @Test + public void testServerAppendResponse() { + EhcacheEntityResponse.ServerAppend serverAppend = new EhcacheEntityResponse.ServerAppend(createPayload(3L), chainOf(createPayload(1L), createPayload(2L))); + + byte[] encoded = RESPONSE_CODEC.encode(serverAppend); + EhcacheEntityResponse.ServerAppend appendDecoded = (EhcacheEntityResponse.ServerAppend) RESPONSE_CODEC.decode(encoded); + + assertThat(appendDecoded.getResponseType(), is(EhcacheResponseType.SERVER_APPEND)); + assertThat(appendDecoded.getAppended().asLongBuffer().get(), is(3L)); + assertThat(appendDecoded.getBeforeAppend(), hasPayloads(1L, 2L)); + } } diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java index 29e36e9bc6..bf8854603d 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java @@ -173,4 +173,14 @@ public void testIteratorAdvanceMessage() { assertThat(decoded.getBatchSize(), is(42)); } + @Test + public void testEnableEventListenerMessage() { + ServerStoreOpMessage enableEventListenerMessage = new ServerStoreOpMessage.EnableEventListenerMessage(true); + + byte[] encoded = STORE_OP_CODEC.encode(enableEventListenerMessage); + ServerStoreOpMessage.EnableEventListenerMessage decoded = (ServerStoreOpMessage.EnableEventListenerMessage) STORE_OP_CODEC.decode(enableEventListenerMessage.getMessageType(), wrap(encoded)); + + assertThat(decoded.getMessageType(), is(EhcacheMessageType.ENABLE_EVENT_LISTENER)); + assertThat(decoded.isEnable(), is(true)); + } } diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index 56b51ca55a..3b60a3411c 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -32,6 +32,7 @@ dependencies { testImplementation "org.terracotta.management.dist:mnm-nms:$terracottaPlatformVersion" testImplementation "org.terracotta.management.dist:mnm-nms-agent:$terracottaPlatformVersion" testImplementation "com.fasterxml.jackson.core:jackson-databind:2.8.0" + testImplementation "org.awaitility:awaitility:3.1.6" testRuntimeOnly project(':clustered:clustered-dist') testRuntimeOnly project(':dist') diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java new file mode 100644 index 0000000000..b27e1d2850 --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -0,0 +1,218 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered; + +import org.ehcache.Cache; +import org.ehcache.CacheManager; +import org.ehcache.PersistentCacheManager; +import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; +import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; +import org.ehcache.clustered.reconnect.ThrowingResiliencyStrategy; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.CacheEventListenerConfigurationBuilder; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.config.builders.ExpiryPolicyBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.config.units.MemoryUnit; +import org.ehcache.event.CacheEvent; +import org.ehcache.event.CacheEventListener; +import org.ehcache.event.EventType; +import org.ehcache.expiry.ExpiryPolicy; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.terracotta.testing.rules.Cluster; + +import java.io.File; +import java.time.Duration; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; + +import static java.util.stream.LongStream.range; +import static org.awaitility.Awaitility.await; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + +public class EventsFailureBehaviorTest extends ClusteredTests { + + private static final int KEYS = 500; + private static final org.awaitility.Duration TIMEOUT = org.awaitility.Duration.FIVE_SECONDS; + + private static final String RESOURCE_CONFIG = + "" + + "" + + "64" + + "" + + "\n"; + + @Rule + public Cluster CLUSTER = + newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + private PersistentCacheManager cacheManager1; + private PersistentCacheManager cacheManager2; + + @Before + public void waitForActive() throws Exception { + CLUSTER.getClusterControl().startAllServers(); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); + + cacheManager1 = CacheManagerBuilder.newCacheManagerBuilder() + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/event-cm")) + .autoCreate() + .defaultServerResource("primary-server-resource")).build(true); + + cacheManager2 = CacheManagerBuilder.newCacheManagerBuilder() + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/event-cm")) + .autoCreate() + .defaultServerResource("primary-server-resource")).build(true); + } + + @After + public void tearDown() { + try { + cacheManager1.close(); + } finally { + cacheManager2.close(); + } + } + + private static Cache createCache(CacheManager cacheManager, CacheEventListener cacheEventListener, ExpiryPolicy expiryPolicy) { + return cacheManager.createCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, byte[].class, + ResourcePoolsBuilder.newResourcePoolsBuilder() + .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 4, MemoryUnit.MB))) + .withResilienceStrategy(new ThrowingResiliencyStrategy<>()) + .add(CacheEventListenerConfigurationBuilder + .newEventListenerConfiguration(cacheEventListener, EnumSet.allOf(EventType.class)) + .unordered().asynchronous()) + .withExpiry(expiryPolicy) + .build()); + } + + private void failover(Cache cache1, Cache cache2) throws Exception { + // failover passive -> active + CLUSTER.getClusterControl().terminateActive(); + CLUSTER.getClusterControl().waitForActive(); + + // wait for clients to be back in business + await().atMost(TIMEOUT).until(() -> { + try { + cache1.replace(1L, new byte[0], new byte[0]); + cache2.replace(1L, new byte[0], new byte[0]); + return true; + } catch (Exception e) { + return false; + } + }); + } + + @Test + public void testEventsFailover() throws Exception { + AccountingCacheEventListener accountingCacheEventListener1 = new AccountingCacheEventListener<>(); + Cache cache1 = createCache(cacheManager1, accountingCacheEventListener1, ExpiryPolicyBuilder.noExpiration()); + AccountingCacheEventListener accountingCacheEventListener2 = new AccountingCacheEventListener<>(); + Cache cache2 = createCache(cacheManager2, accountingCacheEventListener2, ExpiryPolicyBuilder.noExpiration()); + + + byte[] value = new byte[10 * 1024]; + + range(0, KEYS).forEach(k -> { + cache1.put(k, value); + }); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.CREATED).size(), greaterThan(0)); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.EVICTED).size(), greaterThan(0)); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.CREATED).size(), greaterThan(0)); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.EVICTED).size(), greaterThan(0)); + + // failover passive -> active + failover(cache1, cache2); + + range(0, KEYS).forEach(k -> { + cache1.put(k, value); + }); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.UPDATED).size(), greaterThan(0)); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.UPDATED).size(), greaterThan(0)); + + range(0, KEYS).forEach(cache1::remove); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.REMOVED).size(), greaterThan(0)); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.REMOVED).size(), greaterThan(0)); + + range(KEYS, KEYS * 2).forEach(k -> { + cache1.put(k, value); + }); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.CREATED).size(), greaterThan(0)); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.EVICTED).size(), greaterThan(0)); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.CREATED).size(), greaterThan(0)); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.EVICTED).size(), greaterThan(0)); + } + + @Test + public void testExpirationFailover() throws Exception { + AccountingCacheEventListener accountingCacheEventListener1 = new AccountingCacheEventListener<>(); + Cache cache1 = createCache(cacheManager1, accountingCacheEventListener1, ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(1))); + AccountingCacheEventListener accountingCacheEventListener2 = new AccountingCacheEventListener<>(); + Cache cache2 = createCache(cacheManager2, accountingCacheEventListener2, ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(1))); + + + byte[] value = new byte[10 * 1024]; + + range(0, KEYS).forEach(k -> { + cache1.put(k, value); + }); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.CREATED).size(), greaterThan(0)); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.EVICTED).size(), greaterThan(0)); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.CREATED).size(), greaterThan(0)); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.EVICTED).size(), greaterThan(0)); + + // failover passive -> active + failover(cache1, cache2); + + range(0, KEYS).forEach(k -> { + assertThat(cache1.get(k), is(nullValue())); + }); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.EXPIRED).size(), greaterThan(0)); + await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.EXPIRED).size(), greaterThan(0)); + } + + + + static class AccountingCacheEventListener implements CacheEventListener { + private final Map>> events; + + AccountingCacheEventListener() { + events = new HashMap<>(); + clear(); + } + + @Override + public void onEvent(CacheEvent event) { + events.get(event.getType()).add(event); + } + + final void clear() { + for (EventType value : EventType.values()) { + events.put(value, new CopyOnWriteArrayList<>()); + } + } + + } +} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java new file mode 100644 index 0000000000..4c349c0d6c --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -0,0 +1,179 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered.reconnect; + +import com.tc.net.proxy.TCPProxy; +import org.ehcache.Cache; +import org.ehcache.PersistentCacheManager; +import org.ehcache.clustered.ClusteredTests; +import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; +import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; +import org.ehcache.clustered.client.internal.store.ReconnectInProgressException; +import org.ehcache.clustered.util.TCPProxyUtil; +import org.ehcache.config.CacheConfiguration; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.CacheEventListenerConfigurationBuilder; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.config.units.MemoryUnit; +import org.ehcache.event.CacheEvent; +import org.ehcache.event.CacheEventListener; +import org.ehcache.event.EventType; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.terracotta.testing.rules.Cluster; + +import java.io.File; +import java.net.URI; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + +import static org.awaitility.Awaitility.await; +import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + +public class EventsReconnectTest extends ClusteredTests { + private static final org.awaitility.Duration TIMEOUT = org.awaitility.Duration.FIVE_SECONDS; + public static final String RESOURCE_CONFIG = + "" + + "" + + "64" + + "" + + "\n" + + "" + + "" + + "5" + + "" + + ""; + + private static PersistentCacheManager cacheManager; + + private static class AccountingCacheEventListener implements CacheEventListener { + private final Map>> events; + + AccountingCacheEventListener() { + events = new HashMap<>(); + clear(); + } + + @Override + public void onEvent(CacheEvent event) { + events.get(event.getType()).add(event); + } + + final void clear() { + for (EventType value : EventType.values()) { + events.put(value, new CopyOnWriteArrayList<>()); + } + } + + } + + private static AccountingCacheEventListener cacheEventListener = new AccountingCacheEventListener<>(); + + private static CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, + ResourcePoolsBuilder.newResourcePoolsBuilder() + .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB))) + .add(CacheEventListenerConfigurationBuilder + .newEventListenerConfiguration(cacheEventListener, EnumSet.allOf(EventType.class)) + .unordered().asynchronous()) + .withResilienceStrategy(new ThrowingResiliencyStrategy<>()) + .build(); + + private static final List proxies = new ArrayList<>(); + + @ClassRule + public static Cluster CLUSTER = + newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + + @BeforeClass + public static void waitForActive() throws Exception { + CLUSTER.getClusterControl().waitForActive(); + + URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.getConnectionURI(), proxies); + + CacheManagerBuilder clusteredCacheManagerBuilder + = CacheManagerBuilder.newCacheManagerBuilder() + .with(ClusteringServiceConfigurationBuilder.cluster(connectionURI.resolve("/crud-cm")) + .autoCreate() + .defaultServerResource("primary-server-resource")); + cacheManager = clusteredCacheManagerBuilder.build(false); + cacheManager.init(); + } + + @Test + public void eventsFlowAgainAfterReconnection() throws Exception { + try { + Cache cache = cacheManager.createCache("clustered-cache", config); + + CompletableFuture future = CompletableFuture.runAsync(() -> + ThreadLocalRandom.current() + .longs() + .filter(val -> val != Long.MAX_VALUE) + .forEach(value -> + cache.put(value, Long.toString(value)))); + + expireLease(); + + try { + future.get(5000, TimeUnit.MILLISECONDS); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause().getCause().getCause(), instanceOf(ReconnectInProgressException.class)); + } + int beforeDisconnectionEventCounter = cacheEventListener.events.get(EventType.CREATED).size(); + + CompletableFuture getSucceededFuture = CompletableFuture.runAsync(() -> { + while (true) { + try { + cache.put(Long.MAX_VALUE, ""); + break; + } catch (RuntimeException e) { + + } + } + }); + + getSucceededFuture.get(20000, TimeUnit.MILLISECONDS); + + await().atMost(TIMEOUT).until(() -> cacheEventListener.events.get(EventType.CREATED).size(), is(beforeDisconnectionEventCounter + 1)); + + } finally { + cacheManager.destroyCache("clustered-cache"); + } + } + + + private static void expireLease() throws InterruptedException { + setDelay(6000, proxies); + Thread.sleep(6000); + + setDelay(0L, proxies); + } +} diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java b/clustered/server/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java index be5a576ebc..863c785cb2 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java @@ -27,7 +27,8 @@ @CommonComponent public interface ServerSideServerStore extends ServerStore, MapInternals { - void setEvictionListener(ServerStoreEvictionListener listener); + void setEventListener(ServerStoreEventListener listener); + void enableEvents(boolean enable); ServerStoreConfiguration getStoreConfiguration(); List> getSegmentKeySets(); void put(long key, Chain chain); diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java b/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java new file mode 100644 index 0000000000..b2c48c8eee --- /dev/null +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java @@ -0,0 +1,48 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered.server; + +import com.tc.classloader.CommonComponent; +import org.ehcache.clustered.common.internal.store.Chain; +import org.ehcache.clustered.server.offheap.InternalChain; + +import java.nio.ByteBuffer; + +/** + * ServerStore event listener interface + */ +@CommonComponent +public interface ServerStoreEventListener { + + /** + * Called when the ServerStore evicts a mapping. + *

+ * Always fired, even when events are not enabled, see: {@link ServerSideServerStore#enableEvents(boolean)}. + * @param key the key of the evicted mapping + * @param evictedChain the evicted chain. + */ + void onEviction(long key, InternalChain evictedChain); + + /** + * Called when the ServerStore appends to a mapping + *

+ * Not always fired, only when events are enabled, see: {@link ServerSideServerStore#enableEvents(boolean)}. + * @param beforeAppend the chain as it was before the append + * @param appended the appended operation + */ + void onAppend(Chain beforeAppend, ByteBuffer appended); + +} diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreEvictionListener.java b/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreEvictionListener.java deleted file mode 100644 index dd1f162663..0000000000 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreEvictionListener.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.ehcache.clustered.server; - -import com.tc.classloader.CommonComponent; - -/** - * ServerStore eviction listener interface - */ -@CommonComponent -public interface ServerStoreEvictionListener { - /** - * Called when the ServerStore evicts a mapping - * @param key the key of the evicted mapping - */ - void onEviction(long key); -} diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java b/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java index 1a2131436a..7548741a22 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java @@ -52,8 +52,14 @@ public ServerStoreImpl(ServerStoreConfiguration storeConfiguration, ResourcePage this.store = new OffHeapServerStore(pageSource, mapper, writeBehindConfigured); } - public void setEvictionListener(ServerStoreEvictionListener listener) { - store.setEvictionListener(listener); + @Override + public void setEventListener(ServerStoreEventListener listener) { + store.setEventListener(listener); + } + + @Override + public void enableEvents(boolean enable) { + store.enableEvents(enable); } /** diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java index 18af113114..63faf6cc67 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java @@ -18,8 +18,10 @@ import java.io.Closeable; import java.nio.ByteBuffer; +import com.tc.classloader.CommonComponent; import org.ehcache.clustered.common.internal.store.Chain; +@CommonComponent public interface InternalChain extends Closeable { Chain detach(); diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java index ec792c55cf..3c9a767397 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java @@ -38,7 +38,7 @@ public class OffHeapChainMap implements MapInternals, Iterable { interface ChainMapEvictionListener { - void onEviction(K key); + void onEviction(K key, InternalChain evictedChain); } protected final ReadWriteLockedOffHeapClockCache heads; @@ -52,7 +52,7 @@ private OffHeapChainMap(PageSource source, ChainStorageEngine storageEngine) Map.Entry entry = callable.call(); try { if (evictionListener != null) { - evictionListener.onEviction(entry.getKey()); + evictionListener.onEviction(entry.getKey(), entry.getValue()); } } finally { entry.getValue().close(); diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java index c4cb03b056..d0bc197351 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java @@ -15,23 +15,23 @@ */ package org.ehcache.clustered.server.offheap; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.function.LongConsumer; -import java.util.function.LongFunction; - import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.ServerStore; import org.ehcache.clustered.server.KeySegmentMapper; -import org.ehcache.clustered.server.ServerStoreEvictionListener; +import org.ehcache.clustered.server.ServerStoreEventListener; import org.ehcache.clustered.server.state.ResourcePageSource; import org.terracotta.offheapstore.MapInternals; import org.terracotta.offheapstore.exceptions.OversizeMappingException; import org.terracotta.offheapstore.paging.PageSource; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.function.LongConsumer; +import java.util.function.LongFunction; + import static org.terracotta.offheapstore.util.MemoryUnit.BYTES; import static org.terracotta.offheapstore.util.MemoryUnit.KILOBYTES; import static org.terracotta.offheapstore.util.MemoryUnit.MEGABYTES; @@ -42,6 +42,8 @@ public class OffHeapServerStore implements ServerStore, MapInternals { private final List> segments; private final KeySegmentMapper mapper; + private volatile ServerStoreEventListener listener; + private volatile boolean fireEvents; public OffHeapServerStore(List> segments, KeySegmentMapper mapper) { this.mapper = mapper; @@ -88,7 +90,11 @@ static long getMaxSize(long poolSize) { return maxSize; } - public void setEvictionListener(final ServerStoreEvictionListener listener) { + public void setEventListener(ServerStoreEventListener listener) { + if (this.listener != null) { + throw new IllegalStateException("ServerStoreEventListener instance already set"); + } + this.listener = listener; OffHeapChainMap.ChainMapEvictionListener chainMapEvictionListener = listener::onEviction; for (OffHeapChainMap segment : segments) { segment.setEvictionListener(chainMapEvictionListener); @@ -102,19 +108,40 @@ public Chain get(long key) { @Override public void append(long key, ByteBuffer payLoad) { + LongConsumer lambda; + if (listener != null && fireEvents) { + lambda = (k) -> { + Chain beforeAppend = segmentFor(k).getAndAppend(k, payLoad); + listener.onAppend(beforeAppend, payLoad.duplicate()); + }; + } else { + lambda = (k) -> segmentFor(k).append(k, payLoad); + } + try { - segmentFor(key).append(key, payLoad); + lambda.accept(key); } catch (OversizeMappingException e) { - consumeOversizeMappingException(key, (long k) -> segmentFor(k).append(k, payLoad)); + consumeOversizeMappingException(key, lambda); } } @Override public Chain getAndAppend(long key, ByteBuffer payLoad) { + LongFunction lambda; + if (listener != null && fireEvents) { + lambda = (k) -> { + Chain beforeAppend = segmentFor(k).getAndAppend(k, payLoad); + listener.onAppend(beforeAppend, payLoad.duplicate()); + return beforeAppend; + }; + } else { + lambda = (k) -> segmentFor(k).getAndAppend(k, payLoad); + } + try { - return segmentFor(key).getAndAppend(key, payLoad); + return lambda.apply(key); } catch (OversizeMappingException e) { - return handleOversizeMappingException(key, (long k) -> segmentFor(k).getAndAppend(k, payLoad)); + return handleOversizeMappingException(key, lambda); } } @@ -349,6 +376,9 @@ protected Iterator getNextIterator() { }; } + public void enableEvents(boolean enable) { + this.fireEvents = enable; + } protected abstract class AggregateIterator implements Iterator { diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java b/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java index 5220dfa788..a88df2224c 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java @@ -34,6 +34,7 @@ import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.AppendMessage; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.ClientInvalidationAck; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.ClientInvalidationAllAck; +import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.EnableEventListenerMessage; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.GetMessage; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.IteratorAdvanceMessage; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage.IteratorCloseMessage; @@ -50,12 +51,14 @@ import org.ehcache.clustered.server.KeySegmentMapper; import org.ehcache.clustered.server.ServerSideServerStore; import org.ehcache.clustered.server.ServerStoreCompatibility; +import org.ehcache.clustered.server.ServerStoreEventListener; import org.ehcache.clustered.server.internal.messages.EhcacheDataSyncMessage; import org.ehcache.clustered.server.internal.messages.EhcacheMessageTrackerMessage; import org.ehcache.clustered.server.internal.messages.PassiveReplicationMessage; import org.ehcache.clustered.server.internal.messages.PassiveReplicationMessage.ClearInvalidationCompleteMessage; import org.ehcache.clustered.server.internal.messages.PassiveReplicationMessage.InvalidationCompleteMessage; import org.ehcache.clustered.server.management.ClusterTierManagement; +import org.ehcache.clustered.server.offheap.InternalChain; import org.ehcache.clustered.server.state.EhcacheStateContext; import org.ehcache.clustered.server.state.EhcacheStateService; import org.ehcache.clustered.server.state.InvalidationTracker; @@ -80,8 +83,8 @@ import org.terracotta.entity.ServiceRegistry; import org.terracotta.entity.StateDumpCollector; +import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -116,6 +119,7 @@ import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.lockFailure; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.lockSuccess; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.resolveRequest; +import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.serverAppend; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.serverInvalidateHash; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.success; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.isLifecycleMessage; @@ -160,6 +164,7 @@ public class ClusterTierActiveEntity implements ActiveServerEntity inflightInvalidations; + private final Set eventListeners = new HashSet<>(); // accesses are synchronized on eventListeners itself private final Map connectedClients = new ConcurrentHashMap<>(); private final Map>> liveIterators = new ConcurrentHashMap<>(); private final int chainCompactionLimit; @@ -224,7 +229,7 @@ public void addStateTo(StateDumpCollector dump) { @Override public void createNew() throws ConfigurationException { ServerSideServerStore store = stateService.createStore(storeIdentifier, configuration, true); - store.setEvictionListener(this::invalidateHashAfterEviction); + store.setEventListener(new Listener()); management.entityCreated(); } @@ -239,19 +244,38 @@ public void loadExisting() { LOGGER.debug("Preparing for handling inflight invalidations"); addInflightInvalidationsForEventualCaches(); } - stateService.loadStore(storeIdentifier, configuration).setEvictionListener(this::invalidateHashAfterEviction); + stateService.loadStore(storeIdentifier, configuration).setEventListener(new Listener()); reconnectComplete.set(false); management.entityPromotionCompleted(); } - private void invalidateHashAfterEviction(long key) { - Set clientsToInvalidate = new HashSet<>(getValidatedClients()); - for (ClientDescriptor clientDescriptorThatHasToInvalidate : clientsToInvalidate) { - LOGGER.debug("SERVER: eviction happened; asking client {} to invalidate hash {} from cache {}", clientDescriptorThatHasToInvalidate, key, storeIdentifier); - try { - clientCommunicator.sendNoResponse(clientDescriptorThatHasToInvalidate, serverInvalidateHash(key)); - } catch (MessageCodecException mce) { - throw new AssertionError("Codec error", mce); + private class Listener implements ServerStoreEventListener { + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + Set clients = new HashSet<>(getValidatedClients()); + for (ClientDescriptor clientDescriptor : clients) { + LOGGER.debug("SERVER: append happened in cache {}; notifying client {} ", storeIdentifier, clientDescriptor); + try { + clientCommunicator.sendNoResponse(clientDescriptor, serverAppend(appended.duplicate(), beforeAppend)); + } catch (MessageCodecException mce) { + throw new AssertionError("Codec error", mce); + } + } + } + @Override + public void onEviction(long key, InternalChain evictedChain) { + Set clientsToInvalidate = new HashSet<>(getValidatedClients()); + if (!clientsToInvalidate.isEmpty()) { + Chain detachedChain = evictedChain.detach(); + for (ClientDescriptor clientDescriptorThatHasToInvalidate : clientsToInvalidate) { + LOGGER.debug("SERVER: eviction happened; asking client {} to invalidate hash {} from cache {}", clientDescriptorThatHasToInvalidate, key, storeIdentifier); + try { + boolean eventsEnabledForClient = isEventsEnabledFor(clientDescriptorThatHasToInvalidate); + clientCommunicator.sendNoResponse(clientDescriptorThatHasToInvalidate, serverInvalidateHash(key, eventsEnabledForClient ? detachedChain : null)); + } catch (MessageCodecException mce) { + throw new AssertionError("Codec error", mce); + } + } } } } @@ -283,6 +307,8 @@ public void disconnected(ClientDescriptor clientDescriptor) { liveIterators.remove(clientDescriptor); + removeEventListener(clientDescriptor, stateService.getStore(storeIdentifier)); + connectedClients.remove(clientDescriptor); } @@ -537,11 +563,53 @@ private EhcacheEntityResponse invokeServerStoreOperation(InvokeContext context, } } } + case ENABLE_EVENT_LISTENER: { + // we need to keep a count of how many clients have registered as events listeners + // as we want to disable events from the store once all listeners are gone + // so we need to keep all requesting client descriptors in a set so that duplicate + // registrations from a single client are ignored + EnableEventListenerMessage enableEventListenerMessage = (EnableEventListenerMessage) message; + if (enableEventListenerMessage.isEnable()) { + addEventListener(clientDescriptor, cacheStore); + } else { + removeEventListener(clientDescriptor, cacheStore); + } + return success(); + } default: throw new AssertionError("Unsupported ServerStore operation : " + message); } } + private void addEventListener(ClientDescriptor clientDescriptor, ServerSideServerStore cacheStore) { + synchronized (eventListeners) { + if (eventListeners.add(clientDescriptor)) { + cacheStore.enableEvents(true); + } + } + } + + private void removeEventListener(ClientDescriptor clientDescriptor, ServerSideServerStore cacheStore) { + synchronized (eventListeners) { + if (eventListeners.remove(clientDescriptor) && eventListeners.isEmpty()) { + cacheStore.enableEvents(false); + } + } + } + + private boolean isEventsEnabledFor(ClientDescriptor clientDescriptor) { + synchronized (eventListeners) { + return eventListeners.contains(clientDescriptor); + } + } + + // for testing + Set getEventListeners() { + synchronized (eventListeners) { + return new HashSet<>(eventListeners); + } + } + private List iteratorBatch(Iterator iterator, int batchSize) { List chains = new ArrayList<>(); int size = 0; @@ -702,6 +770,9 @@ public ReconnectHandler startReconnect() { ServerSideServerStore serverStore = stateService.getStore(storeIdentifier); addInflightInvalidationsForStrongCache(clientDescriptor, reconnectMessage, serverStore); lockManager.createLockStateAfterFailover(clientDescriptor, reconnectMessage.getLocksHeld()); + if (reconnectMessage.isEventsEnabled()) { + addEventListener(clientDescriptor, serverStore); + } LOGGER.info("Client '{}' successfully reconnected to newly promoted ACTIVE after failover.", clientDescriptor); diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java index a2c96625c8..0df77069e1 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java @@ -16,11 +16,14 @@ package org.ehcache.clustered.server.offheap; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; import java.util.Random; import java.util.concurrent.locks.ReentrantLock; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.server.KeySegmentMapper; +import org.ehcache.clustered.server.ServerStoreEventListener; import org.ehcache.clustered.server.store.ChainBuilder; import org.ehcache.clustered.server.store.ElementBuilder; import org.ehcache.clustered.common.internal.store.ServerStore; @@ -41,6 +44,8 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.lessThanOrEqualTo; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.Is.is; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; @@ -52,6 +57,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.terracotta.offheapstore.util.MemoryUnit.GIGABYTES; +import static org.terracotta.offheapstore.util.MemoryUnit.KILOBYTES; import static org.terracotta.offheapstore.util.MemoryUnit.MEGABYTES; public class OffHeapServerStoreTest extends ServerStoreTest { @@ -331,4 +337,117 @@ public void testServerSideUsageStats() { } + @Test + public void testEvictionFiresEventsWithChainWhenEvictionIsEnabled() { + OffHeapServerStore store = new OffHeapServerStore(new UpfrontAllocatingPageSource(new OffHeapBufferSource(), (long) MEGABYTES.toBytes(1), MEGABYTES.toBytes(1)), new KeySegmentMapper(16), false); + AuditingServerStoreEventListener audit = new AuditingServerStoreEventListener(); + store.setEventListener(audit); + store.enableEvents(true); + + ByteBuffer buffer = ByteBuffer.allocate(KILOBYTES.toBytes(500)); + + store.append(1L, buffer.duplicate()); + store.append(2L, buffer.duplicate()); + store.append(3L, buffer.duplicate()); + + assertThat(store.getSize(), is(1L)); + assertThat(audit.onEviction.size(), is(2)); + assertThat(audit.onEviction.get(0).key, is(1L)); + assertThat(audit.onEviction.get(0).evictedChain, is(notNullValue())); + assertThat(audit.onEviction.get(1).key, is(2L)); + assertThat(audit.onEviction.get(1).evictedChain, is(notNullValue())); + } + + @Test + public void testNoEventFiredWhenDisabled() { + OffHeapServerStore store = new OffHeapServerStore(new UpfrontAllocatingPageSource(new OffHeapBufferSource(), (long) MEGABYTES.toBytes(1), MEGABYTES.toBytes(1)), new KeySegmentMapper(16), false); + AuditingServerStoreEventListener audit = new AuditingServerStoreEventListener(); + store.setEventListener(audit); + + store.append(1L, toBuffer(1)); + store.getAndAppend(1L, toBuffer(2)); + + store.enableEvents(true); + store.append(1L, toBuffer(3)); + store.getAndAppend(1L, toBuffer(4)); + + store.enableEvents(false); + store.append(1L, toBuffer(5)); + store.getAndAppend(1L, toBuffer(6)); + + assertThat(audit.onAppend.size(), is(2)); + assertThat(audit.onAppend.get(0).appended.asIntBuffer().get(), is(3)); + assertThat(audit.onAppend.get(1).appended.asIntBuffer().get(), is(4)); + } + + @Test + public void testAppendFiresEvents() { + OffHeapServerStore store = new OffHeapServerStore(new UpfrontAllocatingPageSource(new OffHeapBufferSource(), (long) MEGABYTES.toBytes(1), MEGABYTES.toBytes(1)), new KeySegmentMapper(16), false); + AuditingServerStoreEventListener audit = new AuditingServerStoreEventListener(); + store.setEventListener(audit); + store.enableEvents(true); + + store.append(1L, toBuffer(1)); + store.append(1L, toBuffer(2)); + store.append(1L, toBuffer(3)); + + assertThat(audit.onAppend.size(), is(3)); + assertThat(audit.onAppend.get(0).appended.asIntBuffer().get(), is(1)); + assertThat(audit.onAppend.get(1).appended.asIntBuffer().get(), is(2)); + assertThat(audit.onAppend.get(2).appended.asIntBuffer().get(), is(3)); + } + + @Test + public void testGetAndAppendFiresEvents() { + OffHeapServerStore store = new OffHeapServerStore(new UpfrontAllocatingPageSource(new OffHeapBufferSource(), (long) MEGABYTES.toBytes(1), MEGABYTES.toBytes(1)), new KeySegmentMapper(16), false); + AuditingServerStoreEventListener audit = new AuditingServerStoreEventListener(); + store.setEventListener(audit); + store.enableEvents(true); + + store.getAndAppend(1L, toBuffer(1)); + store.getAndAppend(1L, toBuffer(2)); + store.getAndAppend(1L, toBuffer(3)); + + assertThat(audit.onAppend.size(), is(3)); + assertThat(audit.onAppend.get(0).appended.asIntBuffer().get(), is(1)); + assertThat(audit.onAppend.get(1).appended.asIntBuffer().get(), is(2)); + assertThat(audit.onAppend.get(2).appended.asIntBuffer().get(), is(3)); + } + + private static class AuditingServerStoreEventListener implements ServerStoreEventListener { + private final List onAppend = new ArrayList<>(); + private final List onEviction = new ArrayList<>(); + @Override + public void onEviction(long key, InternalChain evictedChain) { + onEviction.add(new OnEvictionArgs(key, evictedChain)); + } + @Override + public void onAppend(Chain beforeAppend, ByteBuffer appended) { + onAppend.add(new OnAppendArgs(appended, beforeAppend)); + } + + static class OnEvictionArgs { + OnEvictionArgs(long key, InternalChain evictedChain) { + this.key = key; + this.evictedChain = evictedChain; + } + long key; + InternalChain evictedChain; + } + + static class OnAppendArgs { + OnAppendArgs(ByteBuffer appended, Chain beforeAppend) { + this.appended = appended; + this.beforeAppend = beforeAppend; + } + ByteBuffer appended; + Chain beforeAppend; + } + } + + private static ByteBuffer toBuffer(int i) { + ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES); + buffer.asIntBuffer().put(i); + return buffer; + } } diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index 8b11cd6c71..daf4faa108 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -36,7 +36,7 @@ import org.ehcache.clustered.server.EhcacheStateServiceImpl; import org.ehcache.clustered.server.KeySegmentMapper; import org.ehcache.clustered.server.ServerSideServerStore; -import org.ehcache.clustered.server.ServerStoreEvictionListener; +import org.ehcache.clustered.server.ServerStoreEventListener; import org.ehcache.clustered.server.TestClientDescriptor; import org.ehcache.clustered.server.TestInvokeContext; import org.ehcache.clustered.server.internal.messages.EhcacheDataSyncMessage; @@ -51,6 +51,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; import org.mockito.Mockito; import org.terracotta.client.message.tracker.OOOMessageHandler; import org.terracotta.client.message.tracker.OOOMessageHandlerConfiguration; @@ -99,6 +100,7 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNotNull; import static org.mockito.Mockito.atLeast; @@ -196,6 +198,41 @@ public void testDisconnected() throws Exception { assertThat(activeEntity.getConnectedClients(), hasSize(0)); } + @Test + public void testEventListenerEnabledTracking() throws Exception { + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + activeEntity.createNew(); + + TestInvokeContext ctx1 = new TestInvokeContext(); + ClientDescriptor client1 = ctx1.getClientDescriptor(); + TestInvokeContext ctx2 = new TestInvokeContext(); + ClientDescriptor client2 = ctx2.getClientDescriptor(); + + // check that connecting clients does not enable listeners by default + activeEntity.connected(client1); + activeEntity.connected(client2); + assertThat(activeEntity.getEventListeners().size(), is(0)); + + assertThat(activeEntity.invokeActive(ctx1, new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); + assertThat(activeEntity.getEventListeners().size(), is(1)); + // a client can register as many times as it wants, it's considered a single listener + assertThat(activeEntity.invokeActive(ctx1, new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); + assertThat(activeEntity.getEventListeners().size(), is(1)); + assertThat(activeEntity.invokeActive(ctx2, new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); + assertThat(activeEntity.getEventListeners().size(), is(2)); + + // check that disabling events is accounted for + assertThat(activeEntity.invokeActive(ctx2, new ServerStoreOpMessage.EnableEventListenerMessage(false)), succeeds()); + assertThat(activeEntity.getEventListeners().size(), is(1)); + // check that disabling events from a client that does not have events enabled is a noop + assertThat(activeEntity.invokeActive(ctx2, new ServerStoreOpMessage.EnableEventListenerMessage(false)), succeeds()); + assertThat(activeEntity.getEventListeners().size(), is(1)); + + // check that disconnected clients are accounted for + activeEntity.disconnected(client1); + assertThat(activeEntity.getEventListeners().size(), is(0)); + } + /** * Ensures the disconnect of a connected client is properly tracked and does not affect others. */ @@ -229,7 +266,35 @@ public void testLoadExistingRegistersEvictionListener() throws Exception { ServiceRegistry registry = getCustomMockedServiceRegistry(stateService, null, entityMessenger, null, null); ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(registry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.loadExisting(); - verify(store).setEvictionListener(any(ServerStoreEvictionListener.class)); + verify(store).setEventListener(any(ServerStoreEventListener.class)); + } + + @Test + public void testEnableEventListenerMessageEnablesOrDisablesEventsOnStore() throws Exception { + EhcacheStateService stateService = mock(EhcacheStateService.class); + + ServerSideServerStore store = mock(ServerSideServerStore.class); + InOrder storeOrderVerifier = Mockito.inOrder(store); + when(stateService.createStore(eq(defaultStoreName), any(), anyBoolean())).thenReturn(store); + when(stateService.getStore(eq(defaultStoreName))).thenReturn(store); + + IEntityMessenger entityMessenger = mock(IEntityMessenger.class); + ServiceRegistry registry = getCustomMockedServiceRegistry(stateService, null, entityMessenger, null, null); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(registry, defaultConfiguration, DEFAULT_MAPPER); + activeEntity.createNew(); + + TestInvokeContext ctx1 = new TestInvokeContext(); + ClientDescriptor client1 = ctx1.getClientDescriptor(); + + activeEntity.connected(client1); + // also check that duplicating enable/disable calls has no effect + assertThat(activeEntity.invokeActive(ctx1, new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); + assertThat(activeEntity.invokeActive(ctx1, new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); + assertThat(activeEntity.invokeActive(ctx1, new ServerStoreOpMessage.EnableEventListenerMessage(false)), succeeds()); + assertThat(activeEntity.invokeActive(ctx1, new ServerStoreOpMessage.EnableEventListenerMessage(false)), succeeds()); + + storeOrderVerifier.verify(store).enableEvents(eq(true)); + storeOrderVerifier.verify(store).enableEvents(eq(false)); } @Test diff --git a/docs/src/docs/asciidoc/developer/clustered-events.adoc b/docs/src/docs/asciidoc/developer/clustered-events.adoc new file mode 100644 index 0000000000..20ee7f6b72 --- /dev/null +++ b/docs/src/docs/asciidoc/developer/clustered-events.adoc @@ -0,0 +1,82 @@ += Ehcache events from clustered caches + +This document describes the core design of what is required to implement ehcache events from caches backed by a +clustered store. + +== High-level requirements + +* Ehcache supports five types of cache events: on *eviction*, on *expiry*, on *removal*, on *update* and on *creation*. +* When an event is fired, every connected client with a registered listener has to receive it. +* Events must be delivered once and only once as long as the client(s), server(s) and network-in-between are all +healthy. +* What happens when there is a client disconnect, a passive take over, a split brain or any other hazard is yet to be +determined. +* No performance impact when the feature isn't used. + +=== Recommandations + +It must be made clear (documentation?) that the eventing mechanism is going to have a performance impact. + +Some features are undesirable because they are unlikely to be practical: + +* Synchronous events would require waiting for a round-trip to all clients before achieving a cache operation. This +would pretty much make such cache unusably slow. Ordered events aren't impossible to do, but would require a serious +engineering effort to get right as keeping the events in a strict order isn't trivial, so it's been left out. +Such configs throw an exception when attempted. +* Guaranteeing event delivery in all cases would require some form of stable store and a fairly complex and costly +2-phase logic. This would also have an unsustainable performance impact. Instead, clients should have a way to figure +out when such hazard happen to compensate for the possible lack of event delivery. + +== Technical facts + +Because of the current implementation: + +* All events find their source in a server: *creation*, *update*, *removal* and *expiration* are additions to the chain. +*Eviction* happens when the server is running low on resource and are detected and notified by the chain. + +This means a cluster-wide listener mechanism has to be created with the following features: + +* Clients can register and unregister themselves. This is because events have a performance impact when enabled. +* Events can be fired from any server. +* Clients have to interpret the server-send event that actually are chain operations and resolve those into +client-facing events. E.g.: the appending of a `RemoveOperation` translates to a *removal* event. + +== The transport mechanism + +An event delivery mechanism must be built to transport the events from the clients and servers to all clients registered +as listeners. It requires the following: + +* API to (un)register a client as a listener, through all layers, down to the chain on the server +* API for a server to fire an `append` event +* Modify existing API for a server to fire an `eviction` event to include the necessary data to fire the client-side +equivalent event(s). + +== The straightforward bits + +Modify the `ClusterTierActiveEntity` listener mechanism: +`ServerStoreEvictionListener` already contains `void onEviction(long key)`. Add an extra `Chain evictedChain` parameter. +Then add `void onAppend(ByteBuffer appended, Chain beforeAppend)` and finally rename the interface to +`ServerStoreEventListener`. + +Assuming the plumbing for firing the above notifications from the servers to the clients is done, the resolver of the +client needs to be modified so that it can be used to interpret the appended to and/or evicted chains. + +== The complicated bits + +The following cases are going to be more complicated to implement: + +* Expiration can't be fired once and only once with the existing chain `Operation` s. A new one has to be introduced +for this purpose: `TimestampOperation`. This basically is a noop that indicates that an expiration has been detected +by a client. +* `TimestampOperation` cannot be interpreted by older clients. Fortunately, the codepath on which it's going to be +added is robust enough to intercept such failure which will en up calling the `ResilienceStrategy` to evict the +value. This is slightly odd, but still correct and we don't expect lots of cases where old clients will be mixed in. +* The new `onAppend` callback is not cheap to perform. Simple appends eventually transform into getAndAppend at the +very lowest layer of the chain to be able to make this call. This also means materializing an offheap chain onto the +heap and sending kilobytes (maybe dozens of them) over the wire. This means it must only be materialized when at least +one client has an event listener configured and only forwarded to clients that do have a configured event listener. +This is going to require a dynamic enabling/disabling mechanism as well as some carefully placed if-not-null checks. +* The new `Chain evictedChain` parameter of the `onEviction` callback isn't cheap to generate (it needs to be +materialized from off-heap onto the heap) nor to transport (can easily reach hundreds of KB) so null must be passed +when it isn't needed, exactly for the same reasons as for `onAppend` above. + diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/AbstractStoreEventDispatcher.java b/impl/src/main/java/org/ehcache/impl/internal/events/AbstractStoreEventDispatcher.java index 47e0f5e164..2e44eccea1 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/events/AbstractStoreEventDispatcher.java +++ b/impl/src/main/java/org/ehcache/impl/internal/events/AbstractStoreEventDispatcher.java @@ -30,7 +30,7 @@ /** * AbstractStoreEventDispatcher */ -abstract class AbstractStoreEventDispatcher implements StoreEventDispatcher { +public abstract class AbstractStoreEventDispatcher implements StoreEventDispatcher { protected static final StoreEventSink NO_OP_EVENT_SINK = new CloseableStoreEventSink() { @Override @@ -143,4 +143,9 @@ public void releaseEventSinkAfterFailure(StoreEventSink eventSink, Throwab public void reset(StoreEventSink eventSink) { ((CloseableStoreEventSink) eventSink).reset(); } + + @Override + public StoreEventSink eventSink() { + return new InvocationScopedEventSink<>(getFilters(), isEventOrdering(), getOrderedQueues(), getListeners()); + } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index 6c5853ef92..a137f03f5b 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -38,7 +38,7 @@ import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.ehcache.impl.copy.SerializingCopier; import org.ehcache.core.events.NullStoreEventDispatcher; -import org.ehcache.impl.internal.events.ScopedStoreEventDispatcher; +import org.ehcache.impl.store.DefaultStoreEventDispatcher; import org.ehcache.impl.internal.sizeof.NoopSizeOfEngine; import org.ehcache.impl.internal.store.heap.holders.CopiedOnHeapValueHolder; import org.ehcache.impl.internal.store.heap.holders.OnHeapValueHolder; @@ -1642,7 +1642,7 @@ public int rankCachingTier(Set> resourceTypes, Collection OnHeapStore createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { - OnHeapStore store = createStoreInternal(storeConfig, new ScopedStoreEventDispatcher<>(storeConfig.getDispatcherConcurrency()), serviceConfigs); + OnHeapStore store = createStoreInternal(storeConfig, new DefaultStoreEventDispatcher<>(storeConfig.getDispatcherConcurrency()), serviceConfigs); tierOperationStatistics.put(store, new OperationStatistic[] { createTranslatedStatistic(store, "get", TierOperationOutcomes.GET_TRANSLATION, "get"), @@ -1755,7 +1755,7 @@ public void initCachingTier(CachingTier resource) { @Override public HigherCachingTier createHigherCachingTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { - OnHeapStore higherCachingTier = createStoreInternal(storeConfig, new ScopedStoreEventDispatcher<>(storeConfig + OnHeapStore higherCachingTier = createStoreInternal(storeConfig, new DefaultStoreEventDispatcher<>(storeConfig .getDispatcherConcurrency()), serviceConfigs); this.tierOperationStatistics.put(higherCachingTier, new OperationStatistic[] { diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/ScopedStoreEventDispatcher.java b/impl/src/main/java/org/ehcache/impl/store/DefaultStoreEventDispatcher.java similarity index 71% rename from impl/src/main/java/org/ehcache/impl/internal/events/ScopedStoreEventDispatcher.java rename to impl/src/main/java/org/ehcache/impl/store/DefaultStoreEventDispatcher.java index 2fba80a9ab..c194991132 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/events/ScopedStoreEventDispatcher.java +++ b/impl/src/main/java/org/ehcache/impl/store/DefaultStoreEventDispatcher.java @@ -14,17 +14,17 @@ * limitations under the License. */ -package org.ehcache.impl.internal.events; +package org.ehcache.impl.store; import org.ehcache.core.events.StoreEventSink; +import org.ehcache.impl.internal.events.AbstractStoreEventDispatcher; /** - * ScopedStoreEventDispatcher + * The default {@link org.ehcache.core.events.StoreEventDispatcher} implementation. */ -public class ScopedStoreEventDispatcher extends AbstractStoreEventDispatcher { +public class DefaultStoreEventDispatcher extends AbstractStoreEventDispatcher { - - public ScopedStoreEventDispatcher(int dispatcherConcurrency) { + public DefaultStoreEventDispatcher(int dispatcherConcurrency) { super(dispatcherConcurrency); } @@ -35,7 +35,7 @@ public StoreEventSink eventSink() { StoreEventSink noOpEventSink = (StoreEventSink) NO_OP_EVENT_SINK; return noOpEventSink; } else { - return new InvocationScopedEventSink<>(getFilters(), isEventOrdering(), getOrderedQueues(), getListeners()); + return super.eventSink(); } } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/events/ScopedStoreEventDispatcherTest.java b/impl/src/test/java/org/ehcache/impl/store/DefaultStoreEventDispatcherTest.java similarity index 89% rename from impl/src/test/java/org/ehcache/impl/internal/events/ScopedStoreEventDispatcherTest.java rename to impl/src/test/java/org/ehcache/impl/store/DefaultStoreEventDispatcherTest.java index 00cd7eceff..5646070ef2 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/events/ScopedStoreEventDispatcherTest.java +++ b/impl/src/test/java/org/ehcache/impl/store/DefaultStoreEventDispatcherTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.impl.internal.events; +package org.ehcache.impl.store; import org.ehcache.event.EventType; import org.ehcache.core.events.StoreEventSink; @@ -45,15 +45,15 @@ import static org.mockito.hamcrest.MockitoHamcrest.argThat; /** - * ScopedStoreEventDispatcherTest + * DefaultStoreEventDispatcherTest */ -public class ScopedStoreEventDispatcherTest { +public class DefaultStoreEventDispatcherTest { - private static final Logger LOGGER = LoggerFactory.getLogger(ScopedStoreEventDispatcherTest.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultStoreEventDispatcherTest.class); @Test public void testRegistersOrderingChange() { - ScopedStoreEventDispatcher dispatcher = new ScopedStoreEventDispatcher<>(1); + DefaultStoreEventDispatcher dispatcher = new DefaultStoreEventDispatcher<>(1); assertThat(dispatcher.isEventOrdering(), is(false)); dispatcher.setEventOrdering(true); @@ -65,7 +65,7 @@ public void testRegistersOrderingChange() { @Test @SuppressWarnings("unchecked") public void testListenerNotifiedUnordered() { - ScopedStoreEventDispatcher dispatcher = new ScopedStoreEventDispatcher<>(1); + DefaultStoreEventDispatcher dispatcher = new DefaultStoreEventDispatcher<>(1); @SuppressWarnings("unchecked") StoreEventListener listener = mock(StoreEventListener.class); dispatcher.addEventListener(listener); @@ -80,7 +80,7 @@ public void testListenerNotifiedUnordered() { @Test @SuppressWarnings("unchecked") public void testListenerNotifiedOrdered() { - ScopedStoreEventDispatcher dispatcher = new ScopedStoreEventDispatcher<>(1); + DefaultStoreEventDispatcher dispatcher = new DefaultStoreEventDispatcher<>(1); @SuppressWarnings("unchecked") StoreEventListener listener = mock(StoreEventListener.class); dispatcher.addEventListener(listener); @@ -95,7 +95,7 @@ public void testListenerNotifiedOrdered() { @Test public void testEventFiltering() { - ScopedStoreEventDispatcher dispatcher = new ScopedStoreEventDispatcher<>(1); + DefaultStoreEventDispatcher dispatcher = new DefaultStoreEventDispatcher<>(1); @SuppressWarnings("unchecked") StoreEventListener listener = mock(StoreEventListener.class, withSettings().verboseLogging()); dispatcher.addEventListener(listener); @@ -118,7 +118,7 @@ public void testEventFiltering() { @Test public void testOrderedEventDelivery() throws Exception { - final ScopedStoreEventDispatcher dispatcher = new ScopedStoreEventDispatcher<>(4); + final DefaultStoreEventDispatcher dispatcher = new DefaultStoreEventDispatcher<>(4); dispatcher.setEventOrdering(true); final ConcurrentHashMap map = new ConcurrentHashMap<>(); final long[] keys = new long[] { 1L, 42L, 256L }; From 70d405eaab9ada853b49470b1816250c514e451a Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 14 May 2019 09:40:21 -0400 Subject: [PATCH 131/372] Fixes #2647 : Strip any qualifier before forming the internal reject pattern for baseline versions --- build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 035ffee2da..c41ee06c22 100644 --- a/build.gradle +++ b/build.gradle @@ -254,9 +254,10 @@ subprojects { } dependencies { baseline(group: group, name: jar.baseName) { + def baseVersion = fixedVersion.replaceAll(/-[a-zA-Z0-9]+$/, "") version { require "(,${fixedVersion}[" - reject "${fixedVersion}-internal+" + reject "${baseVersion}-internal+" } force = true transitive = false From ec16fea53281151e95b1b595349104ce0f9a570a Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 25 Feb 2019 14:28:53 -0500 Subject: [PATCH 132/372] Issue 2613 : Make manager configurations derivable --- .../jsr107/EhcacheCachingProvider.java | 2 +- .../jsr107/config/Jsr107Configuration.java | 2 +- .../Jsr107ServiceConfigurationParser.java | 4 +- .../jsr107/ConfigurationMergerTest.java | 2 +- .../ehcache/config/CacheConfiguration.java | 9 + .../org/ehcache/config/Configuration.java | 16 +- .../FluentCacheConfigurationBuilder.java | 36 ++ .../config/FluentConfigurationBuilder.java | 327 ++++++++++++++++++ .../service/ServiceCreationConfiguration.java | 38 +- .../ClusteringServiceConfiguration.java | 15 +- ...ClusteringServiceConfigurationBuilder.java | 103 +++++- .../ServerSideConfigurationBuilder.java | 14 +- ...acheManagerServiceConfigurationParser.java | 4 +- ...teredLoaderWriterStoreProviderFactory.java | 2 +- ...atingLoaderWriterStoreProviderFactory.java | 2 +- ...steredWriteBehindStoreProviderFactory.java | 2 +- .../service/ClusteringServiceFactory.java | 2 +- .../store/ClusteredStoreProviderFactory.java | 2 +- .../ClusteredResourcePoolUpdationTest.java | 6 +- .../client/BasicClusteredCacheExpiryTest.java | 2 +- .../client/BasicClusteredCacheTest.java | 14 +- .../client/CacheManagerDestroyTest.java | 7 +- .../client/ClusteredCacheDestroyTest.java | 4 +- .../client/ClusteredCacheExpirationTest.java | 2 +- .../client/ClusteredConcurrencyTest.java | 8 +- .../clustered/client/EntityServiceTest.java | 3 +- ...tedCombinationsWithClusteredCacheTest.java | 6 +- .../ClusteringServiceConfigurationTest.java | 25 ++ .../clustered/client/docs/GettingStarted.java | 37 +- .../clustered/client/docs/Resilience.java | 2 +- .../clustered/client/docs/Tiering.java | 2 +- ...ManagerServiceConfigurationParserTest.java | 21 +- ...ClusterStateRepositoryReplicationTest.java | 4 +- ...rTierManagerClientEntityExceptionTest.java | 12 +- .../service/ConnectionClosedTest.java | 3 +- .../internal/service/ConnectionStateTest.java | 2 +- .../service/DefaultClusteringServiceTest.java | 221 ++++++------ .../internal/service/ReconnectTest.java | 2 +- .../StateRepositoryWhitelistingTest.java | 2 +- .../lock/LockRetentionDuringFailoverTest.java | 2 +- .../ActivePassiveClientIdTest.java | 2 +- .../BasicClusteredLoaderWriterTest.java | 20 +- ...icClusteredWriteBehindPassthroughTest.java | 2 +- .../BasicCacheOpsMultiThreadedTest.java | 12 +- .../clustered/BasicClusteredCacheOpsTest.java | 9 +- .../clustered/BasicEntityInteractionTest.java | 9 +- ...anagerLifecycleEhcacheIntegrationTest.java | 4 +- .../clustered/ClusteredLoaderWriterTest.java | 2 +- .../ehcache/clustered/DestroyLoopTest.java | 4 +- .../clustered/EventsFailureBehaviorTest.java | 6 +- .../IterationFailureBehaviorTest.java | 6 +- .../java/org/ehcache/clustered/LeaseTest.java | 12 +- .../clustered/OversizedCacheOpsTest.java | 4 +- .../clustered/ReconnectDuringDestroyTest.java | 10 +- .../ResourcePoolAllocationFailureTest.java | 7 +- .../clustered/TerminatedServerTest.java | 42 +-- .../AbstractClusteringManagementTest.java | 8 +- .../management/CMClosedEventSentTest.java | 8 +- .../EhcacheConfigWithManagementTest.java | 8 +- .../EhcacheManagerToStringTest.java | 5 +- .../ManagementClusterConnectionTest.java | 4 +- .../reconnect/BasicCacheReconnectTest.java | 10 +- .../CacheManagerDestroyReconnectTest.java | 3 +- .../reconnect/EventsReconnectTest.java | 3 +- ...dCacheOpsReplicationMultiThreadedTest.java | 3 +- ...BasicClusteredCacheOpsReplicationTest.java | 3 +- ...OpsReplicationWithMultipleClientsTest.java | 5 +- ...CacheOpsReplicationWithServersApiTest.java | 3 +- .../BasicLifeCyclePassiveReplicationTest.java | 2 +- .../clustered/replication/DuplicateTest.java | 3 +- .../OversizedCacheOpsPassiveTest.java | 3 +- .../clustered/sync/PassiveSyncTest.java | 6 +- .../writebehind/WriteBehindTestBase.java | 2 +- .../org/ehcache/osgi/ClusteredOsgiTest.java | 2 +- core/build.gradle | 2 +- .../java/org/ehcache/core/EhcacheManager.java | 5 +- .../core/config/CoreConfigurationBuilder.java | 210 +++++++++++ .../core/config/DefaultConfiguration.java | 17 +- .../org/ehcache/core/config/package-info.java | 5 +- .../org/ehcache/core/spi/ServiceLocator.java | 2 +- .../core/spi/service/ServiceFactory.java | 2 +- .../org/ehcache/core/EhcacheManagerTest.java | 4 +- .../config/CoreConfigurationBuilderTest.java | 51 +++ .../services/FancyCacheProviderFactory.java | 2 +- .../services/TestMandatoryServiceFactory.java | 4 +- .../services/TestProvidedServiceFactory.java | 2 +- .../core/spi/services/TestServiceFactory.java | 2 +- .../ranking/HighRankServiceAFactory.java | 2 +- .../ranking/LowRankServiceBFactory.java | 2 +- .../MandatoryHighRankServiceBFactory.java | 2 +- .../MandatoryLowRankServiceAFactory.java | 2 +- gradle.properties | 2 +- .../config/builders/CacheManagerBuilder.java | 109 +++--- .../config/builders/ConfigurationBuilder.java | 168 +++++---- ...dExecutionServiceConfigurationBuilder.java | 19 + .../builders/UserManagedCacheBuilder.java | 6 +- .../DefaultCopyProviderConfiguration.java | 12 +- ...heEventDispatcherFactoryConfiguration.java | 12 +- .../PooledExecutionServiceConfiguration.java | 23 +- ...acheLoaderWriterProviderConfiguration.java | 20 +- .../WriteBehindProviderConfiguration.java | 12 +- .../DefaultPersistenceConfiguration.java | 12 +- ...efaultResilienceStrategyConfiguration.java | 4 + ...silienceStrategyProviderConfiguration.java | 18 +- ...ultSerializationProviderConfiguration.java | 12 +- ...OffHeapDiskStoreProviderConfiguration.java | 12 +- ...aultSizeOfEngineProviderConfiguration.java | 12 +- .../internal/TimeSourceConfiguration.java | 11 +- .../internal/TimeSourceServiceFactory.java | 2 +- .../classes/ClassInstanceConfiguration.java | 10 + .../ClassInstanceProviderConfiguration.java | 12 +- ...icationListenerServiceProviderFactory.java | 2 +- .../DefaultExecutionServiceFactory.java | 2 +- .../WriteBehindProviderFactory.java | 2 +- .../DefaultDiskResourceServiceFactory.java | 2 +- ...DefaultLocalPersistenceServiceFactory.java | 2 +- .../DefaultSizeOfEngineProviderFactory.java | 2 +- .../spi/copy/DefaultCopyProviderFactory.java | 2 +- ...aultCacheEventListenerProviderFactory.java | 2 +- ...faultCacheLoaderWriterProviderFactory.java | 2 +- ...aultResilienceStrategyProviderFactory.java | 2 +- .../DefaultSerializationProviderFactory.java | 2 +- .../DefaultStatisticsServiceFactory.java | 2 +- .../disk/OffHeapDiskStoreProviderFactory.java | 2 +- .../heap/OnHeapStoreProviderFactory.java | 2 +- .../LoaderWriterStoreProviderFactory.java | 2 +- .../offheap/OffHeapStoreProviderFactory.java | 2 +- .../CompoundCachingTierProviderFactory.java | 2 +- .../tiering/TieredStoreProviderFactory.java | 2 +- .../builders/CacheManagerBuilderTest.java | 38 +- .../DefaultCopyProviderConfigurationTest.java | 39 +++ ...entDispatcherFactoryConfigurationTest.java | 36 ++ ...oledExecutionServiceConfigurationTest.java | 37 ++ ...LoaderWriterProviderConfigurationTest.java | 41 +++ .../WriteBehindProviderConfigurationTest.java | 36 ++ .../DefaultPersistenceConfigurationTest.java | 38 ++ ...ltResilienceStrategyConfigurationTest.java | 4 +- ...enceStrategyProviderConfigurationTest.java | 45 +++ ...erializationProviderConfigurationTest.java | 16 + ...eapDiskStoreProviderConfigurationTest.java | 36 ++ .../internal/TimeSourceConfigurationTest.java | 38 ++ ...SizeOfEngineProviderConfigurationTest.java | 17 +- .../ehcache/integration/EhcacheBaseTest.java | 4 +- ...anagementRegistryServiceConfiguration.java | 2 +- .../management/cluster/Clustering.java | 2 +- ...steringManagementServiceConfiguration.java | 2 +- .../DefaultClusteringManagementService.java | 4 +- ...steringManagementServiceConfiguration.java | 2 +- .../DefaultManagementRegistryFactory.java | 2 +- ...entRegistryServiceConfigurationParser.java | 4 +- .../management/registry/XmlConfigTest.java | 2 +- .../configuration/XAStoreProviderFactory.java | 2 +- .../DefaultJournalProviderFactory.java | 2 +- ...aultTransactionManagerProviderFactory.java | 2 +- ...acheManagerServiceConfigurationParser.java | 4 +- ...ansactionManagerProviderConfiguration.java | 12 +- ...ctionManagerProviderConfigurationTest.java | 37 ++ ...acheManagerServiceConfigurationParser.java | 4 +- .../org/ehcache/xml/ConfigurationParser.java | 22 +- ...oreServiceCreationConfigurationParser.java | 5 +- .../ServiceCreationConfigurationParser.java | 8 +- .../org/ehcache/xml/XmlConfiguration.java | 9 +- ...oreServiceCreationConfigurationParser.java | 10 +- ...oolServiceCreationConfigurationParser.java | 2 +- .../org/ehcache/xml/BarConfiguration.java | 2 +- .../test/java/org/ehcache/xml/BarParser.java | 4 +- .../org/ehcache/xml/XmlConfigurationTest.java | 6 +- ...patcherFactoryConfigurationParserTest.java | 4 +- ...gerPersistenceConfigurationParserTest.java | 2 +- ...ltCopyProviderConfigurationParserTest.java | 4 +- ...zationProviderConfigurationParserTest.java | 4 +- ...EngineProviderConfigurationParserTest.java | 4 +- ...kStoreProviderConfigurationParserTest.java | 4 +- ...ecutionServiceConfigurationParserTest.java | 4 +- ...BehindProviderConfigurationParserTest.java | 4 +- 175 files changed, 2022 insertions(+), 625 deletions(-) create mode 100644 api/src/main/java/org/ehcache/config/FluentCacheConfigurationBuilder.java create mode 100644 api/src/main/java/org/ehcache/config/FluentConfigurationBuilder.java create mode 100644 core/src/main/java/org/ehcache/core/config/CoreConfigurationBuilder.java create mode 100644 core/src/test/java/org/ehcache/core/config/CoreConfigurationBuilderTest.java create mode 100644 impl/src/test/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfigurationTest.java create mode 100644 impl/src/test/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfigurationTest.java create mode 100644 impl/src/test/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfigurationTest.java create mode 100644 impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfigurationTest.java create mode 100644 impl/src/test/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfigurationTest.java create mode 100644 impl/src/test/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfigurationTest.java create mode 100644 impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfigurationTest.java create mode 100644 impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfigurationTest.java create mode 100644 impl/src/test/java/org/ehcache/impl/internal/TimeSourceConfigurationTest.java create mode 100644 transactions/src/test/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfigurationTest.java diff --git a/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java b/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java index fd0b415ba0..15febe4e31 100644 --- a/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java +++ b/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java @@ -140,7 +140,7 @@ Eh107CacheManager getCacheManager(ConfigSupplier configSupplier, Properties prop } private Eh107CacheManager createCacheManager(URI uri, Configuration config, Properties properties) { - Collection> serviceCreationConfigurations = config.getServiceCreationConfigurations(); + Collection> serviceCreationConfigurations = config.getServiceCreationConfigurations(); Jsr107Service jsr107Service = new DefaultJsr107Service(ServiceUtils.findSingletonAmongst(Jsr107Configuration.class, serviceCreationConfigurations)); Eh107CacheLoaderWriterProvider cacheLoaderWriterFactory = new Eh107CacheLoaderWriterProvider(); diff --git a/107/src/main/java/org/ehcache/jsr107/config/Jsr107Configuration.java b/107/src/main/java/org/ehcache/jsr107/config/Jsr107Configuration.java index d2eeb8bdb7..a6cf09ce10 100644 --- a/107/src/main/java/org/ehcache/jsr107/config/Jsr107Configuration.java +++ b/107/src/main/java/org/ehcache/jsr107/config/Jsr107Configuration.java @@ -25,7 +25,7 @@ /** * {@link ServiceCreationConfiguration} for default {@link Jsr107Service} implementation. */ -public class Jsr107Configuration implements ServiceCreationConfiguration { +public class Jsr107Configuration implements ServiceCreationConfiguration { private final String defaultTemplate; private final boolean jsr107CompliantAtomics; diff --git a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java b/107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java index 325be8163f..83250dbfe5 100644 --- a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java +++ b/107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java @@ -63,7 +63,7 @@ public URI getNamespace() { } @Override - public ServiceCreationConfiguration parseServiceCreationConfiguration(final Element fragment, ClassLoader classLoader) { + public ServiceCreationConfiguration parseServiceCreationConfiguration(final Element fragment, ClassLoader classLoader) { boolean jsr107CompliantAtomics = true; ConfigurationElementState enableManagementAll = ConfigurationElementState.UNSPECIFIED; ConfigurationElementState enableStatisticsAll = ConfigurationElementState.UNSPECIFIED; @@ -96,7 +96,7 @@ public Class getServiceType() { } @Override - public Element unparseServiceCreationConfiguration(ServiceCreationConfiguration serviceCreationConfiguration) { + public Element unparseServiceCreationConfiguration(ServiceCreationConfiguration serviceCreationConfiguration) { throw new XmlConfigurationException("XML translation of JSR-107 cache elements are not supported"); } diff --git a/107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java b/107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java index b386b67620..e1df48b7b8 100644 --- a/107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java +++ b/107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java @@ -355,7 +355,7 @@ public void jsr107DefaultEh107IdentityCopierForImmutableTypesWithCMLevelDefaults assertThat(configHolder1.cacheConfiguration.getServiceConfigurations().isEmpty(), is(true)); - for (ServiceCreationConfiguration serviceCreationConfiguration : xmlConfiguration.getServiceCreationConfigurations()) { + for (ServiceCreationConfiguration serviceCreationConfiguration : xmlConfiguration.getServiceCreationConfigurations()) { if (serviceCreationConfiguration instanceof DefaultCopyProviderConfiguration) { DefaultCopyProviderConfiguration copierConfig = (DefaultCopyProviderConfiguration)serviceCreationConfiguration; assertThat(copierConfig.getDefaults().size(), is(6)); diff --git a/api/src/main/java/org/ehcache/config/CacheConfiguration.java b/api/src/main/java/org/ehcache/config/CacheConfiguration.java index a00f258d72..fd0817e728 100644 --- a/api/src/main/java/org/ehcache/config/CacheConfiguration.java +++ b/api/src/main/java/org/ehcache/config/CacheConfiguration.java @@ -112,4 +112,13 @@ public interface CacheConfiguration { */ ResourcePools getResourcePools(); + /** + * Create a builder seeded with this configuration. + * + * @see FluentConfigurationBuilder + * @return a configuration builder + */ + default FluentCacheConfigurationBuilder derive() { + return () -> this; + } } diff --git a/api/src/main/java/org/ehcache/config/Configuration.java b/api/src/main/java/org/ehcache/config/Configuration.java index d61e335e77..93a1067085 100644 --- a/api/src/main/java/org/ehcache/config/Configuration.java +++ b/api/src/main/java/org/ehcache/config/Configuration.java @@ -46,7 +46,7 @@ public interface Configuration { * * @return a collection of service creations configurations */ - Collection> getServiceCreationConfigurations(); + Collection> getServiceCreationConfigurations(); /** * The {@link ClassLoader} for the {@link org.ehcache.CacheManager CacheManager}. @@ -59,4 +59,18 @@ public interface Configuration { * @return the cache manager {@code ClassLoader} */ ClassLoader getClassLoader(); + + /** + * Creates a builder seeded with this configuration. + *

+ * The default implementation throws {@code UnsupportedOperationException} to indicate that configuration derivation + * is not supported. + * + * @see FluentConfigurationBuilder + * @return a configuration builder + * @throws UnsupportedOperationException if configuration derivation is not supported + */ + default FluentConfigurationBuilder derive() { + throw new UnsupportedOperationException(); + } } diff --git a/api/src/main/java/org/ehcache/config/FluentCacheConfigurationBuilder.java b/api/src/main/java/org/ehcache/config/FluentCacheConfigurationBuilder.java new file mode 100644 index 0000000000..f8c2aa4ede --- /dev/null +++ b/api/src/main/java/org/ehcache/config/FluentCacheConfigurationBuilder.java @@ -0,0 +1,36 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.config; + +import org.ehcache.config.CacheConfiguration; + +/** + * A fluent builder of {@link CacheConfiguration} instances. + * + * @param cache key type + * @param cache value type + */ +public interface FluentCacheConfigurationBuilder extends Builder> { + + /** + * Builds a new {@link CacheConfiguration}. + * + * @return a new {@code CacheConfiguration} + */ + CacheConfiguration build(); +} + diff --git a/api/src/main/java/org/ehcache/config/FluentConfigurationBuilder.java b/api/src/main/java/org/ehcache/config/FluentConfigurationBuilder.java new file mode 100644 index 0000000000..20e1cde5b4 --- /dev/null +++ b/api/src/main/java/org/ehcache/config/FluentConfigurationBuilder.java @@ -0,0 +1,327 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.config; + +import org.ehcache.spi.service.ServiceCreationConfiguration; + +import java.util.Collection; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +/** + * A fluent builder of {@link Configuration} instances. + * + * @param builder sub-type + */ +public interface FluentConfigurationBuilder> extends Builder { + + /** + * Return the cache configuration for the given alias. + * + * @param alias cache alias + * @return associated cache configuration + * + * @see #withCache(String, CacheConfiguration) + * @see #withCache(String, Builder) + * @see #updateCache(String, UnaryOperator) + * @see #withoutCache(String) + * @see #updateCaches(UnaryOperator) + */ + CacheConfiguration getCache(String alias); + + /** + * Adds the given cache to this configuration. + *

+ * This will overwrite any existing configuration for the cache with this alias. + * + * @param alias cache alias + * @param config cache configuration + * @return an updated builder + * + * @see #getCache(String) + * @see #withCache(String, Builder) + * @see #updateCache(String, UnaryOperator) + * @see #withoutCache(String) + * @see #updateCaches(UnaryOperator) + */ + B withCache(String alias, CacheConfiguration config); + + /** + * Adds the cache configuration built by a builder to this configuration. + *

+ * This will overwrite any existing configuration for the cache with this alias. + * + * @param alias cache alias + * @param builder cache configuration builder + * @return an updated builder + * + * @see #getCache(String) + * @see #withCache(String, Builder) + * @see #updateCache(String, UnaryOperator) + * @see #withoutCache(String) + * @see #updateCaches(UnaryOperator) + */ + default B withCache(String alias, Builder> builder) { + return withCache(alias, builder.build()); + } + + /** + * Removes the given cache from this configuration. + * + * @param alias cache alias + * @return an updated builder + * + * @see #getCache(String) + * @see #withCache(String, CacheConfiguration) + * @see #withCache(String, Builder) + * @see #updateCache(String, UnaryOperator) + * @see #updateCaches(UnaryOperator) + */ + B withoutCache(String alias); + + /** + * Updates the configuration of the identified cache. + *

+ * If a cache exists for the given alias then the following process is performed: + *

    + *
  1. The configuration is converted to a builder seeded with that configuration. + *
  2. The builder is then transformed using the {@code update} unary operator.
  3. + *
  4. A new configuration is generated by calling {@code build()} on the resultant builder.
  5. + *
  6. The new configuration is associated with the given alias.
  7. + *
+ * If there is no cache associated with the given {@code alias} then an {@code IllegalStateException} will be thrown. + * + * @param alias cache alias + * @param update configuration mutation function + * @return an updated builder + * @throws IllegalArgumentException if no cache configuration exists for {@code alias} + * + * @see #getCache(String) + * @see #withCache(String, CacheConfiguration) + * @see #withCache(String, Builder) + * @see #withoutCache(String) + * @see #updateCaches(UnaryOperator) + */ + B updateCache(String alias, UnaryOperator> update) throws IllegalArgumentException; + + /** + * Updates the configuration of the all caches. + *

+ * For every existing cache the following process is performed: + *

    + *
  1. The configuration is converted to a builder seeded with that configuration. + *
  2. The builder is then transformed using the {@code update} unary operator.
  3. + *
  4. A new configuration is generated by calling {@code build()} on the resultant builder.
  5. + *
  6. The new configuration is associated with the given alias.
  7. + *
+ * + * @param update configuration mutation function + * @return an updated builder + * + * @see #getCache(String) + * @see #withCache(String, CacheConfiguration) + * @see #withCache(String, Builder) + * @see #updateCache(String, UnaryOperator) + * @see #withoutCache(String) + */ + B updateCaches(UnaryOperator> update); + + /** + * Return the unique service creation configuration of the given type. + *

+ * If there are multiple configuration instances of this type (or subtypes) then an {@code IllegalArgumentException} + * will be thrown. + * + * @param configurationType desired configuration type + * @param configuration type + * @return the given configuration type + * @throws IllegalArgumentException if there are multiple instances of this type + * + * @see #getServices(Class) + * @see #withService(ServiceCreationConfiguration) + * @see #withService(Builder) + * @see #withoutServices(Class) + * @see #withoutServices(Class, Predicate) + * @see #updateServices(Class, UnaryOperator) + */ + default > C getService(Class configurationType) throws IllegalArgumentException { + Collection services = getServices(configurationType); + + switch (services.size()) { + case 0: + return null; + case 1: + return services.iterator().next(); + default: + throw new IllegalArgumentException(configurationType + " does not identify a unique service configuration: " + services); + } + } + + /** + * Return the service creation configurations of the given type. + * + * @param configurationType desired configuration type + * @param configuration type + * @return all services of this type + * + * @see #getService(Class) + * @see #withService(ServiceCreationConfiguration) + * @see #withService(Builder) + * @see #withoutServices(Class) + * @see #withoutServices(Class, Predicate) + * @see #updateServices(Class, UnaryOperator) + */ + > Collection getServices(Class configurationType); + + /** + * Adds a service creation configuration to this configuration. + *

+ * This will remove any existing service creation configurations that are incompatible with the supplied one. + * This removal is equivalent to the following: + *

{@code configurations.removeIf(
+   *     existing -> !config.compatibleWith(existing) || !existing.compatibleWith(config)
+   * );}
+ * + * @param config service creation configuration + * @return an updated builder + * @see ServiceCreationConfiguration#compatibleWith(ServiceCreationConfiguration) + * + * @see #getService(Class) + * @see #getServices(Class) + * @see #withService(Builder) + * @see #withoutServices(Class) + * @see #withoutServices(Class, Predicate) + * @see #updateServices(Class, UnaryOperator) + */ + B withService(ServiceCreationConfiguration config); + + /** + * Adds a service creation configuration built by the given builder to this configuration. + *

+ * This will remove any existing configurations that are incompatible with the supplied one. + * + * @param builder service creation configuration builder + * @return an updated builder + * + * @see #getService(Class) + * @see #getServices(Class) + * @see #withService(ServiceCreationConfiguration) + * @see #withoutServices(Class) + * @see #withoutServices(Class, Predicate) + * @see #updateServices(Class, UnaryOperator) + */ + default B withService(Builder> builder) { + return withService(builder.build()); + } + + /** + * Removes all service creation configurations of the given type from this configuration. + * + * @param clazz service configuration type + * @return an updated builder + * + * @see #getService(Class) + * @see #getServices(Class) + * @see #withService(ServiceCreationConfiguration) + * @see #withService(Builder) + * @see #withoutServices(Class, Predicate) + * @see #updateServices(Class, UnaryOperator) + */ + default B withoutServices(Class> clazz) { + return withoutServices(clazz, c -> true); + } + + /** + * Removes all service creation configurations of the given type that pass the predicate. + * + * @param clazz service configuration type + * @param predicate predicate controlling removal + * @param configuration type + * @return an updated builder + * + * @see #getService(Class) + * @see #getServices(Class) + * @see #withService(ServiceCreationConfiguration) + * @see #withService(Builder) + * @see #withoutServices(Class) + * @see #updateServices(Class, UnaryOperator) + */ + > B withoutServices(Class clazz, Predicate predicate); + + /** + * Updates all service creation configurations of the given type. + *

+ * For each existing service creation configuration instance that is assignment compatible with {@code clazz} the + * following process is performed: + *

    + *
  1. The configuration is converted to its detached representations using the + * {@link ServiceCreationConfiguration#derive()} method.
  2. + *
  3. The detached representation is transformed using the {@code update} unary operator.
  4. + *
  5. A new configuration is generated by passing the transformed detached representation to the existing + * configurations {@link ServiceCreationConfiguration#build(Object)} method.
  6. + *
  7. The new configuration is added to the builders service configuration set.
  8. + *
+ * If there are no service creation configurations assignment compatible with {@code clazz} then an + * {@code IllegalStateException} will be thrown. + * + * @param clazz service creation configuration type + * @param update configuration mutation function + * @param configuration detached representation type + * @param service configuration type + * @return an updated builder + * @throws IllegalStateException if no configurations of type {@code C} exist + * + * @see #getService(Class) + * @see #getServices(Class) + * @see #withService(ServiceCreationConfiguration) + * @see #withService(Builder) + * @see #withoutServices(Class) + * @see #withoutServices(Class, Predicate) + */ + > B updateServices(Class clazz, UnaryOperator update) throws IllegalStateException; + + /** + * Return the configured classloader instance. + * + * @return configured classloader + * + * @see #withClassLoader(ClassLoader) + * @see #withDefaultClassLoader() + */ + ClassLoader getClassLoader(); + + /** + * Sets the given class loader as the cache manager classloader + * + * @param classLoader cache manager classloader + * @return an updated builder + * + * @see #getClassLoader() + * @see #withDefaultClassLoader() + */ + B withClassLoader(ClassLoader classLoader); + + /** + * Removes any provided class loader returning to default behavior + * + * @return an updated builder + * + * @see #getClassLoader() + * @see #withClassLoader(ClassLoader) + */ + B withDefaultClassLoader(); +} diff --git a/api/src/main/java/org/ehcache/spi/service/ServiceCreationConfiguration.java b/api/src/main/java/org/ehcache/spi/service/ServiceCreationConfiguration.java index 4db06f3209..e2636e2263 100644 --- a/api/src/main/java/org/ehcache/spi/service/ServiceCreationConfiguration.java +++ b/api/src/main/java/org/ehcache/spi/service/ServiceCreationConfiguration.java @@ -20,9 +20,9 @@ * A configuration type used when creating a {@link Service}. * * @param the service type this configuration works with - * + * @param the type of the detached representation */ -public interface ServiceCreationConfiguration { +public interface ServiceCreationConfiguration { /** * Indicates which service consumes this configuration at creation. @@ -30,4 +30,38 @@ public interface ServiceCreationConfiguration { * @return the service type */ Class getServiceType(); + + /** + * Derive a detached representation from this configuration + * + * @return a detached representation + * @throws UnsupportedOperationException if the configuration has no representation + */ + default R derive() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Construct a new configuration from the given detached representation. + * + * @param representation a detached representation + * @return a new configuration + * @throws UnsupportedOperationException if the configuration has no representation + */ + default ServiceCreationConfiguration build(R representation) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Returns true if this configuration can co-exist with {@code other} in the same manager configuration. + *

+ * The default implementation of {@code compatibleWith} (as used by many of the implementations) considers any + * instance of the same type (or a sub-type) to be incompatible with this instance. + * + * @param other other service creation configuration + * @return {@code true} if the two configurations are compatible + */ + default boolean compatibleWith(ServiceCreationConfiguration other) { + return !getClass().isInstance(other); + }; } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java b/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java index 8c486ea821..22c81869bb 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java @@ -18,6 +18,7 @@ import org.ehcache.CacheManager; import org.ehcache.PersistentCacheManager; +import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.internal.ConnectionSource; import org.ehcache.clustered.client.service.ClusteringService; import org.ehcache.config.builders.CacheManagerBuilder; @@ -33,11 +34,13 @@ import org.ehcache.clustered.common.ServerSideConfiguration; +import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.seededFrom; + /** * Specifies the configuration for a {@link ClusteringService}. */ public class ClusteringServiceConfiguration - implements ServiceCreationConfiguration, + implements ServiceCreationConfiguration, CacheManagerConfiguration, HumanReadable { @@ -365,4 +368,14 @@ private String readablePoolsString() { } return pools.toString(); } + + @Override + public ClusteringServiceConfigurationBuilder derive() { + return seededFrom(this); + } + + @Override + public ClusteringServiceConfiguration build(ClusteringServiceConfigurationBuilder representation) { + return representation.build(); + } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteringServiceConfigurationBuilder.java b/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteringServiceConfigurationBuilder.java index 86ab700b8f..3c44b920a1 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteringServiceConfigurationBuilder.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteringServiceConfigurationBuilder.java @@ -25,6 +25,8 @@ import java.util.Objects; import java.util.Properties; import java.util.concurrent.TimeUnit; +import java.util.function.UnaryOperator; + import org.ehcache.clustered.client.config.Timeouts; import org.ehcache.clustered.client.internal.ConnectionSource; import org.ehcache.clustered.common.ServerSideConfiguration; @@ -40,6 +42,8 @@ public final class ClusteringServiceConfigurationBuilder implements Builder servers, String clusterTierManager) { - return new ClusteringServiceConfigurationBuilder(new ConnectionSource.ServerList(servers, clusterTierManager), TimeoutsBuilder.timeouts().build(), DEFAULT_AUTOCREATE); + return new ClusteringServiceConfigurationBuilder(new ConnectionSource.ServerList(servers, clusterTierManager), TimeoutsBuilder.timeouts().build(), DEFAULT_AUTOCREATE, null, new Properties()); } - private ClusteringServiceConfigurationBuilder(ConnectionSource connectionSource, Timeouts timeouts, boolean autoCreate) { + /** + * Creates a new builder seeded from an existing configuration. + * + * @param configuration existing clustering configuration + * @return a clustering service configuration builder + */ + public static ClusteringServiceConfigurationBuilder seededFrom(ClusteringServiceConfiguration configuration) { + + ServerSideConfiguration serverSideConfiguration = configuration.getServerConfiguration(); + if (serverSideConfiguration == null) { + return new ClusteringServiceConfigurationBuilder(configuration.getConnectionSource(), configuration.getTimeouts(), + configuration.isAutoCreate(), null, configuration.getProperties()); + } else { + return new ClusteringServiceConfigurationBuilder(configuration.getConnectionSource(), configuration.getTimeouts(), + configuration.isAutoCreate(), new ServerSideConfigurationBuilder(serverSideConfiguration), configuration.getProperties()); + } + } + + private ClusteringServiceConfigurationBuilder(ConnectionSource connectionSource, Timeouts timeouts, boolean autoCreate, ServerSideConfigurationBuilder serverSideConfiguration, Properties properties) { this.connectionSource = connectionSource; this.timeouts = Objects.requireNonNull(timeouts, "Timeouts can't be null"); this.autoCreate = autoCreate; + this.serverSideConfiguration = serverSideConfiguration; + this.properties = properties; + } + + /** + * Reconfigure to connect to a different URI. + * + * @return a clustering service configuration builder + */ + public ClusteringServiceConfigurationBuilder usingUri(URI clusterUri) { + return new ClusteringServiceConfigurationBuilder(new ConnectionSource.ClusterUri(clusterUri), timeouts, autoCreate, serverSideConfiguration, properties); + } + + /** + * Reconfigure to connect to a different cluster. + * + * @return a clustering service configuration builder + */ + public ClusteringServiceConfigurationBuilder usingServers(Iterable servers) { + return new ClusteringServiceConfigurationBuilder(new ConnectionSource.ServerList(servers, connectionSource.getClusterTierManager()), timeouts, autoCreate, serverSideConfiguration, properties); + } + + /** + * Reconfigure to connect to a different cluster and manager name. + * + * @return a clustering service configuration builder + */ + public ClusteringServiceConfigurationBuilder usingServers(Iterable servers, String clusterTierManager) { + return new ClusteringServiceConfigurationBuilder(new ConnectionSource.ServerList(servers, clusterTierManager), timeouts, autoCreate, serverSideConfiguration, properties); } /** * Support connection to an existing entity or create if the entity if absent. * * @return a clustering service configuration builder + * @deprecated in favor of {@link ClusteringServiceConfigurationBuilder#autoCreate(UnaryOperator)} */ + @Deprecated public ServerSideConfigurationBuilder autoCreate() { - return new ServerSideConfigurationBuilder(new ClusteringServiceConfigurationBuilder(this.connectionSource, this.timeouts, true)); + return new ServerSideConfigurationBuilder(new ClusteringServiceConfigurationBuilder(this.connectionSource, this.timeouts, true, serverSideConfiguration, properties)); } /** * Only support connection to an existing entity. * * @return a clustering service configuration builder + * @deprecated in favor of {@link ClusteringServiceConfigurationBuilder#expecting(UnaryOperator)} */ + @Deprecated public ServerSideConfigurationBuilder expecting() { - return new ServerSideConfigurationBuilder(new ClusteringServiceConfigurationBuilder(this.connectionSource, this.timeouts, false)); + return new ServerSideConfigurationBuilder(new ClusteringServiceConfigurationBuilder(this.connectionSource, this.timeouts, false, serverSideConfiguration, properties)); + } + + /** + * Support connection to an existing entity or create if the entity if absent. + *

+ * An empty server-side configuration can be created by performing no operations on the supplied builder: + * {@code builder.autoCreate(b -> b)} + * + * @return a clustering service configuration builder + */ + public ClusteringServiceConfigurationBuilder autoCreate(UnaryOperator serverSideConfig) { + return new ClusteringServiceConfigurationBuilder(this.connectionSource, this.timeouts, true, + serverSideConfig.apply(new ServerSideConfigurationBuilder()), properties); + } + + /** + * Only support connection to an existing entity. + *

+ * An empty server-side configuration can be requested by performing no operations on the supplied builder: + * {@code builder.expecting(b -> b)} + * + * @return a clustering service configuration builder + */ + public ClusteringServiceConfigurationBuilder expecting(UnaryOperator serverSideConfig) { + return new ClusteringServiceConfigurationBuilder(this.connectionSource, this.timeouts, false, + serverSideConfig.apply(new ServerSideConfigurationBuilder()), properties); } /** @@ -101,7 +182,7 @@ public ServerSideConfigurationBuilder expecting() { * @throws NullPointerException if {@code timeouts} is {@code null} */ public ClusteringServiceConfigurationBuilder timeouts(Timeouts timeouts) { - return new ClusteringServiceConfigurationBuilder(this.connectionSource, timeouts, this.autoCreate); + return new ClusteringServiceConfigurationBuilder(connectionSource, timeouts, autoCreate, serverSideConfiguration, properties); } /** @@ -117,7 +198,7 @@ public ClusteringServiceConfigurationBuilder timeouts(Timeouts timeouts) { * @throws NullPointerException if {@code timeouts} is {@code null} */ public ClusteringServiceConfigurationBuilder timeouts(Builder timeoutsBuilder) { - return new ClusteringServiceConfigurationBuilder(this.connectionSource, timeoutsBuilder.build(), this.autoCreate); + return new ClusteringServiceConfigurationBuilder(connectionSource, timeoutsBuilder.build(), autoCreate, serverSideConfiguration, properties); } /** @@ -143,7 +224,11 @@ public ClusteringServiceConfigurationBuilder readOperationTimeout(long duration, @Override public ClusteringServiceConfiguration build() { - return build(null); + if (serverSideConfiguration == null) { + return build(null); + } else { + return build(serverSideConfiguration.buildServerSideConfiguration()); + } } /** @@ -155,7 +240,7 @@ public ClusteringServiceConfiguration build() { * {@code ClusteringServiceConfigurationBuilder} and the {@code serverSideConfiguration} provided */ ClusteringServiceConfiguration build(ServerSideConfiguration serverSideConfiguration) { - return new ClusteringServiceConfiguration(connectionSource, timeouts, autoCreate, serverSideConfiguration, new Properties()); + return new ClusteringServiceConfiguration(connectionSource, timeouts, autoCreate, serverSideConfiguration, properties); } private static ChronoUnit toChronoUnit(TimeUnit unit) { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ServerSideConfigurationBuilder.java b/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ServerSideConfigurationBuilder.java index e956aec4fb..5b54784588 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ServerSideConfigurationBuilder.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ServerSideConfigurationBuilder.java @@ -39,6 +39,12 @@ public class ServerSideConfigurationBuilder implements Builder pools; + ServerSideConfigurationBuilder() { + this.clientSideBuilder = null; + this.defaultServerResource = null; + this.pools = emptyMap(); + } + ServerSideConfigurationBuilder(ClusteringServiceConfigurationBuilder clientSideBuilder) { if (clientSideBuilder == null) { throw new NullPointerException("clientSideBuilder can not be null"); @@ -48,6 +54,12 @@ public class ServerSideConfigurationBuilder implements Builder parseServiceCreationConfiguration(final Element fragment, ClassLoader classLoader) { + public ServiceCreationConfiguration parseServiceCreationConfiguration(final Element fragment, ClassLoader classLoader) { if ("cluster".equals(fragment.getLocalName())) { @@ -235,7 +235,7 @@ public Class getServiceType() { * @param serviceCreationConfiguration */ @Override - public Element unparseServiceCreationConfiguration(final ServiceCreationConfiguration serviceCreationConfiguration) { + public Element unparseServiceCreationConfiguration(final ServiceCreationConfiguration serviceCreationConfiguration) { Element rootElement = unparseConfig(serviceCreationConfiguration); return rootElement; } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderFactory.java index 529c2bf1f6..98a26168d8 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderFactory.java @@ -23,7 +23,7 @@ public class ClusteredLoaderWriterStoreProviderFactory implements ServiceFactory { @Override - public ClusteredLoaderWriterStore.Provider create(ServiceCreationConfiguration configuration) { + public ClusteredLoaderWriterStore.Provider create(ServiceCreationConfiguration configuration) { return new ClusteredLoaderWriterStore.Provider(); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProviderFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProviderFactory.java index 2b1d811ffd..0ddca5007d 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProviderFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProviderFactory.java @@ -23,7 +23,7 @@ public class DelegatingLoaderWriterStoreProviderFactory implements ServiceFactory { @Override - public DelegatingLoaderWriterStoreProvider create(ServiceCreationConfiguration configuration) { + public DelegatingLoaderWriterStoreProvider create(ServiceCreationConfiguration configuration) { return new DelegatingLoaderWriterStoreProvider(); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderFactory.java index 662c4720ab..434468a148 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderFactory.java @@ -23,7 +23,7 @@ public class ClusteredWriteBehindStoreProviderFactory implements ServiceFactory { @Override - public ClusteredWriteBehindStore.Provider create(ServiceCreationConfiguration configuration) { + public ClusteredWriteBehindStore.Provider create(ServiceCreationConfiguration configuration) { return new ClusteredWriteBehindStore.Provider(); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java index 61b81ea307..6592f75702 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java @@ -32,7 +32,7 @@ public class ClusteringServiceFactory implements ServiceFactory { @Override - public ClusteringService create(final ServiceCreationConfiguration configuration) { + public ClusteringService create(final ServiceCreationConfiguration configuration) { return new DefaultClusteringService((ClusteringServiceConfiguration) configuration); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java index 03d9a209de..aef0dc5113 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java @@ -26,7 +26,7 @@ @Component public class ClusteredStoreProviderFactory implements ServiceFactory { @Override - public ClusteredStore.Provider create(final ServiceCreationConfiguration configuration) { + public ClusteredStore.Provider create(final ServiceCreationConfiguration configuration) { return new ClusteredStore.Provider(); } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java index 946df0deba..1509ff8c70 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java @@ -25,9 +25,7 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.junit.After; import org.junit.AfterClass; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; @@ -55,10 +53,10 @@ public static void setUp() throws Exception { .build()); cacheManager = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER_URI).autoCreate() + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER_URI).autoCreate(server -> server .defaultServerResource("primary-server-resource") .resourcePool("resource-pool-a", 2, MemoryUnit.MB, "secondary-server-resource") - .resourcePool("resource-pool-b", 4, MemoryUnit.MB)) + .resourcePool("resource-pool-b", 4, MemoryUnit.MB))) .withCache("dedicated-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 4, MemoryUnit.MB)))) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java index 7d88e1f4ea..be4181afa6 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java @@ -49,7 +49,7 @@ public class BasicClusteredCacheExpiryTest { private static final URI CLUSTER_URI = URI.create("terracotta://example.com:9540/my-application"); private static final CacheManagerBuilder commonClusteredCacheManagerBuilder = newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java index 5163527489..914a5aa088 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java @@ -26,7 +26,6 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.statistics.CacheStatistics; import org.ehcache.impl.internal.statistics.DefaultStatisticsService; import org.junit.After; import org.junit.Before; @@ -36,7 +35,6 @@ import java.math.BigInteger; import java.net.URI; import java.util.Random; -import java.util.concurrent.atomic.LongAdder; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; @@ -74,7 +72,7 @@ public void testClusteredCacheSingleClient() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB)))); @@ -92,7 +90,7 @@ public void testClusteredCacheSingleClient() throws Exception { public void testClusteredCacheTwoClients() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(100, EntryUnit.ENTRIES) .with(clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) @@ -121,7 +119,7 @@ public void testClusteredCacheTwoClients() throws Exception { public void testClustered3TierCacheTwoClients() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(1, EntryUnit.ENTRIES).offheap(1, MemoryUnit.MB) .with(clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) @@ -174,7 +172,7 @@ public void testClustered3TierCacheTwoClients() throws Exception { public void testTieredClusteredCache() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, heap(2) .with(clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB)))); @@ -191,7 +189,7 @@ public void testTieredClusteredCache() throws Exception { @Test public void testClusteredCacheWithSerializableValue() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = - newCacheManagerBuilder().with(cluster(CLUSTER_URI).autoCreate()) + newCacheManagerBuilder().with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, Person.class, newResourcePoolsBuilder().with(clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB)))); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); @@ -214,7 +212,7 @@ public void testLargeValues() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() .using(statisticsService) - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("small-cache", newCacheConfigurationBuilder(Long.class, BigInteger.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(clusteredDedicated("secondary-server-resource", 4, MemoryUnit.MB)))); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java index 128712f18c..3fb323beff 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java @@ -23,7 +23,6 @@ import org.ehcache.Status; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.internal.UnitTestConnectionService; -import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; @@ -47,7 +46,7 @@ public class CacheManagerDestroyTest { private static final CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()); + .with(cluster(CLUSTER_URI).autoCreate(c -> c)); @Before public void definePassthroughServer() throws Exception { @@ -75,8 +74,8 @@ public void testDestroyCacheManagerWithSingleClient() throws CachePersistenceExc @Test public void testCreateDestroyCreate() throws Exception { - PersistentCacheManager cacheManager = newCacheManagerBuilder().with(cluster(CLUSTER_URI).autoCreate() - .defaultServerResource("primary-server-resource")) + PersistentCacheManager cacheManager = newCacheManagerBuilder().with(cluster(CLUSTER_URI) + .autoCreate(c -> c.defaultServerResource("primary-server-resource"))) .withCache("my-cache", newCacheConfigurationBuilder(Long.class, String.class, heap(10).with(ClusteredResourcePoolBuilder .clusteredDedicated(2, MemoryUnit.MB)))) .build(true); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java index 833e26c035..63f651e763 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java @@ -57,7 +57,7 @@ public class ClusteredCacheDestroyTest { private static final CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache(CLUSTERED_CACHE, newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) @@ -120,7 +120,7 @@ public void testDestroyFreesUpTheAllocatedResource() throws CachePersistenceExce public void testDestroyUnknownCacheAlias() throws Exception { clusteredCacheManagerBuilder.build(true).close(); - PersistentCacheManager cacheManager = newCacheManagerBuilder().with(cluster(CLUSTER_URI).expecting()).build(true); + PersistentCacheManager cacheManager = newCacheManagerBuilder().with(cluster(CLUSTER_URI).expecting(c -> c)).build(true); cacheManager.destroyCache(CLUSTERED_CACHE); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java index 4b02f488d3..96547a30a7 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java @@ -59,7 +59,7 @@ private CacheManagerBuilder cacheManagerBuilder(ExpiryPo return newCacheManagerBuilder() .using(statisticsService) .using(new TimeSourceConfiguration(timeSource)) - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache(CLUSTERED_CACHE, newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .heap(10, EntryUnit.ENTRIES) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java index 17f770f66a..43ebff5ce4 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java @@ -94,10 +94,10 @@ private Runnable content(final CountDownLatch latch) { return () -> { try { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER_URI).autoCreate() - .defaultServerResource("primary-server-resource") - .resourcePool("resource-pool-a", 8, MemoryUnit.MB) - .resourcePool("resource-pool-b", 8, MemoryUnit.MB, "secondary-server-resource")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER_URI) + .autoCreate(server -> server.defaultServerResource("primary-server-resource") + .resourcePool("resource-pool-a", 8, MemoryUnit.MB) + .resourcePool("resource-pool-b", 8, MemoryUnit.MB, "secondary-server-resource"))) .withCache(CACHE_NAME, CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java index d220400d2d..5e4002f84d 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java @@ -20,7 +20,6 @@ import org.ehcache.clustered.client.internal.UnitTestConnectionService.PassthroughServerBuilder; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLockClient; import org.ehcache.clustered.client.service.ClientEntityFactory; -import org.ehcache.clustered.client.service.ClusteringService; import org.ehcache.clustered.client.service.EntityBusyException; import org.ehcache.clustered.client.service.EntityService; import org.ehcache.config.units.MemoryUnit; @@ -65,7 +64,7 @@ public void test() throws Exception { CacheManager cacheManager = newCacheManagerBuilder() .using(clusteredManagementService) - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .build(true); assertThat(clusteredManagementService.clientEntityFactory, is(notNullValue())); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java index 87ec3b5126..92e9b1f524 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java @@ -76,7 +76,7 @@ public void testClusteredCacheWithOrderedEventListeners() { final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .autoCreate()); + .autoCreate(b -> b)); final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); try { @@ -103,7 +103,7 @@ public void testClusteredCacheWithSynchronousEventListeners() { final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .autoCreate()); + .autoCreate(c -> c)); final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); try { @@ -132,7 +132,7 @@ public void testClusteredCacheWithXA() throws Exception { try { CacheManagerBuilder.newCacheManagerBuilder() .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) - .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")).autoCreate()) + .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")).autoCreate(c -> c)) .withCache("xaCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB)) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java index ec7921e3f7..65256785d1 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java @@ -29,7 +29,11 @@ import java.net.URI; import java.util.Collections; import java.util.Iterator; +import java.util.Map; +import java.util.Properties; +import static java.time.Duration.ofSeconds; +import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; public class ClusteringServiceConfigurationTest { @@ -180,4 +184,25 @@ public void testReadableString() { assertThat(cfg.readableString()).isNotNull(); } + @Test + public void testDerivedConfiguration() { + URI uri = URI.create("blah-blah"); + Timeouts timeouts = new Timeouts(ofSeconds(1), ofSeconds(2), ofSeconds(3)); + Map pools = singletonMap("default", new ServerSideConfiguration.Pool(42L, "resource")); + ServerSideConfiguration serverSideConfiguration = new ServerSideConfiguration("default", pools); + Properties properties = new Properties(); + properties.setProperty("foo", "bar"); + + ClusteringServiceConfiguration configuration = new ClusteringServiceConfiguration(uri, timeouts, true, serverSideConfiguration, properties); + + + ClusteringServiceConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived).isNotSameAs(configuration); + assertThat(derived.getClusterUri()).isEqualTo(uri); + assertThat(derived.getTimeouts()).isEqualTo(timeouts); + assertThat(derived.getServerConfiguration().getDefaultServerResource()).isEqualTo("default"); + assertThat(derived.getServerConfiguration().getResourcePools()).isEqualTo(pools); + assertThat(derived.getProperties()).isEqualTo(properties); + } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java index 5ea95fae52..93d899629b 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java @@ -61,7 +61,7 @@ public void clusteredCacheManagerExample() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() // <1> .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) // <2> - .autoCreate()); // <3> + .autoCreate(c -> c)); // <3> PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); // <4> cacheManager.close(); // <5> @@ -73,10 +73,10 @@ public void clusteredCacheManagerWithServerSideConfigExample() throws Exception // tag::clusteredCacheManagerWithServerSideConfigExample[] CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")).autoCreate() + .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")).autoCreate(server -> server .defaultServerResource("primary-server-resource") // <1> .resourcePool("resource-pool-a", 8, MemoryUnit.MB, "secondary-server-resource") // <2> - .resourcePool("resource-pool-b", 10, MemoryUnit.MB)) // <3> + .resourcePool("resource-pool-b", 10, MemoryUnit.MB))) // <3> .withCache("clustered-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, // <4> ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB)))) // <5> @@ -98,9 +98,8 @@ public void clusteredCacheManagerWithDynamicallyAddedCacheExample() throws Excep CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .autoCreate() - .defaultServerResource("primary-server-resource") - .resourcePool("resource-pool-a", 8, MemoryUnit.MB)); + .autoCreate(server -> server.defaultServerResource("primary-server-resource") + .resourcePool("resource-pool-a", 8, MemoryUnit.MB))); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); @@ -122,9 +121,8 @@ public void explicitConsistencyConfiguration() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .autoCreate() - .defaultServerResource("primary-server-resource") - .resourcePool("resource-pool-a", 8, MemoryUnit.MB)); + .autoCreate(server -> server.defaultServerResource("primary-server-resource") + .resourcePool("resource-pool-a", 8, MemoryUnit.MB))); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); @@ -150,9 +148,8 @@ public void clusteredCacheTieredExample() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .autoCreate() - .defaultServerResource("primary-server-resource") - .resourcePool("resource-pool-a", 8, MemoryUnit.MB)); + .autoCreate(server -> server.defaultServerResource("primary-server-resource") + .resourcePool("resource-pool-a", 8, MemoryUnit.MB))); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); @@ -179,16 +176,16 @@ public void clusteredCacheManagerLifecycleExamples() throws Exception { // tag::clusteredCacheManagerLifecycle[] CacheManagerBuilder autoCreate = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .autoCreate() // <1> - .resourcePool("resource-pool", 8, MemoryUnit.MB, "primary-server-resource")) + .autoCreate(server -> server // <1> + .resourcePool("resource-pool", 8, MemoryUnit.MB, "primary-server-resource"))) .withCache("clustered-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredShared("resource-pool")))); CacheManagerBuilder expecting = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .expecting() // <2> - .resourcePool("resource-pool", 8, MemoryUnit.MB, "primary-server-resource")) + .expecting(server -> server // <2> + .resourcePool("resource-pool", 8, MemoryUnit.MB, "primary-server-resource"))) .withCache("clustered-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredShared("resource-pool")))); @@ -218,8 +215,8 @@ public void unknownClusteredCacheExample() CacheManagerBuilder cacheManagerBuilderAutoCreate = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .autoCreate() // <1> - .resourcePool("resource-pool", 8, MemoryUnit.MB, "primary-server-resource")); + .autoCreate(server -> server // <1> + .resourcePool("resource-pool", 8, MemoryUnit.MB, "primary-server-resource"))); PersistentCacheManager cacheManager1 = cacheManagerBuilderAutoCreate.build(false); cacheManager1.init(); @@ -234,8 +231,8 @@ public void unknownClusteredCacheExample() CacheManagerBuilder cacheManagerBuilderExpecting = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .expecting() // <4> - .resourcePool("resource-pool", 8, MemoryUnit.MB, "primary-server-resource")); + .expecting(server -> server // <4> + .resourcePool("resource-pool", 8, MemoryUnit.MB, "primary-server-resource"))); PersistentCacheManager cacheManager2 = cacheManagerBuilderExpecting.build(false); cacheManager2.init(); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java index 8e6e86dd3f..fd15cf8436 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java @@ -56,7 +56,7 @@ public void clusteredCacheManagerExample() throws Exception { .read(Duration.ofSeconds(10)) // <2> .write(Timeouts.DEFAULT_OPERATION_TIMEOUT) // <3> .connection(Timeouts.INFINITE_TIMEOUT)) // <4> - .autoCreate()); + .autoCreate(c -> c)); // end::timeoutsExample[] } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java index 561836d52f..7f90b671dc 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java @@ -66,7 +66,7 @@ public void testSingleTier() { public void threeTiersCacheManager() throws Exception { // tag::threeTiersCacheManager[] PersistentCacheManager persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) // <1> + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) // <1> .withCache("threeTierCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java index 5fcfe3cc4a..bb45fdda78 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java @@ -136,7 +136,7 @@ public void testGetTimeout() throws Exception { final Configuration configuration = new XmlConfiguration(makeConfig(config)); - Collection> serviceCreationConfigurations = + Collection> serviceCreationConfigurations = configuration.getServiceCreationConfigurations(); assertThat(serviceCreationConfigurations, is(not(Matchers.empty()))); @@ -170,7 +170,7 @@ public void testGetTimeoutNone() throws Exception { final Configuration configuration = new XmlConfiguration(makeConfig(config)); - Collection> serviceCreationConfigurations = + Collection> serviceCreationConfigurations = configuration.getServiceCreationConfigurations(); assertThat(serviceCreationConfigurations, is(not(Matchers.empty()))); @@ -202,7 +202,7 @@ public void testGetTimeoutUnitDefault() throws Exception { final Configuration configuration = new XmlConfiguration(makeConfig(config)); - Collection> serviceCreationConfigurations = + Collection> serviceCreationConfigurations = configuration.getServiceCreationConfigurations(); assertThat(serviceCreationConfigurations, is(not(Matchers.empty()))); @@ -366,7 +366,7 @@ public void testServersWithClusterTierManager() throws Exception { }; final Configuration configuration = new XmlConfiguration(makeConfig(config)); - Collection> serviceCreationConfigurations = configuration.getServiceCreationConfigurations(); + Collection> serviceCreationConfigurations = configuration.getServiceCreationConfigurations(); ClusteringServiceConfiguration clusteringServiceConfiguration = ServiceUtils.findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); ConnectionSource.ServerList connectionSource = (ConnectionSource.ServerList) clusteringServiceConfiguration.getConnectionSource(); @@ -403,7 +403,7 @@ public void testServersWithClusterTierManagerAndOptionalPorts() throws Exception }; final Configuration configuration = new XmlConfiguration(makeConfig(config)); - Collection> serviceCreationConfigurations = configuration.getServiceCreationConfigurations(); + Collection> serviceCreationConfigurations = configuration.getServiceCreationConfigurations(); ClusteringServiceConfiguration clusteringServiceConfiguration = ServiceUtils.findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); ConnectionSource.ServerList connectionSource = (ConnectionSource.ServerList)clusteringServiceConfiguration.getConnectionSource(); @@ -424,10 +424,10 @@ public void testTranslateServiceCreationConfiguration() throws Exception { URI connectionUri = new URI("terracotta://localhost:9510/my-application"); ClusteringServiceConfiguration serviceConfig = ClusteringServiceConfigurationBuilder.cluster(connectionUri) .timeouts(Timeouts.DEFAULT) - .autoCreate() - .defaultServerResource("main") - .resourcePool("primaryresource", 5, MemoryUnit.GB) - .resourcePool("secondaryresource", 10, MemoryUnit.GB, "optional") + .autoCreate(server -> server + .defaultServerResource("main") + .resourcePool("primaryresource", 5, MemoryUnit.GB) + .resourcePool("secondaryresource", 10, MemoryUnit.GB, "optional")) .build(); ClusteringCacheManagerServiceConfigurationParser parser = new ClusteringCacheManagerServiceConfigurationParser(); @@ -452,8 +452,7 @@ public void testTranslateServiceCreationConfigurationWithNoResourcePoolAndAutoCr URI connectionUri = new URI("terracotta://localhost:9510/my-application"); ClusteringServiceConfiguration serviceConfig = ClusteringServiceConfigurationBuilder.cluster(connectionUri) .timeouts(Timeouts.DEFAULT) - .expecting() - .defaultServerResource("main") + .expecting(server -> server.defaultServerResource("main")) .build(); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java index c9c4d57905..246e6cdc0b 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java @@ -91,7 +91,7 @@ public void tearDown() throws Exception { public void testClusteredStateRepositoryReplication() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(STRIPE_URI)) - .autoCreate() + .autoCreate(c -> c) .build(); ClusteringService service = new ClusteringServiceFactory().create(configuration); @@ -126,7 +126,7 @@ public void testClusteredStateRepositoryReplication() throws Exception { public void testClusteredStateRepositoryReplicationWithSerializableKV() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(STRIPE_URI)) - .autoCreate() + .autoCreate(c -> c) .build(); ClusteringService service = new ClusteringServiceFactory().create(configuration); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java index 9e1c959b42..50024caddd 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java @@ -75,21 +75,21 @@ public void removePassThroughServer() throws Exception { public void testServerExceptionPassThrough() throws Exception { ClusteringServiceConfiguration creationConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(creationConfig); creationService.start(null); creationService.stop(); ClusteringServiceConfiguration accessConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .expecting() - .defaultServerResource("different") - .build(); + .expecting(server -> server + .defaultServerResource("different")) + .build(); DefaultClusteringService accessService = new DefaultClusteringService(accessConfig); /* * Induce an "InvalidStoreException: cluster tier 'cacheAlias' does not exist" on the server. diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java index ea417720cf..c3f7712a38 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java @@ -41,7 +41,6 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; public class ConnectionClosedTest { @@ -78,7 +77,7 @@ public void testCacheOperationThrowsAfterConnectionClosed() throws Exception { .timeouts() .connection(Duration.ofSeconds(20)) .build()) - .autoCreate()) + .autoCreate(c -> c)) .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, resourcePoolsBuilder)); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java index e2a12e8793..c34c01dc27 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java @@ -48,7 +48,7 @@ public class ConnectionStateTest { private final ClusteringServiceConfiguration serviceConfiguration = ClusteringServiceConfigurationBuilder .cluster(CLUSTER_URI) - .autoCreate() + .autoCreate(c -> c) .build(); @Rule diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java index 997df9e5cd..b25e6a17d1 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java @@ -136,7 +136,7 @@ public void removePassthroughServer() throws Exception { public void testHandlesResourceType() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(c -> c) .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); @@ -172,7 +172,7 @@ public int getTierHeight() { public void testGetPersistenceSpaceIdentifier() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(c -> c) .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); @@ -190,7 +190,7 @@ public void testCreate() throws Exception { .with(ClusteredResourcePoolBuilder.clusteredShared("primary"))); ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(c -> c) .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); @@ -224,7 +224,7 @@ public void testStartStopAutoCreate() throws Exception { URI clusterUri = URI.create(CLUSTER_URI_BASE + "my-application"); ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(clusterUri) - .autoCreate() + .autoCreate(c -> c) .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); assertThat(service.isConnected(), is(false)); @@ -276,7 +276,7 @@ public void testStartStopNoAutoCreate() throws Exception { public void testStartStopAutoCreateTwiceA() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(c -> c) .build(); DefaultClusteringService firstService = new DefaultClusteringService(configuration); firstService.start(null); @@ -307,7 +307,7 @@ public void testStartStopAutoCreateTwiceA() throws Exception { public void testStartStopAutoCreateTwiceB() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(c -> c) .build(); DefaultClusteringService firstService = new DefaultClusteringService(configuration); firstService.start(null); @@ -336,7 +336,7 @@ public void testStartForMaintenanceAutoStart() throws Exception { URI clusterUri = URI.create(CLUSTER_URI_BASE + "my-application"); ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(clusterUri) - .autoCreate() + .autoCreate(c -> c) .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); assertThat(service.isConnected(), is(false)); @@ -358,7 +358,7 @@ public void testStartForMaintenanceAutoStart() throws Exception { public void testStartForMaintenanceOtherAutoCreate() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(c -> c) .build(); DefaultClusteringService createService = new DefaultClusteringService(configuration); createService.start(null); @@ -390,7 +390,7 @@ public void testStartForMaintenanceOtherAutoCreate() throws Exception { public void testStartForMaintenanceOtherCreated() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(c -> c) .build(); DefaultClusteringService createService = new DefaultClusteringService(configuration); createService.start(null); @@ -423,7 +423,7 @@ public void testStartForMaintenanceOtherCreated() throws Exception { public void testMultipleAutoCreateClientsRunConcurrently() throws InterruptedException, ExecutionException { final ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(c -> c) .build(); Callable task = () -> { @@ -450,7 +450,7 @@ public void testMultipleAutoCreateClientsRunConcurrently() throws InterruptedExc public void testStartForMaintenanceInterlock() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(c -> c) .build(); DefaultClusteringService maintenanceService1 = new DefaultClusteringService(configuration); maintenanceService1.startForMaintenance(null, MaintainableService.MaintenanceScope.CACHE_MANAGER); @@ -473,7 +473,7 @@ public void testStartForMaintenanceInterlock() throws Exception { public void testStartForMaintenanceSequence() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(c -> c) .build(); DefaultClusteringService maintenanceService1 = new DefaultClusteringService(configuration); maintenanceService1.startForMaintenance(null, MaintainableService.MaintenanceScope.CACHE_MANAGER); @@ -494,12 +494,12 @@ public void testStartForMaintenanceSequence() throws Exception { public void testBasicConfiguration() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService createService = new DefaultClusteringService(configuration); createService.start(null); @@ -530,12 +530,12 @@ public void testGetServerStoreProxySharedAutoCreate() throws Exception { String targetPool = "sharedPrimary"; ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); service.start(null); @@ -579,24 +579,24 @@ public void testGetServerStoreProxySharedNoAutoCreateNonExistent() throws Except String targetPool = "sharedPrimary"; ClusteringServiceConfiguration creationConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(creationConfig); creationService.start(null); creationService.stop(); ClusteringServiceConfiguration accessConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .expecting() + .expecting(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService accessService = new DefaultClusteringService(accessConfig); accessService.start(null); @@ -637,12 +637,12 @@ public void testGetServerStoreProxySharedNoAutoCreateExists() throws Exception { String targetPool = "sharedPrimary"; ClusteringServiceConfiguration creationConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(creationConfig); creationService.start(null); @@ -674,12 +674,12 @@ public void testGetServerStoreProxySharedNoAutoCreateExists() throws Exception { ClusteringServiceConfiguration accessConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .expecting() + .expecting(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService accessService = new DefaultClusteringService(accessConfig); accessService.start(null); @@ -718,12 +718,12 @@ public void testGetServerStoreProxySharedAutoCreateTwice() throws Exception { String targetPool = "sharedPrimary"; ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService firstService = new DefaultClusteringService(configuration); firstService.start(null); @@ -780,12 +780,12 @@ public void testReleaseServerStoreProxyShared() throws Exception { String targetPool = "sharedPrimary"; ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(configuration); creationService.start(null); @@ -831,12 +831,12 @@ public void testGetServerStoreProxyDedicatedAutoCreate() throws Exception { String targetResource = "serverResource2"; ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); service.start(null); @@ -882,24 +882,24 @@ public void testGetServerStoreProxyDedicatedNoAutoCreateNonExistent() throws Exc String targetResource = "serverResource2"; ClusteringServiceConfiguration creationConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(creationConfig); creationService.start(null); creationService.stop(); ClusteringServiceConfiguration accessConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .expecting() + .expecting(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService accessService = new DefaultClusteringService(accessConfig); accessService.start(null); @@ -942,12 +942,12 @@ public void testGetServerStoreProxyDedicatedNoAutoCreateExists() throws Exceptio String targetResource = "serverResource2"; ClusteringServiceConfiguration creationConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(creationConfig); creationService.start(null); @@ -979,12 +979,12 @@ public void testGetServerStoreProxyDedicatedNoAutoCreateExists() throws Exceptio ClusteringServiceConfiguration accessConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .expecting() + .expecting(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService accessService = new DefaultClusteringService(accessConfig); accessService.start(null); @@ -1025,12 +1025,12 @@ public void testGetServerStoreProxyDedicatedAutoCreateTwice() throws Exception { String targetResource = "serverResource2"; ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService firstService = new DefaultClusteringService(configuration); firstService.start(null); @@ -1092,12 +1092,12 @@ public void testReleaseServerStoreProxyDedicated() throws Exception { String targetResource = "serverResource2"; ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(configuration); creationService.start(null); @@ -1144,12 +1144,12 @@ public void testGetServerStoreProxySharedDestroy() throws Exception { String targetPool = "sharedPrimary"; ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(configuration); creationService.start(null); @@ -1197,12 +1197,12 @@ public void testGetServerStoreProxyDedicatedDestroy() throws Exception { String targetResource = "serverResource2"; ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(configuration); creationService.start(null); @@ -1252,8 +1252,8 @@ public void testDestroyCantBeCalledIfStopped() throws Exception { String targetResource = "serverResource2"; ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() - .defaultServerResource("defaultResource") + .autoCreate(server -> server + .defaultServerResource("defaultResource")) .build(); DefaultClusteringService creationService = new DefaultClusteringService(configuration); @@ -1267,12 +1267,12 @@ public void testDestroyCantBeCalledIfStopped() throws Exception { public void testDestroyAllNoStores() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService createService = new DefaultClusteringService(configuration); createService.start(null); createService.stop(); @@ -1311,12 +1311,12 @@ public void testDestroyAllNoStores() throws Exception { public void testDestroyAllWithStores() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService createService = new DefaultClusteringService(configuration); createService.start(null); @@ -1373,12 +1373,12 @@ public void testDestroyAllWithStores() throws Exception { public void testStartNoAutoCreateThenAutoCreate() throws Exception { ClusteringServiceConfiguration creationConfigBad = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .expecting() + .expecting(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationServiceBad = new DefaultClusteringService(creationConfigBad); try { @@ -1393,12 +1393,12 @@ public void testStartNoAutoCreateThenAutoCreate() throws Exception { ClusteringServiceConfiguration creationConfigGood = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationServiceGood = new DefaultClusteringService(creationConfigGood); creationServiceGood.start(null); @@ -1409,12 +1409,12 @@ public void testStoreValidation_autoCreateConfigGood_autoCreateConfigBad() throw String cacheAlias = "cacheAlias"; ClusteringServiceConfiguration config = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(config); creationService.start(null); @@ -1471,12 +1471,12 @@ public void testStoreValidation_autoCreateConfigGood_autoCreateConfigGood() thro String cacheAlias = "cacheAlias"; ClusteringServiceConfiguration config = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(config); creationService.start(null); @@ -1523,12 +1523,12 @@ public void testStoreValidation_autoCreateConfigBad() throws Exception { String cacheAlias = "cacheAlias"; ClusteringServiceConfiguration config = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(config); creationService.start(null); @@ -1570,12 +1570,12 @@ public void testStoreValidation_autoCreateConfigGood_noAutoCreateConfigBad() thr String cacheAlias = "cacheAlias"; ClusteringServiceConfiguration autoConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(autoConfig); creationService.start(null); @@ -1589,12 +1589,12 @@ public void testStoreValidation_autoCreateConfigGood_noAutoCreateConfigBad() thr ClusteringServiceConfiguration noAutoConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .expecting() + .expecting(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService accessService = new DefaultClusteringService(noAutoConfig); accessService.start(null); @@ -1639,12 +1639,12 @@ public void testStoreValidation_autoCreateConfigGood_noAutoCreateConfigGood() th String cacheAlias = "cacheAlias"; ClusteringServiceConfiguration autoConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(autoConfig); creationService.start(null); @@ -1659,12 +1659,11 @@ public void testStoreValidation_autoCreateConfigGood_noAutoCreateConfigGood() th ClusteringServiceConfiguration noAutoConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .expecting() - .defaultServerResource("defaultResource") + .expecting(server -> server.defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService accessService = new DefaultClusteringService(noAutoConfig); accessService.start(null); @@ -1701,12 +1700,12 @@ public void testStoreValidation_MismatchedPoolTypes_ConfiguredDedicatedValidateS String cacheAlias = "cacheAlias"; ClusteringServiceConfiguration creationConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(creationConfig); creationService.start(null); @@ -1722,12 +1721,12 @@ public void testStoreValidation_MismatchedPoolTypes_ConfiguredDedicatedValidateS ClusteringServiceConfiguration accessConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService accessService = new DefaultClusteringService(accessConfig); accessService.start(null); @@ -1769,12 +1768,12 @@ public void testStoreValidation_MismatchedPoolTypes_ConfiguredSharedValidateDedi String cacheAlias = "cacheAlias"; ClusteringServiceConfiguration creationConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService creationService = new DefaultClusteringService(creationConfig); creationService.start(null); @@ -1790,12 +1789,12 @@ public void testStoreValidation_MismatchedPoolTypes_ConfiguredSharedValidateDedi ClusteringServiceConfiguration accessConfig = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") - .resourcePool("sharedTertiary", 4, MemoryUnit.MB) - .build(); + .resourcePool("sharedTertiary", 4, MemoryUnit.MB)) + .build(); DefaultClusteringService accessService = new DefaultClusteringService(accessConfig); accessService.start(null); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java index c2607aaf9b..54b7802e6f 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java @@ -37,7 +37,7 @@ public class ReconnectTest { private final ClusteringServiceConfiguration serviceConfiguration = ClusteringServiceConfigurationBuilder .cluster(CLUSTER_URI) - .autoCreate() + .autoCreate(c -> c) .build(); @Test(expected = RuntimeException.class) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java index c3b29980e4..1737a3304a 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java @@ -84,7 +84,7 @@ public void setUp() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(STRIPE_URI)) - .autoCreate() + .autoCreate(c -> c) .build(); service = new ClusteringServiceFactory().create(configuration); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java index be452bb883..09c492d949 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java @@ -90,7 +90,7 @@ public void setUp() throws Exception { .withLoaderWriter(loaderWriter) .build(); - CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().with(cluster(URI.create(STRIPE_URI)).autoCreate()) + CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().with(cluster(URI.create(STRIPE_URI)).autoCreate(c -> c)) .withCache("cache-1", config) .build(true); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java index 598a83e2e5..c133e3fb50 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java @@ -101,7 +101,7 @@ public void setUp() throws Exception { ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(STRIPE_URI)) - .autoCreate() + .autoCreate(c -> c) .build(); service = new ClusteringServiceFactory().create(configuration); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java index 0b04121358..4569fff991 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java @@ -68,7 +68,7 @@ public void testAllClientsNeedToHaveLoaderWriterConfigured() { CacheManager cacheManager = CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) .build(true); @@ -82,7 +82,7 @@ public void testAllClientsNeedToHaveLoaderWriterConfigured() { try { CacheManager anotherManager = CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", withoutLoaderWriter) .build(true); } catch (RuntimeException e) { @@ -99,7 +99,7 @@ public void testBasicClusteredCacheLoaderWriter() { CacheManager cacheManager = CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) .build(true); @@ -122,13 +122,13 @@ public void testLoaderWriterMultipleClients() { CacheManager cacheManager1 = CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) .build(true); CacheManager cacheManager2 = CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) .build(true); @@ -156,13 +156,13 @@ public void testCASOpsMultipleClients() { CacheManager cacheManager1 = CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) .build(true); CacheManager cacheManager2 = CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) .build(true); @@ -199,7 +199,7 @@ public void testBulkOps() { CacheManager cacheManager = CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) .build(true); @@ -234,13 +234,13 @@ public void testCASOps() { CacheManager cacheManager1 = CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) .build(true); CacheManager cacheManager2 = CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) .build(true); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java index 4777934eb2..fdaade8afe 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java @@ -254,7 +254,7 @@ private PersistentCacheManager createCacheManager() { return CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate()) + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache(CACHE_NAME, cacheConfiguration) .build(true); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index ba74b1872d..0aa5f2adad 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -21,7 +21,6 @@ import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; -import org.ehcache.clustered.client.config.builders.ServerSideConfigurationBuilder; import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.common.Consistency; import org.ehcache.config.ResourcePool; @@ -46,6 +45,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; +import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -154,18 +154,16 @@ private void doSyncAndPut(PersistentCacheManager cacheManager) throws Interrupte } private static PersistentCacheManager createCacheManager(URI clusterURI) { - ServerSideConfigurationBuilder serverSideConfigBuilder = ClusteringServiceConfigurationBuilder - .cluster(clusterURI.resolve(CACHE_MANAGER_NAME)) - .timeouts(TimeoutsBuilder.timeouts().read(Duration.ofSeconds(20)).write(Duration.ofSeconds(30))) - .autoCreate() - .defaultServerResource(PRIMARY_SERVER_RESOURCE_NAME); + ClusteringServiceConfigurationBuilder clusteringConfig = cluster(clusterURI.resolve(CACHE_MANAGER_NAME)) + .timeouts(TimeoutsBuilder.timeouts().read(Duration.ofSeconds(20)).write(Duration.ofSeconds(30))) + .autoCreate(server -> server.defaultServerResource(PRIMARY_SERVER_RESOURCE_NAME)); ResourcePool resourcePool = ClusteredResourcePoolBuilder .clusteredDedicated(PRIMARY_SERVER_RESOURCE_NAME, PRIMARY_SERVER_RESOURCE_SIZE, MemoryUnit.MB); CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder .newCacheManagerBuilder() - .with(serverSideConfigBuilder) + .with(clusteringConfig) .withCache(CLUSTERED_CACHE_NAME, CacheConfigurationBuilder .newCacheConfigurationBuilder(Long.class, String.class, diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java index bff2b8cda4..2608be4ae3 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java @@ -28,7 +28,6 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.hamcrest.collection.IsIterableWithSize; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -38,7 +37,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; @@ -76,8 +74,7 @@ public void basicCacheCRUD() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/crud-cm")) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); @@ -112,7 +109,7 @@ public void basicCacheCRUD() throws Exception { public void basicCacheCAS() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() - .with(cluster(CLUSTER.getConnectionURI().resolve("/cas-cm")).autoCreate()) + .with(cluster(CLUSTER.getConnectionURI().resolve("/cas-cm")).autoCreate(c -> c)) .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(100, EntryUnit.ENTRIES) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) @@ -140,7 +137,7 @@ public void basicCacheCAS() throws Exception { public void basicClusteredBulk() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() - .with(cluster(CLUSTER.getConnectionURI().resolve("/bulk-cm")).autoCreate()) + .with(cluster(CLUSTER.getConnectionURI().resolve("/bulk-cm")).autoCreate(c -> c)) .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java index 3a4f1c412e..a42bafbc4d 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java @@ -85,8 +85,7 @@ public void testClusteringServiceConfigurationBuilderThrowsNPE() throws Exceptio .heap(100, ENTRIES) .with(clusteredDedicated(offheap, 2, MemoryUnit.MB))) ).with(ClusteringServiceConfigurationBuilder.cluster(tsaUri) - .autoCreate() - .defaultServerResource(offheap) + .autoCreate(server -> server.defaultServerResource(offheap)) ).build(true)) { Cache cache = cacheManager.getCache(cacheName, Long.class, String.class); cache.put(1L, "one"); @@ -98,9 +97,6 @@ public void testClusteringServiceConfigurationBuilderThrowsNPE() throws Exceptio .with(clusteredDedicated(offheap, 2, MemoryUnit.MB)) ) ).with(ClusteringServiceConfigurationBuilder.cluster(tsaUri) - // these two shouldn't be needed as the clustered cache entity has already been created -// .autoCreate() -// .defaultServerResource(offheap) ).using(new DefaultStatisticsService() ).using(new DefaultClusteringManagementService() ).build(true)) { @@ -121,8 +117,7 @@ public void testServicesStoppedTwice() throws Exception { .heap(100, ENTRIES) .with(clusteredDedicated(offheap, 2, MemoryUnit.MB))) ).with(ClusteringServiceConfigurationBuilder.cluster(tsaUri) - .autoCreate() - .defaultServerResource(offheap) + .autoCreate(server -> server.defaultServerResource(offheap)) // manually adding the following two services should work ).using(new DefaultStatisticsService() ).using(new DefaultClusteringManagementService() diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java index 689d51a7a6..abc0c08047 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java @@ -81,7 +81,7 @@ public static void waitForActive() throws Exception { public void testAutoCreatedCacheManager() throws Exception { assertEntityNotExists(ClusterTierManagerClientEntity.class, "testAutoCreatedCacheManager"); PersistentCacheManager manager = newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/testAutoCreatedCacheManager")).autoCreate().build()) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/testAutoCreatedCacheManager")).autoCreate(c -> c).build()) .build(); assertEntityNotExists(ClusterTierManagerClientEntity.class, "testAutoCreatedCacheManager"); manager.init(); @@ -112,7 +112,7 @@ public void testMultipleClientsAutoCreatingCacheManager() throws Exception { assertEntityNotExists(ClusterTierManagerClientEntity.class, "testMultipleClientsAutoCreatingCacheManager"); final CacheManagerBuilder managerBuilder = newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/testMultipleClientsAutoCreatingCacheManager")).autoCreate().build()); + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/testMultipleClientsAutoCreatingCacheManager")).autoCreate(c -> c).build()); Callable task = () -> { PersistentCacheManager manager = managerBuilder.build(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java index dfd8e54614..9b40eddc6c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java @@ -98,7 +98,7 @@ private static PersistentCacheManager newCacheManager() { .timeouts(TimeoutsBuilder.timeouts() .read(Duration.ofSeconds(30)) .write(Duration.ofSeconds(30))) - .autoCreate() + .autoCreate(c -> c) .build()) .using(managementRegistry) .build(true); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java index 444631d2d0..948f1eb963 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java @@ -81,14 +81,14 @@ public void testDestroyLoop() throws Exception { private void destroyCacheManager() throws CachePersistenceException { PersistentCacheManager cacheManager = newCacheManagerBuilder().with( ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve(CACHE_MANAGER_NAME)) - .expecting()).build(false); + .expecting(c -> c)).build(false); cacheManager.destroy(); } private PersistentCacheManager createCacheManager() { CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() - .with(cluster(CLUSTER.getConnectionURI().resolve(CACHE_MANAGER_NAME)).autoCreate()) + .with(cluster(CLUSTER.getConnectionURI().resolve(CACHE_MANAGER_NAME)).autoCreate(c -> c)) .withCache(CACHE_NAME, newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(100, EntryUnit.ENTRIES) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index b27e1d2850..5294050489 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -78,13 +78,11 @@ public void waitForActive() throws Exception { cacheManager1 = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/event-cm")) - .autoCreate() - .defaultServerResource("primary-server-resource")).build(true); + .autoCreate(s -> s.defaultServerResource("primary-server-resource"))).build(true); cacheManager2 = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/event-cm")) - .autoCreate() - .defaultServerResource("primary-server-resource")).build(true); + .autoCreate(s -> s.defaultServerResource("primary-server-resource"))).build(true); } @After diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java index 5bba702ccf..18a43942c0 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java @@ -79,8 +79,7 @@ public void testIteratorFailover() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/iterator-cm")) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); @@ -138,8 +137,7 @@ public void testIteratorReconnect() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/iterator-cm")) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java index c5025a2b74..98e92122f4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java @@ -46,6 +46,7 @@ import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; +import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; @@ -100,13 +101,10 @@ public static ResourcePoolsBuilder[] data() { public void leaseExpiry() throws Exception { URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.getConnectionURI(), proxies); - CacheManagerBuilder clusteredCacheManagerBuilder - = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(connectionURI.resolve("/crud-cm")) - .timeouts(TimeoutsBuilder.timeouts() - .connection(Duration.ofSeconds(20))) - .autoCreate() - .defaultServerResource("primary-server-resource")); + CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() + .with(ClusteringServiceConfigurationBuilder.cluster(connectionURI.resolve("/crud-cm")) + .timeouts(TimeoutsBuilder.timeouts().connection(Duration.ofSeconds(20))) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java index 210a781176..69be2cbe20 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java @@ -25,7 +25,6 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; @@ -57,8 +56,7 @@ public void overSizedCacheOps() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/crud-cm")) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); try (PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true)) { CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java index 5ce3033044..b59047d078 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -17,9 +17,9 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; +import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; -import org.ehcache.clustered.client.config.builders.ServerSideConfigurationBuilder; import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntity; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock; import org.ehcache.clustered.client.service.EntityBusyException; @@ -79,14 +79,12 @@ public static void waitForActive() throws Exception { @Before public void initializeCacheManager() { - ServerSideConfigurationBuilder serverSideConfigurationBuilder = + ClusteringServiceConfiguration clusteringConfiguration = ClusteringServiceConfigurationBuilder.cluster(connectionURI.resolve("/crud-cm")) - .autoCreate() - .defaultServerResource("primary-server-resource"); + .autoCreate(server -> server.defaultServerResource("primary-server-resource")).build(); CacheManagerBuilder clusteredCacheManagerBuilder - = CacheManagerBuilder.newCacheManagerBuilder() - .with(serverSideConfigurationBuilder); + = CacheManagerBuilder.newCacheManagerBuilder().with(clusteringConfiguration); cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java index d067541f17..fea6e912f2 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java @@ -19,10 +19,10 @@ import org.ehcache.CachePersistenceException; import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; +import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; import org.ehcache.clustered.client.config.DedicatedClusteredResourcePool; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; -import org.ehcache.clustered.client.config.builders.ServerSideConfigurationBuilder; import org.ehcache.clustered.common.Consistency; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; @@ -85,11 +85,10 @@ public void testTooLowResourceException() throws InterruptedException { private CacheManagerBuilder getPersistentCacheManagerCacheManagerBuilder(DedicatedClusteredResourcePool resourcePool) { ClusteringServiceConfigurationBuilder clusteringServiceConfigurationBuilder = ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/crud-cm")); - ServerSideConfigurationBuilder serverSideConfigurationBuilder = clusteringServiceConfigurationBuilder.autoCreate() - .defaultServerResource("primary-server-resource"); + ClusteringServiceConfiguration clusteringConfiguration = clusteringServiceConfigurationBuilder.autoCreate(server -> server.defaultServerResource("primary-server-resource")).build(); return CacheManagerBuilder.newCacheManagerBuilder() - .with(serverSideConfigurationBuilder) + .with(clusteringConfiguration) .withCache("test-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(resourcePool) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java index d3856aade0..7a49a8bb61 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java @@ -207,8 +207,7 @@ public void testTerminationBeforeCacheManagerClose() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); @@ -230,8 +229,7 @@ public void testTerminationBeforeCacheManagerCloseWithCaches() throws Exception CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) - .autoCreate() - .defaultServerResource("primary-server-resource")) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -255,8 +253,7 @@ public void testTerminationBeforeCacheManagerRetrieve() throws Exception { CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) .timeouts(TimeoutsBuilder.timeouts().connection(Duration.ofSeconds(1))) // Need a connection timeout shorter than the TimeLimitedTask timeout - .expecting() - .defaultServerResource("primary-server-resource")); + .expecting(server -> server.defaultServerResource("primary-server-resource"))); PersistentCacheManager cacheManagerExisting = clusteredCacheManagerBuilder.build(false); // Base test time limit on observed TRANSPORT_HANDSHAKE_SYNACK_TIMEOUT; might not have been set in time to be effective @@ -279,8 +276,7 @@ public void testTerminationBeforeCacheManagerDestroyCache() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) - .autoCreate() - .defaultServerResource("primary-server-resource")) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -313,8 +309,7 @@ public void testTerminationBeforeCacheCreate() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); @@ -338,8 +333,7 @@ public void testTerminationBeforeCacheRemove() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) - .autoCreate() - .defaultServerResource("primary-server-resource")) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -358,8 +352,7 @@ public void testTerminationThenGet() throws Exception { CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) .timeouts(TimeoutsBuilder.timeouts().read(Duration.of(1, ChronoUnit.SECONDS)).build()) - .autoCreate() - .defaultServerResource("primary-server-resource")) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -392,8 +385,7 @@ public void testTerminationThenContainsKey() throws Exception { CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) .timeouts(TimeoutsBuilder.timeouts().read(Duration.of(1, ChronoUnit.SECONDS)).build()) - .autoCreate() - .defaultServerResource("primary-server-resource")) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -427,8 +419,7 @@ public void testTerminationThenIterator() throws Exception { CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) .timeouts(TimeoutsBuilder.timeouts().read(Duration.of(1, ChronoUnit.SECONDS)).build()) - .autoCreate() - .defaultServerResource("primary-server-resource")) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -459,8 +450,7 @@ public void testTerminationThenPut() throws Exception { CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) .timeouts(TimeoutsBuilder.timeouts().write(Duration.of(1, ChronoUnit.SECONDS)).build()) - .autoCreate() - .defaultServerResource("primary-server-resource")) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -491,8 +481,7 @@ public void testTerminationThenPutIfAbsent() throws Exception { CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) .timeouts(TimeoutsBuilder.timeouts().write(Duration.of(1, ChronoUnit.SECONDS)).build()) - .autoCreate() - .defaultServerResource("primary-server-resource")) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -522,8 +511,7 @@ public void testTerminationThenRemove() throws Exception { CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) .timeouts(TimeoutsBuilder.timeouts().write(Duration.of(1, ChronoUnit.SECONDS)).build()) - .autoCreate() - .defaultServerResource("primary-server-resource")) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -555,8 +543,7 @@ public void testTerminationThenClear() throws Exception { .using(statisticsService) .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) .timeouts(TimeoutsBuilder.timeouts().write(Duration.of(1, ChronoUnit.SECONDS)).build()) - .autoCreate() - .defaultServerResource("primary-server-resource")) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -596,8 +583,7 @@ public void testTerminationFreezesTheClient() throws Exception { .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) .timeouts(TimeoutsBuilder.timeouts() .read(readOperationTimeout)) - .autoCreate() - .defaultServerResource("primary-server-resource")) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 7a854f80e5..976dd9e7d6 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -136,10 +136,10 @@ protected void initCM() throws InterruptedException { cacheManager = newCacheManagerBuilder() // cluster config .with(cluster(CLUSTER.getConnectionURI().resolve("/my-server-entity-1")) - .autoCreate() - .defaultServerResource("primary-server-resource") - .resourcePool("resource-pool-a", 10, MemoryUnit.MB, "secondary-server-resource") // <2> - .resourcePool("resource-pool-b", 8, MemoryUnit.MB)) // will take from primary-server-resource + .autoCreate(server -> server + .defaultServerResource("primary-server-resource") + .resourcePool("resource-pool-a", 10, MemoryUnit.MB, "secondary-server-resource") // <2> + .resourcePool("resource-pool-b", 8, MemoryUnit.MB))) // will take from primary-server-resource // management config .using(new DefaultManagementRegistryConfiguration() .addTags("webapp-1", "server-node-1") diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java index c444348b80..59cb022bda 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java @@ -63,10 +63,10 @@ public void test_CACHE_MANAGER_CLOSED() throws Exception { createNmsService(CLUSTER); try (CacheManager cacheManager = newCacheManagerBuilder().with(cluster(CLUSTER.getConnectionURI().resolve("/my-server-entity-1")) - .autoCreate() - .defaultServerResource("primary-server-resource") - .resourcePool("resource-pool-a", 10, MemoryUnit.MB, "secondary-server-resource") // <2> - .resourcePool("resource-pool-b", 10, MemoryUnit.MB)) // will take from primary-server-resource + .autoCreate(server -> server + .defaultServerResource("primary-server-resource") + .resourcePool("resource-pool-a", 10, MemoryUnit.MB, "secondary-server-resource") // <2> + .resourcePool("resource-pool-b", 10, MemoryUnit.MB))) // will take from primary-server-resource // management config .using(new DefaultManagementRegistryConfiguration() .addTags("webapp-1", "server-node-1") diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java index 44d1dca2d0..0ed6918f8c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java @@ -59,10 +59,10 @@ public void create_cache_manager() throws Exception { CacheManager cacheManager = newCacheManagerBuilder() // cluster config .with(cluster(CLUSTER.getConnectionURI().resolve("/my-server-entity-3")) - .autoCreate() - .defaultServerResource("primary-server-resource") - .resourcePool("resource-pool-a", 10, MemoryUnit.MB, "secondary-server-resource") // <2> - .resourcePool("resource-pool-b", 8, MemoryUnit.MB)) // will take from primary-server-resource + .autoCreate(server -> server + .defaultServerResource("primary-server-resource") + .resourcePool("resource-pool-a", 10, MemoryUnit.MB, "secondary-server-resource") // <2> + .resourcePool("resource-pool-b", 8, MemoryUnit.MB))) // will take from primary-server-resource // management config .using(new DefaultManagementRegistryConfiguration() .addTags("webapp-1", "server-node-1") diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java index dd5dbe36be..6c33d9977b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java @@ -87,9 +87,8 @@ public void clusteredToString() throws Exception { try (CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() // cluster config .with(ClusteringServiceConfigurationBuilder.cluster(uri) - .autoCreate() - .defaultServerResource("primary-server-resource") - .resourcePool("resource-pool-a", 10, MemoryUnit.MB)) + .autoCreate(server -> server.defaultServerResource("primary-server-resource") + .resourcePool("resource-pool-a", 10, MemoryUnit.MB))) // management config .using(new DefaultManagementRegistryConfiguration() .addTags("webapp-1", "server-node-1") diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index 6d70c9dc93..c37923437c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -97,10 +97,10 @@ public static void beforeClass() throws Exception { cacheManager = newCacheManagerBuilder() // cluster config .with(cluster(connectionURI.resolve("/my-server-entity-1")) - .autoCreate() + .autoCreate(server -> server .defaultServerResource("primary-server-resource") .resourcePool("resource-pool-a", 10, MemoryUnit.MB, "secondary-server-resource") // <2> - .resourcePool("resource-pool-b", 10, MemoryUnit.MB)) // will take from primary-server-resource + .resourcePool("resource-pool-b", 10, MemoryUnit.MB))) // will take from primary-server-resource // management config .using(new DefaultManagementRegistryConfiguration() .addTags("webapp-1", "server-node-1") diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java index 162baf2b26..ac62918a55 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java @@ -17,9 +17,7 @@ import com.tc.net.proxy.TCPProxy; import org.ehcache.Cache; -import org.ehcache.CacheManager; import org.ehcache.PersistentCacheManager; -import org.ehcache.StateTransitionException; import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; @@ -32,7 +30,6 @@ import org.ehcache.config.units.MemoryUnit; import org.junit.BeforeClass; import org.junit.ClassRule; -import org.junit.Ignore; import org.junit.Test; import org.terracotta.testing.rules.Cluster; @@ -42,13 +39,11 @@ import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; @@ -91,8 +86,7 @@ public static void waitForActive() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(connectionURI.resolve("/crud-cm")) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); } @@ -170,4 +164,4 @@ private static void expireLease() throws InterruptedException { setDelay(0L, proxies); } -} \ No newline at end of file +} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java index bbb3dc92ca..30da4a99ed 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java @@ -55,8 +55,7 @@ public static void waitForActive() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(connectionURI.resolve("/crud-cm")) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index 4c349c0d6c..1ba2884d0e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -121,8 +121,7 @@ public static void waitForActive() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(connectionURI.resolve("/crud-cm")) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(s -> s.defaultServerResource("primary-server-resource"))); cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index 24c12f7c2d..0aa8d3fb75 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -123,8 +123,7 @@ public void startServers() throws Exception { .timeouts(TimeoutsBuilder.timeouts() // we need to give some time for the failover to occur .read(Duration.ofMinutes(1)) .write(Duration.ofMinutes(1))) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); CACHE_MANAGER1 = clusteredCacheManagerBuilder.build(true); CACHE_MANAGER2 = clusteredCacheManagerBuilder.build(true); CacheConfiguration config = CacheConfigurationBuilder diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java index 536e614e93..9d8e7e05bb 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java @@ -91,8 +91,7 @@ public void startServers() throws Exception { .timeouts(TimeoutsBuilder.timeouts() // we need to give some time for the failover to occur .read(Duration.ofMinutes(1)) .write(Duration.ofMinutes(1))) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); CACHE_MANAGER = clusteredCacheManagerBuilder.build(true); CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(100, EntryUnit.ENTRIES) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java index 3860a9eb77..cec715c7c9 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java @@ -97,9 +97,8 @@ public void startServers() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/crud-cm-replication")) - .timeouts(TimeoutsBuilder.timeouts().read(Duration.ofSeconds(20)).write(Duration.ofSeconds(20))) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .timeouts(TimeoutsBuilder.timeouts().read(Duration.ofSeconds(20)).write(Duration.ofSeconds(20))) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); CACHE_MANAGER1 = clusteredCacheManagerBuilder.build(true); CACHE_MANAGER2 = clusteredCacheManagerBuilder.build(true); CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, BlobValue.class, diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java index d2d1889d3c..0cb870ed12 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java @@ -72,8 +72,7 @@ public void setUp() throws Exception { .timeouts(TimeoutsBuilder.timeouts() // we need to give some time for the failover to occur .read(Duration.ofMinutes(1)) .write(Duration.ofMinutes(1))) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); CACHE_MANAGER = clusteredCacheManagerBuilder.build(true); CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(100, EntryUnit.ENTRIES) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java index a2ed0c85ea..911bf4a025 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java @@ -67,7 +67,7 @@ public void tearDown() throws Exception { @Test public void testDestroyCacheManager() throws Exception { CacheManagerBuilder configBuilder = newCacheManagerBuilder().with(cluster(CLUSTER.getConnectionURI().resolve("/destroy-CM")) - .autoCreate().defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); PersistentCacheManager cacheManager1 = configBuilder.build(true); PersistentCacheManager cacheManager2 = configBuilder.build(true); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java index dfd16ecab9..bbb69a35b3 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java @@ -84,8 +84,7 @@ public void duplicateAfterFailoverAreReturningTheCorrectResponse() throws Except CacheManagerBuilder builder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI()) .timeouts(TimeoutsBuilder.timeouts().write(Duration.ofSeconds(30))) - .autoCreate() - .defaultServerResource("primary-server-resource")) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Integer.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 10, MemoryUnit.MB))) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java index 68f1b7639e..af056e0ff1 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java @@ -73,8 +73,7 @@ public void oversizedPuts() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/crud-cm")) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); CountDownLatch syncLatch = new CountDownLatch(2); CompletableFuture f1 = CompletableFuture.runAsync(() -> doPuts(clusteredCacheManagerBuilder, syncLatch)); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java index 6f27031f6d..2d357063bb 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java @@ -69,8 +69,7 @@ public void testSync() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/op-sync")) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); @@ -109,8 +108,7 @@ public void testLifeCycleOperationsOnSync() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/lifecycle-sync")) - .autoCreate() - .defaultServerResource("primary-server-resource")); + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); try (PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true)) { CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java index ea7b04bf33..b2d5eb6ddb 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java @@ -109,7 +109,7 @@ PersistentCacheManager createCacheManager(URI clusterUri) { return CacheManagerBuilder .newCacheManagerBuilder() - .with(cluster(clusterUri.resolve("/cm-wb")).timeouts(TimeoutsBuilder.timeouts().read(Duration.ofMinutes(1)).write(Duration.ofMinutes(1))).autoCreate()) + .with(cluster(clusterUri.resolve("/cm-wb")).timeouts(TimeoutsBuilder.timeouts().read(Duration.ofMinutes(1)).write(Duration.ofMinutes(1))).autoCreate(c -> c)) .withCache(CACHE_NAME, cacheConfiguration) .build(true); } diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java index 59c41de9df..3171facb43 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java @@ -125,7 +125,7 @@ private static class TestMethods { public static void testProgrammaticClusteredCache(OsgiTestUtils.Cluster cluster) throws Throwable { try (PersistentCacheManager cacheManager = newCacheManagerBuilder() - .with(cluster(cluster.getConnectionUri()).autoCreate()) + .with(cluster(cluster.getConnectionUri()).autoCreate(c -> c)) .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, newResourcePoolsBuilder().with(clusteredDedicated("main", 2, MemoryUnit.MB)))) .build(true)) { diff --git a/core/build.gradle b/core/build.gradle index 8a3a64aad8..40fa709263 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -28,6 +28,6 @@ jar { bnd ( 'Bundle-Activator': 'org.ehcache.core.osgi.EhcacheActivator', 'Import-Package': '!javax.annotation, *', - 'Export-Package': '!org.ehcache.core.internal.*, org.ehcache.core.*', + 'Export-Package': '!org.ehcache.core.internal.*, org.ehcache.core.*, org.ehcache.config.builders.*' ) } diff --git a/core/src/main/java/org/ehcache/core/EhcacheManager.java b/core/src/main/java/org/ehcache/core/EhcacheManager.java index 7664143e79..2481d8bfd4 100644 --- a/core/src/main/java/org/ehcache/core/EhcacheManager.java +++ b/core/src/main/java/org/ehcache/core/EhcacheManager.java @@ -49,7 +49,6 @@ import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.loaderwriter.CacheLoaderWriterConfiguration; import org.ehcache.spi.loaderwriter.CacheLoaderWriterProvider; -import org.ehcache.spi.loaderwriter.WriteBehindConfiguration; import org.ehcache.spi.loaderwriter.WriteBehindProvider; import org.ehcache.spi.persistence.PersistableResourceService; import org.ehcache.spi.resilience.ResilienceStrategy; @@ -129,7 +128,7 @@ public EhcacheManager(Configuration config, UnaryOperator> classes = new HashSet<>(); - for (ServiceCreationConfiguration service : configuration.getServiceCreationConfigurations()) { + for (ServiceCreationConfiguration service : configuration.getServiceCreationConfigurations()) { if (!classes.add(service.getServiceType())) { throw new IllegalStateException("Duplicate creation configuration for service " + service.getServiceType()); } @@ -150,7 +149,7 @@ private ServiceLocator resolveServices(UnaryOperator serviceConfig : configuration.getServiceCreationConfigurations()) { + for (ServiceCreationConfiguration serviceConfig : configuration.getServiceCreationConfigurations()) { builder = builder.with(serviceConfig); } return builder.build(); diff --git a/core/src/main/java/org/ehcache/core/config/CoreConfigurationBuilder.java b/core/src/main/java/org/ehcache/core/config/CoreConfigurationBuilder.java new file mode 100644 index 0000000000..54da1a991e --- /dev/null +++ b/core/src/main/java/org/ehcache/core/config/CoreConfigurationBuilder.java @@ -0,0 +1,210 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.config; + +import org.ehcache.Cache; +import org.ehcache.config.CacheConfiguration; +import org.ehcache.config.Configuration; +import org.ehcache.config.FluentCacheConfigurationBuilder; +import org.ehcache.config.FluentConfigurationBuilder; +import org.ehcache.spi.service.ServiceCreationConfiguration; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; + +import static java.util.Collections.emptyList; +import static java.util.Collections.emptyMap; +import static java.util.Collections.unmodifiableCollection; +import static java.util.Collections.unmodifiableMap; +import static java.util.Objects.requireNonNull; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; + +public class CoreConfigurationBuilder> implements FluentConfigurationBuilder { + + private final Map> caches; + private final Collection> serviceConfigurations; + private final ClassLoader classLoader; + + /** + * Create a configuration builder seeded from the given configuration. + *

+ * Calling {@link #build()} on the returned builder will produce a functionally equivalent configuration to + * {@code seed}. + * + * @param seed configuration to duplicate + * @return a new configuration builder + */ + protected static CoreConfigurationBuilder newConfigurationBuilder(Configuration seed) { + return new CoreConfigurationBuilder<>(new CoreConfigurationBuilder<>(new CoreConfigurationBuilder<>(new CoreConfigurationBuilder<>(), + seed.getCacheConfigurations()), seed.getServiceCreationConfigurations()), seed.getClassLoader()); + } + + protected CoreConfigurationBuilder() { + this.caches = emptyMap(); + this.serviceConfigurations = emptyList(); + this.classLoader = null; + } + + protected CoreConfigurationBuilder(CoreConfigurationBuilder builder, Map> caches) { + this.caches = unmodifiableMap(caches); + this.serviceConfigurations = builder.serviceConfigurations; + this.classLoader = builder.classLoader; + } + + protected CoreConfigurationBuilder(CoreConfigurationBuilder builder, Collection> serviceConfigurations) { + this.caches = builder.caches; + this.serviceConfigurations = unmodifiableCollection(serviceConfigurations); + this.classLoader = builder.classLoader; + } + + protected CoreConfigurationBuilder(CoreConfigurationBuilder builder, ClassLoader classLoader) { + this.caches = builder.caches; + this.serviceConfigurations = builder.serviceConfigurations; + this.classLoader = classLoader; + } + + @Override + public Configuration build() { + return new DefaultConfiguration(caches, classLoader, serviceConfigurations.toArray(new ServiceCreationConfiguration[serviceConfigurations.size()])); + } + + @Override + public CacheConfiguration getCache(String alias) { + return caches.get(alias); + } + + @Override + public B withCache(String alias, CacheConfiguration config) { + Map> newCaches = new HashMap<>(caches); + newCaches.put(alias, config); + return newBuilderWith(newCaches); + } + + @Override + public B withoutCache(String alias) { + Map> newCaches = new HashMap<>(caches); + newCaches.remove(alias); + return newBuilderWith(newCaches); + } + + @Override + public B updateCache(String alias, UnaryOperator> update) { + CacheConfiguration existing = getCache(alias); + if (existing == null) { + throw new IllegalArgumentException("Cache does not exist"); + } else { + return withCache(alias, update.apply(existing.derive()).build()); + } + } + + @Override + public B updateCaches(UnaryOperator> update) { + return newBuilderWith(caches.entrySet().stream().collect( + toMap(Map.Entry::getKey, e -> update.apply(e.getValue().derive()).build()) + )); + } + + @Override + public > Collection getServices(Class configurationType) { + return serviceConfigurations.stream().filter(service -> configurationType.isAssignableFrom(service.getClass())).map(configurationType::cast).collect(toList()); + } + + @Override + public B withService(ServiceCreationConfiguration config) { + List> newServiceConfigurations = new ArrayList<>(serviceConfigurations); + newServiceConfigurations.removeIf(other -> !other.compatibleWith(config) || !config.compatibleWith(other)); + newServiceConfigurations.add(config); + return newBuilderWith(newServiceConfigurations); + } + + @Override + public > B withoutServices(Class clazz, Predicate predicate) { + List> newServiceConfigurations = new ArrayList<>(serviceConfigurations); + newServiceConfigurations.removeIf(c -> clazz.isInstance(c) && predicate.test(clazz.cast(c))); + return newBuilderWith(newServiceConfigurations); + } + + @Override + public > B updateServices(Class clazz, UnaryOperator update) { + @SuppressWarnings("unchecked") + Collection> existing = getServices(clazz); + + if (existing.isEmpty()) { + throw new IllegalStateException("Cannot updates service configurations. No services exist"); + } else { + B otherBuilder = withoutServices(clazz); + for (ServiceCreationConfiguration configuration : existing) { + ServiceCreationConfiguration replacement = configuration.build(update.apply(configuration.derive())); + if (replacement == null) { + throw new NullPointerException(configuration.getClass().getSimpleName() + ".build(...) returned a null configuration instance"); + } else { + otherBuilder = otherBuilder.withService(replacement); + } + } + return otherBuilder; + } + } + + @Override + public ClassLoader getClassLoader() { + return classLoader; + } + + @Override + public B withClassLoader(ClassLoader classLoader) { + return newBuilderWith(requireNonNull(classLoader)); + } + + @Override + public B withDefaultClassLoader() { + return newBuilderWith((ClassLoader) null); + } + + @SuppressWarnings("unchecked") + protected B newBuilderWith(Map> caches) { + if (getClass().equals(CoreConfigurationBuilder.class)) { + return (B) new CoreConfigurationBuilder<>(this, caches); + } else { + throw new AssertionError(); + } + } + + @SuppressWarnings("unchecked") + protected B newBuilderWith(Collection> serviceConfigurations) { + if (getClass().equals(CoreConfigurationBuilder.class)) { + return (B) new CoreConfigurationBuilder<>(this, serviceConfigurations); + } else { + throw new AssertionError(); + } + } + + @SuppressWarnings("unchecked") + protected B newBuilderWith(ClassLoader classLoader) { + if (getClass().equals(CoreConfigurationBuilder.class)) { + return (B) new CoreConfigurationBuilder<>(this, classLoader); + } else { + throw new AssertionError(); + } + } + +} diff --git a/core/src/main/java/org/ehcache/core/config/DefaultConfiguration.java b/core/src/main/java/org/ehcache/core/config/DefaultConfiguration.java index fe7d4821d8..835f08b477 100644 --- a/core/src/main/java/org/ehcache/core/config/DefaultConfiguration.java +++ b/core/src/main/java/org/ehcache/core/config/DefaultConfiguration.java @@ -26,12 +26,14 @@ import org.ehcache.config.CacheConfiguration; import org.ehcache.config.CacheRuntimeConfiguration; import org.ehcache.config.Configuration; +import org.ehcache.config.FluentConfigurationBuilder; import org.ehcache.core.HumanReadable; import org.ehcache.core.util.ClassLoading; import org.ehcache.spi.service.ServiceCreationConfiguration; import static java.util.Collections.unmodifiableCollection; import static java.util.Collections.unmodifiableMap; +import static org.ehcache.core.config.CoreConfigurationBuilder.newConfigurationBuilder; /** * Base implementation of {@link Configuration}. @@ -39,7 +41,7 @@ public final class DefaultConfiguration implements Configuration, HumanReadable { private final ConcurrentMap> caches; - private final Collection> services; + private final Collection> services; private final ClassLoader classLoader; /** @@ -66,7 +68,7 @@ public DefaultConfiguration(Configuration cfg) { * * @see #addCacheConfiguration(String, CacheConfiguration) */ - public DefaultConfiguration(ClassLoader classLoader, ServiceCreationConfiguration... services) { + public DefaultConfiguration(ClassLoader classLoader, ServiceCreationConfiguration... services) { this(emptyCacheMap(), classLoader, services); } @@ -78,7 +80,7 @@ public DefaultConfiguration(ClassLoader classLoader, ServiceCreationConfiguratio * @param classLoader the class loader to use for user types * @param services an array of service configurations */ - public DefaultConfiguration(Map> caches, ClassLoader classLoader, ServiceCreationConfiguration... services) { + public DefaultConfiguration(Map> caches, ClassLoader classLoader, ServiceCreationConfiguration... services) { this.services = unmodifiableCollection(Arrays.asList(services)); this.caches = new ConcurrentHashMap<>(caches); this.classLoader = classLoader == null ? ClassLoading.getDefaultClassLoader() : classLoader; @@ -96,7 +98,7 @@ public DefaultConfiguration(Map> caches, ClassL * {@inheritDoc} */ @Override - public Collection> getServiceCreationConfigurations() { + public Collection> getServiceCreationConfigurations() { return services; } @@ -108,6 +110,11 @@ public ClassLoader getClassLoader() { return classLoader; } + @Override + public FluentConfigurationBuilder derive() { + return newConfigurationBuilder(this); + } + private static Map> emptyCacheMap() { return Collections.emptyMap(); } @@ -168,7 +175,7 @@ public String readableString() { } StringBuilder serviceCreationConfigurationsToStringBuilder = new StringBuilder(); - for (ServiceCreationConfiguration serviceCreationConfiguration : services) { + for (ServiceCreationConfiguration serviceCreationConfiguration : services) { serviceCreationConfigurationsToStringBuilder.append("- "); if(serviceCreationConfiguration instanceof HumanReadable) { serviceCreationConfigurationsToStringBuilder diff --git a/core/src/main/java/org/ehcache/core/config/package-info.java b/core/src/main/java/org/ehcache/core/config/package-info.java index 6ffe44b748..205a0afd5d 100644 --- a/core/src/main/java/org/ehcache/core/config/package-info.java +++ b/core/src/main/java/org/ehcache/core/config/package-info.java @@ -15,7 +15,6 @@ */ /** - * Package holding some core implementations related to configuration such as - * {@link org.ehcache.core.config.ResourcePoolsImpl} and {@link org.ehcache.core.config.DefaultConfiguration}. + * Package holding core configuration implementations and utilities. */ -package org.ehcache.core.config; \ No newline at end of file +package org.ehcache.core.config; diff --git a/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java b/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java index 875340fa41..a14090d6ea 100644 --- a/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java +++ b/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java @@ -249,7 +249,7 @@ public DependencySet with(Iterable services) { return this; } - public DependencySet with(ServiceCreationConfiguration config) { + public DependencySet with(ServiceCreationConfiguration config) { Class serviceType = config.getServiceType(); //TODO : This stanza is due to the way we use configure the JSR-107 service diff --git a/core/src/main/java/org/ehcache/core/spi/service/ServiceFactory.java b/core/src/main/java/org/ehcache/core/spi/service/ServiceFactory.java index b3cfbf0013..ae9c873a91 100644 --- a/core/src/main/java/org/ehcache/core/spi/service/ServiceFactory.java +++ b/core/src/main/java/org/ehcache/core/spi/service/ServiceFactory.java @@ -58,7 +58,7 @@ default int rank() { * @param configuration the creation configuration, can be {@code null} for some services * @return the new service, not {@link Service#start(ServiceProvider) started} */ - T create(ServiceCreationConfiguration configuration); + T create(ServiceCreationConfiguration configuration); /** * Queries a {@code ServiceFactory} to know which {@link Service} type it produces. diff --git a/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java b/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java index bbc0abfb67..0e7d9528c9 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java @@ -146,7 +146,7 @@ public void testCanDestroyAndClose() throws Exception { @Test public void testConstructionThrowsWhenNotBeingToResolveService() { Map> caches = newCacheMap(); - final DefaultConfiguration config = new DefaultConfiguration(caches, null, (ServiceCreationConfiguration) () -> NoSuchService.class); + final DefaultConfiguration config = new DefaultConfiguration(caches, null, (ServiceCreationConfiguration) () -> NoSuchService.class); try { new EhcacheManager(config); fail("Should have thrown..."); @@ -158,7 +158,7 @@ public void testConstructionThrowsWhenNotBeingToResolveService() { @Test public void testCreationFailsOnDuplicateServiceCreationConfiguration() { Map> caches = newCacheMap(); - DefaultConfiguration config = new DefaultConfiguration(caches, null, (ServiceCreationConfiguration) () -> NoSuchService.class, (ServiceCreationConfiguration) () -> NoSuchService.class); + DefaultConfiguration config = new DefaultConfiguration(caches, null, (ServiceCreationConfiguration) () -> NoSuchService.class, (ServiceCreationConfiguration) () -> NoSuchService.class); try { new EhcacheManager(config); fail("Should have thrown ..."); diff --git a/core/src/test/java/org/ehcache/core/config/CoreConfigurationBuilderTest.java b/core/src/test/java/org/ehcache/core/config/CoreConfigurationBuilderTest.java new file mode 100644 index 0000000000..78e54d6596 --- /dev/null +++ b/core/src/test/java/org/ehcache/core/config/CoreConfigurationBuilderTest.java @@ -0,0 +1,51 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.config; + +import org.ehcache.config.Configuration; +import org.ehcache.core.util.ClassLoading; +import org.junit.Test; + +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +public class CoreConfigurationBuilderTest { + + @Test + public void testWithClassLoader() { + ClassLoader classLoader = mock(ClassLoader.class); + + Configuration configuration = new CoreConfigurationBuilder<>() + .withClassLoader(classLoader) + .build(); + + assertThat(configuration.getClassLoader(), sameInstance(classLoader)); + } + + @Test + public void testWithDefaultClassLoader() { + ClassLoader classLoader = mock(ClassLoader.class); + + Configuration configuration = new CoreConfigurationBuilder<>() + .withClassLoader(classLoader) + .withDefaultClassLoader() + .build(); + + assertThat(configuration.getClassLoader(), sameInstance(ClassLoading.getDefaultClassLoader())); + } + +} diff --git a/core/src/test/java/org/ehcache/core/spi/services/FancyCacheProviderFactory.java b/core/src/test/java/org/ehcache/core/spi/services/FancyCacheProviderFactory.java index dd351289c4..e790e16f70 100644 --- a/core/src/test/java/org/ehcache/core/spi/services/FancyCacheProviderFactory.java +++ b/core/src/test/java/org/ehcache/core/spi/services/FancyCacheProviderFactory.java @@ -24,7 +24,7 @@ */ public class FancyCacheProviderFactory implements ServiceFactory { @Override - public FancyCacheProvider create(ServiceCreationConfiguration configuration) { + public FancyCacheProvider create(ServiceCreationConfiguration configuration) { return new FancyCacheProvider(); } diff --git a/core/src/test/java/org/ehcache/core/spi/services/TestMandatoryServiceFactory.java b/core/src/test/java/org/ehcache/core/spi/services/TestMandatoryServiceFactory.java index 43e04a9de7..2ed51b19c7 100644 --- a/core/src/test/java/org/ehcache/core/spi/services/TestMandatoryServiceFactory.java +++ b/core/src/test/java/org/ehcache/core/spi/services/TestMandatoryServiceFactory.java @@ -28,7 +28,7 @@ public boolean isMandatory() { } @Override - public TestMandatoryService create(ServiceCreationConfiguration configuration) { + public TestMandatoryService create(ServiceCreationConfiguration configuration) { if (configuration == null) { return new TestMandatoryService(null); } else { @@ -41,7 +41,7 @@ public Class getServiceType() { return TestMandatoryService.class; } - public static class TestMandatoryServiceConfiguration implements ServiceCreationConfiguration { + public static class TestMandatoryServiceConfiguration implements ServiceCreationConfiguration { private final String config; diff --git a/core/src/test/java/org/ehcache/core/spi/services/TestProvidedServiceFactory.java b/core/src/test/java/org/ehcache/core/spi/services/TestProvidedServiceFactory.java index 10233e0343..9b463bbe39 100644 --- a/core/src/test/java/org/ehcache/core/spi/services/TestProvidedServiceFactory.java +++ b/core/src/test/java/org/ehcache/core/spi/services/TestProvidedServiceFactory.java @@ -24,7 +24,7 @@ */ public class TestProvidedServiceFactory implements ServiceFactory { @Override - public TestProvidedService create(ServiceCreationConfiguration configuration) { + public TestProvidedService create(ServiceCreationConfiguration configuration) { return new DefaultTestProvidedService(); } diff --git a/core/src/test/java/org/ehcache/core/spi/services/TestServiceFactory.java b/core/src/test/java/org/ehcache/core/spi/services/TestServiceFactory.java index d056e7324a..386b73c222 100644 --- a/core/src/test/java/org/ehcache/core/spi/services/TestServiceFactory.java +++ b/core/src/test/java/org/ehcache/core/spi/services/TestServiceFactory.java @@ -24,7 +24,7 @@ */ public class TestServiceFactory implements ServiceFactory { @Override - public TestService create(ServiceCreationConfiguration configuration) { + public TestService create(ServiceCreationConfiguration configuration) { return new DefaultTestService(); } diff --git a/core/src/test/java/org/ehcache/core/spi/services/ranking/HighRankServiceAFactory.java b/core/src/test/java/org/ehcache/core/spi/services/ranking/HighRankServiceAFactory.java index 3861823c67..d7753b7675 100644 --- a/core/src/test/java/org/ehcache/core/spi/services/ranking/HighRankServiceAFactory.java +++ b/core/src/test/java/org/ehcache/core/spi/services/ranking/HighRankServiceAFactory.java @@ -26,7 +26,7 @@ public int rank() { } @Override - public RankServiceA create(ServiceCreationConfiguration configuration) { + public RankServiceA create(ServiceCreationConfiguration configuration) { return new RankServiceA("high-rank"); } diff --git a/core/src/test/java/org/ehcache/core/spi/services/ranking/LowRankServiceBFactory.java b/core/src/test/java/org/ehcache/core/spi/services/ranking/LowRankServiceBFactory.java index 67892987ff..6ddbd6c7b0 100644 --- a/core/src/test/java/org/ehcache/core/spi/services/ranking/LowRankServiceBFactory.java +++ b/core/src/test/java/org/ehcache/core/spi/services/ranking/LowRankServiceBFactory.java @@ -21,7 +21,7 @@ public class LowRankServiceBFactory implements ServiceFactory { @Override - public RankServiceB create(ServiceCreationConfiguration configuration) { + public RankServiceB create(ServiceCreationConfiguration configuration) { return new RankServiceB("low-rank"); } diff --git a/core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryHighRankServiceBFactory.java b/core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryHighRankServiceBFactory.java index 76fc641d29..bdb6e2599a 100644 --- a/core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryHighRankServiceBFactory.java +++ b/core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryHighRankServiceBFactory.java @@ -31,7 +31,7 @@ public int rank() { } @Override - public RankServiceB create(ServiceCreationConfiguration configuration) { + public RankServiceB create(ServiceCreationConfiguration configuration) { return new RankServiceB("high-rank"); } diff --git a/core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryLowRankServiceAFactory.java b/core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryLowRankServiceAFactory.java index df08065adb..b691e4cff5 100644 --- a/core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryLowRankServiceAFactory.java +++ b/core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryLowRankServiceAFactory.java @@ -26,7 +26,7 @@ public boolean isMandatory() { } @Override - public RankServiceA create(ServiceCreationConfiguration configuration) { + public RankServiceA create(ServiceCreationConfiguration configuration) { return new RankServiceA("low-rank"); } diff --git a/gradle.properties b/gradle.properties index 616370f8f7..c40ab04242 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # Ehcache version -ehcacheVersion = 3.7-SNAPSHOT +ehcacheVersion = 3.8-SNAPSHOT # Terracotta third parties offheapVersion = 2.4.3 diff --git a/impl/src/main/java/org/ehcache/config/builders/CacheManagerBuilder.java b/impl/src/main/java/org/ehcache/config/builders/CacheManagerBuilder.java index 376678c73f..72af567224 100644 --- a/impl/src/main/java/org/ehcache/config/builders/CacheManagerBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/CacheManagerBuilder.java @@ -21,6 +21,7 @@ import org.ehcache.config.Builder; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.Configuration; +import org.ehcache.config.FluentConfigurationBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.EhcacheManager; import org.ehcache.core.spi.store.heap.SizeOfEngine; @@ -40,6 +41,8 @@ import java.util.Collection; import java.util.HashSet; import java.util.Set; +import java.util.function.Supplier; +import java.util.function.UnaryOperator; import static java.util.Collections.emptySet; import static java.util.Collections.unmodifiableSet; @@ -57,7 +60,7 @@ */ public class CacheManagerBuilder implements Builder { - private final ConfigurationBuilder configBuilder; + private final FluentConfigurationBuilder configBuilder; private final Set services; /** @@ -94,7 +97,7 @@ private CacheManagerBuilder(CacheManagerBuilder builder, Set service this.services = unmodifiableSet(services); } - private CacheManagerBuilder(CacheManagerBuilder builder, ConfigurationBuilder configBuilder) { + private CacheManagerBuilder(CacheManagerBuilder builder, FluentConfigurationBuilder configBuilder) { this.configBuilder = configBuilder; this.services = builder.services; } @@ -132,7 +135,7 @@ T cast(EhcacheManager ehcacheManager) { * @see CacheConfigurationBuilder */ public CacheManagerBuilder withCache(String alias, CacheConfiguration configuration) { - return new CacheManagerBuilder<>(this, configBuilder.addCache(alias, configuration)); + return new CacheManagerBuilder<>(this, configBuilder.withCache(alias, configuration)); } /** @@ -203,16 +206,7 @@ public CacheManagerBuilder using(Service service) { * @return a new builder with the added default copier */ public CacheManagerBuilder withCopier(Class clazz, Class> copier) { - DefaultCopyProviderConfiguration service = configBuilder.findServiceByClass(DefaultCopyProviderConfiguration.class); - if (service == null) { - service = new DefaultCopyProviderConfiguration(); - service.addCopierFor(clazz, copier); - return new CacheManagerBuilder<>(this, configBuilder.addService(service)); - } else { - DefaultCopyProviderConfiguration newConfig = new DefaultCopyProviderConfiguration(service); - newConfig.addCopierFor(clazz, copier, true); - return new CacheManagerBuilder<>(this, configBuilder.removeService(service).addService(newConfig)); - } + return ensureThenUpdate(DefaultCopyProviderConfiguration::new, existing -> existing.addCopierFor(clazz, copier, true)); } /** @@ -224,16 +218,7 @@ public CacheManagerBuilder withCopier(Class clazz, Class CacheManagerBuilder withSerializer(Class clazz, Class> serializer) { - DefaultSerializationProviderConfiguration service = configBuilder.findServiceByClass(DefaultSerializationProviderConfiguration.class); - if (service == null) { - service = new DefaultSerializationProviderConfiguration(); - service.addSerializerFor(clazz, serializer); - return new CacheManagerBuilder<>(this, configBuilder.addService(service)); - } else { - DefaultSerializationProviderConfiguration newConfig = new DefaultSerializationProviderConfiguration(service); - newConfig.addSerializerFor(clazz, serializer, true); - return new CacheManagerBuilder<>(this, configBuilder.removeService(service).addService(newConfig)); - } + return ensureThenUpdate(DefaultSerializationProviderConfiguration::new, config -> config.addSerializerFor(clazz, serializer, true)); } /** @@ -244,14 +229,10 @@ public CacheManagerBuilder withSerializer(Class clazz, Class withDefaultSizeOfMaxObjectGraph(long size) { - DefaultSizeOfEngineProviderConfiguration configuration = configBuilder.findServiceByClass(DefaultSizeOfEngineProviderConfiguration.class); - if (configuration == null) { - return new CacheManagerBuilder<>(this, configBuilder.addService(new DefaultSizeOfEngineProviderConfiguration(DEFAULT_MAX_OBJECT_SIZE, DEFAULT_UNIT, size))); - } else { - ConfigurationBuilder builder = configBuilder.removeService(configuration); - return new CacheManagerBuilder<>(this, builder.addService(new DefaultSizeOfEngineProviderConfiguration(configuration - .getMaxObjectSize(), configuration.getUnit(), size))); - } + return ensureThenUpdate( + () -> new DefaultSizeOfEngineProviderConfiguration(DEFAULT_MAX_OBJECT_SIZE, DEFAULT_UNIT, DEFAULT_OBJECT_GRAPH_SIZE), + existing -> new DefaultSizeOfEngineProviderConfiguration(existing.getMaxObjectSize(), existing.getUnit(), size) + ); } /** @@ -263,14 +244,10 @@ public CacheManagerBuilder withDefaultSizeOfMaxObjectGraph(long size) { * @return a new builder with the added configuration */ public CacheManagerBuilder withDefaultSizeOfMaxObjectSize(long size, MemoryUnit unit) { - DefaultSizeOfEngineProviderConfiguration configuration = configBuilder.findServiceByClass(DefaultSizeOfEngineProviderConfiguration.class); - if (configuration == null) { - return new CacheManagerBuilder<>(this, configBuilder.addService(new DefaultSizeOfEngineProviderConfiguration(size, unit, DEFAULT_OBJECT_GRAPH_SIZE))); - } else { - ConfigurationBuilder builder = configBuilder.removeService(configuration); - return new CacheManagerBuilder<>(this, builder.addService(new DefaultSizeOfEngineProviderConfiguration(size, unit, configuration - .getMaxObjectGraphSize()))); - } + return ensureThenUpdate( + () -> new DefaultSizeOfEngineProviderConfiguration(DEFAULT_MAX_OBJECT_SIZE, DEFAULT_UNIT, DEFAULT_OBJECT_GRAPH_SIZE), + existing -> new DefaultSizeOfEngineProviderConfiguration(size, unit, existing.getMaxObjectGraphSize()) + ); } /** @@ -282,13 +259,7 @@ public CacheManagerBuilder withDefaultSizeOfMaxObjectSize(long size, MemoryUn * @see PooledExecutionServiceConfigurationBuilder */ public CacheManagerBuilder withDefaultWriteBehindThreadPool(String threadPoolAlias) { - WriteBehindProviderConfiguration config = configBuilder.findServiceByClass(WriteBehindProviderConfiguration.class); - if (config == null) { - return new CacheManagerBuilder<>(this, configBuilder.addService(new WriteBehindProviderConfiguration(threadPoolAlias))); - } else { - ConfigurationBuilder builder = configBuilder.removeService(config); - return new CacheManagerBuilder<>(this, builder.addService(new WriteBehindProviderConfiguration(threadPoolAlias))); - } + return using(new WriteBehindProviderConfiguration(threadPoolAlias)); } /** @@ -301,13 +272,7 @@ public CacheManagerBuilder withDefaultWriteBehindThreadPool(String threadPool * @see PooledExecutionServiceConfigurationBuilder */ public CacheManagerBuilder withDefaultDiskStoreThreadPool(String threadPoolAlias) { - OffHeapDiskStoreProviderConfiguration config = configBuilder.findServiceByClass(OffHeapDiskStoreProviderConfiguration.class); - if (config == null) { - return new CacheManagerBuilder<>(this, configBuilder.addService(new OffHeapDiskStoreProviderConfiguration(threadPoolAlias))); - } else { - ConfigurationBuilder builder = configBuilder.removeService(config); - return new CacheManagerBuilder<>(this, builder.addService(new OffHeapDiskStoreProviderConfiguration(threadPoolAlias))); - } + return using(new OffHeapDiskStoreProviderConfiguration(threadPoolAlias)); } /** @@ -320,25 +285,21 @@ public CacheManagerBuilder withDefaultDiskStoreThreadPool(String threadPoolAl * @see PooledExecutionServiceConfigurationBuilder */ public CacheManagerBuilder withDefaultEventListenersThreadPool(String threadPoolAlias) { - CacheEventDispatcherFactoryConfiguration config = configBuilder.findServiceByClass(CacheEventDispatcherFactoryConfiguration.class); - if (config == null) { - return new CacheManagerBuilder<>(this, configBuilder.addService(new CacheEventDispatcherFactoryConfiguration(threadPoolAlias))); - } else { - ConfigurationBuilder builder = configBuilder.removeService(config); - return new CacheManagerBuilder<>(this, builder.addService(new CacheEventDispatcherFactoryConfiguration(threadPoolAlias))); - } + return using(new CacheEventDispatcherFactoryConfiguration(threadPoolAlias)); } /** * Adds a {@link ServiceCreationConfiguration} to the returned builder. *

- * These configurations are used to load services and configure them at creation time. + * These configurations are used to load services and configure them at creation time. This method will remove any + * existing configuration incompatible with the given configuration, before adding the new configuration. * * @param serviceConfiguration the {@code ServiceCreationConfiguration} to use * @return a new builder with the added configuration + * @see FluentConfigurationBuilder#withService(ServiceCreationConfiguration) */ - public CacheManagerBuilder using(ServiceCreationConfiguration serviceConfiguration) { - return new CacheManagerBuilder<>(this, configBuilder.addService(serviceConfiguration)); + public CacheManagerBuilder using(ServiceCreationConfiguration serviceConfiguration) { + return new CacheManagerBuilder<>(this, configBuilder.withService(serviceConfiguration)); } /** @@ -348,11 +309,12 @@ public CacheManagerBuilder using(ServiceCreationConfiguration serviceConfi * * @param overwriteServiceConfiguration the new {@code ServiceCreationConfiguration} to use * @return a new builder with the replaced configuration + * + * @deprecated in favor of {@link #using(ServiceCreationConfiguration)} whose refined contract matches this one */ - public CacheManagerBuilder replacing(ServiceCreationConfiguration overwriteServiceConfiguration) { - ServiceCreationConfiguration existingConfiguration = configBuilder.findServiceByClass(overwriteServiceConfiguration.getClass()); - return new CacheManagerBuilder<>(this, configBuilder.removeService(existingConfiguration) - .addService(overwriteServiceConfiguration)); + @Deprecated + public CacheManagerBuilder replacing(ServiceCreationConfiguration overwriteServiceConfiguration) { + return using(overwriteServiceConfiguration); } /** @@ -365,6 +327,19 @@ public CacheManagerBuilder withClassLoader(ClassLoader classLoader) { return new CacheManagerBuilder<>(this, configBuilder.withClassLoader(classLoader)); } + private > CacheManagerBuilder ensureThenUpdate(Supplier supplier, UnaryOperator update) { + C emptyConfig = supplier.get(); + @SuppressWarnings("unchecked") + Class configType = (Class) emptyConfig.getClass(); + + FluentConfigurationBuilder fluentBuilder = configBuilder; + if (configBuilder.getService(configType) == null) { + fluentBuilder = fluentBuilder.withService(emptyConfig); + } + + return new CacheManagerBuilder<>(this, fluentBuilder.updateServices(configType, update)); + } + /** * Creates a new {@code CacheManagerBuilder} * diff --git a/impl/src/main/java/org/ehcache/config/builders/ConfigurationBuilder.java b/impl/src/main/java/org/ehcache/config/builders/ConfigurationBuilder.java index d4bafacc76..bc10763298 100644 --- a/impl/src/main/java/org/ehcache/config/builders/ConfigurationBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/ConfigurationBuilder.java @@ -16,110 +16,154 @@ package org.ehcache.config.builders; -import org.ehcache.config.Builder; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.Configuration; -import org.ehcache.core.config.DefaultConfiguration; +import org.ehcache.core.config.CoreConfigurationBuilder; import org.ehcache.spi.service.ServiceCreationConfiguration; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Collection; import java.util.List; import java.util.Map; - -import static java.util.Collections.emptyList; -import static java.util.Collections.emptyMap; -import static java.util.Collections.unmodifiableList; -import static java.util.Collections.unmodifiableMap; +import java.util.function.Predicate; /** - * Companion type to the {@link CacheManagerBuilder} that handles the {@link Configuration} building. + * The {@code ConfigurationBuilder} enables building {@link Configuration}s using a fluent style. * * @author Alex Snaps */ -public class ConfigurationBuilder implements Builder { - - private final Map> caches; - private final List> serviceConfigurations; - private final ClassLoader classLoader; +public final class ConfigurationBuilder extends CoreConfigurationBuilder { + /** + * Create a new 'empty' configuration builder. + * + * @return a new empty configuration builder + */ public static ConfigurationBuilder newConfigurationBuilder() { return new ConfigurationBuilder(); } - private ConfigurationBuilder() { - this.caches = emptyMap(); - this.serviceConfigurations = emptyList(); - this.classLoader = null; + /** + * Create a configuration builder seeded from the given configuration. + *

+ * Calling {@link #build()} on the returned builder will produce a functionally equivalent configuration to + * {@code seed}. + * + * @param seed configuration to duplicate + * @return a new configuration builder + */ + public static ConfigurationBuilder newConfigurationBuilder(Configuration seed) { + return new ConfigurationBuilder(new ConfigurationBuilder(new ConfigurationBuilder(new ConfigurationBuilder(), + seed.getCacheConfigurations()), seed.getServiceCreationConfigurations()), seed.getClassLoader()); } - private ConfigurationBuilder(ConfigurationBuilder builder, Map> caches) { - this.caches = unmodifiableMap(caches); - this.serviceConfigurations = builder.serviceConfigurations; - this.classLoader = builder.classLoader; + protected ConfigurationBuilder() { + super(); } - private ConfigurationBuilder(ConfigurationBuilder builder, List> serviceConfigurations) { - this.caches = builder.caches; - this.serviceConfigurations = unmodifiableList(serviceConfigurations); - this.classLoader = builder.classLoader; + protected ConfigurationBuilder(ConfigurationBuilder builder, Map> caches) { + super(builder, caches); } - private ConfigurationBuilder(ConfigurationBuilder builder, ClassLoader classLoader) { - this.caches = builder.caches; - this.serviceConfigurations = builder.serviceConfigurations; - this.classLoader = classLoader; + protected ConfigurationBuilder(ConfigurationBuilder builder, Collection> serviceConfigurations) { + super(builder, serviceConfigurations); } - @Override - public Configuration build() { - return new DefaultConfiguration(caches, classLoader, serviceConfigurations.toArray(new ServiceCreationConfiguration[serviceConfigurations.size()])); + protected ConfigurationBuilder(ConfigurationBuilder builder, ClassLoader classLoader) { + super(builder, classLoader); } - public ConfigurationBuilder addCache(String alias, CacheConfiguration config) { - Map> newCaches = new HashMap<>(caches); - if(newCaches.put(alias, config) != null) { - throw new IllegalArgumentException("Cache alias '" + alias + "' already exists"); + /** + * Add a cache configuration with the given alias. + *

+ * If a cache with the given alias already exists then an {@code IllegalArgumentException} will be thrown. + * + * @param alias cache alias to be added + * @param config cache configuration + * @return an updated builder + * @deprecated in favor of {@link #withCache(String, CacheConfiguration)} + */ + @Deprecated + public ConfigurationBuilder addCache(String alias, CacheConfiguration config) throws IllegalArgumentException { + CacheConfiguration existing = getCache(alias); + if (existing == null) { + return withCache(alias, config); + } else { + throw new IllegalArgumentException("Cache '" + alias + "' already exists: " + existing); } - return new ConfigurationBuilder(this, newCaches); } + /** + * Removes the cache with the given alias. + * + * @param alias cache alias to be removed + * @return an updated builder + * @deprecated in favor of {@link #withoutCache(String)} + */ + @Deprecated public ConfigurationBuilder removeCache(String alias) { - Map> newCaches = new HashMap<>(caches); - newCaches.remove(alias); - return new ConfigurationBuilder(this, newCaches); + return withoutCache(alias); } - public ConfigurationBuilder addService(ServiceCreationConfiguration serviceConfiguration) { - if (findServiceByClass(serviceConfiguration.getClass()) != null) { - throw new IllegalArgumentException("There is already a ServiceCreationConfiguration registered for service " + serviceConfiguration - .getServiceType() + " of type " + serviceConfiguration.getClass()); + /** + * Adds the given service to this configuration. + *

+ * If a a service creation configuration of the same concrete type is already present then an {@code IllegalArgumentException} + * will be thrown. + * + * @param serviceConfiguration service creation configuration + * @return an updated builder + * @deprecated in favor of {@link #withService(ServiceCreationConfiguration)} + */ + @Deprecated + public ConfigurationBuilder addService(ServiceCreationConfiguration serviceConfiguration) { + ServiceCreationConfiguration existing = getService(serviceConfiguration.getClass()); + if (existing == null) { + return withService(serviceConfiguration); + } else { + throw new IllegalArgumentException("There is already an instance of " + serviceConfiguration.getClass() + " registered: " + existing.getClass()); } - List> newServiceConfigurations = new ArrayList<>(serviceConfigurations); - newServiceConfigurations.add(serviceConfiguration); + } + + /** + * Removes the given service configuration. + * + * @param serviceConfiguration service creation configuration + * @return an updated builder + * @deprecated in favor of {@link #withoutServices(Class)} or {@link #withoutServices(Class, Predicate)} + */ + @Deprecated + public ConfigurationBuilder removeService(ServiceCreationConfiguration serviceConfiguration) { + @SuppressWarnings("unchecked") + List> newServiceConfigurations = new ArrayList>(getServices((Class) ServiceCreationConfiguration.class)); + newServiceConfigurations.remove(serviceConfiguration); return new ConfigurationBuilder(this, newServiceConfigurations); } - T findServiceByClass(Class type) { - for (ServiceCreationConfiguration serviceConfiguration : serviceConfigurations) { - if (serviceConfiguration.getClass().equals(type)) { - return type.cast(serviceConfiguration); - } - } - return null; + /** + * Returns {@code true} if a cache configuration is associated with the given alias. + * + * @param alias cache configuration alias + * @return {@code true} if the given alias is present + * @deprecated in favor of {@link #getCache(String)} + */ + @Deprecated + public boolean containsCache(String alias) { + return getCache(alias) != null; } - public ConfigurationBuilder removeService(ServiceCreationConfiguration serviceConfiguration) { - List> newServiceConfigurations = new ArrayList<>(serviceConfigurations); - newServiceConfigurations.remove(serviceConfiguration); - return new ConfigurationBuilder(this, newServiceConfigurations); + @Override + protected ConfigurationBuilder newBuilderWith(Map> caches) { + return new ConfigurationBuilder(this, caches); } - public ConfigurationBuilder withClassLoader(ClassLoader classLoader) { - return new ConfigurationBuilder(this, classLoader); + @Override + protected ConfigurationBuilder newBuilderWith(Collection> serviceConfigurations) { + return new ConfigurationBuilder(this, serviceConfigurations); } - public boolean containsCache(String alias) { - return caches.containsKey(alias); + @Override + protected ConfigurationBuilder newBuilderWith(ClassLoader classLoader) { + return new ConfigurationBuilder(this, classLoader); } } diff --git a/impl/src/main/java/org/ehcache/config/builders/PooledExecutionServiceConfigurationBuilder.java b/impl/src/main/java/org/ehcache/config/builders/PooledExecutionServiceConfigurationBuilder.java index ef83df8006..3920d29a24 100644 --- a/impl/src/main/java/org/ehcache/config/builders/PooledExecutionServiceConfigurationBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/PooledExecutionServiceConfigurationBuilder.java @@ -43,6 +43,16 @@ private PooledExecutionServiceConfigurationBuilder(PooledExecutionServiceConfigu this.pools.addAll(other.pools); } + private PooledExecutionServiceConfigurationBuilder(PooledExecutionServiceConfiguration seed) { + seed.getPoolConfigurations().forEach((alias, config) -> { + Pool pool = new Pool(alias, config.minSize(), config.maxSize()); + if (alias.equals(seed.getDefaultPoolAlias())) { + defaultPool = pool; + } + pools.add(pool); + }); + } + /** * Creates a new instance of {@code PooledExecutionServiceConfigurationBuilder} * @@ -52,6 +62,15 @@ public static PooledExecutionServiceConfigurationBuilder newPooledExecutionServi return new PooledExecutionServiceConfigurationBuilder(); } + /** + * Creates a seeded instance of {@code PooledExecutionServiceConfigurationBuilder} + * + * @return the builder + */ + public static PooledExecutionServiceConfigurationBuilder newPooledExecutionServiceConfigurationBuilder(PooledExecutionServiceConfiguration seed) { + return new PooledExecutionServiceConfigurationBuilder(seed); + } + /** * Adds a default pool configuration to the returned builder. * diff --git a/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java b/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java index b9503178d8..a601146715 100644 --- a/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java @@ -112,7 +112,7 @@ public class UserManagedCacheBuilder> imp private final Class valueType; private String id; private final Set services = new HashSet<>(); - private final Set> serviceCreationConfigurations = new HashSet<>(); + private final Set> serviceCreationConfigurations = new HashSet<>(); private ExpiryPolicy expiry = ExpiryPolicy.NO_EXPIRY; private ClassLoader classLoader = ClassLoading.getDefaultClassLoader(); private EvictionAdvisor evictionAdvisor; @@ -171,7 +171,7 @@ T build(ServiceLocator.DependencySet serviceLocatorBuilder) throws IllegalStateE ServiceLocator serviceLocator; try { - for (ServiceCreationConfiguration serviceCreationConfig : serviceCreationConfigurations) { + for (ServiceCreationConfiguration serviceCreationConfig : serviceCreationConfigurations) { serviceLocatorBuilder = serviceLocatorBuilder.with(serviceCreationConfig); } serviceLocatorBuilder = serviceLocatorBuilder.with(Store.Provider.class); @@ -813,7 +813,7 @@ public UserManagedCacheBuilder using(Service service) { * * @see #using(Service) */ - public UserManagedCacheBuilder using(ServiceCreationConfiguration serviceConfiguration) { + public UserManagedCacheBuilder using(ServiceCreationConfiguration serviceConfiguration) { UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this); if (serviceConfiguration instanceof DefaultSizeOfEngineProviderConfiguration) { removeAnySizeOfEngine(otherBuilder); diff --git a/impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfiguration.java index 9542fb7703..db7658d6e2 100644 --- a/impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfiguration.java @@ -27,7 +27,7 @@ * Enables configuring {@link Class} - {@link Copier} pairs that will be selected unless cache level configurations * are provided. */ -public class DefaultCopyProviderConfiguration extends ClassInstanceProviderConfiguration, DefaultCopierConfiguration> implements ServiceCreationConfiguration { +public class DefaultCopyProviderConfiguration extends ClassInstanceProviderConfiguration, DefaultCopierConfiguration> implements ServiceCreationConfiguration { /** * Default constructor. @@ -95,4 +95,14 @@ public DefaultCopyProviderConfiguration addCopierFor(Class clazz, Class(copierClass)); return this; } + + @Override + public DefaultCopyProviderConfiguration derive() { + return new DefaultCopyProviderConfiguration(this); + } + + @Override + public DefaultCopyProviderConfiguration build(DefaultCopyProviderConfiguration configuration) { + return configuration; + } } diff --git a/impl/src/main/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfiguration.java index ae6abc605c..486d5b2e76 100644 --- a/impl/src/main/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfiguration.java @@ -25,7 +25,7 @@ * Enables configuring the default thread pool alias to be used by the * {@link org.ehcache.core.events.CacheEventDispatcher}s */ -public class CacheEventDispatcherFactoryConfiguration implements ServiceCreationConfiguration { +public class CacheEventDispatcherFactoryConfiguration implements ServiceCreationConfiguration { private final String threadPoolAlias; @@ -54,4 +54,14 @@ public String getThreadPoolAlias() { public Class getServiceType() { return CacheEventDispatcherFactory.class; } + + @Override + public String derive() { + return getThreadPoolAlias(); + } + + @Override + public CacheEventDispatcherFactoryConfiguration build(String alias) { + return new CacheEventDispatcherFactoryConfiguration(alias); + } } diff --git a/impl/src/main/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfiguration.java index 37adf3c05f..1073f8630f 100644 --- a/impl/src/main/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfiguration.java @@ -18,10 +18,13 @@ import java.util.HashMap; import java.util.Map; + +import org.ehcache.config.builders.PooledExecutionServiceConfigurationBuilder; import org.ehcache.core.spi.service.ExecutionService; import org.ehcache.spi.service.ServiceCreationConfiguration; import static java.util.Collections.unmodifiableMap; +import static org.ehcache.config.builders.PooledExecutionServiceConfigurationBuilder.newPooledExecutionServiceConfigurationBuilder; /** * {@link ServiceCreationConfiguration} for the pooled {@link ExecutionService} implementation. @@ -36,7 +39,7 @@ * @see org.ehcache.impl.config.store.disk.OffHeapDiskStoreProviderConfiguration * @see org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration */ -public class PooledExecutionServiceConfiguration implements ServiceCreationConfiguration { +public class PooledExecutionServiceConfiguration implements ServiceCreationConfiguration { private final Map poolConfigurations = new HashMap<>(); @@ -52,18 +55,20 @@ public class PooledExecutionServiceConfiguration implements ServiceCreationConfi * @param alias the pool alias * @param minSize the minimum size * @param maxSize the maximum size + * @return this configuration object with a new default pool * * @throws NullPointerException if alias is null * @throws IllegalArgumentException if another default was configured already or if another pool with the same * alias was configured already */ - public void addDefaultPool(String alias, int minSize, int maxSize) { + public PooledExecutionServiceConfiguration addDefaultPool(String alias, int minSize, int maxSize) { if (alias == null) { throw new NullPointerException("Pool alias cannot be null"); } if (defaultAlias == null) { addPool(alias, minSize, maxSize); defaultAlias = alias; + return this; } else { throw new IllegalArgumentException("'" + defaultAlias + "' is already configured as the default pool"); } @@ -75,11 +80,12 @@ public void addDefaultPool(String alias, int minSize, int maxSize) { * @param alias the pool alias * @param minSize the minimum size * @param maxSize the maximum size + * @return this configuration object with a new pool * * @throws NullPointerException if alias is null * @throws IllegalArgumentException if another pool with the same alias was configured already */ - public void addPool(String alias, int minSize, int maxSize) { + public PooledExecutionServiceConfiguration addPool(String alias, int minSize, int maxSize) { if (alias == null) { throw new NullPointerException("Pool alias cannot be null"); } @@ -87,6 +93,7 @@ public void addPool(String alias, int minSize, int maxSize) { throw new IllegalArgumentException("A pool with the alias '" + alias + "' is already configured"); } else { poolConfigurations.put(alias, new PoolConfiguration(minSize, maxSize)); + return this; } } @@ -116,6 +123,16 @@ public Class getServiceType() { return ExecutionService.class; } + @Override + public PooledExecutionServiceConfigurationBuilder derive() { + return newPooledExecutionServiceConfigurationBuilder(this); + } + + @Override + public PooledExecutionServiceConfiguration build(PooledExecutionServiceConfigurationBuilder builder) { + return builder.build(); + } + /** * Configuration class representing a pool configuration. */ diff --git a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfiguration.java index 6bdbb156ec..cf3b4bd744 100644 --- a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfiguration.java @@ -24,7 +24,15 @@ /** * {@link ServiceCreationConfiguration} for the default {@link CacheLoaderWriterProvider}. */ -public class DefaultCacheLoaderWriterProviderConfiguration extends ClassInstanceProviderConfiguration implements ServiceCreationConfiguration { +public class DefaultCacheLoaderWriterProviderConfiguration extends ClassInstanceProviderConfiguration implements ServiceCreationConfiguration { + + public DefaultCacheLoaderWriterProviderConfiguration() { + super(); + } + + public DefaultCacheLoaderWriterProviderConfiguration(DefaultCacheLoaderWriterProviderConfiguration config) { + super(config); + } /** * {@inheritDoc} @@ -48,4 +56,14 @@ public DefaultCacheLoaderWriterProviderConfiguration addLoaderFor(String alias, getDefaults().put(alias, new DefaultCacheLoaderWriterConfiguration(clazz, arguments)); return this; } + + @Override + public DefaultCacheLoaderWriterProviderConfiguration derive() { + return new DefaultCacheLoaderWriterProviderConfiguration(this); + } + + @Override + public DefaultCacheLoaderWriterProviderConfiguration build(DefaultCacheLoaderWriterProviderConfiguration configuration) { + return configuration; + } } diff --git a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfiguration.java index 114f7dda21..1d116a1007 100644 --- a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfiguration.java @@ -23,7 +23,7 @@ * * @author cdennis */ -public class WriteBehindProviderConfiguration implements ServiceCreationConfiguration { +public class WriteBehindProviderConfiguration implements ServiceCreationConfiguration { private final String threadPoolAlias; @@ -39,4 +39,14 @@ public String getThreadPoolAlias() { public Class getServiceType() { return WriteBehindProvider.class; } + + @Override + public String derive() { + return getThreadPoolAlias(); + } + + @Override + public WriteBehindProviderConfiguration build(String alias) { + return new WriteBehindProviderConfiguration(alias); + } } diff --git a/impl/src/main/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfiguration.java index 743e6c0022..76030889c9 100644 --- a/impl/src/main/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfiguration.java @@ -24,7 +24,7 @@ /** * {@link ServiceCreationConfiguration} for the default {@link LocalPersistenceService}. */ -public class DefaultPersistenceConfiguration implements ServiceCreationConfiguration { +public class DefaultPersistenceConfiguration implements ServiceCreationConfiguration { private final File rootDirectory; @@ -53,4 +53,14 @@ public File getRootDirectory() { public Class getServiceType() { return LocalPersistenceService.class; } + + @Override + public File derive() { + return getRootDirectory(); + } + + @Override + public DefaultPersistenceConfiguration build(File file) { + return new DefaultPersistenceConfiguration(file); + } } diff --git a/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfiguration.java index 96fdc78630..843514e8b6 100644 --- a/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfiguration.java @@ -52,6 +52,10 @@ public DefaultResilienceStrategyConfiguration(ResilienceStrategy instance) super(instance); } + protected DefaultResilienceStrategyConfiguration(DefaultResilienceStrategyConfiguration configuration) { + super(configuration); + } + @Override public Class getServiceType() { return ResilienceStrategyProvider.class; diff --git a/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java index 6b38ff73b6..1538bceb5e 100644 --- a/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java @@ -25,7 +25,7 @@ /** * {@link ServiceCreationConfiguration} for the default {@link ResilienceStrategyProvider}. */ -public class DefaultResilienceStrategyProviderConfiguration extends ClassInstanceProviderConfiguration implements ServiceCreationConfiguration { +public class DefaultResilienceStrategyProviderConfiguration extends ClassInstanceProviderConfiguration implements ServiceCreationConfiguration { @SuppressWarnings("rawtypes") private static final Class DEFAULT_RESILIENCE = RobustResilienceStrategy.class; @@ -35,6 +35,12 @@ public class DefaultResilienceStrategyProviderConfiguration extends ClassInstanc private DefaultResilienceStrategyConfiguration defaultRegularConfiguration; private DefaultResilienceStrategyConfiguration defaultLoaderWriterConfiguration; + private DefaultResilienceStrategyProviderConfiguration(DefaultResilienceStrategyProviderConfiguration config) { + super(config); + this.defaultRegularConfiguration = config.defaultRegularConfiguration; + this.defaultLoaderWriterConfiguration = config.defaultLoaderWriterConfiguration; + } + public DefaultResilienceStrategyProviderConfiguration() { this.defaultRegularConfiguration = new DefaultResilienceStrategyConfiguration(DEFAULT_RESILIENCE); this.defaultLoaderWriterConfiguration = new DefaultResilienceStrategyConfiguration(DEFAULT_LOADER_WRITER_RESILIENCE); @@ -154,4 +160,14 @@ public DefaultResilienceStrategyProviderConfiguration addResilienceStrategyFor(S getDefaults().put(alias, new DefaultResilienceStrategyConfiguration(resilienceStrategy)); return this; } + + @Override + public DefaultResilienceStrategyProviderConfiguration derive() { + return new DefaultResilienceStrategyProviderConfiguration(this); + } + + @Override + public DefaultResilienceStrategyProviderConfiguration build(DefaultResilienceStrategyProviderConfiguration configuration) { + return configuration; + } } diff --git a/impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfiguration.java index 184cbd963f..961ce124ca 100644 --- a/impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfiguration.java @@ -30,7 +30,7 @@ /** * {@link ServiceCreationConfiguration} for the default {@link SerializationProvider}. */ -public class DefaultSerializationProviderConfiguration implements ServiceCreationConfiguration { +public class DefaultSerializationProviderConfiguration implements ServiceCreationConfiguration { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSerializationProviderConfiguration.class); @@ -130,4 +130,14 @@ private static boolean isConstructorPresent(Class clazz, Class... args) { public Map, Class>> getDefaultSerializers() { return unmodifiableMap(defaultSerializers); } + + @Override + public DefaultSerializationProviderConfiguration derive() { + return new DefaultSerializationProviderConfiguration(this); + } + + @Override + public DefaultSerializationProviderConfiguration build(DefaultSerializationProviderConfiguration configuration) { + return configuration; + } } diff --git a/impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfiguration.java index c597a181b6..61c2161337 100644 --- a/impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfiguration.java @@ -22,7 +22,7 @@ /** * {@link ServiceCreationConfiguration} for the default {@link org.ehcache.core.spi.store.Store off heap disk store}. */ -public class OffHeapDiskStoreProviderConfiguration implements ServiceCreationConfiguration { +public class OffHeapDiskStoreProviderConfiguration implements ServiceCreationConfiguration { private final String threadPoolAlias; @@ -55,4 +55,14 @@ public String getThreadPoolAlias() { public Class getServiceType() { return OffHeapDiskStore.Provider.class; } + + @Override + public String derive() { + return getThreadPoolAlias(); + } + + @Override + public OffHeapDiskStoreProviderConfiguration build(String alias) { + return new OffHeapDiskStoreProviderConfiguration(alias); + } } diff --git a/impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineProviderConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineProviderConfiguration.java index 169acbd632..53543da5d8 100644 --- a/impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineProviderConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineProviderConfiguration.java @@ -23,7 +23,7 @@ /** * {@link ServiceCreationConfiguration} for the default {@link SizeOfEngineProvider}. */ -public class DefaultSizeOfEngineProviderConfiguration implements ServiceCreationConfiguration { +public class DefaultSizeOfEngineProviderConfiguration implements ServiceCreationConfiguration { private final long objectGraphSize; private final long maxObjectSize; @@ -89,4 +89,14 @@ public long getMaxObjectSize() { public MemoryUnit getUnit() { return this.unit; } + + @Override + public DefaultSizeOfEngineProviderConfiguration derive() { + return new DefaultSizeOfEngineProviderConfiguration(maxObjectSize, unit, objectGraphSize); + } + + @Override + public DefaultSizeOfEngineProviderConfiguration build(DefaultSizeOfEngineProviderConfiguration configuration) { + return configuration; + } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/TimeSourceConfiguration.java b/impl/src/main/java/org/ehcache/impl/internal/TimeSourceConfiguration.java index f8c6a178a7..28c400f961 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/TimeSourceConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/internal/TimeSourceConfiguration.java @@ -24,7 +24,7 @@ * * This configuration has to be applied at the {@link org.ehcache.CacheManager} level. */ -public class TimeSourceConfiguration implements ServiceCreationConfiguration { +public class TimeSourceConfiguration implements ServiceCreationConfiguration { private final TimeSource timeSource; @@ -51,4 +51,13 @@ public TimeSource getTimeSource() { return this.timeSource; } + @Override + public TimeSource derive() { + return getTimeSource(); + } + + @Override + public TimeSourceConfiguration build(TimeSource timeSource) { + return new TimeSourceConfiguration(timeSource); + } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java b/impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java index 1efd9becf4..4e5523c33a 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java @@ -27,7 +27,7 @@ @Component public class TimeSourceServiceFactory implements ServiceFactory { @Override - public TimeSourceService create(ServiceCreationConfiguration configuration) { + public TimeSourceService create(ServiceCreationConfiguration configuration) { return new DefaultTimeSourceService((TimeSourceConfiguration) configuration); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceConfiguration.java b/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceConfiguration.java index e7cea1f690..5ebcc3355a 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceConfiguration.java @@ -43,6 +43,16 @@ public ClassInstanceConfiguration(T instance) { this.arguments = null; } + protected ClassInstanceConfiguration(ClassInstanceConfiguration configuration) { + this.instance = configuration.getInstance(); + this.clazz = configuration.getClazz(); + if (instance == null) { + this.arguments = asList(configuration.getArguments()); + } else { + this.arguments = null; + } + } + public Class getClazz() { return clazz; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfiguration.java b/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfiguration.java index fc53901160..cd102c7dc9 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfiguration.java @@ -16,8 +16,6 @@ package org.ehcache.impl.internal.classes; -import org.ehcache.impl.internal.classes.ClassInstanceConfiguration; - import java.util.LinkedHashMap; import java.util.Map; @@ -29,7 +27,15 @@ */ public class ClassInstanceProviderConfiguration> { - private final Map defaults = new LinkedHashMap<>(); + private final Map defaults; + + public ClassInstanceProviderConfiguration() { + this.defaults = new LinkedHashMap<>(); + } + + public ClassInstanceProviderConfiguration(ClassInstanceProviderConfiguration config) { + this.defaults = new LinkedHashMap<>(config.getDefaults()); + } public Map getDefaults() { return defaults; diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/CacheEventNotificationListenerServiceProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/events/CacheEventNotificationListenerServiceProviderFactory.java index 9b3c58db51..5c16d68427 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/events/CacheEventNotificationListenerServiceProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/events/CacheEventNotificationListenerServiceProviderFactory.java @@ -25,7 +25,7 @@ public class CacheEventNotificationListenerServiceProviderFactory implements ServiceFactory { @Override - public CacheEventDispatcherFactory create(ServiceCreationConfiguration configuration) { + public CacheEventDispatcherFactory create(ServiceCreationConfiguration configuration) { if (configuration == null) { return new CacheEventDispatcherFactoryImpl(); } else if (configuration instanceof CacheEventDispatcherFactoryConfiguration) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java b/impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java index f3fb706a92..bb7ca8f6fb 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java @@ -29,7 +29,7 @@ public class DefaultExecutionServiceFactory implements ServiceFactory { @Override - public ExecutionService create(ServiceCreationConfiguration configuration) { + public ExecutionService create(ServiceCreationConfiguration configuration) { if (configuration == null) { return new OnDemandExecutionService(); } else if (configuration instanceof PooledExecutionServiceConfiguration) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java index f4cfd3f303..e60815f3e4 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java @@ -35,7 +35,7 @@ public class WriteBehindProviderFactory implements ServiceFactory { @Override - public WriteBehindProvider create(ServiceCreationConfiguration configuration) { + public WriteBehindProvider create(ServiceCreationConfiguration configuration) { if (configuration == null) { return new Provider(); } else if (configuration instanceof WriteBehindProviderConfiguration) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java b/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java index 7630656387..222706b55b 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java @@ -25,7 +25,7 @@ public class DefaultDiskResourceServiceFactory implements ServiceFactory { @Override - public DefaultDiskResourceService create(final ServiceCreationConfiguration serviceConfiguration) { + public DefaultDiskResourceService create(final ServiceCreationConfiguration serviceConfiguration) { return new DefaultDiskResourceService(); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java b/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java index 5bcf93a490..2b3082fe82 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java @@ -31,7 +31,7 @@ public class DefaultLocalPersistenceServiceFactory implements ServiceFactory { @Override - public DefaultLocalPersistenceService create(final ServiceCreationConfiguration serviceConfiguration) { + public DefaultLocalPersistenceService create(final ServiceCreationConfiguration serviceConfiguration) { return new DefaultLocalPersistenceService((DefaultPersistenceConfiguration) serviceConfiguration); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java index b1a1043d11..1cb0d1d1bc 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java @@ -31,7 +31,7 @@ public class DefaultSizeOfEngineProviderFactory implements ServiceFactory { @Override - public SizeOfEngineProvider create(ServiceCreationConfiguration configuration) { + public SizeOfEngineProvider create(ServiceCreationConfiguration configuration) { long maxTraversals = DefaultSizeOfEngineConfiguration.DEFAULT_OBJECT_GRAPH_SIZE; long maxSize = DefaultSizeOfEngineConfiguration.DEFAULT_MAX_OBJECT_SIZE; if(configuration != null) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java index a1efec10e4..8e6be51e45 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java @@ -29,7 +29,7 @@ public class DefaultCopyProviderFactory implements ServiceFactory { @Override - public CopyProvider create(final ServiceCreationConfiguration configuration) { + public CopyProvider create(final ServiceCreationConfiguration configuration) { if (configuration != null && !(configuration instanceof DefaultCopyProviderConfiguration)) { throw new IllegalArgumentException("Expected a configuration of type DefaultCopyProviderConfiguration but got " + configuration.getClass().getSimpleName()); diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java index e16d07e6c1..eaef9911a2 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java @@ -28,7 +28,7 @@ public class DefaultCacheEventListenerProviderFactory implements ServiceFactory { @Override - public DefaultCacheEventListenerProvider create(ServiceCreationConfiguration configuration) { + public DefaultCacheEventListenerProvider create(ServiceCreationConfiguration configuration) { return new DefaultCacheEventListenerProvider(); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java index 8c5591ad6f..b420322cc1 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java @@ -29,7 +29,7 @@ public class DefaultCacheLoaderWriterProviderFactory implements ServiceFactory { @Override - public DefaultCacheLoaderWriterProvider create(ServiceCreationConfiguration configuration) { + public DefaultCacheLoaderWriterProvider create(ServiceCreationConfiguration configuration) { if (configuration != null && !(configuration instanceof DefaultCacheLoaderWriterProviderConfiguration)) { throw new IllegalArgumentException("Expected a configuration of type DefaultCacheLoaderWriterProviderConfiguration but got " + configuration .getClass() diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java index 5248a34014..a53b27f5bf 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java @@ -24,7 +24,7 @@ @Component public class DefaultResilienceStrategyProviderFactory implements ServiceFactory { @Override - public ResilienceStrategyProvider create(ServiceCreationConfiguration configuration) { + public ResilienceStrategyProvider create(ServiceCreationConfiguration configuration) { if (configuration == null) { return new DefaultResilienceStrategyProvider(); } else if (configuration instanceof DefaultResilienceStrategyProviderConfiguration) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java index b1f75c8280..fc1a3cd499 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java @@ -29,7 +29,7 @@ public class DefaultSerializationProviderFactory implements ServiceFactory { @Override - public DefaultSerializationProvider create(ServiceCreationConfiguration configuration) { + public DefaultSerializationProvider create(ServiceCreationConfiguration configuration) { if (configuration != null && !(configuration instanceof DefaultSerializationProviderConfiguration)) { throw new IllegalArgumentException("Expected a configuration of type DefaultSerializationProviderConfiguration but got " + configuration .getClass() diff --git a/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceFactory.java b/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceFactory.java index 182fed5666..ba2a2ecff4 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceFactory.java @@ -25,7 +25,7 @@ public class DefaultStatisticsServiceFactory implements ServiceFactory { @Override - public StatisticsService create(ServiceCreationConfiguration serviceConfiguration) { + public StatisticsService create(ServiceCreationConfiguration serviceConfiguration) { return new DefaultStatisticsService(); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java index 6a81d69be9..9172596cfb 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java @@ -28,7 +28,7 @@ public class OffHeapDiskStoreProviderFactory implements ServiceFactory { @Override - public OffHeapDiskStore.Provider create(ServiceCreationConfiguration configuration) { + public OffHeapDiskStore.Provider create(ServiceCreationConfiguration configuration) { if (configuration == null) { return new OffHeapDiskStore.Provider(); } else if (configuration instanceof OffHeapDiskStoreProviderConfiguration) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java index d0b4ff9edd..3a6229396e 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java @@ -27,7 +27,7 @@ public class OnHeapStoreProviderFactory implements ServiceFactory { @Override - public OnHeapStore.Provider create(ServiceCreationConfiguration configuration) { + public OnHeapStore.Provider create(ServiceCreationConfiguration configuration) { return new OnHeapStore.Provider(); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProviderFactory.java index 7330837d0a..2a5137b9b1 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProviderFactory.java @@ -22,7 +22,7 @@ @Component public class LoaderWriterStoreProviderFactory implements ServiceFactory { @Override - public LoaderWriterStoreProvider create(ServiceCreationConfiguration configuration) { + public LoaderWriterStoreProvider create(ServiceCreationConfiguration configuration) { return new LoaderWriterStoreProvider(); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java index a7df475f21..800c82a35b 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java @@ -27,7 +27,7 @@ public class OffHeapStoreProviderFactory implements ServiceFactory { @Override - public OffHeapStore.Provider create(ServiceCreationConfiguration configuration) { + public OffHeapStore.Provider create(ServiceCreationConfiguration configuration) { return new OffHeapStore.Provider(); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java index 55ef0ec1a1..b7e33273ec 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java @@ -25,7 +25,7 @@ @Component public class CompoundCachingTierProviderFactory implements ServiceFactory { @Override - public CompoundCachingTier.Provider create(ServiceCreationConfiguration serviceConfiguration) { + public CompoundCachingTier.Provider create(ServiceCreationConfiguration serviceConfiguration) { return new CompoundCachingTier.Provider(); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java index 85ffcf22b4..e009aac754 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java @@ -27,7 +27,7 @@ public class TieredStoreProviderFactory implements ServiceFactory { @Override - public TieredStore.Provider create(ServiceCreationConfiguration configuration) { + public TieredStore.Provider create(ServiceCreationConfiguration configuration) { return new TieredStore.Provider(); } diff --git a/impl/src/test/java/org/ehcache/config/builders/CacheManagerBuilderTest.java b/impl/src/test/java/org/ehcache/config/builders/CacheManagerBuilderTest.java index 828d472853..bcdf46f2ab 100644 --- a/impl/src/test/java/org/ehcache/config/builders/CacheManagerBuilderTest.java +++ b/impl/src/test/java/org/ehcache/config/builders/CacheManagerBuilderTest.java @@ -76,31 +76,41 @@ public void testCanOverrideSerializerConfig() { assertThat(managerBuilder.withSerializer(String.class, serializer2)).isNotNull(); } - @Test(expected = IllegalArgumentException.class) - public void testDuplicateServiceCreationConfigurationFails() { - newCacheManagerBuilder().using(new DefaultCopyProviderConfiguration()) - .using(new DefaultCopyProviderConfiguration()); + @Test + public void testDuplicateServiceCreationConfigurationOk() { + DefaultCopyProviderConfiguration configOne = new DefaultCopyProviderConfiguration(); + DefaultCopyProviderConfiguration configTwo = new DefaultCopyProviderConfiguration(); + CacheManagerBuilder builder = newCacheManagerBuilder() + .using(configOne) + .using(configTwo); + + assertThat(builder.build().getRuntimeConfiguration().getServiceCreationConfigurations()).contains(configTwo).doesNotContain(configOne); } - @Test + @Test @SuppressWarnings("deprecation") public void testDuplicateServiceCreationConfigurationOkWhenExplicit() { - assertThat(newCacheManagerBuilder().using(new DefaultCopyProviderConfiguration()) - .replacing(new DefaultCopyProviderConfiguration())).isNotNull(); + CacheManagerBuilder builder = newCacheManagerBuilder().using(new DefaultCopyProviderConfiguration()) + .replacing(new DefaultCopyProviderConfiguration()); + + assertThat(builder.build()).isNotNull(); } @Test public void testShouldNotBeAllowedToRegisterTwoCachesWithSameAlias() { - String cacheAlias = "cacheAliasSameName"; + String cacheAlias = "alias"; + + CacheConfiguration configOne = CacheConfigurationBuilder + .newCacheConfigurationBuilder(Integer.class, String.class, ResourcePoolsBuilder.heap(10)) + .build(); - CacheConfiguration cacheConfig = CacheConfigurationBuilder + CacheConfiguration configTwo = CacheConfigurationBuilder .newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10)) .build(); - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Cache alias 'cacheAliasSameName' already exists"); + CacheManager build = newCacheManagerBuilder() + .withCache(cacheAlias, configOne) + .withCache(cacheAlias, configTwo).build(); - CacheManagerBuilder.newCacheManagerBuilder() - .withCache(cacheAlias, cacheConfig) - .withCache(cacheAlias, cacheConfig); + assertThat(build.getRuntimeConfiguration().getCacheConfigurations().get(cacheAlias).getKeyType()).isEqualTo(Long.class); } } diff --git a/impl/src/test/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfigurationTest.java new file mode 100644 index 0000000000..2fa864af79 --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfigurationTest.java @@ -0,0 +1,39 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.config.copy; + +import org.ehcache.impl.copy.IdentityCopier; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; + +public class DefaultCopyProviderConfigurationTest { + + @Test @SuppressWarnings({"unchecked", "rawtypes"}) + public void testDerivedConfigurationDetachesCorrectly() { + DefaultCopyProviderConfiguration configuration = new DefaultCopyProviderConfiguration(); + configuration.addCopierFor(String.class, (Class) IdentityCopier.class); + + DefaultCopyProviderConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getDefaults().get(String.class).getClazz(), sameInstance(IdentityCopier.class)); + } +} diff --git a/impl/src/test/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfigurationTest.java new file mode 100644 index 0000000000..c4a4aa2608 --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfigurationTest.java @@ -0,0 +1,36 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.config.event; + +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; + +public class CacheEventDispatcherFactoryConfigurationTest { + + @Test + public void testDeriveDetachesCorrectly() { + CacheEventDispatcherFactoryConfiguration configuration = new CacheEventDispatcherFactoryConfiguration("foobar"); + CacheEventDispatcherFactoryConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getThreadPoolAlias(), is(configuration.getThreadPoolAlias())); + } +} diff --git a/impl/src/test/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfigurationTest.java new file mode 100644 index 0000000000..0ebf3c9f0b --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfigurationTest.java @@ -0,0 +1,37 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.config.executor; + +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; + +public class PooledExecutionServiceConfigurationTest { + + @Test + public void testDeriveDetachesCorrectly() { + PooledExecutionServiceConfiguration configuration = new PooledExecutionServiceConfiguration(); + configuration.addPool("foo", 1, 2); + + PooledExecutionServiceConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + } +} diff --git a/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfigurationTest.java new file mode 100644 index 0000000000..0f6c2e4d69 --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfigurationTest.java @@ -0,0 +1,41 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.config.loaderwriter; + +import org.ehcache.spi.loaderwriter.CacheLoaderWriter; +import org.junit.Test; + +import static org.ehcache.test.MockitoUtil.mock; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; + +public class DefaultCacheLoaderWriterProviderConfigurationTest { + + @Test @SuppressWarnings("unchecked") + public void testDeriveDetachesCorrectly() { + DefaultCacheLoaderWriterProviderConfiguration configuration = new DefaultCacheLoaderWriterProviderConfiguration(); + configuration.addLoaderFor("foo", (Class>) mock(CacheLoaderWriter.class).getClass()); + + DefaultCacheLoaderWriterProviderConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getDefaults(), is(not(sameInstance(configuration.getDefaults())))); + assertThat(derived.getDefaults(), is(configuration.getDefaults())); + } +} diff --git a/impl/src/test/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfigurationTest.java new file mode 100644 index 0000000000..3acf766d2b --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfigurationTest.java @@ -0,0 +1,36 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.config.loaderwriter.writebehind; + +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; + +public class WriteBehindProviderConfigurationTest { + + @Test + public void testDeriveDetachesCorrectly() { + WriteBehindProviderConfiguration configuration = new WriteBehindProviderConfiguration("foobar"); + WriteBehindProviderConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getThreadPoolAlias(), is(configuration.getThreadPoolAlias())); + } +} diff --git a/impl/src/test/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfigurationTest.java new file mode 100644 index 0000000000..1ac0882491 --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfigurationTest.java @@ -0,0 +1,38 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.config.persistence; + +import org.junit.Test; + +import java.io.File; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; + +public class DefaultPersistenceConfigurationTest { + + @Test + public void testDeriveDetachesCorrectly() { + DefaultPersistenceConfiguration configuration = new DefaultPersistenceConfiguration(new File("foo")); + DefaultPersistenceConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getRootDirectory(), is(configuration.getRootDirectory())); + } +} diff --git a/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java index 142b7b5116..2cf35fee69 100644 --- a/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java @@ -32,13 +32,13 @@ public class DefaultResilienceStrategyConfigurationTest { @Test public void testBindOnInstanceConfigurationReturnsSelf() { - DefaultResilienceStrategyConfiguration configuration = new DefaultResilienceStrategyConfiguration(mock(ResilienceStrategy.class)); + DefaultResilienceStrategyConfiguration configuration = new DefaultResilienceStrategyConfiguration((ResilienceStrategy) mock(ResilienceStrategy.class)); assertThat(configuration.bind(null), sameInstance(configuration)); } @Test public void testLoaderWriterBindOnInstanceConfigurationReturnsSelf() { - DefaultResilienceStrategyConfiguration configuration = new DefaultResilienceStrategyConfiguration(mock(ResilienceStrategy.class)); + DefaultResilienceStrategyConfiguration configuration = new DefaultResilienceStrategyConfiguration((ResilienceStrategy) mock(ResilienceStrategy.class)); assertThat(configuration.bind(null, null), sameInstance(configuration)); } diff --git a/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfigurationTest.java new file mode 100644 index 0000000000..ddefe0f673 --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfigurationTest.java @@ -0,0 +1,45 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.config.resilience; + +import org.ehcache.spi.resilience.ResilienceStrategy; +import org.junit.Test; + +import static org.ehcache.test.MockitoUtil.mock; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; + +public class DefaultResilienceStrategyProviderConfigurationTest { + + @Test + public void testDeriveDetachesCorrectly() { + DefaultResilienceStrategyProviderConfiguration configuration = new DefaultResilienceStrategyProviderConfiguration(); + configuration.setDefaultResilienceStrategy(mock(ResilienceStrategy.class)); + configuration.setDefaultLoaderWriterResilienceStrategy(mock(ResilienceStrategy.class)); + configuration.addResilienceStrategyFor("foo", mock(ResilienceStrategy.class)); + + DefaultResilienceStrategyProviderConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getDefaultConfiguration(), is(configuration.getDefaultConfiguration())); + assertThat(derived.getDefaultLoaderWriterConfiguration(), is(configuration.getDefaultLoaderWriterConfiguration())); + assertThat(derived.getDefaults(), is(not(sameInstance(configuration.getDefaults())))); + assertThat(derived.getDefaults(), is(configuration.getDefaults())); + } +} diff --git a/impl/src/test/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfigurationTest.java index c4cbb3ae98..523f98ca2f 100644 --- a/impl/src/test/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfigurationTest.java @@ -16,6 +16,7 @@ package org.ehcache.impl.config.serializer; +import org.ehcache.impl.serialization.JavaSerializer; import org.ehcache.spi.persistence.StateRepository; import org.ehcache.spi.serialization.SerializerException; import org.ehcache.spi.serialization.Serializer; @@ -27,6 +28,9 @@ import java.nio.ByteBuffer; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; import static org.junit.Assert.*; public class DefaultSerializationProviderConfigurationTest { @@ -82,6 +86,18 @@ public void testAddSerializerForLegacySerializer() throws Exception { config.addSerializerFor(Long.class, LegacySerializer.class); } + @Test @SuppressWarnings("unchecked") + public void testDeriveDetachesCorrectly() { + DefaultSerializationProviderConfiguration configuration = new DefaultSerializationProviderConfiguration(); + configuration.addSerializerFor(String.class, (Class) JavaSerializer.class); + + DefaultSerializationProviderConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getDefaultSerializers(), is(not(sameInstance(configuration.getDefaultSerializers())))); + assertThat(derived.getDefaultSerializers().get(String.class), sameInstance(JavaSerializer.class)); + } + private static class MinimalSerializer implements Serializer { public MinimalSerializer(ClassLoader loader) { diff --git a/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfigurationTest.java new file mode 100644 index 0000000000..af0ac2fffb --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfigurationTest.java @@ -0,0 +1,36 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.config.store.disk; + +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; + +public class OffHeapDiskStoreProviderConfigurationTest { + + @Test + public void testDeriveDetachesCorrectly() { + OffHeapDiskStoreProviderConfiguration configuration = new OffHeapDiskStoreProviderConfiguration("foobar"); + OffHeapDiskStoreProviderConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getThreadPoolAlias(), is(configuration.getThreadPoolAlias())); + } +} diff --git a/impl/src/test/java/org/ehcache/impl/internal/TimeSourceConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/internal/TimeSourceConfigurationTest.java new file mode 100644 index 0000000000..8f71faa7a6 --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/internal/TimeSourceConfigurationTest.java @@ -0,0 +1,38 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.internal; + +import org.ehcache.core.spi.time.TimeSource; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +public class TimeSourceConfigurationTest { + + @Test + public void testDeriveDetachesCorrectly() { + TimeSourceConfiguration configuration = new TimeSourceConfiguration(mock(TimeSource.class)); + TimeSourceConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getTimeSource(), sameInstance(configuration.getTimeSource())); + } +} diff --git a/impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderConfigurationTest.java index ef6807946b..4d5a3b4cfb 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderConfigurationTest.java @@ -22,12 +22,15 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; import static org.junit.Assert.fail; + /** * @author Abhilash * */ - public class DefaultSizeOfEngineProviderConfigurationTest { @Test @@ -59,4 +62,16 @@ public void testValidArguments() { assertThat(configuration.getMaxObjectSize(), equalTo(10l)); assertThat(configuration.getUnit(), equalTo(MemoryUnit.B)); } + + @Test + public void testDeriveDetachesCorrectly() { + DefaultSizeOfEngineProviderConfiguration configuration = new DefaultSizeOfEngineProviderConfiguration(42L, MemoryUnit.B, 100L); + + DefaultSizeOfEngineProviderConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getMaxObjectGraphSize(), is(configuration.getMaxObjectGraphSize())); + assertThat(derived.getMaxObjectSize(), is(configuration.getMaxObjectSize())); + assertThat(derived.getUnit(), is(configuration.getUnit())); + } } diff --git a/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java b/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java index 9110cb6317..7772f1e9de 100644 --- a/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java @@ -81,8 +81,8 @@ private void createCacheManager(CacheManagerBuilder builder) { private void createNotAtomicCacheManager() throws IOException { Configuration config = ConfigurationBuilder.newConfigurationBuilder() - .addService(new TimeSourceConfiguration(timeSource)) - .addService(new DefaultPersistenceConfiguration(diskPath.newFolder())) + .withService(new TimeSourceConfiguration(timeSource)) + .withService(new DefaultPersistenceConfiguration(diskPath.newFolder())) .build(); Collection services = Collections.singleton(statisticsService); diff --git a/management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java b/management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java index 490fb78f59..a17532326f 100644 --- a/management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java +++ b/management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java @@ -24,7 +24,7 @@ /** * Configuration interface for a {@link ManagementRegistryService}. */ -public interface ManagementRegistryServiceConfiguration extends ServiceCreationConfiguration { +public interface ManagementRegistryServiceConfiguration extends ServiceCreationConfiguration { /** * The context used to identify this cache manager diff --git a/management/src/main/java/org/ehcache/management/cluster/Clustering.java b/management/src/main/java/org/ehcache/management/cluster/Clustering.java index 4b35df0642..d441141ad2 100644 --- a/management/src/main/java/org/ehcache/management/cluster/Clustering.java +++ b/management/src/main/java/org/ehcache/management/cluster/Clustering.java @@ -46,7 +46,7 @@ public static boolean isAvailable(ServiceProvider serviceProvider) { /** * Creates a new ${@link ClusteringManagementService} to handle the management integration with the cluster */ - public static ClusteringManagementService newClusteringManagementService(ClusteringManagementServiceConfiguration configuration) { + public static ClusteringManagementService newClusteringManagementService(ClusteringManagementServiceConfiguration configuration) { return new DefaultClusteringManagementService(configuration); } diff --git a/management/src/main/java/org/ehcache/management/cluster/ClusteringManagementServiceConfiguration.java b/management/src/main/java/org/ehcache/management/cluster/ClusteringManagementServiceConfiguration.java index a20d72cde9..a18ab82e93 100644 --- a/management/src/main/java/org/ehcache/management/cluster/ClusteringManagementServiceConfiguration.java +++ b/management/src/main/java/org/ehcache/management/cluster/ClusteringManagementServiceConfiguration.java @@ -20,7 +20,7 @@ /** * Configuration interface for a {@link ClusteringManagementService}. */ -public interface ClusteringManagementServiceConfiguration extends ServiceCreationConfiguration { +public interface ClusteringManagementServiceConfiguration extends ServiceCreationConfiguration { /** * @return The alias of the executor used to run management call queries. diff --git a/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java b/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java index d35b1a1642..9b4661962c 100644 --- a/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java +++ b/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java @@ -49,7 +49,7 @@ @ServiceDependencies({CacheManagerProviderService.class, ExecutionService.class, TimeSourceService.class, ManagementRegistryService.class, EntityService.class, ClusteringService.class}) public class DefaultClusteringManagementService implements ClusteringManagementService, CacheManagerListener, CollectorService.Collector { - private final ClusteringManagementServiceConfiguration configuration; + private final ClusteringManagementServiceConfiguration configuration; private volatile ManagementRegistryService managementRegistryService; private volatile CollectorService collectorService; @@ -63,7 +63,7 @@ public DefaultClusteringManagementService() { this(new DefaultClusteringManagementServiceConfiguration()); } - public DefaultClusteringManagementService(ClusteringManagementServiceConfiguration configuration) { + public DefaultClusteringManagementService(ClusteringManagementServiceConfiguration configuration) { this.configuration = configuration == null ? new DefaultClusteringManagementServiceConfiguration() : configuration; } diff --git a/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementServiceConfiguration.java b/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementServiceConfiguration.java index 95c460f4b1..e502abcfeb 100644 --- a/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementServiceConfiguration.java +++ b/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementServiceConfiguration.java @@ -15,7 +15,7 @@ */ package org.ehcache.management.cluster; -public class DefaultClusteringManagementServiceConfiguration implements ClusteringManagementServiceConfiguration { +public class DefaultClusteringManagementServiceConfiguration implements ClusteringManagementServiceConfiguration { private String managementCallExecutorAlias = "managementCallExecutor"; private int managementCallQueueSize = 1024; diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryFactory.java b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryFactory.java index 287e2595cb..81256a7c2f 100644 --- a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryFactory.java +++ b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryFactory.java @@ -23,7 +23,7 @@ public class DefaultManagementRegistryFactory implements ServiceFactory { @Override - public ManagementRegistryService create(ServiceCreationConfiguration configuration) { + public ManagementRegistryService create(ServiceCreationConfiguration configuration) { return configuration instanceof ManagementRegistryServiceConfiguration ? new DefaultManagementRegistryService((ManagementRegistryServiceConfiguration) configuration) : new DefaultManagementRegistryService(new DefaultManagementRegistryConfiguration()); diff --git a/management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java b/management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java index 336c63f178..d83c5bc5f6 100644 --- a/management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java +++ b/management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java @@ -53,7 +53,7 @@ public URI getNamespace() { } @Override - public ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment, ClassLoader classLoader) { + public ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment, ClassLoader classLoader) { if ("management".equals(fragment.getLocalName())) { DefaultManagementRegistryConfiguration registryConfiguration = new DefaultManagementRegistryConfiguration(); @@ -102,7 +102,7 @@ public Class getServiceType() { } @Override - public Element unparseServiceCreationConfiguration(ServiceCreationConfiguration serviceCreationConfiguration) { + public Element unparseServiceCreationConfiguration(ServiceCreationConfiguration serviceCreationConfiguration) { return unparseConfig(serviceCreationConfiguration); } diff --git a/management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java b/management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java index ee6bd99abb..e2e97e3a7a 100644 --- a/management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java +++ b/management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java @@ -85,7 +85,7 @@ public void test_config_loaded() throws Exception { try { DefaultManagementRegistryConfiguration registryConfiguration = null; - for (ServiceCreationConfiguration configuration : myCacheManager.getRuntimeConfiguration().getServiceCreationConfigurations()) { + for (ServiceCreationConfiguration configuration : myCacheManager.getRuntimeConfiguration().getServiceCreationConfigurations()) { if (configuration instanceof DefaultManagementRegistryConfiguration) { registryConfiguration = (DefaultManagementRegistryConfiguration) configuration; break; diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java index b405504892..42d2eaf1f9 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java @@ -27,7 +27,7 @@ @Component public class XAStoreProviderFactory implements ServiceFactory { @Override - public XAStore.Provider create(ServiceCreationConfiguration configuration) { + public XAStore.Provider create(ServiceCreationConfiguration configuration) { return new XAStore.Provider(); } diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java index a0c8ef818d..1371fe0cf7 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java @@ -27,7 +27,7 @@ public class DefaultJournalProviderFactory implements ServiceFactory { @Override - public JournalProvider create(ServiceCreationConfiguration configuration) { + public JournalProvider create(ServiceCreationConfiguration configuration) { return new DefaultJournalProvider(); } diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java index 71db33048a..27176ae91d 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java @@ -36,7 +36,7 @@ public class DefaultTransactionManagerProviderFactory implements ServiceFactory< * {@inheritDoc} */ @Override - public TransactionManagerProvider create(ServiceCreationConfiguration configuration) { + public TransactionManagerProvider create(ServiceCreationConfiguration configuration) { return new LookupTransactionManagerProvider((LookupTransactionManagerProviderConfiguration) configuration); } diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java index 5f282685e6..d412299de9 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java @@ -59,7 +59,7 @@ public URI getNamespace() { } @Override - public ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment, ClassLoader classLoader) { + public ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment, ClassLoader classLoader) { String localName = fragment.getLocalName(); if ("jta-tm".equals(localName)) { String transactionManagerProviderConfigurationClassName = fragment.getAttribute("transaction-manager-lookup-class"); @@ -86,7 +86,7 @@ public Class getServiceType() { } @Override - public Element unparseServiceCreationConfiguration(ServiceCreationConfiguration serviceCreationConfiguration) { + public Element unparseServiceCreationConfiguration(ServiceCreationConfiguration serviceCreationConfiguration) { return unparseConfig(serviceCreationConfiguration); } diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfiguration.java b/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfiguration.java index 78bb33f3cc..3a6935512e 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfiguration.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfiguration.java @@ -23,7 +23,7 @@ /** * Specialized {@link ServiceCreationConfiguration} for the {@link LookupTransactionManagerProvider}. */ -public class LookupTransactionManagerProviderConfiguration implements ServiceCreationConfiguration { +public class LookupTransactionManagerProviderConfiguration implements ServiceCreationConfiguration> { private final Class lookupClass; @@ -48,4 +48,14 @@ public Class getTransactionManagerLookup() { public Class getServiceType() { return TransactionManagerProvider.class; } + + @Override + public Class derive() { + return getTransactionManagerLookup(); + } + + @Override + public LookupTransactionManagerProviderConfiguration build(Class clazz) { + return new LookupTransactionManagerProviderConfiguration(clazz); + } } diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfigurationTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfigurationTest.java new file mode 100644 index 0000000000..f5425eedad --- /dev/null +++ b/transactions/src/test/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfigurationTest.java @@ -0,0 +1,37 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.transactions.xa.txmgr.provider; + +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +public class LookupTransactionManagerProviderConfigurationTest { + + @Test + public void testDeriveDetachesCorrectly() { + LookupTransactionManagerProviderConfiguration configuration = new LookupTransactionManagerProviderConfiguration(mock(TransactionManagerLookup.class).getClass()); + LookupTransactionManagerProviderConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getTransactionManagerLookup(), sameInstance(configuration.getTransactionManagerLookup())); + } +} diff --git a/xml/src/main/java/org/ehcache/xml/CacheManagerServiceConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/CacheManagerServiceConfigurationParser.java index b5e9180c53..d62e79f5fe 100644 --- a/xml/src/main/java/org/ehcache/xml/CacheManagerServiceConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/CacheManagerServiceConfigurationParser.java @@ -33,9 +33,9 @@ public interface CacheManagerServiceConfigurationParser { URI getNamespace(); - ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment, ClassLoader classLoader); + ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment, ClassLoader classLoader); Class getServiceType(); - Element unparseServiceCreationConfiguration(ServiceCreationConfiguration serviceCreationConfiguration); + Element unparseServiceCreationConfiguration(ServiceCreationConfiguration serviceCreationConfiguration); } diff --git a/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java index c68f1eb6e3..3f9b462af3 100644 --- a/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java @@ -18,9 +18,9 @@ import org.ehcache.config.CacheConfiguration; import org.ehcache.config.Configuration; +import org.ehcache.config.FluentConfigurationBuilder; import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.CacheConfigurationBuilder; -import org.ehcache.config.builders.ConfigurationBuilder; import org.ehcache.core.util.ClassLoading; import org.ehcache.xml.exceptions.XmlConfigurationException; import org.ehcache.xml.model.BaseCacheType; @@ -50,7 +50,10 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; @@ -292,12 +295,12 @@ public XmlConfigurationWrapper documentToConfig(Document document, ClassLoader c Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); ConfigType jaxbModel = unmarshaller.unmarshal(document, configTypeClass).getValue(); - ConfigurationBuilder managerBuilder = newConfigurationBuilder().withClassLoader(classLoader); + FluentConfigurationBuilder managerBuilder = newConfigurationBuilder().withClassLoader(classLoader); managerBuilder = serviceCreationConfigurationParser.parseServiceCreationConfiguration(jaxbModel, classLoader, managerBuilder); for (CacheDefinition cacheDefinition : getCacheElements(jaxbModel)) { String alias = cacheDefinition.id(); - if(managerBuilder.containsCache(alias)) { + if(managerBuilder.getCache(alias) != null) { throw new XmlConfigurationException("Two caches defined with the same alias: " + alias); } @@ -323,7 +326,7 @@ public XmlConfigurationWrapper documentToConfig(Document document, ClassLoader c } cacheBuilder = parseServiceConfigurations(cacheBuilder, cacheClassLoader, cacheDefinition); - managerBuilder = managerBuilder.addCache(alias, cacheBuilder.build()); + managerBuilder = managerBuilder.withCache(alias, cacheBuilder.build()); } Map templates = getTemplates(jaxbModel); @@ -399,11 +402,20 @@ public Map getTemplates() { public static String documentToText(Document xml) throws IOException, TransformerException { try (StringWriter writer = new StringWriter()) { - TRANSFORMER_FACTORY.newTransformer().transform(new DOMSource(xml), new StreamResult(writer)); + transformer().transform(new DOMSource(xml), new StreamResult(writer)); return writer.toString(); } } + private static Transformer transformer() throws TransformerConfigurationException { + Transformer transformer = TRANSFORMER_FACTORY.newTransformer(); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); + transformer.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name()); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + return transformer; + } + public static String urlToText(URL url, String encoding) throws IOException { Charset charset = encoding == null ? StandardCharsets.UTF_8 : Charset.forName(encoding); try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), charset))) { diff --git a/xml/src/main/java/org/ehcache/xml/CoreServiceCreationConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/CoreServiceCreationConfigurationParser.java index 998c3fd01b..a5d951d8b3 100644 --- a/xml/src/main/java/org/ehcache/xml/CoreServiceCreationConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/CoreServiceCreationConfigurationParser.java @@ -17,13 +17,12 @@ package org.ehcache.xml; import org.ehcache.config.Configuration; -import org.ehcache.config.builders.ConfigurationBuilder; +import org.ehcache.config.FluentConfigurationBuilder; import org.ehcache.xml.model.ConfigType; public interface CoreServiceCreationConfigurationParser { - ConfigurationBuilder parseServiceCreationConfiguration(ConfigType root, ClassLoader classLoader, ConfigurationBuilder builder) throws ClassNotFoundException; - + FluentConfigurationBuilder parseServiceCreationConfiguration(ConfigType root, ClassLoader classLoader, FluentConfigurationBuilder builder) throws ClassNotFoundException; ConfigType unparseServiceCreationConfiguration(Configuration configuration, ConfigType root); } diff --git a/xml/src/main/java/org/ehcache/xml/ServiceCreationConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/ServiceCreationConfigurationParser.java index 944da7e4cf..adc4050533 100644 --- a/xml/src/main/java/org/ehcache/xml/ServiceCreationConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/ServiceCreationConfigurationParser.java @@ -17,7 +17,7 @@ package org.ehcache.xml; import org.ehcache.config.Configuration; -import org.ehcache.config.builders.ConfigurationBuilder; +import org.ehcache.config.FluentConfigurationBuilder; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.xml.model.ConfigType; import org.ehcache.xml.model.ServiceType; @@ -59,7 +59,7 @@ public ServiceCreationConfigurationParser(Map, CacheManagerServiceConfi this.extensionParsers = extensionParsers; } - ConfigurationBuilder parseServiceCreationConfiguration(ConfigType configRoot, ClassLoader classLoader, ConfigurationBuilder managerBuilder) throws ClassNotFoundException { + FluentConfigurationBuilder parseServiceCreationConfiguration(ConfigType configRoot, ClassLoader classLoader, FluentConfigurationBuilder managerBuilder) throws ClassNotFoundException { for (CoreServiceCreationConfigurationParser parser : CORE_SERVICE_CREATION_CONFIGURATION_PARSERS) { managerBuilder = parser.parseServiceCreationConfiguration(configRoot, classLoader, managerBuilder); } @@ -73,8 +73,8 @@ ConfigurationBuilder parseServiceCreationConfiguration(ConfigType configRoot, Cl if(cacheManagerServiceConfigurationParser == null) { throw new IllegalArgumentException("Can't find parser for namespace: " + namespace); } - ServiceCreationConfiguration serviceConfiguration = cacheManagerServiceConfigurationParser.parseServiceCreationConfiguration(element, classLoader); - managerBuilder = managerBuilder.addService(serviceConfiguration); + ServiceCreationConfiguration serviceConfiguration = cacheManagerServiceConfigurationParser.parseServiceCreationConfiguration(element, classLoader); + managerBuilder = managerBuilder.withService(serviceConfiguration); } return managerBuilder; diff --git a/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java b/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java index 7feac9be08..199c3c0177 100644 --- a/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java +++ b/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java @@ -21,6 +21,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.Builder; import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.FluentConfigurationBuilder; import org.ehcache.core.util.ClassLoading; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.xml.exceptions.XmlConfigurationException; @@ -38,6 +39,7 @@ import static java.util.Arrays.asList; import static java.util.Collections.emptyMap; import static java.util.Objects.requireNonNull; +import static org.ehcache.config.builders.ConfigurationBuilder.newConfigurationBuilder; import static org.ehcache.xml.ConfigurationParser.documentToText; import static org.ehcache.xml.XmlConfiguration.PrettyClassFormat.when; @@ -347,7 +349,7 @@ public CacheConfigurationBuilder newCacheConfigurationBuilderFromTe } @Override - public Collection> getServiceCreationConfigurations() { + public Collection> getServiceCreationConfigurations() { return configuration.getServiceCreationConfigurations(); } @@ -356,6 +358,11 @@ public ClassLoader getClassLoader() { return configuration.getClassLoader(); } + @Override + public FluentConfigurationBuilder derive() { + return newConfigurationBuilder(this); + } + public interface Template { CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resourcePools) throws ClassNotFoundException, InstantiationException, IllegalAccessException; } diff --git a/xml/src/main/java/org/ehcache/xml/provider/SimpleCoreServiceCreationConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/provider/SimpleCoreServiceCreationConfigurationParser.java index 78a5382541..f9e2c01ca7 100644 --- a/xml/src/main/java/org/ehcache/xml/provider/SimpleCoreServiceCreationConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/provider/SimpleCoreServiceCreationConfigurationParser.java @@ -17,7 +17,7 @@ package org.ehcache.xml.provider; import org.ehcache.config.Configuration; -import org.ehcache.config.builders.ConfigurationBuilder; +import org.ehcache.config.FluentConfigurationBuilder; import org.ehcache.core.spi.service.ServiceUtils; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.xml.CoreServiceCreationConfigurationParser; @@ -27,7 +27,7 @@ import java.util.function.BinaryOperator; import java.util.function.Function; -class SimpleCoreServiceCreationConfigurationParser> implements CoreServiceCreationConfigurationParser { +class SimpleCoreServiceCreationConfigurationParser> implements CoreServiceCreationConfigurationParser { private final Class configType; @@ -68,12 +68,12 @@ class SimpleCoreServiceCreationConfigurationParser parseServiceCreationConfiguration(ConfigType root, ClassLoader classLoader, FluentConfigurationBuilder builder) throws ClassNotFoundException { T config = getter.apply(root); if (config == null) { return builder; } else { - return builder.addService(parser.parse(config, classLoader)); + return builder.withService(parser.parse(config, classLoader)); } } @@ -94,7 +94,7 @@ public ConfigType unparseServiceCreationConfiguration(Configuration configuratio } @FunctionalInterface - interface Parser> { + interface Parser> { U parse(T t, ClassLoader classLoader) throws ClassNotFoundException; } diff --git a/xml/src/main/java/org/ehcache/xml/provider/ThreadPoolServiceCreationConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/provider/ThreadPoolServiceCreationConfigurationParser.java index 6b3d8c6f94..c039471933 100644 --- a/xml/src/main/java/org/ehcache/xml/provider/ThreadPoolServiceCreationConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/provider/ThreadPoolServiceCreationConfigurationParser.java @@ -23,7 +23,7 @@ import java.util.function.BiConsumer; import java.util.function.Function; -class ThreadPoolServiceCreationConfigurationParser> extends SimpleCoreServiceCreationConfigurationParser { +class ThreadPoolServiceCreationConfigurationParser> extends SimpleCoreServiceCreationConfigurationParser { ThreadPoolServiceCreationConfigurationParser(Class configType, Function getter, BiConsumer setter, diff --git a/xml/src/test/java/org/ehcache/xml/BarConfiguration.java b/xml/src/test/java/org/ehcache/xml/BarConfiguration.java index 43de91b5c0..80fedfa68a 100644 --- a/xml/src/test/java/org/ehcache/xml/BarConfiguration.java +++ b/xml/src/test/java/org/ehcache/xml/BarConfiguration.java @@ -22,7 +22,7 @@ /** * BarConfiguration */ -public class BarConfiguration implements ServiceCreationConfiguration { +public class BarConfiguration implements ServiceCreationConfiguration { @Override public Class getServiceType() { return Service.class; diff --git a/xml/src/test/java/org/ehcache/xml/BarParser.java b/xml/src/test/java/org/ehcache/xml/BarParser.java index 3a3a396952..bd38ee2f65 100644 --- a/xml/src/test/java/org/ehcache/xml/BarParser.java +++ b/xml/src/test/java/org/ehcache/xml/BarParser.java @@ -50,7 +50,7 @@ public URI getNamespace() { } @Override - public ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment, ClassLoader classLoader) { + public ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment, ClassLoader classLoader) { return new BarConfiguration(); } @@ -60,7 +60,7 @@ public Class getServiceType() { } @Override - public Element unparseServiceCreationConfiguration(ServiceCreationConfiguration serviceCreationConfiguration) { + public Element unparseServiceCreationConfiguration(ServiceCreationConfiguration serviceCreationConfiguration) { try { Document document = DomUtil.createAndGetDocumentBuilder().newDocument(); return document.createElementNS(NAMESPACE.toString(), "bar:bar"); diff --git a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java index f94638e6c1..0b6c0c5747 100644 --- a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java @@ -409,7 +409,7 @@ public void testDefaultSerializerConfiguration() throws Exception { assertThat(xmlConfig.getServiceCreationConfigurations().size(), is(1)); - ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); + ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); assertThat(configuration, instanceOf(DefaultSerializationProviderConfiguration.class)); @@ -461,7 +461,7 @@ public void testCacheCopierConfiguration() throws Exception { assertThat(xmlConfig.getServiceCreationConfigurations().size(), is(1)); - ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); + ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); assertThat(configuration, instanceOf(DefaultCopyProviderConfiguration.class)); @@ -503,7 +503,7 @@ public void testPersistenceConfig() throws Exception { final URL resource = XmlConfigurationTest.class.getResource("/configs/persistence-config.xml"); XmlConfiguration xmlConfig = new XmlConfiguration(new XmlConfiguration(resource)); - ServiceCreationConfiguration serviceConfig = xmlConfig.getServiceCreationConfigurations().iterator().next(); + ServiceCreationConfiguration serviceConfig = xmlConfig.getServiceCreationConfigurations().iterator().next(); assertThat(serviceConfig, instanceOf(DefaultPersistenceConfiguration.class)); DefaultPersistenceConfiguration persistenceConfiguration = (DefaultPersistenceConfiguration)serviceConfig; diff --git a/xml/src/test/java/org/ehcache/xml/provider/CacheEventDispatcherFactoryConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/provider/CacheEventDispatcherFactoryConfigurationParserTest.java index 1b61d6a604..eb126f095d 100644 --- a/xml/src/test/java/org/ehcache/xml/provider/CacheEventDispatcherFactoryConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/provider/CacheEventDispatcherFactoryConfigurationParserTest.java @@ -40,7 +40,7 @@ public void parseServiceCreationConfiguration() throws SAXException, JAXBExcepti assertThat(xmlConfig.getServiceCreationConfigurations()).hasSize(1); - ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); + ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); assertThat(configuration).isInstanceOf(CacheEventDispatcherFactoryConfiguration.class); CacheEventDispatcherFactoryConfiguration providerConfiguration = (CacheEventDispatcherFactoryConfiguration) configuration; @@ -50,7 +50,7 @@ public void parseServiceCreationConfiguration() throws SAXException, JAXBExcepti @Test public void unparseServiceCreationConfiguration() { Configuration config = ConfigurationBuilder.newConfigurationBuilder() - .addService(new CacheEventDispatcherFactoryConfiguration("foo")).build(); + .withService(new CacheEventDispatcherFactoryConfiguration("foo")).build(); ConfigType configType = new CacheEventDispatcherFactoryConfigurationParser().unparseServiceCreationConfiguration(config, new ConfigType()); assertThat(configType.getEventDispatch().getThreadPool()).isEqualTo("foo"); diff --git a/xml/src/test/java/org/ehcache/xml/provider/CacheManagerPersistenceConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/provider/CacheManagerPersistenceConfigurationParserTest.java index f2a3160f32..0cc26057eb 100644 --- a/xml/src/test/java/org/ehcache/xml/provider/CacheManagerPersistenceConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/provider/CacheManagerPersistenceConfigurationParserTest.java @@ -53,7 +53,7 @@ public void parseServiceCreationConfiguration() throws SAXException, JAXBExcepti @Test public void unparseServiceCreationConfiguration() { Configuration config = ConfigurationBuilder.newConfigurationBuilder() - .addService(new CacheManagerPersistenceConfiguration(new File("foo"))).build(); + .withService(new CacheManagerPersistenceConfiguration(new File("foo"))).build(); ConfigType configType = new CacheManagerPersistenceConfigurationParser().unparseServiceCreationConfiguration(config, new ConfigType()); assertThat(configType.getPersistence().getDirectory()).isEqualTo("foo"); diff --git a/xml/src/test/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParserTest.java index 10e7dadc79..c950fc01a3 100644 --- a/xml/src/test/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParserTest.java @@ -49,7 +49,7 @@ public void parseServiceCreationConfiguration() throws SAXException, JAXBExcepti assertThat(xmlConfig.getServiceCreationConfigurations()).hasSize(1); - ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); + ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); assertThat(configuration).isExactlyInstanceOf(DefaultCopyProviderConfiguration.class); @@ -66,7 +66,7 @@ public void unparseServiceCreationConfiguration() { providerConfig.addCopierFor(Description.class, DescriptionCopier.class); providerConfig.addCopierFor(Person.class, PersonCopier.class); - Configuration config = ConfigurationBuilder.newConfigurationBuilder().addService(providerConfig).build(); + Configuration config = ConfigurationBuilder.newConfigurationBuilder().withService(providerConfig).build(); ConfigType configType = new DefaultCopyProviderConfigurationParser().unparseServiceCreationConfiguration(config, new ConfigType()); List copiers = configType.getDefaultCopiers().getCopier(); diff --git a/xml/src/test/java/org/ehcache/xml/provider/DefaultSerializationProviderConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/provider/DefaultSerializationProviderConfigurationParserTest.java index b077dc89be..ea08c210c8 100644 --- a/xml/src/test/java/org/ehcache/xml/provider/DefaultSerializationProviderConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/provider/DefaultSerializationProviderConfigurationParserTest.java @@ -51,7 +51,7 @@ public void parseServiceCreationConfiguration() throws SAXException, JAXBExcepti assertThat(xmlConfig.getServiceCreationConfigurations()).hasSize(1); - ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); + ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); assertThat(configuration).isExactlyInstanceOf(DefaultSerializationProviderConfiguration.class); @@ -71,7 +71,7 @@ public void unparseServiceCreationConfiguration() { providerConfig.addSerializerFor(Description.class, (Class) TestSerializer3.class); providerConfig.addSerializerFor(Person.class, (Class) TestSerializer4.class); - Configuration config = ConfigurationBuilder.newConfigurationBuilder().addService(providerConfig).build(); + Configuration config = ConfigurationBuilder.newConfigurationBuilder().withService(providerConfig).build(); ConfigType configType = new DefaultSerializationProviderConfigurationParser().unparseServiceCreationConfiguration(config, new ConfigType()); List serializers = configType.getDefaultSerializers().getSerializer(); diff --git a/xml/src/test/java/org/ehcache/xml/provider/DefaultSizeOfEngineProviderConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/provider/DefaultSizeOfEngineProviderConfigurationParserTest.java index e5def5da4c..3ad074be31 100644 --- a/xml/src/test/java/org/ehcache/xml/provider/DefaultSizeOfEngineProviderConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/provider/DefaultSizeOfEngineProviderConfigurationParserTest.java @@ -43,7 +43,7 @@ public void parseServiceCreationConfiguration() throws SAXException, JAXBExcepti assertThat(xmlConfig.getServiceCreationConfigurations()).hasSize(1); - ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); + ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); assertThat(configuration).isExactlyInstanceOf(DefaultSizeOfEngineProviderConfiguration.class); DefaultSizeOfEngineProviderConfiguration sizeOfEngineProviderConfig = (DefaultSizeOfEngineProviderConfiguration) configuration; @@ -55,7 +55,7 @@ public void parseServiceCreationConfiguration() throws SAXException, JAXBExcepti public void unparseServiceCreationConfiguration() { ConfigType configType = new ConfigType(); Configuration config = ConfigurationBuilder.newConfigurationBuilder() - .addService(new DefaultSizeOfEngineProviderConfiguration(123, MemoryUnit.MB, 987)).build(); + .withService(new DefaultSizeOfEngineProviderConfiguration(123, MemoryUnit.MB, 987)).build(); configType = new DefaultSizeOfEngineProviderConfigurationParser().unparseServiceCreationConfiguration(config, configType); SizeofType heapStore = configType.getHeapStore(); diff --git a/xml/src/test/java/org/ehcache/xml/provider/OffHeapDiskStoreProviderConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/provider/OffHeapDiskStoreProviderConfigurationParserTest.java index d8c23f2b30..e5600e8290 100644 --- a/xml/src/test/java/org/ehcache/xml/provider/OffHeapDiskStoreProviderConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/provider/OffHeapDiskStoreProviderConfigurationParserTest.java @@ -41,7 +41,7 @@ public void parseServiceCreationConfiguration() throws SAXException, JAXBExcepti assertThat(xmlConfig.getServiceCreationConfigurations()).hasSize(1); - ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); + ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); assertThat(configuration).isExactlyInstanceOf(OffHeapDiskStoreProviderConfiguration.class); @@ -53,7 +53,7 @@ public void parseServiceCreationConfiguration() throws SAXException, JAXBExcepti public void unparseServiceCreationConfiguration() { ConfigType configType = new ConfigType(); Configuration config = ConfigurationBuilder.newConfigurationBuilder() - .addService(new OffHeapDiskStoreProviderConfiguration("foo")).build(); + .withService(new OffHeapDiskStoreProviderConfiguration("foo")).build(); configType = new OffHeapDiskStoreProviderConfigurationParser().unparseServiceCreationConfiguration(config, configType); assertThat(configType.getDiskStore().getThreadPool()).isEqualTo("foo"); diff --git a/xml/src/test/java/org/ehcache/xml/provider/PooledExecutionServiceConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/provider/PooledExecutionServiceConfigurationParserTest.java index 92b780781d..2c55ccbd6e 100644 --- a/xml/src/test/java/org/ehcache/xml/provider/PooledExecutionServiceConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/provider/PooledExecutionServiceConfigurationParserTest.java @@ -42,7 +42,7 @@ public void parseServiceCreationConfiguration() throws SAXException, JAXBExcepti assertThat(xmlConfig.getServiceCreationConfigurations()).hasSize(1); - ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); + ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); assertThat(configuration).isExactlyInstanceOf(PooledExecutionServiceConfiguration.class); PooledExecutionServiceConfiguration providerConfiguration = (PooledExecutionServiceConfiguration) configuration; @@ -65,7 +65,7 @@ public void unparseServiceCreationConfiguration() { providerConfig.addDefaultPool("foo", 5, 9); providerConfig.addPool("bar", 2, 6); - Configuration config = ConfigurationBuilder.newConfigurationBuilder().addService(providerConfig).build(); + Configuration config = ConfigurationBuilder.newConfigurationBuilder().withService(providerConfig).build(); ConfigType configType = new ConfigType(); configType = new PooledExecutionServiceConfigurationParser().unparseServiceCreationConfiguration(config, configType); diff --git a/xml/src/test/java/org/ehcache/xml/provider/WriteBehindProviderConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/provider/WriteBehindProviderConfigurationParserTest.java index 7ab0007314..fd35e5b71b 100644 --- a/xml/src/test/java/org/ehcache/xml/provider/WriteBehindProviderConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/provider/WriteBehindProviderConfigurationParserTest.java @@ -40,7 +40,7 @@ public void parseServiceCreationConfiguration() throws SAXException, JAXBExcepti assertThat(xmlConfig.getServiceCreationConfigurations()).hasSize(1); - ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); + ServiceCreationConfiguration configuration = xmlConfig.getServiceCreationConfigurations().iterator().next(); assertThat(configuration).isExactlyInstanceOf(WriteBehindProviderConfiguration.class); @@ -52,7 +52,7 @@ public void parseServiceCreationConfiguration() throws SAXException, JAXBExcepti public void unparseServiceCreationConfiguration() { ConfigType configType = new ConfigType(); Configuration config = ConfigurationBuilder.newConfigurationBuilder() - .addService(new WriteBehindProviderConfiguration("foo")).build(); + .withService(new WriteBehindProviderConfiguration("foo")).build(); configType = new WriteBehindProviderConfigurationParser().unparseServiceCreationConfiguration(config, configType); assertThat(configType.getWriteBehind().getThreadPool()).isEqualTo("foo"); From 1b9326f3b9bd6fe558c4ba84f40b249bb16786b0 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 28 Feb 2019 11:57:13 -0500 Subject: [PATCH 133/372] Issue 2613 : Make cache configurations derivable --- .../ehcache/jsr107/ConfigurationMerger.java | 20 +- .../org/ehcache/jsr107/Eh107CacheManager.java | 2 +- .../jsr107/Eh107CompleteConfiguration.java | 5 +- .../config/Jsr107CacheConfiguration.java | 2 +- .../Jsr107CacheConfigurationParser.java | 4 +- .../ConfigStatsManagementActivationTest.java | 2 +- .../jsr107/ConfigurationMergerTest.java | 18 +- .../ehcache/config/CacheConfiguration.java | 10 +- .../config/CacheRuntimeConfiguration.java | 7 +- .../FluentCacheConfigurationBuilder.java | 497 ++++++++++++++++- .../config/FluentConfigurationBuilder.java | 2 +- .../java/org/ehcache/expiry/ExpiryPolicy.java | 5 + .../org/ehcache/spi/copy/CopyProvider.java | 4 +- .../CacheLoaderWriterConfiguration.java | 4 +- .../CacheLoaderWriterProvider.java | 2 +- .../WriteBehindConfiguration.java | 4 +- .../spi/loaderwriter/WriteBehindProvider.java | 2 +- .../PersistableResourceService.java | 2 +- .../serialization/SerializationProvider.java | 4 +- .../spi/service/ServiceConfiguration.java | 38 +- .../config/ClusteredStoreConfiguration.java | 12 +- .../config/ClusteredResourcePoolImpl.java | 2 +- .../DedicatedClusteredResourcePoolImpl.java | 2 +- .../SharedClusteredResourcePoolImpl.java | 2 +- ...teringCacheServiceConfigurationParser.java | 4 +- .../ClusteredLoaderWriterStore.java | 4 +- .../DelegatingLoaderWriterStoreProvider.java | 8 +- .../ClusteredWriteBehindStore.java | 6 +- .../client/internal/store/ClusteredStore.java | 10 +- .../client/BasicClusteredCacheExpiryTest.java | 2 +- .../client/BasicClusteredCacheTest.java | 6 +- .../client/ClusteredCacheDestroyTest.java | 2 +- .../client/ClusteredCacheExpirationTest.java | 2 +- .../client/ClusteredConcurrencyTest.java | 2 +- ...tedCombinationsWithClusteredCacheTest.java | 6 +- .../ClusteredConfigurationDerivationTest.java | 50 ++ .../ClusteredStoreConfigurationTest.java | 38 ++ .../clustered/client/docs/GettingStarted.java | 8 +- ...lusteredLoaderWriterStoreProviderTest.java | 2 +- ...ClusteredWriteBehindStoreProviderTest.java | 4 +- ...ClusterStateRepositoryReplicationTest.java | 2 +- .../StateRepositoryWhitelistingTest.java | 2 +- .../store/ClusteredStoreProviderTest.java | 10 +- ...icClusteredWriteBehindPassthroughTest.java | 4 +- .../BasicCacheOpsMultiThreadedTest.java | 4 +- .../clustered/BasicClusteredCacheOpsTest.java | 4 +- .../clustered/ClusteredLoaderWriterTest.java | 2 +- .../ehcache/clustered/DestroyLoopTest.java | 2 +- .../clustered/EventsFailureBehaviorTest.java | 2 +- .../ResourcePoolAllocationFailureTest.java | 2 +- .../EhcacheManagerToStringTest.java | 2 +- .../reconnect/EventsReconnectTest.java | 2 +- ...dCacheOpsReplicationMultiThreadedTest.java | 2 +- ...BasicClusteredCacheOpsReplicationTest.java | 2 +- ...OpsReplicationWithMultipleClientsTest.java | 2 +- .../clustered/replication/DuplicateTest.java | 2 +- .../writebehind/WriteBehindTestBase.java | 4 +- .../test/resources/clusteredConfiguration.txt | 4 +- .../ehcache/internal/store/StoreFactory.java | 2 +- .../internal/tier/CachingTierFactory.java | 2 +- .../java/org/ehcache/core/EhcacheManager.java | 55 +- .../core/EhcacheRuntimeConfiguration.java | 74 ++- .../core/config/CoreConfigurationBuilder.java | 2 +- .../store/StoreEventSourceConfiguration.java | 4 +- .../store/StoreStatisticsConfiguration.java | 12 +- .../events/CacheEventDispatcherFactory.java | 2 +- .../CacheEventListenerConfiguration.java | 2 +- .../events/CacheEventListenerProvider.java | 2 +- .../org/ehcache/core/spi/ServiceLocator.java | 2 +- .../core/spi/service/DiskResourceService.java | 2 +- .../store/AbstractWrapperStoreProvider.java | 6 +- .../org/ehcache/core/spi/store/Store.java | 5 +- .../ehcache/core/spi/store/WrapperStore.java | 2 +- .../spi/store/heap/SizeOfEngineProvider.java | 2 +- .../spi/store/tiering/AuthoritativeTier.java | 4 +- .../core/spi/store/tiering/CachingTier.java | 4 +- .../spi/store/tiering/HigherCachingTier.java | 2 +- .../spi/store/tiering/LowerCachingTier.java | 2 +- .../org/ehcache/core/store/StoreSupport.java | 4 +- .../CacheConfigurationChangeListenerTest.java | 12 +- .../ehcache/core/EhcacheBasicCrudBase.java | 9 +- .../core/EhcacheBasicPutIfAbsentTest.java | 8 +- .../org/ehcache/core/EhcacheManagerTest.java | 71 ++- .../java/org/ehcache/core/EhcacheTest.java | 7 +- .../ehcache/core/UserManagedCacheTest.java | 8 +- .../core/config/ResourcePoolsHelper.java | 80 +-- .../StoreStatisticsConfigurationTest.java | 36 ++ .../ehcache/core/spi/ServiceLocatorTest.java | 2 +- .../core/spi/services/FancyCacheProvider.java | 2 +- .../ehcache/core/spi/store/CacheProvider.java | 2 +- .../ehcache/core/store/StoreSupportTest.java | 12 +- .../ehcache/core/util/TestCacheConfig.java | 262 +++++++++ .../builders/CacheConfigurationBuilder.java | 507 +++++++++--------- ...acheEventListenerConfigurationBuilder.java | 2 +- .../config/builders/ResourcePoolsBuilder.java | 6 +- .../builders/UserManagedCacheBuilder.java | 13 +- .../WriteBehindConfigurationBuilder.java | 8 +- .../impl}/config/AbstractResourcePool.java | 2 +- .../impl}/config/BaseCacheConfiguration.java | 17 +- .../impl}/config/ResourcePoolsImpl.java | 3 +- .../impl}/config/SizedResourcePoolImpl.java | 2 +- .../copy/DefaultCopierConfiguration.java | 14 +- ...aultCacheEventDispatcherConfiguration.java | 12 +- ...efaultCacheEventListenerConfiguration.java | 11 +- .../DefaultEventSourceConfiguration.java | 12 +- ...DefaultCacheLoaderWriterConfiguration.java | 15 +- .../DefaultWriteBehindConfiguration.java | 2 +- ...efaultResilienceStrategyConfiguration.java | 12 +- .../DefaultSerializerConfiguration.java | 14 +- .../disk/OffHeapDiskStoreConfiguration.java | 12 +- .../DefaultSizeOfEngineConfiguration.java | 12 +- .../classes/ClassInstanceProvider.java | 4 +- .../CacheEventDispatcherFactoryImpl.java | 2 +- .../BatchingLocalHeapWriteBehindQueue.java | 2 +- .../NonBatchingLocalHeapWriteBehindQueue.java | 2 +- .../writebehind/StripedWriteBehind.java | 2 +- .../WriteBehindProviderFactory.java | 2 +- .../sizeof/DefaultSizeOfEngineProvider.java | 2 +- .../spi/copy/DefaultCopyProvider.java | 8 +- .../DefaultCacheEventListenerProvider.java | 2 +- .../DefaultCacheLoaderWriterProvider.java | 4 +- .../DefaultSerializationProvider.java | 8 +- .../internal/store/disk/OffHeapDiskStore.java | 11 +- .../impl/internal/store/heap/OnHeapStore.java | 12 +- .../LoaderWriterStoreProvider.java | 10 +- .../internal/store/offheap/OffHeapStore.java | 12 +- .../store/tiering/CompoundCachingTier.java | 4 +- .../internal/store/tiering/TieredStore.java | 14 +- .../EhcacheRuntimeConfigurationTest.java | 5 +- .../CacheConfigurationBuilderTest.java | 445 +++++++++++---- .../builders/ResourcePoolsBuilderTest.java | 2 +- .../java/org/ehcache/docs/GettingStarted.java | 4 +- .../java/org/ehcache/docs/ThreadPools.java | 8 +- .../test/java/org/ehcache/docs/Tiering.java | 4 +- .../config/BaseCacheConfigurationTest.java | 2 +- .../impl}/config/ResourcePoolsImplTest.java | 50 +- .../config/SizedResourcePoolImplTest.java | 3 +- ...CacheEventDispatcherConfigurationTest.java | 36 ++ .../DefaultEventSourceConfigurationTest.java | 36 ++ ...ultCacheLoaderWriterConfigurationTest.java | 39 ++ ...ltResilienceStrategyConfigurationTest.java | 12 + .../serializer/SerializerCountingTest.java | 12 +- .../OffHeapDiskStoreConfigurationTest.java | 38 ++ .../classes/ClassInstanceProviderTest.java | 8 +- .../AbstractWriteBehindTestBase.java | 38 +- .../WriteBehindProviderFactoryTest.java | 10 +- .../DefaultSizeOfEngineConfigurationTest.java | 13 + ...DefaultCacheEventListenerProviderTest.java | 10 +- .../DefaultCacheLoaderWriterProviderTest.java | 10 +- .../DefaultCacheStatisticsTest.java | 4 +- .../statistics/DefaultTierStatisticsTest.java | 2 +- .../internal/statistics/StatsUtilsTest.java | 2 +- .../store/disk/OffHeapDiskStoreSPITest.java | 4 +- .../ByteSizedOnHeapStoreByRefSPITest.java | 4 +- .../ByteSizedOnHeapStoreByValueSPITest.java | 4 +- .../store/heap/OnHeapStoreByRefSPITest.java | 4 +- .../store/heap/OnHeapStoreByValueSPITest.java | 4 +- .../store/heap/OnHeapStoreByValueTest.java | 3 +- .../OnHeapStoreCachingTierByRefSPITest.java | 4 +- .../OnHeapStoreCachingTierByValueSPITest.java | 4 +- .../store/heap/OnHeapStoreProviderTest.java | 2 +- .../OnHeapStoreCachingTierByRefSPITest.java | 4 +- .../OnHeapStoreCachingTierByValueSPITest.java | 4 +- .../store/offheap/OffHeapStoreSPITest.java | 4 +- .../store/offheap/OffHeapStoreTest.java | 2 +- .../tiering/CompoundCachingTierSPITest.java | 4 +- .../TieredStoreFlushWhileShutdownTest.java | 1 - .../store/tiering/TieredStoreSPITest.java | 21 +- .../tiering/TieredStoreWith3TiersSPITest.java | 21 +- .../ehcache/integration/CacheCopierTest.java | 10 +- .../integration/EhcacheBulkMethodsITest.java | 4 +- .../ehcache/integration/ExpiryEventsTest.java | 2 +- .../LoaderWriterErrorEhcacheTest.java | 1 - .../integration/StoreStatisticsTest.java | 2 +- .../statistics/TierCalculationTest.java | 2 +- .../transactions/xa/XACacheTest.java | 51 +- .../StandardEhCacheStatisticsQueryTest.java | 2 +- .../DefaultManagementRegistryServiceTest.java | 4 +- .../java/org/ehcache/osgi/SimpleOsgiTest.java | 4 +- .../ehcache/osgi/TransactionalOsgiTest.java | 2 +- .../configuration/XAStoreConfiguration.java | 12 +- .../transactions/xa/internal/XAStore.java | 13 +- .../TxCacheServiceConfigurationParser.java | 4 +- .../transactions/xa/XAGettingStarted.java | 12 +- .../XAStoreConfigurationTest.java | 36 ++ .../integration/StatefulSerializerTest.java | 2 +- .../internal/UnSupportedResourceTypeTest.java | 2 +- .../transactions/xa/internal/XAStoreTest.java | 4 +- .../xml/CacheServiceConfigurationParser.java | 4 +- .../xml/ResourceConfigurationParser.java | 2 +- .../xml/ServiceConfigurationParser.java | 2 +- .../org/ehcache/xml/XmlConfiguration.java | 2 +- ...CacheEventListenerConfigurationParser.java | 2 +- .../DefaultCopierConfigurationParser.java | 4 +- .../DefaultSerializerConfigurationParser.java | 4 +- ...DefaultWriteBehindConfigurationParser.java | 7 +- .../SimpleCoreServiceConfigurationParser.java | 4 +- .../java/org/ehcache/xml/FancyParser.java | 4 +- .../org/ehcache/xml/FooConfiguration.java | 2 +- .../test/java/org/ehcache/xml/FooParser.java | 4 +- .../xml/IntegrationConfigurationTest.java | 10 +- .../org/ehcache/xml/XmlConfigurationTest.java | 16 +- ...ventDispatcherConfigurationParserTest.java | 2 +- ...eEventListenerConfigurationParserTest.java | 4 +- ...heLoaderWriterConfigurationParserTest.java | 4 +- .../DefaultCopierConfigurationParserTest.java | 6 +- ...lienceStrategyConfigurationParserTest.java | 4 +- ...aultSerializerConfigurationParserTest.java | 6 +- ...ltSizeOfEngineConfigurationParserTest.java | 2 +- ...ultWriteBehindConfigurationParserTest.java | 4 +- ...fHeapDiskStoreConfigurationParserTest.java | 2 +- 211 files changed, 2476 insertions(+), 1021 deletions(-) create mode 100644 clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredConfigurationDerivationTest.java create mode 100644 clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredStoreConfigurationTest.java create mode 100644 core/src/test/java/org/ehcache/core/config/store/StoreStatisticsConfigurationTest.java create mode 100644 core/src/test/java/org/ehcache/core/util/TestCacheConfig.java rename {core/src/main/java/org/ehcache/core => impl/src/main/java/org/ehcache/impl}/config/AbstractResourcePool.java (98%) rename {core/src/main/java/org/ehcache/core => impl/src/main/java/org/ehcache/impl}/config/BaseCacheConfiguration.java (85%) rename {core/src/main/java/org/ehcache/core => impl/src/main/java/org/ehcache/impl}/config/ResourcePoolsImpl.java (98%) rename {core/src/main/java/org/ehcache/core => impl/src/main/java/org/ehcache/impl}/config/SizedResourcePoolImpl.java (98%) rename {core/src/test/java/org/ehcache/core => impl/src/test/java/org/ehcache/impl}/config/BaseCacheConfigurationTest.java (98%) rename {core/src/test/java/org/ehcache/core => impl/src/test/java/org/ehcache/impl}/config/ResourcePoolsImplTest.java (84%) rename {core/src/test/java/org/ehcache/core => impl/src/test/java/org/ehcache/impl}/config/SizedResourcePoolImplTest.java (93%) create mode 100644 impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfigurationTest.java create mode 100644 impl/src/test/java/org/ehcache/impl/config/event/DefaultEventSourceConfigurationTest.java create mode 100644 impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfigurationTest.java create mode 100644 impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfigurationTest.java create mode 100644 transactions/src/test/java/org/ehcache/transactions/xa/configuration/XAStoreConfigurationTest.java diff --git a/107/src/main/java/org/ehcache/jsr107/ConfigurationMerger.java b/107/src/main/java/org/ehcache/jsr107/ConfigurationMerger.java index 9d312ee038..2987736314 100644 --- a/107/src/main/java/org/ehcache/jsr107/ConfigurationMerger.java +++ b/107/src/main/java/org/ehcache/jsr107/ConfigurationMerger.java @@ -32,6 +32,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -106,7 +107,7 @@ ConfigHolder mergeConfigurations(String cacheName, Configuration ehcacheLoaderWriterConfiguration = builder.getService(DefaultCacheLoaderWriterConfiguration.class); if (ehcacheLoaderWriterConfiguration == null) { useEhcacheLoaderWriter = false; // No template loader/writer - let's activate the JSR-107 one if any @@ -144,8 +145,9 @@ ConfigHolder mergeConfigurations(String cacheName, Configuration CacheConfigurationBuilder handleStoreByValue(Eh107CompleteConfiguration jsr107Configuration, CacheConfigurationBuilder builder, String cacheName) { - DefaultCopierConfiguration copierConfig = builder.getExistingServiceConfiguration(DefaultCopierConfiguration.class); - if(copierConfig == null) { + @SuppressWarnings("unchecked") + Collection> copierConfigs = builder.getServices((Class>) (Class) DefaultCopierConfiguration.class); + if(copierConfigs.isEmpty()) { if(jsr107Configuration.isStoreByValue()) { if (xmlConfiguration != null) { DefaultCopyProviderConfiguration defaultCopyProviderConfiguration = findSingletonAmongst(DefaultCopyProviderConfiguration.class, @@ -157,12 +159,12 @@ private CacheConfigurationBuilder handleStoreByValue(Eh107CompleteC if (defaults.containsKey(jsr107Configuration.getKeyType())) { matchingDefault = true; } else { - builder = builder.add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.KEY)); + builder = builder.withService(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.KEY)); } if (defaults.containsKey(jsr107Configuration.getValueType())) { matchingDefault = true; } else { - builder = builder.add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)); + builder = builder.withService(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)); } if (matchingDefault) { LOG.info("CacheManager level copier configuration overwriting JSR-107 by-value semantics for cache {}", cacheName); @@ -189,15 +191,15 @@ private static CacheConfigurationBuilder addDefaultCopiers(CacheCon immutableTypes.add(Character.class); immutableTypes.add(Integer.class); if (immutableTypes.contains(keyType)) { - builder = builder.add(new DefaultCopierConfiguration((Class)Eh107IdentityCopier.class, DefaultCopierConfiguration.Type.KEY)); + builder = builder.withService(new DefaultCopierConfiguration((Class)Eh107IdentityCopier.class, DefaultCopierConfiguration.Type.KEY)); } else { - builder = builder.add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.KEY)); + builder = builder.withService(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.KEY)); } if (immutableTypes.contains(valueType)) { - builder = builder.add(new DefaultCopierConfiguration((Class)Eh107IdentityCopier.class, DefaultCopierConfiguration.Type.VALUE)); + builder = builder.withService(new DefaultCopierConfiguration((Class)Eh107IdentityCopier.class, DefaultCopierConfiguration.Type.VALUE)); } else { - builder = builder.add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)); + builder = builder.withService(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)); } return builder; } diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107CacheManager.java b/107/src/main/java/org/ehcache/jsr107/Eh107CacheManager.java index caa07cc3bf..fb86e17131 100644 --- a/107/src/main/java/org/ehcache/jsr107/Eh107CacheManager.java +++ b/107/src/main/java/org/ehcache/jsr107/Eh107CacheManager.java @@ -113,7 +113,7 @@ private Eh107Cache wrapEhcacheCache(String alias, InternalCache cacheLoaderWriter = cache.getCacheLoaderWriter(); boolean storeByValueOnHeap = false; - for (ServiceConfiguration serviceConfiguration : cache.getRuntimeConfiguration().getServiceConfigurations()) { + for (ServiceConfiguration serviceConfiguration : cache.getRuntimeConfiguration().getServiceConfigurations()) { if (serviceConfiguration instanceof DefaultCopierConfiguration) { DefaultCopierConfiguration copierConfig = (DefaultCopierConfiguration) serviceConfiguration; if(!copierConfig.getClazz().isAssignableFrom(IdentityCopier.class)) diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107CompleteConfiguration.java b/107/src/main/java/org/ehcache/jsr107/Eh107CompleteConfiguration.java index 041da404fe..0dba47507c 100644 --- a/107/src/main/java/org/ehcache/jsr107/Eh107CompleteConfiguration.java +++ b/107/src/main/java/org/ehcache/jsr107/Eh107CompleteConfiguration.java @@ -20,7 +20,6 @@ import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.spi.service.ServiceConfiguration; -import java.io.ObjectStreamException; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -110,8 +109,8 @@ public Eh107CompleteConfiguration(Configuration config, final CacheConfigu private static boolean isStoreByValue(Configuration config, CacheConfiguration ehcacheConfig) { if(ehcacheConfig != null) { - Collection> serviceConfigurations = ehcacheConfig.getServiceConfigurations(); - for (ServiceConfiguration serviceConfiguration : serviceConfigurations) { + Collection> serviceConfigurations = ehcacheConfig.getServiceConfigurations(); + for (ServiceConfiguration serviceConfiguration : serviceConfigurations) { if (serviceConfiguration instanceof DefaultCopierConfiguration) { DefaultCopierConfiguration copierConfig = (DefaultCopierConfiguration)serviceConfiguration; if(copierConfig.getType().equals(DefaultCopierConfiguration.Type.VALUE)) { diff --git a/107/src/main/java/org/ehcache/jsr107/config/Jsr107CacheConfiguration.java b/107/src/main/java/org/ehcache/jsr107/config/Jsr107CacheConfiguration.java index e9d8abd9d9..cba5dfa4f9 100644 --- a/107/src/main/java/org/ehcache/jsr107/config/Jsr107CacheConfiguration.java +++ b/107/src/main/java/org/ehcache/jsr107/config/Jsr107CacheConfiguration.java @@ -22,7 +22,7 @@ /** * Jsr107CacheConfiguration */ -public class Jsr107CacheConfiguration implements ServiceConfiguration { +public class Jsr107CacheConfiguration implements ServiceConfiguration { private final ConfigurationElementState statisticsEnabled; private final ConfigurationElementState managementEnabled; diff --git a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java b/107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java index 149acb6375..81203ee0a9 100644 --- a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java +++ b/107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java @@ -55,7 +55,7 @@ public URI getNamespace() { } @Override - public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { + public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { String localName = fragment.getLocalName(); if ("mbeans".equals(localName)) { ConfigurationElementState managementEnabled = ConfigurationElementState.UNSPECIFIED; @@ -79,7 +79,7 @@ public Class getServiceType() { } @Override - public Element unparseServiceConfiguration(ServiceConfiguration serviceConfiguration) { + public Element unparseServiceConfiguration(ServiceConfiguration serviceConfiguration) { throw new XmlConfigurationException("XML translation of JSR-107 cache elements are not supported"); } diff --git a/107/src/test/java/org/ehcache/jsr107/ConfigStatsManagementActivationTest.java b/107/src/test/java/org/ehcache/jsr107/ConfigStatsManagementActivationTest.java index a9d90e53f3..8be0438d08 100644 --- a/107/src/test/java/org/ehcache/jsr107/ConfigStatsManagementActivationTest.java +++ b/107/src/test/java/org/ehcache/jsr107/ConfigStatsManagementActivationTest.java @@ -130,7 +130,7 @@ public void testEnableCacheLevelProgrammatic() throws Exception { CacheManager cacheManager = provider.getCacheManager(); CacheConfigurationBuilder configurationBuilder = newCacheConfigurationBuilder(Long.class, String.class, heap(10)) - .add(new Jsr107CacheConfiguration(ConfigurationElementState.ENABLED, ConfigurationElementState.ENABLED)); + .withService(new Jsr107CacheConfiguration(ConfigurationElementState.ENABLED, ConfigurationElementState.ENABLED)); Cache cache = cacheManager.createCache("test", Eh107Configuration.fromEhcacheCacheConfiguration(configurationBuilder)); @SuppressWarnings("unchecked") diff --git a/107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java b/107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java index e1df48b7b8..750b005cfe 100644 --- a/107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java +++ b/107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java @@ -92,8 +92,8 @@ public void mergeConfigNoTemplateNoLoaderWriter() { assertThat(configHolder.useEhcacheLoaderWriter, is(false)); boolean storeByValue = false; - Collection> serviceConfigurations = configHolder.cacheConfiguration.getServiceConfigurations(); - for (ServiceConfiguration serviceConfiguration : serviceConfigurations) { + Collection> serviceConfigurations = configHolder.cacheConfiguration.getServiceConfigurations(); + for (ServiceConfiguration serviceConfiguration : serviceConfigurations) { if (serviceConfiguration instanceof DefaultCopierConfiguration) { storeByValue = true; break; @@ -183,7 +183,7 @@ public void jsr107ExpiryGetsOverriddenByTemplate() throws Exception { public void jsr107LoaderGetsOverriddenByTemplate() throws Exception { when(jsr107Service.getTemplateNameForCache("cache")).thenReturn("cacheTemplate"); when(xmlConfiguration.newCacheConfigurationBuilderFromTemplate("cacheTemplate", Object.class, Object.class)).thenReturn( - newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).add(new DefaultCacheLoaderWriterConfiguration((Class)null)) + newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(new DefaultCacheLoaderWriterConfiguration((Class)null)) ); MutableConfiguration configuration = new MutableConfiguration<>(); @@ -200,8 +200,8 @@ public void jsr107LoaderGetsOverriddenByTemplate() throws Exception { @Test public void jsr107StoreByValueGetsOverriddenByTemplate() throws Exception { CacheConfigurationBuilder builder = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) - .add(new DefaultCopierConfiguration((Class)IdentityCopier.class, DefaultCopierConfiguration.Type.KEY)) - .add(new DefaultCopierConfiguration((Class)IdentityCopier.class, DefaultCopierConfiguration.Type.VALUE)); + .withService(new DefaultCopierConfiguration((Class)IdentityCopier.class, DefaultCopierConfiguration.Type.KEY)) + .withService(new DefaultCopierConfiguration((Class)IdentityCopier.class, DefaultCopierConfiguration.Type.VALUE)); when(jsr107Service.getTemplateNameForCache("cache")).thenReturn("cacheTemplate"); when(xmlConfiguration.newCacheConfigurationBuilderFromTemplate("cacheTemplate", Object.class, Object.class)) @@ -212,8 +212,8 @@ public void jsr107StoreByValueGetsOverriddenByTemplate() throws Exception { ConfigurationMerger.ConfigHolder configHolder = merger.mergeConfigurations("cache", configuration); boolean storeByValue = true; - Collection> serviceConfigurations = configHolder.cacheConfiguration.getServiceConfigurations(); - for (ServiceConfiguration serviceConfiguration : serviceConfigurations) { + Collection> serviceConfigurations = configHolder.cacheConfiguration.getServiceConfigurations(); + for (ServiceConfiguration serviceConfiguration : serviceConfigurations) { if (serviceConfiguration instanceof DefaultCopierConfiguration) { DefaultCopierConfiguration copierConfig = (DefaultCopierConfiguration)serviceConfiguration; if(copierConfig.getClazz().isAssignableFrom(IdentityCopier.class)) @@ -378,9 +378,9 @@ public void jsr107DefaultEh107IdentityCopierForImmutableTypesWithoutTemplates() assertDefaultCopier(configHolder1.cacheConfiguration.getServiceConfigurations()); } - private static void assertDefaultCopier(Collection> serviceConfigurations) { + private static void assertDefaultCopier(Collection> serviceConfigurations) { boolean noCopierConfigPresent = false; - for (ServiceConfiguration serviceConfiguration : serviceConfigurations) { + for (ServiceConfiguration serviceConfiguration : serviceConfigurations) { if (serviceConfiguration instanceof DefaultCopierConfiguration) { noCopierConfigPresent = true; DefaultCopierConfiguration copierConfig = (DefaultCopierConfiguration)serviceConfiguration; diff --git a/api/src/main/java/org/ehcache/config/CacheConfiguration.java b/api/src/main/java/org/ehcache/config/CacheConfiguration.java index fd0817e728..ab808dbe7b 100644 --- a/api/src/main/java/org/ehcache/config/CacheConfiguration.java +++ b/api/src/main/java/org/ehcache/config/CacheConfiguration.java @@ -40,7 +40,7 @@ public interface CacheConfiguration { * * @return service configurations */ - Collection> getServiceConfigurations(); + Collection> getServiceConfigurations(); /** * The key type for the {@link Cache}. @@ -114,11 +114,15 @@ public interface CacheConfiguration { /** * Create a builder seeded with this configuration. + *

+ * The default implementation throws {@code UnsupportedOperationException} to indicate that configuration derivation + * is not supported. * * @see FluentConfigurationBuilder * @return a configuration builder + * @throws UnsupportedOperationException if configuration derivation is not supported */ - default FluentCacheConfigurationBuilder derive() { - return () -> this; + default FluentCacheConfigurationBuilder derive() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); } } diff --git a/api/src/main/java/org/ehcache/config/CacheRuntimeConfiguration.java b/api/src/main/java/org/ehcache/config/CacheRuntimeConfiguration.java index c111d5aaf6..26d30b59e2 100644 --- a/api/src/main/java/org/ehcache/config/CacheRuntimeConfiguration.java +++ b/api/src/main/java/org/ehcache/config/CacheRuntimeConfiguration.java @@ -21,6 +21,7 @@ import org.ehcache.event.EventOrdering; import org.ehcache.event.EventType; +import java.util.EnumSet; import java.util.Set; /** @@ -68,8 +69,10 @@ void registerCacheEventListener(CacheEventListener listene * * @throws java.lang.IllegalStateException if the listener is already registered */ - void registerCacheEventListener(CacheEventListener listener, - EventOrdering ordering, EventFiring firing, EventType eventType, EventType... eventTypes); + default void registerCacheEventListener(CacheEventListener listener, + EventOrdering ordering, EventFiring firing, EventType eventType, EventType... eventTypes) { + registerCacheEventListener(listener, ordering, firing, EnumSet.of(eventType, eventTypes)); + } /** * Deregisters a previously registered {@link org.ehcache.event.CacheEventListener CacheEventListener} instance. diff --git a/api/src/main/java/org/ehcache/config/FluentCacheConfigurationBuilder.java b/api/src/main/java/org/ehcache/config/FluentCacheConfigurationBuilder.java index f8c2aa4ede..2bd70992fa 100644 --- a/api/src/main/java/org/ehcache/config/FluentCacheConfigurationBuilder.java +++ b/api/src/main/java/org/ehcache/config/FluentCacheConfigurationBuilder.java @@ -16,15 +16,25 @@ package org.ehcache.config; -import org.ehcache.config.CacheConfiguration; +import org.ehcache.expiry.ExpiryPolicy; +import org.ehcache.spi.copy.Copier; +import org.ehcache.spi.loaderwriter.CacheLoaderWriter; +import org.ehcache.spi.resilience.ResilienceStrategy; +import org.ehcache.spi.serialization.Serializer; +import org.ehcache.spi.service.ServiceConfiguration; + +import java.util.Collection; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; /** * A fluent builder of {@link CacheConfiguration} instances. * * @param cache key type * @param cache value type + * @param builder sub-type */ -public interface FluentCacheConfigurationBuilder extends Builder> { +public interface FluentCacheConfigurationBuilder> extends Builder> { /** * Builds a new {@link CacheConfiguration}. @@ -32,5 +42,488 @@ public interface FluentCacheConfigurationBuilder extends Builder build(); + + /** + * Return the unique service configuration of the given type. + *

+ * If there are multiple configuration instances of this type (or subtypes) then an {@code IllegalArgumentException} + * will be thrown. + * + * @param configurationType desired configuration type + * @param configuration type + * @return the service configuration of the given type; @{code null} if there is no service configuration of the given type + * @throws IllegalArgumentException if there are multiple instances of this type + * + * @see #getServices(Class) + * @see #withService(ServiceConfiguration) + * @see #withService(Builder) + * @see #withoutServices(Class) + * @see #withoutServices(Class, Predicate) + * @see #updateServices(Class, UnaryOperator) + */ + default > C getService(Class configurationType) throws IllegalArgumentException { + Collection services = getServices(configurationType); + + switch (services.size()) { + case 0: + return null; + case 1: + return services.iterator().next(); + default: + throw new IllegalArgumentException(configurationType + " does not identify a unique service configuration: " + services); + } + } + + /** + * Returns all the service configurations of the given type. + * + * @param configurationType desired configuration type + * @param configuration type + * @return all services of this type + * + * @see #getService(Class) + * @see #withService(ServiceConfiguration) + * @see #withService(Builder) + * @see #withoutServices(Class) + * @see #withoutServices(Class, Predicate) + * @see #updateServices(Class, UnaryOperator) + */ + > Collection getServices(Class configurationType); + + /** + * Adds a service configuration to this configuration. + *

+ * This will remove any existing service configurations that are incompatible with the supplied one. + * This removal is equivalent to the following: + *

{@code configurations.removeIf(
+   *     existing -> !config.compatibleWith(existing) || !existing.compatibleWith(config)
+   * );}
+ * + * @param config service configuration + * @return an updated builder + * @see ServiceConfiguration#compatibleWith(ServiceConfiguration) + * + * @see #getService(Class) + * @see #getServices(Class) + * @see #withService(Builder) + * @see #withoutServices(Class) + * @see #withoutServices(Class, Predicate) + * @see #updateServices(Class, UnaryOperator) + */ + B withService(ServiceConfiguration config); + + /** + * Adds a service configuration built by the given builder to this configuration. + *

+ * This will remove any existing configurations that are incompatible with the configuration returned by + * {@code builder.build()}. + * + * @param builder service configuration builder + * @return an updated builder + * @see #withService(ServiceConfiguration) + * + * @see #getService(Class) + * @see #getServices(Class) + * @see #withService(ServiceConfiguration) + * @see #withoutServices(Class) + * @see #withoutServices(Class, Predicate) + * @see #updateServices(Class, UnaryOperator) + */ + default B withService(Builder> builder) { + return withService(builder.build()); + } + + /** + * Removes all service configurations of the given type from this configuration. + * + * @param clazz service configuration type + * @return an updated builder + * + * @see #getService(Class) + * @see #getServices(Class) + * @see #withService(ServiceConfiguration) + * @see #withService(Builder) + * @see #withoutServices(Class, Predicate) + * @see #updateServices(Class, UnaryOperator) + */ + default B withoutServices(Class> clazz) { + return withoutServices(clazz, c -> true); + } + + /** + * Removes all service configurations of the given type that pass the predicate. + * + * @param clazz service configuration type + * @param predicate predicate controlling removal + * @param configuration type + * @return an updated builder + * + * @see #getService(Class) + * @see #getServices(Class) + * @see #withService(ServiceConfiguration) + * @see #withService(Builder) + * @see #withoutServices(Class) + * @see #updateServices(Class, UnaryOperator) + */ + > B withoutServices(Class clazz, Predicate predicate); + + /** + * Updates all service configurations of the given type. + *

+ * For each existing service creation configuration instance that is assignment compatible with {@code clazz} the + * following process is performed: + *

    + *
  1. The configuration is converted to its detached representations using the + * {@link ServiceConfiguration#derive()} method.
  2. + *
  3. The detached representation is transformed using the {@code update} unary operator.
  4. + *
  5. A new configuration is generated by passing the transformed detached representation to the existing + * configurations {@link ServiceConfiguration#build(Object)} method.
  6. + *
  7. The new configuration is added to the builders service configuration set.
  8. + *
+ * If there are no service creation configurations assignment compatible with {@code clazz} then an + * {@code IllegalStateException} will be thrown. + * + * @param clazz service configuration concrete type + * @param update configuration mutation function + * @param configuration detached representation type + * @param service configuration type + * @return an updated builder + * @throws IllegalStateException if no matching service configurations exist + * + * @see #getService(Class) + * @see #getServices(Class) + * @see #withService(ServiceConfiguration) + * @see #withService(Builder) + * @see #withoutServices(Class) + * @see #withoutServices(Class, Predicate) + */ + > B updateServices(Class clazz, UnaryOperator update) throws IllegalStateException; + + /** + * Sets the {@link EvictionAdvisor} in the returned builder. + * + * @param evictionAdvisor the eviction advisor to be used + * @return a new builder with the added eviction advisor + * + * @see Eviction#NO_ADVICE + */ + B withEvictionAdvisor(final EvictionAdvisor evictionAdvisor); + + /** + * Sets the {@link ClassLoader} in the returned builder. + *

+ * The {@link ClassLoader} will be used for resolving all non Ehcache types. + * + * @param classLoader the class loader to use + * @return a new builder with the added class loader + * + * @see #withDefaultClassLoader() + */ + B withClassLoader(ClassLoader classLoader); + + /** + * Removes any previously installed custom class loader + * + * @return a new build using the default class loader + * + * @see #withClassLoader(ClassLoader) + */ + B withDefaultClassLoader(); + + /** + * Sets the {@link ResourcePools} in the returned builder. + *

+ * {@link ResourcePools} is what determines the tiering of a cache. + * + * @param resourcePools the resource pools to use + * @return a new builder with the added resource pools + * + * @see #withResourcePools(Builder) + * @see #updateResourcePools(UnaryOperator) + */ + B withResourcePools(ResourcePools resourcePools); + + /** + * Convenience method to set the {@link ResourcePools} through a {@link Builder}. + * + * @param builder the builder providing the resource pool + * @return a new builder with the added resource pools + * + * @see #withResourcePools(ResourcePools) + * @see #updateResourcePools(UnaryOperator) + */ + default B withResourcePools(Builder builder) { + return withResourcePools(builder.build()); + } + + /** + * Updates the configured resource pools. + * + * @param update resource pool update operation + * @return a new build with updated resource pools + * + * @see #withResourcePools(ResourcePools) + * @see #withResourcePools(Builder) + */ + B updateResourcePools(UnaryOperator update); + + /** + * Sets the {@link ExpiryPolicy} configuration in the returned builder. + *

+ * {@code ExpiryPolicy} is what controls data freshness in a cache. + * + * @param expiry the expiry to use + * @return a new builder with the added expiry + * + * @see ExpiryPolicy#NO_EXPIRY + */ + B withExpiry(ExpiryPolicy expiry); + + /** + * Sets the {@link CacheLoaderWriter} in the returned builder. + *

+ * Configuration of a {@link CacheLoaderWriter} is what enables cache-through patterns. + * + * @param loaderWriter the loaderwriter to use + * @return a new builder with the added loaderwriter configuration + * + * @see #withLoaderWriter(Class, Object...) + * @see #withoutLoaderWriter() + */ + B withLoaderWriter(CacheLoaderWriter loaderWriter); + + /** + * Sets the {@link CacheLoaderWriter} (using a class and constructor arguments) in the returned builder. + *

+ * Configuration of a {@link CacheLoaderWriter} is what enables cache-through patterns. + * + * @param loaderWriterClass the loaderwrite class + * @param arguments optional constructor arguments + * @return a new builder with the added loaderwriter configuration + * + * @see #withLoaderWriter(CacheLoaderWriter) + * @see #withoutLoaderWriter() + */ + B withLoaderWriter(Class> loaderWriterClass, Object... arguments); + + /** + * Removes any configured loader-writer. + * + * @return a new build with no configured loader-writer + * + * @see #withLoaderWriter(CacheLoaderWriter) + * @see #withLoaderWriter(Class, Object...) + */ + B withoutLoaderWriter(); + + /** + * Sets the {@link ResilienceStrategy} in the returned builder. + * + * @param resilienceStrategy the resilience strategy to use + * @return a new builder with the added resilience strategy configuration + * + * @see #withResilienceStrategy(Class, Object...) + * @see #withDefaultResilienceStrategy() + */ + B withResilienceStrategy(ResilienceStrategy resilienceStrategy); + + /** + * Sets the {@link ResilienceStrategy} (using a class and constructor arguments) in the returned builder. + * + * @param resilienceStrategyClass the resilience strategy class + * @param arguments optional constructor arguments + * @return a new builder with the added resilience strategy configuration + * + * @see #withResilienceStrategy(ResilienceStrategy) + * @see #withDefaultResilienceStrategy() + */ + @SuppressWarnings("rawtypes") + B withResilienceStrategy(Class resilienceStrategyClass, Object... arguments); + + /** + * Restores configuration of the implementations default resilience strategy. + * + * @return a new builder using the default resilience strategy + * + * @see #withResilienceStrategy(ResilienceStrategy) + * @see #withResilienceStrategy(Class, Object...) + */ + B withDefaultResilienceStrategy(); + + /** + * Adds by-value semantics using the cache key serializer for the key on heap. + *

+ * {@link Copier}s are what enable control of by-reference / by-value semantics for on-heap tier. + * + * @return a new builder with the added key copier + * + * @see #withKeyCopier(Copier) + * @see #withKeyCopier(Class) + * @see #withoutKeyCopier() + */ + B withKeySerializingCopier(); + + /** + * Adds by-value semantics using the cache value serializer for the value on heap. + *

+ * {@link Copier}s are what enable control of by-reference / by-value semantics for on-heap tier. + * + * @return a new builder with the added value copier + * + * @see #withValueCopier(Copier) + * @see #withValueCopier(Class) + * @see #withoutValueCopier() + */ + B withValueSerializingCopier(); + + /** + * Adds by-value semantics using the provided {@link Copier} for the key on heap. + *

+ * {@link Copier}s are what enable control of by-reference / by-value semantics for on-heap tier. + * + * @param keyCopier the key copier to use + * @return a new builder with the added key copier + * + * @see #withKeySerializingCopier() + * @see #withKeyCopier(Class) + * @see #withoutKeyCopier() + */ + B withKeyCopier(Copier keyCopier); + + /** + * Adds by-value semantics using the provided {@link Copier} class for the key on heap. + *

+ * {@link Copier}s are what enable control of by-reference / by-value semantics for on-heap tier. + * + * @param keyCopierClass the key copier class to use + * @return a new builder with the added key copier + * + * @see #withKeySerializingCopier() + * @see #withKeyCopier(Copier) + * @see #withoutKeyCopier() + */ + B withKeyCopier(Class> keyCopierClass); + + /** + * Removes any configured {@link Copier} for keys on heap. + * + * @return a new builder without a key copier + * + * @see #withKeySerializingCopier() + * @see #withKeyCopier(Copier) + * @see #withKeyCopier(Class) + */ + B withoutKeyCopier(); + + /** + * Adds by-value semantics using the provided {@link Copier} for the value on heap. + *

+ * {@link Copier}s are what enable control of by-reference / by-value semantics for on-heap tier. + * + * @param valueCopier the value copier to use + * @return a new builder with the added value copier + * + * @see #withValueSerializingCopier() + * @see #withValueCopier(Class) + * @see #withoutValueCopier() + */ + B withValueCopier(Copier valueCopier); + + /** + * Adds by-value semantics using the provided {@link Copier} class for the value on heap. + *

+ * {@link Copier}s are what enable control of by-reference / by-value semantics for on-heap tier. + * + * @param valueCopierClass the value copier class to use + * @return a new builder with the added value copier + * + * @see #withValueSerializingCopier() + * @see #withValueCopier(Copier) + * @see #withoutValueCopier() + */ + B withValueCopier(Class> valueCopierClass); + + /** + * Removes any configured {@link Copier} for values on heap. + * + * @return a new builder without a value copier + * + * @see #withValueSerializingCopier() + * @see #withValueCopier(Copier) + * @see #withValueCopier(Class) + */ + B withoutValueCopier(); + + /** + * Sets the {@link Serializer} for cache keys in the returned builder. + *

+ * {@link Serializer}s are what enables cache storage beyond the heap tier. + * + * @param keySerializer the key serializer to use + * @return a new builder with the added key serializer + * + * @see #withKeySerializer(Class) + * @see #withDefaultKeySerializer() + */ + B withKeySerializer(Serializer keySerializer); + + /** + * Sets the {@link Serializer} class for cache keys in the returned builder. + *

+ * {@link Serializer}s are what enables cache storage beyond the heap tier. + * + * @param keySerializerClass the key serializer to use + * @return a new builder with the added key serializer + * + * @see #withKeySerializer(Serializer) + * @see #withDefaultKeySerializer() + */ + B withKeySerializer(Class> keySerializerClass); + + /** + * Removes any explicitly configured {@link Serializer} for cache keys. + * + * @return a new builder with no configured key serializer + * + * @see #withKeySerializer(Serializer) + * @see #withKeySerializer(Class) + */ + B withDefaultKeySerializer(); + + /** + * Sets the {@link Serializer} for cache values in the returned builder. + *

+ * {@link Serializer}s are what enables cache storage beyond the heap tier. + * + * @param valueSerializer the key serializer to use + * @return a new builder with the added value serializer + * + * @see #withValueSerializer(Class) + * @see #withDefaultValueSerializer() + */ + B withValueSerializer(Serializer valueSerializer); + + /** + * Sets the {@link Serializer} class for cache values in the returned builder. + *

+ * {@link Serializer}s are what enables cache storage beyond the heap tier. + * + * @param valueSerializerClass the key serializer to use + * @return a new builder with the added value serializer + * + * @see #withValueSerializer(Serializer) + * @see #withDefaultValueSerializer() + */ + B withValueSerializer(Class> valueSerializerClass); + + /** + * Removes any explicitly configured {@link Serializer} for cache values. + * + * @return a new builder with no configured value serializer + * + * @see #withValueSerializer(Serializer) + * @see #withValueSerializer(Class) + */ + B withDefaultValueSerializer(); } diff --git a/api/src/main/java/org/ehcache/config/FluentConfigurationBuilder.java b/api/src/main/java/org/ehcache/config/FluentConfigurationBuilder.java index 20e1cde5b4..0b2495f111 100644 --- a/api/src/main/java/org/ehcache/config/FluentConfigurationBuilder.java +++ b/api/src/main/java/org/ehcache/config/FluentConfigurationBuilder.java @@ -116,7 +116,7 @@ default B withCache(String alias, Builder> bu * @see #withoutCache(String) * @see #updateCaches(UnaryOperator) */ - B updateCache(String alias, UnaryOperator> update) throws IllegalArgumentException; + B updateCache(String alias, UnaryOperator> update) throws IllegalArgumentException; /** * Updates the configuration of the all caches. diff --git a/api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java b/api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java index c50c95abaa..979d319a25 100644 --- a/api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java +++ b/api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java @@ -48,6 +48,11 @@ public interface ExpiryPolicy { * An {@code ExpiryPolicy} that represents a no expiration policy */ ExpiryPolicy NO_EXPIRY = new ExpiryPolicy() { + @Override + public String toString() { + return "No Expiry"; + } + @Override public Duration getExpiryForCreation(Object key, Object value) { return INFINITE; diff --git a/api/src/main/java/org/ehcache/spi/copy/CopyProvider.java b/api/src/main/java/org/ehcache/spi/copy/CopyProvider.java index d52f1ff636..076c0cda39 100644 --- a/api/src/main/java/org/ehcache/spi/copy/CopyProvider.java +++ b/api/src/main/java/org/ehcache/spi/copy/CopyProvider.java @@ -43,7 +43,7 @@ public interface CopyProvider extends Service { * @param the type to copy to/from * @return a non {@code null} {@link Copier} instance */ - Copier createKeyCopier(Class clazz, Serializer serializer, ServiceConfiguration... configs); + Copier createKeyCopier(Class clazz, Serializer serializer, ServiceConfiguration... configs); /** * Creates a value {@link Copier} with the given parameters. @@ -56,7 +56,7 @@ public interface CopyProvider extends Service { * @param the type to copy to/from * @return a non {@code null} {@link Copier} instance */ - Copier createValueCopier(Class clazz, Serializer serializer, ServiceConfiguration... configs); + Copier createValueCopier(Class clazz, Serializer serializer, ServiceConfiguration... configs); /** * Releases the provided {@link Copier} instance. diff --git a/api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterConfiguration.java b/api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterConfiguration.java index dbe07f0318..dee84aec39 100644 --- a/api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterConfiguration.java +++ b/api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterConfiguration.java @@ -22,8 +22,10 @@ *

* The {@code CacheLoaderWriterProvider} provides write-behind services to a * {@link org.ehcache.Cache Cache}. + * + * @param representation type */ -public interface CacheLoaderWriterConfiguration extends ServiceConfiguration { +public interface CacheLoaderWriterConfiguration extends ServiceConfiguration { /** * {@inheritDoc} */ diff --git a/api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterProvider.java b/api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterProvider.java index 34f77b1114..cbef48f166 100644 --- a/api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterProvider.java +++ b/api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterProvider.java @@ -65,7 +65,7 @@ public interface CacheLoaderWriterProvider extends Service { * * @return {@code CacheLoaderWriterConfiguration} configured for the {@code Cache}, otherwise null */ - CacheLoaderWriterConfiguration getPreConfiguredCacheLoaderWriterConfig(String alias); + CacheLoaderWriterConfiguration getPreConfiguredCacheLoaderWriterConfig(String alias); /** * Checks whether {@link org.ehcache.spi.loaderwriter.CacheLoaderWriter} was provided using jsr api diff --git a/api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindConfiguration.java b/api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindConfiguration.java index b71622f044..b178e56575 100644 --- a/api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindConfiguration.java +++ b/api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindConfiguration.java @@ -24,8 +24,10 @@ *

* The {@code WriteBehindProvider} provides write-behind services to a * {@link org.ehcache.Cache Cache}. + * + * @param representation type */ -public interface WriteBehindConfiguration extends ServiceConfiguration { +public interface WriteBehindConfiguration extends ServiceConfiguration { /** * The concurrency of the write behind engines queues. diff --git a/api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindProvider.java b/api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindProvider.java index baa7d0b92a..905faf19a8 100644 --- a/api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindProvider.java +++ b/api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindProvider.java @@ -37,7 +37,7 @@ public interface WriteBehindProvider extends Service { * * @return the write-behind decorated loader writer */ - CacheLoaderWriter createWriteBehindLoaderWriter(CacheLoaderWriter cacheLoaderWriter, WriteBehindConfiguration configuration); + CacheLoaderWriter createWriteBehindLoaderWriter(CacheLoaderWriter cacheLoaderWriter, WriteBehindConfiguration configuration); /** * Releases a write-behind decorator when the associated {@link org.ehcache.Cache Cache} diff --git a/api/src/main/java/org/ehcache/spi/persistence/PersistableResourceService.java b/api/src/main/java/org/ehcache/spi/persistence/PersistableResourceService.java index 41e9e12cd2..43453d3e36 100644 --- a/api/src/main/java/org/ehcache/spi/persistence/PersistableResourceService.java +++ b/api/src/main/java/org/ehcache/spi/persistence/PersistableResourceService.java @@ -105,5 +105,5 @@ public interface PersistableResourceService extends MaintainableService { /** * An identifier for an existing persistable resource. */ - interface PersistenceSpaceIdentifier extends ServiceConfiguration {} + interface PersistenceSpaceIdentifier extends ServiceConfiguration {} } diff --git a/api/src/main/java/org/ehcache/spi/serialization/SerializationProvider.java b/api/src/main/java/org/ehcache/spi/serialization/SerializationProvider.java index a297362b08..05befb3695 100644 --- a/api/src/main/java/org/ehcache/spi/serialization/SerializationProvider.java +++ b/api/src/main/java/org/ehcache/spi/serialization/SerializationProvider.java @@ -50,7 +50,7 @@ public interface SerializationProvider extends Service { * * @throws UnsupportedTypeException if a serializer cannot be created for the given type */ - Serializer createKeySerializer(Class clazz, ClassLoader classLoader, ServiceConfiguration... configs) throws UnsupportedTypeException; + Serializer createKeySerializer(Class clazz, ClassLoader classLoader, ServiceConfiguration... configs) throws UnsupportedTypeException; /** * Creates a value {@link Serializer} with the given parameters. @@ -65,7 +65,7 @@ public interface SerializationProvider extends Service { * * @throws UnsupportedTypeException if a serializer cannot be created for the given type */ - Serializer createValueSerializer(Class clazz, ClassLoader classLoader, ServiceConfiguration... configs) throws UnsupportedTypeException; + Serializer createValueSerializer(Class clazz, ClassLoader classLoader, ServiceConfiguration... configs) throws UnsupportedTypeException; /** * Releases the given {@link Serializer} instance. diff --git a/api/src/main/java/org/ehcache/spi/service/ServiceConfiguration.java b/api/src/main/java/org/ehcache/spi/service/ServiceConfiguration.java index b7766dc7cf..2358109150 100644 --- a/api/src/main/java/org/ehcache/spi/service/ServiceConfiguration.java +++ b/api/src/main/java/org/ehcache/spi/service/ServiceConfiguration.java @@ -20,9 +20,9 @@ * A configuration type to be used when interacting with a {@link Service}. * * @param the service type this configuration works with - * + * @param the type of the detached representation */ -public interface ServiceConfiguration { +public interface ServiceConfiguration { /** * Indicates which service this configuration works with. @@ -30,4 +30,38 @@ public interface ServiceConfiguration { * @return the service type */ Class getServiceType(); + + /** + * Derive a detached representation from this configuration + * + * @return a detached representation + * @throws UnsupportedOperationException if the configuration has no representation + */ + default R derive() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Construct a new configuration from the given detached representation. + * + * @param representation a detached representation + * @return a new configuration + * @throws UnsupportedOperationException if the configuration has no representation + */ + default ServiceConfiguration build(R representation) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Returns true if this configuration can co-exist with {@code other} in the same cache configuration. + *

+ * The default implementation of {@code compatibleWith} (as used by many of the implementations) considers any + * instance of the same type (or a sub-type) to be incompatible with this instance. + * + * @param other other service configuration + * @return {@code true} if the two configurations are compatible + */ + default boolean compatibleWith(ServiceConfiguration other) { + return !getClass().isInstance(other); + }; } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteredStoreConfiguration.java b/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteredStoreConfiguration.java index 7faa760d85..5c39d03ce3 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteredStoreConfiguration.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteredStoreConfiguration.java @@ -23,7 +23,7 @@ /** * {@link ServiceConfiguration} for the {@link ClusteredStore}. */ -public class ClusteredStoreConfiguration implements ServiceConfiguration { +public class ClusteredStoreConfiguration implements ServiceConfiguration { private final Consistency consistency; @@ -59,4 +59,14 @@ public Class getServiceType() { public Consistency getConsistency() { return consistency; } + + @Override + public Consistency derive() { + return getConsistency(); + } + + @Override + public ClusteredStoreConfiguration build(Consistency representation) { + return new ClusteredStoreConfiguration(representation); + } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/ClusteredResourcePoolImpl.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/ClusteredResourcePoolImpl.java index 5e91d126a9..35bab3ea89 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/ClusteredResourcePoolImpl.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/ClusteredResourcePoolImpl.java @@ -20,7 +20,7 @@ import org.ehcache.clustered.client.config.ClusteredResourcePool; import org.ehcache.clustered.common.PoolAllocation; import org.ehcache.config.ResourcePool; -import org.ehcache.core.config.AbstractResourcePool; +import org.ehcache.impl.config.AbstractResourcePool; /** * Implementation for {@link ClusteredResourcePool}. diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/DedicatedClusteredResourcePoolImpl.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/DedicatedClusteredResourcePoolImpl.java index dd5eed3d30..b45f234bc6 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/DedicatedClusteredResourcePoolImpl.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/DedicatedClusteredResourcePoolImpl.java @@ -21,7 +21,7 @@ import org.ehcache.config.ResourcePool; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.HumanReadable; -import org.ehcache.core.config.SizedResourcePoolImpl; +import org.ehcache.impl.config.SizedResourcePoolImpl; import org.ehcache.clustered.client.config.DedicatedClusteredResourcePool; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/SharedClusteredResourcePoolImpl.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/SharedClusteredResourcePoolImpl.java index 5f74e57cce..338bd2046a 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/SharedClusteredResourcePoolImpl.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/SharedClusteredResourcePoolImpl.java @@ -20,7 +20,7 @@ import org.ehcache.clustered.client.config.SharedClusteredResourcePool; import org.ehcache.clustered.common.PoolAllocation; import org.ehcache.config.ResourcePool; -import org.ehcache.core.config.AbstractResourcePool; +import org.ehcache.impl.config.AbstractResourcePool; /** * Implementation for {@link SharedClusteredResourcePool}. diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java index fb3fa2c357..35be7d00c4 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java @@ -62,7 +62,7 @@ public URI getNamespace() { } @Override - public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { + public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { if (CLUSTERED_STORE_ELEMENT_NAME.equals(fragment.getLocalName())) { if (fragment.hasAttribute(CONSISTENCY_ATTRIBUTE_NAME)) { return new ClusteredStoreConfiguration(Consistency.valueOf(fragment.getAttribute("consistency").toUpperCase())); @@ -80,7 +80,7 @@ public Class getServiceType() { } @Override - public Element unparseServiceConfiguration(ServiceConfiguration serviceConfiguration) { + public Element unparseServiceConfiguration(ServiceConfiguration serviceConfiguration) { return unparseConfig(serviceConfiguration); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java index ed8c4505a2..66d4457ffb 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java @@ -308,7 +308,7 @@ protected ClusteredStore createStore(Configuration storeConfi } @Override - public int rank(Set> resourceTypes, Collection> serviceConfigs) { + public int rank(Set> resourceTypes, Collection> serviceConfigs) { int parentRank = super.rank(resourceTypes, serviceConfigs); if (parentRank == 0 || serviceConfigs.stream().noneMatch(CacheLoaderWriterConfiguration.class::isInstance)) { return 0; @@ -317,7 +317,7 @@ public int rank(Set> resourceTypes, Collection authorityResource, Collection> serviceConfigs) { + public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { int parentRank = super.rankAuthority(authorityResource, serviceConfigs); if (parentRank == 0 || serviceConfigs.stream().noneMatch(CacheLoaderWriterConfiguration.class::isInstance)) { return 0; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java index 0f356a4da8..2856814131 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java @@ -33,18 +33,18 @@ public class DelegatingLoaderWriterStoreProvider extends AbstractWrapperStoreProvider { @Override - protected Store wrap(Store store, Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + protected Store wrap(Store store, Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { return new DelegatingLoaderWriterStore<>(store); } @Override - public int rank(Set> resourceTypes, Collection> serviceConfigs) { + public int rank(Set> resourceTypes, Collection> serviceConfigs) { throw new UnsupportedOperationException("Its a Wrapper store provider, does not support regular ranking"); } @Override - public int wrapperStoreRank(Collection> serviceConfigs) { - CacheLoaderWriterConfiguration loaderWriterConfiguration = findSingletonAmongst(CacheLoaderWriterConfiguration.class, serviceConfigs); + public int wrapperStoreRank(Collection> serviceConfigs) { + CacheLoaderWriterConfiguration loaderWriterConfiguration = findSingletonAmongst(CacheLoaderWriterConfiguration.class, serviceConfigs); ClusteredCacheIdentifier clusteredCacheIdentifier = findSingletonAmongst(ClusteredCacheIdentifier.class, serviceConfigs); if (clusteredCacheIdentifier != null && loaderWriterConfiguration != null) { return 3; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java index 4f06701007..c96c622e78 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java @@ -256,7 +256,7 @@ protected ClusteredStore createStore(Configuration storeConfi TimeSource timeSource, boolean useLoaderInAtomics, Object[] serviceConfigs) { - WriteBehindConfiguration writeBehindConfiguration = findSingletonAmongst(WriteBehindConfiguration.class, serviceConfigs); + WriteBehindConfiguration writeBehindConfiguration = findSingletonAmongst(WriteBehindConfiguration.class, serviceConfigs); if (writeBehindConfiguration != null) { ExecutorService executorService = executionService.getOrderedExecutor(writeBehindConfiguration.getThreadPoolAlias(), @@ -282,7 +282,7 @@ protected ServerStoreProxy.ServerCallback getServerCallback(ClusteredStor } @Override - public int rank(Set> resourceTypes, Collection> serviceConfigs) { + public int rank(Set> resourceTypes, Collection> serviceConfigs) { int parentRank = super.rank(resourceTypes, serviceConfigs); if (parentRank == 0 || serviceConfigs.stream().noneMatch(WriteBehindConfiguration.class::isInstance)) { return 0; @@ -291,7 +291,7 @@ public int rank(Set> resourceTypes, Collection authorityResource, Collection> serviceConfigs) { + public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { int parentRank = super.rankAuthority(authorityResource, serviceConfigs); if (parentRank == 0 || serviceConfigs.stream().noneMatch(WriteBehindConfiguration.class::isInstance)) { return 0; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index 0da2ae3234..db5ff3387b 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -609,7 +609,7 @@ protected ClusteredResourceType getResourceType() { } @Override - public ClusteredStore createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public ClusteredStore createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { ClusteredStore store = createStoreInternal(storeConfig, serviceConfigs); tierOperationStatistics.put(store, new OperationStatistic[] { @@ -623,7 +623,7 @@ public ClusteredStore createStore(Configuration storeConfig, private ClusteredStore createStoreInternal(Configuration storeConfig, Object[] serviceConfigs) { connectLock.lock(); try { - CacheEventListenerConfiguration eventListenerConfiguration = findSingletonAmongst(CacheEventListenerConfiguration.class, serviceConfigs); + CacheEventListenerConfiguration eventListenerConfiguration = findSingletonAmongst(CacheEventListenerConfiguration.class, serviceConfigs); if (eventListenerConfiguration != null) { if (eventListenerConfiguration.firingMode() == EventFiring.SYNCHRONOUS) { // Forget it. Never. @@ -854,7 +854,7 @@ public void compact(ServerStoreProxy.ChainEntry chain) { } @Override - public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { + public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { if (clusteringService == null || resourceTypes.size() > 1 || Collections.disjoint(resourceTypes, CLUSTER_RESOURCES)) { // A ClusteredStore requires a ClusteringService *and* ClusteredResourcePool instances return 0; @@ -863,7 +863,7 @@ public int rank(final Set> resourceTypes, final Collection authorityResource, Collection> serviceConfigs) { + public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { if (clusteringService == null) { return 0; } else { @@ -895,7 +895,7 @@ public void stop() { } @Override - public AuthoritativeTier createAuthoritativeTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public AuthoritativeTier createAuthoritativeTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { ClusteredStore authoritativeTier = createStoreInternal(storeConfig, serviceConfigs); tierOperationStatistics.put(authoritativeTier, new OperationStatistic[] { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java index be4181afa6..aad2ca8b25 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java @@ -54,7 +54,7 @@ public class BasicClusteredCacheExpiryTest { ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(1L))) - .add(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG))); + .withService(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG))); @Before public void definePassthroughServer() throws Exception { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java index 914a5aa088..6311fc33e1 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java @@ -94,8 +94,7 @@ public void testClusteredCacheTwoClients() throws Exception { .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(100, EntryUnit.ENTRIES) .with(clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) - .add(new ClusteredStoreConfiguration(Consistency.STRONG))) - ; + .withService(new ClusteredStoreConfiguration(Consistency.STRONG))); final PersistentCacheManager cacheManager1 = clusteredCacheManagerBuilder.build(true); final PersistentCacheManager cacheManager2 = clusteredCacheManagerBuilder.build(true); @@ -123,8 +122,7 @@ public void testClustered3TierCacheTwoClients() throws Exception { .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(1, EntryUnit.ENTRIES).offheap(1, MemoryUnit.MB) .with(clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) - .add(new ClusteredStoreConfiguration(Consistency.STRONG))) - ; + .withService(new ClusteredStoreConfiguration(Consistency.STRONG))); final PersistentCacheManager cacheManager1 = clusteredCacheManagerBuilder.build(true); final PersistentCacheManager cacheManager2 = clusteredCacheManagerBuilder.build(true); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java index 63f651e763..808cd71982 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java @@ -61,7 +61,7 @@ public class ClusteredCacheDestroyTest { .withCache(CLUSTERED_CACHE, newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) - .add(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG))); + .withService(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG))); @Before public void definePassthroughServer() throws Exception { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java index 96547a30a7..f0b460f036 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java @@ -66,7 +66,7 @@ private CacheManagerBuilder cacheManagerBuilder(ExpiryPo .offheap(6, MemoryUnit.MB) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) .withExpiry(expiry) - .add(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG))); + .withService(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG))); } private ExpiryPolicy oneSecondExpiration() { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java index 43ebff5ce4..8a015d870a 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java @@ -101,7 +101,7 @@ private Runnable content(final CountDownLatch latch) { .withCache(CACHE_NAME, CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) - .add(new ClusteredStoreConfiguration(Consistency.STRONG))); + .withService(new ClusteredStoreConfiguration(Consistency.STRONG))); latch.countDown(); try { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java index 92e9b1f524..43eef7e3d8 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java @@ -83,7 +83,7 @@ public void testClusteredCacheWithOrderedEventListeners() { CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) - .add(cacheEventListenerConfiguration) + .withService(cacheEventListenerConfiguration) .build(); cacheManager.createCache("test", config); @@ -110,7 +110,7 @@ public void testClusteredCacheWithSynchronousEventListeners() { CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) - .add(cacheEventListenerConfiguration) + .withService(cacheEventListenerConfiguration) .build(); cacheManager.createCache("test", config); @@ -137,7 +137,7 @@ public void testClusteredCacheWithXA() throws Exception { ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB)) ) - .add(new XAStoreConfiguration("xaCache")) + .withService(new XAStoreConfiguration("xaCache")) .build() ) .build(true); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredConfigurationDerivationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredConfigurationDerivationTest.java new file mode 100644 index 0000000000..5c98d54751 --- /dev/null +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredConfigurationDerivationTest.java @@ -0,0 +1,50 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered.client.config; + +import org.ehcache.clustered.common.Consistency; +import org.ehcache.config.Configuration; +import org.ehcache.xml.XmlConfiguration; +import org.junit.Test; + +import java.net.URI; + +import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class ClusteredConfigurationDerivationTest { + private static final String SIMPLE_CLUSTER_XML = "/configs/simple-cluster.xml"; + private static final URI UPDATED_CLUSTER_URI = URI.create("terracotta://updated.example.com:9540/cachemanager"); + + @Test + public void testUpdateUri() throws Exception { + final XmlConfiguration configuration = new XmlConfiguration(this.getClass().getResource(SIMPLE_CLUSTER_XML)); + + Configuration newServer = configuration.derive().updateServices(ClusteringServiceConfiguration.class, existing -> + existing.usingUri(UPDATED_CLUSTER_URI)).build(); + assertThat(findSingletonAmongst(ClusteringServiceConfiguration.class, newServer.getServiceCreationConfigurations()).getClusterUri(), is(UPDATED_CLUSTER_URI)); + } + + @Test + public void testAddConsistency() { + final XmlConfiguration configuration = new XmlConfiguration(this.getClass().getResource(SIMPLE_CLUSTER_XML)); + + Configuration newConsistency = configuration.derive().updateCache("simple-cache", existing -> + existing.withService(new ClusteredStoreConfiguration(Consistency.STRONG))).build(); + assertThat(findSingletonAmongst(ClusteredStoreConfiguration.class, newConsistency.getCacheConfigurations().get("simple-cache").getServiceConfigurations()).getConsistency(), is(Consistency.STRONG)); + } +} diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredStoreConfigurationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredStoreConfigurationTest.java new file mode 100644 index 0000000000..408533807f --- /dev/null +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredStoreConfigurationTest.java @@ -0,0 +1,38 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered.client.config; + +import org.ehcache.clustered.common.Consistency; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +public class ClusteredStoreConfigurationTest { + + @Test + public void testDeriveDetachesProperly() { + ClusteredStoreConfiguration configuration = new ClusteredStoreConfiguration(Consistency.EVENTUAL); + ClusteredStoreConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getConsistency(), is(configuration.getConsistency())); + } +} diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java index 93d899629b..00d335dfd7 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java @@ -131,7 +131,7 @@ public void explicitConsistencyConfiguration() throws Exception { CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) - .add(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG)) // <1> + .withService(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG)) // <1> .build(); Cache cache = cacheManager.createCache("clustered-cache", config); @@ -159,7 +159,7 @@ public void clusteredCacheTieredExample() throws Exception { ResourcePoolsBuilder.newResourcePoolsBuilder() .heap(2, MemoryUnit.MB) // <1> .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) // <2> - .add(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG)) + .withService(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG)) .build(); Cache cache = cacheManager.createCache("clustered-cache-tiered", config); @@ -224,7 +224,7 @@ public void unknownClusteredCacheExample() CacheConfiguration cacheConfigDedicated = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) // <2> - .add(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG)) + .withService(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG)) .build(); Cache cacheDedicated = cacheManager1.createCache("my-dedicated-cache", cacheConfigDedicated); // <3> @@ -240,7 +240,7 @@ public void unknownClusteredCacheExample() CacheConfiguration cacheConfigUnspecified = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clustered())) // <5> - .add(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG)) + .withService(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG)) .build(); Cache cacheUnspecified = cacheManager2.createCache("my-dedicated-cache", cacheConfigUnspecified); // <6> diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java index b8bf723321..477b364301 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java @@ -37,7 +37,7 @@ public class ClusteredLoaderWriterStoreProviderTest { - private final CacheLoaderWriterConfiguration cacheLoaderWriterConfiguration = mock(CacheLoaderWriterConfiguration.class); + private final CacheLoaderWriterConfiguration cacheLoaderWriterConfiguration = mock(CacheLoaderWriterConfiguration.class); @Test public void testRank() { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java index 489c772f0b..97478a704e 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java @@ -39,8 +39,8 @@ public class ClusteredWriteBehindStoreProviderTest { - private final CacheLoaderWriterConfiguration cacheLoaderWriterConfiguration = mock(CacheLoaderWriterConfiguration.class); - private final WriteBehindConfiguration writeBehindConfiguration = mock(WriteBehindConfiguration.class); + private final CacheLoaderWriterConfiguration cacheLoaderWriterConfiguration = mock(CacheLoaderWriterConfiguration.class); + private final WriteBehindConfiguration writeBehindConfiguration = mock(WriteBehindConfiguration.class); @Test public void testRank() { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java index 246e6cdc0b..ac032505be 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java @@ -30,7 +30,7 @@ import org.ehcache.clustered.lock.server.VoltronReadWriteLockServerEntityService; import org.ehcache.clustered.server.ClusterTierManagerServerEntityService; import org.ehcache.clustered.server.store.ClusterTierServerEntityService; -import org.ehcache.core.config.BaseCacheConfiguration; +import org.ehcache.impl.config.BaseCacheConfiguration; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.spi.persistence.StateHolder; import org.junit.After; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java index 1737a3304a..b8d188035e 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java @@ -29,7 +29,7 @@ import org.ehcache.clustered.lock.server.VoltronReadWriteLockServerEntityService; import org.ehcache.clustered.server.ClusterTierManagerServerEntityService; import org.ehcache.clustered.server.store.ClusterTierServerEntityService; -import org.ehcache.core.config.BaseCacheConfiguration; +import org.ehcache.impl.config.BaseCacheConfiguration; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.spi.persistence.StateHolder; import org.junit.After; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java index 1b922b6337..93ccf19544 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java @@ -27,7 +27,7 @@ import org.ehcache.config.ResourceType; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.config.ResourcePoolsImpl; +import org.ehcache.impl.config.ResourcePoolsImpl; import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.store.Store; @@ -124,14 +124,14 @@ public void testAuthoritativeRank() throws Exception { ServiceLocator serviceLocator = dependencySet().with(mock(ClusteringService.class)).build(); provider.start(serviceLocator); - assertThat(provider.rankAuthority(ClusteredResourceType.Types.DEDICATED, Collections.>emptyList()), is(1)); - assertThat(provider.rankAuthority(ClusteredResourceType.Types.SHARED, Collections.>emptyList()), is(1)); - assertThat(provider.rankAuthority(new UnmatchedResourceType(), Collections.>emptyList()), is(0)); + assertThat(provider.rankAuthority(ClusteredResourceType.Types.DEDICATED, Collections.>emptyList()), is(1)); + assertThat(provider.rankAuthority(ClusteredResourceType.Types.SHARED, Collections.>emptyList()), is(1)); + assertThat(provider.rankAuthority(new UnmatchedResourceType(), Collections.>emptyList()), is(0)); } private void assertRank(final Store.Provider provider, final int expectedRank, final ResourceType... resources) { - final List> serviceConfigs = Collections.emptyList(); + final List> serviceConfigs = Collections.emptyList(); if (expectedRank == -1) { try { provider.rank(new HashSet<>(Arrays.asList(resources)), diff --git a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java index fdaade8afe..e6f1ad7982 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java @@ -248,8 +248,8 @@ private PersistentCacheManager createCacheManager() { .offheap(1, MemoryUnit.MB) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) .withLoaderWriter(loaderWriter) - .add(WriteBehindConfigurationBuilder.newUnBatchedWriteBehindConfiguration()) - .add(new ClusteredStoreConfiguration(Consistency.STRONG)) + .withService(WriteBehindConfigurationBuilder.newUnBatchedWriteBehindConfiguration()) + .withService(new ClusteredStoreConfiguration(Consistency.STRONG)) .build(); return CacheManagerBuilder diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index 0aa5f2adad..846ce29299 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -169,13 +169,13 @@ private static PersistentCacheManager createCacheManager(URI clusterURI) { .newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(resourcePool)) - .add(new ClusteredStoreConfiguration(Consistency.STRONG))) + .withService(new ClusteredStoreConfiguration(Consistency.STRONG))) .withCache(SYN_CACHE_NAME, CacheConfigurationBuilder .newCacheConfigurationBuilder(String.class, Boolean.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(resourcePool)) - .add(new ClusteredStoreConfiguration(Consistency.STRONG))); + .withService(new ClusteredStoreConfiguration(Consistency.STRONG))); return clusteredCacheManagerBuilder.build(false); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java index 2608be4ae3..e9f19abd82 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java @@ -113,7 +113,7 @@ public void basicCacheCAS() throws Exception { .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(100, EntryUnit.ENTRIES) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) - .add(new ClusteredStoreConfiguration(Consistency.STRONG))); + .withService(new ClusteredStoreConfiguration(Consistency.STRONG))); try (PersistentCacheManager cacheManager1 = clusteredCacheManagerBuilder.build(true)) { @@ -141,7 +141,7 @@ public void basicClusteredBulk() throws Exception { .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) - .add(new ClusteredStoreConfiguration(Consistency.STRONG))); + .withService(new ClusteredStoreConfiguration(Consistency.STRONG))); try (PersistentCacheManager cacheManager1 = clusteredCacheManagerBuilder.build(true)) { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java index 9b40eddc6c..72620af66f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java @@ -118,7 +118,7 @@ private CacheConfiguration getCacheConfig() { .heap(20) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) .withLoaderWriter(new TestCacheLoaderWriter(sor)) - .add(ClusteredStoreConfigurationBuilder.withConsistency(cacheConsistency)) + .withService(ClusteredStoreConfigurationBuilder.withConsistency(cacheConsistency)) .withResilienceStrategy(new ThrowingResilienceStrategy<>()) .build(); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java index 948f1eb963..e7142cd121 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java @@ -92,7 +92,7 @@ private PersistentCacheManager createCacheManager() { .withCache(CACHE_NAME, newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(100, EntryUnit.ENTRIES) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) - .add(new ClusteredStoreConfiguration(Consistency.STRONG))); + .withService(new ClusteredStoreConfiguration(Consistency.STRONG))); return clusteredCacheManagerBuilder.build(true); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index 5294050489..d69af161f8 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -99,7 +99,7 @@ private static Cache createCache(CacheManager cacheManager, CacheE ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 4, MemoryUnit.MB))) .withResilienceStrategy(new ThrowingResiliencyStrategy<>()) - .add(CacheEventListenerConfigurationBuilder + .withService(CacheEventListenerConfigurationBuilder .newEventListenerConfiguration(cacheEventListener, EnumSet.allOf(EventType.class)) .unordered().asynchronous()) .withExpiry(expiryPolicy) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java index fea6e912f2..cd1daf19e0 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java @@ -92,7 +92,7 @@ private CacheManagerBuilder getPersistentCacheManagerCac .withCache("test-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(resourcePool) - ).add(new ClusteredStoreConfiguration(Consistency.EVENTUAL))); + ).withService(new ClusteredStoreConfiguration(Consistency.EVENTUAL))); } private static Throwable getCause(Throwable e, Class causeClass) { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java index 6c33d9977b..aa54307367 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java @@ -56,7 +56,7 @@ public void simpleOnHeapToString() throws Exception { .offheap(1, MemoryUnit.MB) .disk(2, MemoryUnit.MB, true)) .withLoaderWriter(new SampleLoaderWriter<>()) - .add(WriteBehindConfigurationBuilder + .withService(WriteBehindConfigurationBuilder .newBatchedWriteBehindConfiguration(1, TimeUnit.SECONDS, 3) .queueSize(3) .concurrencyLevel(1) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index 1ba2884d0e..b5ca56aa5a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -100,7 +100,7 @@ final void clear() { private static CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB))) - .add(CacheEventListenerConfigurationBuilder + .withService(CacheEventListenerConfigurationBuilder .newEventListenerConfiguration(cacheEventListener, EnumSet.allOf(EventType.class)) .unordered().asynchronous()) .withResilienceStrategy(new ThrowingResiliencyStrategy<>()) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index 0aa8d3fb75..77d9689f8d 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -130,7 +130,7 @@ public void startServers() throws Exception { .newCacheConfigurationBuilder(Long.class, BlobValue.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(500, EntryUnit.ENTRIES) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 4, MemoryUnit.MB))) - .add(ClusteredStoreConfigurationBuilder.withConsistency(cacheConsistency)) + .withService(ClusteredStoreConfigurationBuilder.withConsistency(cacheConsistency)) .build(); CACHE1 = CACHE_MANAGER1.createCache("clustered-cache", config); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java index 9d8e7e05bb..93aae3fad2 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java @@ -96,7 +96,7 @@ public void startServers() throws Exception { CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(100, EntryUnit.ENTRIES) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 4, MemoryUnit.MB))) - .add(ClusteredStoreConfigurationBuilder.withConsistency(cacheConsistency)) + .withService(ClusteredStoreConfigurationBuilder.withConsistency(cacheConsistency)) .build(); CACHE1 = CACHE_MANAGER.createCache("clustered-cache", config); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java index cec715c7c9..5fcc7cf13a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java @@ -104,7 +104,7 @@ public void startServers() throws Exception { CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, BlobValue.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(500, EntryUnit.ENTRIES) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 4, MemoryUnit.MB))) - .add(ClusteredStoreConfigurationBuilder.withConsistency(cacheConsistency)) + .withService(ClusteredStoreConfigurationBuilder.withConsistency(cacheConsistency)) .build(); CACHE1 = CACHE_MANAGER1.createCache("clustered-cache", config); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java index bbb69a35b3..ab56c9c3e4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java @@ -89,7 +89,7 @@ public void duplicateAfterFailoverAreReturningTheCorrectResponse() throws Except ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 10, MemoryUnit.MB))) .withResilienceStrategy(failingResilienceStrategy()) - .add(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG))); + .withService(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG))); cacheManager = builder.build(true); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java index b2d5eb6ddb..6d3dac4313 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java @@ -102,9 +102,9 @@ PersistentCacheManager createCacheManager(URI clusterUri) { .offheap(1, MemoryUnit.MB) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) .withLoaderWriter(loaderWriter) - .add(WriteBehindConfigurationBuilder.newUnBatchedWriteBehindConfiguration()) + .withService(WriteBehindConfigurationBuilder.newUnBatchedWriteBehindConfiguration()) .withResilienceStrategy(new ThrowingResilienceStrategy<>()) - .add(new ClusteredStoreConfiguration(Consistency.STRONG)) + .withService(new ClusteredStoreConfiguration(Consistency.STRONG)) .build(); return CacheManagerBuilder diff --git a/clustered/integration-test/src/test/resources/clusteredConfiguration.txt b/clustered/integration-test/src/test/resources/clusteredConfiguration.txt index b72691f038..e1b6721eac 100644 --- a/clustered/integration-test/src/test/resources/clusteredConfiguration.txt +++ b/clustered/integration-test/src/test/resources/clusteredConfiguration.txt @@ -4,7 +4,7 @@ caches: valueType: java.lang.String serviceConfigurations: None evictionAdvisor: None - expiry: NoExpiryPolicy + expiry: No Expiry resourcePools: pools: heap: @@ -18,7 +18,7 @@ caches: valueType: java.lang.String serviceConfigurations: None evictionAdvisor: None - expiry: NoExpiryPolicy + expiry: No Expiry resourcePools: pools: heap: diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreFactory.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreFactory.java index c2133a97ed..05bd94f3fd 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreFactory.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreFactory.java @@ -43,7 +43,7 @@ public interface StoreFactory { Class getValueType(); - ServiceConfiguration[] getServiceConfigurations(); + ServiceConfiguration[] getServiceConfigurations(); ServiceProvider getServiceProvider(); diff --git a/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierFactory.java b/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierFactory.java index f3337891c6..3d81c07b9e 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierFactory.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierFactory.java @@ -39,7 +39,7 @@ public interface CachingTierFactory { Class getValueType(); - ServiceConfiguration[] getServiceConfigurations(); + ServiceConfiguration[] getServiceConfigurations(); ServiceProvider getServiceProvider(); diff --git a/core/src/main/java/org/ehcache/core/EhcacheManager.java b/core/src/main/java/org/ehcache/core/EhcacheManager.java index 2481d8bfd4..b4a05b71a4 100644 --- a/core/src/main/java/org/ehcache/core/EhcacheManager.java +++ b/core/src/main/java/org/ehcache/core/EhcacheManager.java @@ -25,7 +25,6 @@ import org.ehcache.config.Configuration; import org.ehcache.config.ResourcePool; import org.ehcache.config.ResourceType; -import org.ehcache.core.config.BaseCacheConfiguration; import org.ehcache.core.config.DefaultConfiguration; import org.ehcache.core.config.store.StoreEventSourceConfiguration; import org.ehcache.core.config.store.StoreStatisticsConfiguration; @@ -309,10 +308,10 @@ private Cache createCache(String alias, CacheConfiguration or InternalCache createNewEhcache(String alias, CacheConfiguration config, Class keyType, Class valueType) { - Collection> adjustedServiceConfigs = new ArrayList<>(config.getServiceConfigurations()); + Collection> adjustedServiceConfigs = new ArrayList<>(config.getServiceConfigurations()); - List> unknownServiceConfigs = new ArrayList<>(); - for (ServiceConfiguration serviceConfig : adjustedServiceConfigs) { + List> unknownServiceConfigs = new ArrayList<>(); + for (ServiceConfiguration serviceConfig : adjustedServiceConfigs) { if (!serviceLocator.knowsServiceFor(serviceConfig)) { unknownServiceConfigs.add(serviceConfig); } @@ -345,7 +344,7 @@ public void close() throws Exception { CacheEventDispatcherFactory cenlProvider = serviceLocator.getService(CacheEventDispatcherFactory.class); CacheEventDispatcher evtService = - cenlProvider.createCacheEventDispatcher(store, adjustedServiceConfigs.toArray(new ServiceConfiguration[adjustedServiceConfigs.size()])); + cenlProvider.createCacheEventDispatcher(store, adjustedServiceConfigs.toArray(new ServiceConfiguration[adjustedServiceConfigs.size()])); lifeCycledList.add(new LifeCycledAdapter() { @Override public void close() { @@ -365,9 +364,10 @@ public void close() { CacheEventListenerProvider evntLsnrFactory = serviceLocator.getService(CacheEventListenerProvider.class); if (evntLsnrFactory != null) { - Collection evtLsnrConfigs = - ServiceUtils.findAmongst(CacheEventListenerConfiguration.class, config.getServiceConfigurations()); - for (CacheEventListenerConfiguration lsnrConfig: evtLsnrConfigs) { + @SuppressWarnings("unchecked") + Collection> evtLsnrConfigs = + ServiceUtils.>>findAmongst((Class) CacheEventListenerConfiguration.class, config.getServiceConfigurations()); + for (CacheEventListenerConfiguration lsnrConfig: evtLsnrConfigs) { CacheEventListener lsnr = evntLsnrFactory.createEventListener(alias, lsnrConfig); if (lsnr != null) { cache.getRuntimeConfiguration().registerCacheEventListener(lsnr, lsnrConfig.orderingMode(), lsnrConfig.firingMode(), @@ -414,7 +414,7 @@ public void close() throws Exception { */ protected Store getStore(String alias, CacheConfiguration config, Class keyType, Class valueType, - Collection> serviceConfigs, + Collection> serviceConfigs, List lifeCycledList, CacheLoaderWriter loaderWriter) { final Set> resourceTypes = config.getResourcePools().getResourceTypeSet(); @@ -441,7 +441,7 @@ public void close() throws Exception { Serializer keySerializer = null; Serializer valueSerializer = null; final SerializationProvider serialization = serviceLocator.getService(SerializationProvider.class); - ServiceConfiguration[] serviceConfigArray = serviceConfigs.toArray(new ServiceConfiguration[serviceConfigs.size()]); + ServiceConfiguration[] serviceConfigArray = serviceConfigs.toArray(new ServiceConfiguration[serviceConfigs.size()]); if (serialization != null) { try { final Serializer keySer = serialization.createKeySerializer(keyType, config.getClassLoader(), serviceConfigArray); @@ -479,9 +479,10 @@ public void close() throws Exception { } } - Collection> serviceConfigurations = config.getServiceConfigurations(); + Collection> serviceConfigurations = config.getServiceConfigurations(); - int dispatcherConcurrency = findOptionalAmongst(StoreEventSourceConfiguration.class, serviceConfigurations) + @SuppressWarnings("unchecked") + int dispatcherConcurrency = findOptionalAmongst((Class>) (Class) StoreEventSourceConfiguration.class, serviceConfigurations) .map(StoreEventSourceConfiguration::getDispatcherConcurrency) .orElse(StoreEventSourceConfiguration.DEFAULT_DISPATCHER_CONCURRENCY); @@ -531,39 +532,23 @@ private PersistableResourceService getPersistableResourceService(ResourceType * adjusts the config to reflect new classloader & serialization provider */ private CacheConfiguration adjustConfigurationWithCacheManagerDefaults(String alias, CacheConfiguration config) { - ClassLoader cacheClassLoader = config.getClassLoader(); + if (config.getClassLoader() == null && cacheManagerClassLoader != null) { + config = config.derive().withClassLoader(cacheManagerClassLoader).build(); + } - List> configurationList = new ArrayList<>(); - configurationList.addAll(config.getServiceConfigurations()); - CacheLoaderWriterConfiguration loaderWriterConfiguration = findSingletonAmongst(CacheLoaderWriterConfiguration.class, config.getServiceConfigurations()); + CacheLoaderWriterConfiguration loaderWriterConfiguration = findSingletonAmongst(CacheLoaderWriterConfiguration.class, config.getServiceConfigurations()); if (loaderWriterConfiguration == null) { CacheLoaderWriterProvider loaderWriterProvider = serviceLocator.getService(CacheLoaderWriterProvider.class); - ServiceConfiguration preConfiguredCacheLoaderWriterConfig = loaderWriterProvider.getPreConfiguredCacheLoaderWriterConfig(alias); + CacheLoaderWriterConfiguration preConfiguredCacheLoaderWriterConfig = loaderWriterProvider.getPreConfiguredCacheLoaderWriterConfig(alias); if (preConfiguredCacheLoaderWriterConfig != null) { - configurationList.add(preConfiguredCacheLoaderWriterConfig); + config = config.derive().withService(preConfiguredCacheLoaderWriterConfig).build(); } if (loaderWriterProvider.isLoaderJsrProvided(alias)) { - configurationList.add(new CacheLoaderWriterConfiguration() { - }); + config = config.derive().withService(new CacheLoaderWriterConfiguration() {}).build(); } } - ServiceConfiguration[] serviceConfigurations = new ServiceConfiguration[configurationList.size()]; - configurationList.toArray(serviceConfigurations); - - if (cacheClassLoader == null) { - cacheClassLoader = cacheManagerClassLoader; - } - if (cacheClassLoader != config.getClassLoader() ) { - config = new BaseCacheConfiguration<>(config.getKeyType(), config.getValueType(), - config.getEvictionAdvisor(), cacheClassLoader, config.getExpiryPolicy(), - config.getResourcePools(), serviceConfigurations); - } else { - config = new BaseCacheConfiguration<>(config.getKeyType(), config.getValueType(), - config.getEvictionAdvisor(), config.getClassLoader(), config.getExpiryPolicy(), - config.getResourcePools(), serviceConfigurations); - } return config; } diff --git a/core/src/main/java/org/ehcache/core/EhcacheRuntimeConfiguration.java b/core/src/main/java/org/ehcache/core/EhcacheRuntimeConfiguration.java index 32f79f36ea..e4e326ad47 100644 --- a/core/src/main/java/org/ehcache/core/EhcacheRuntimeConfiguration.java +++ b/core/src/main/java/org/ehcache/core/EhcacheRuntimeConfiguration.java @@ -20,7 +20,7 @@ import org.ehcache.config.CacheRuntimeConfiguration; import org.ehcache.config.EvictionAdvisor; import org.ehcache.config.ResourcePools; -import org.ehcache.core.config.ExpiryUtils; +import org.ehcache.config.FluentCacheConfigurationBuilder; import org.ehcache.core.events.EventListenerWrapper; import org.ehcache.event.CacheEventListener; import org.ehcache.event.EventFiring; @@ -31,21 +31,18 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.EnumSet; import java.util.List; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; +import static java.util.Collections.unmodifiableCollection; + class EhcacheRuntimeConfiguration implements CacheRuntimeConfiguration, InternalRuntimeConfiguration, HumanReadable { - private final Collection> serviceConfigurations; - private final CacheConfiguration config; - private final Class keyType; - private final Class valueType; - private final EvictionAdvisor evictionAdvisor; - private final ClassLoader classLoader; - private final ExpiryPolicy expiry; + private final CacheConfiguration config; + + private final Collection> addedServiceConfigurations = new ArrayList<>(); private volatile ResourcePools resourcePools; private final List cacheConfigurationListenerList @@ -53,12 +50,6 @@ class EhcacheRuntimeConfiguration implements CacheRuntimeConfiguration config) { this.config = config; - this.serviceConfigurations = copy(config.getServiceConfigurations()); - this.keyType = config.getKeyType(); - this.valueType = config.getValueType(); - this.evictionAdvisor = config.getEvictionAdvisor(); - this.classLoader = config.getClassLoader(); - this.expiry = config.getExpiryPolicy(); this.resourcePools = config.getResourcePools(); } @@ -75,39 +66,41 @@ public synchronized void updateResourcePools(ResourcePools pools) { } @Override - public Collection> getServiceConfigurations() { - return this.serviceConfigurations; + public Collection> getServiceConfigurations() { + Collection> configurations = new ArrayList<>(config.getServiceConfigurations()); + configurations.addAll(addedServiceConfigurations); + return unmodifiableCollection(configurations); } @Override public Class getKeyType() { - return this.keyType; + return config.getKeyType(); } @Override public Class getValueType() { - return this.valueType; + return config.getValueType(); } @Override public EvictionAdvisor getEvictionAdvisor() { - return this.evictionAdvisor; + return config.getEvictionAdvisor(); } @Override public ClassLoader getClassLoader() { - return this.classLoader; + return config.getClassLoader(); } @SuppressWarnings("deprecation") @Override public org.ehcache.expiry.Expiry getExpiry() { - return ExpiryUtils.convertToExpiry(expiry); + return config.getExpiry(); } @Override public ExpiryPolicy getExpiryPolicy() { - return expiry; + return config.getExpiryPolicy(); } @Override @@ -115,6 +108,15 @@ public ResourcePools getResourcePools() { return this.resourcePools; } + @Override + public FluentCacheConfigurationBuilder derive() { + FluentCacheConfigurationBuilder builder = config.derive(); + for (ServiceConfiguration service : addedServiceConfigurations) { + builder = builder.withService(service); + } + return builder.updateResourcePools(existing -> resourcePools); + } + @Override public boolean addCacheConfigurationListener(List listeners) { return this.cacheConfigurationListenerList.addAll(listeners); @@ -137,18 +139,12 @@ public synchronized void registerCacheEventListener(CacheEventListener listener, EventOrdering ordering, EventFiring firing, EventType eventType, EventType... eventTypes) { - EventListenerWrapper listenerWrapper = new EventListenerWrapper<>(listener, firing, ordering, EnumSet.of(eventType, eventTypes)); - fireCacheConfigurationChange(CacheConfigurationProperty.ADD_LISTENER, listenerWrapper, listenerWrapper); - } - private Collection copy(Collection collection) { if (collection == null) { return null; } - return Collections.unmodifiableCollection(new ArrayList<>(collection)); + return unmodifiableCollection(new ArrayList<>(collection)); } @SuppressWarnings("unchecked") @@ -163,7 +159,7 @@ private void fireCacheConfigurationChange(CacheConfigurationProperty prop, f @Override public String readableString() { StringBuilder serviceConfigurationsToStringBuilder = new StringBuilder(); - for (ServiceConfiguration serviceConfiguration : serviceConfigurations) { + for (ServiceConfiguration serviceConfiguration : getServiceConfigurations()) { serviceConfigurationsToStringBuilder .append("\n ") .append("- "); @@ -184,20 +180,12 @@ public String readableString() { serviceConfigurationsToStringBuilder.append(" None"); } - String expiryPolicy; - - if (ExpiryPolicy.NO_EXPIRY == expiry) { - expiryPolicy = "NoExpiryPolicy"; - } else { - expiryPolicy = expiry.toString(); - } - return - "keyType: " + keyType.getName() + "\n" + - "valueType: " + valueType.getName() + "\n" + + "keyType: " + getKeyType().getName() + "\n" + + "valueType: " + getValueType().getName() + "\n" + "serviceConfigurations:" + serviceConfigurationsToStringBuilder.toString().replace("\n", "\n ") + "\n" + - "evictionAdvisor: " + ((evictionAdvisor != null) ? evictionAdvisor.getClass().getName() : "None") + "\n" + - "expiry: " + expiryPolicy + "\n" + + "evictionAdvisor: " + ((getEvictionAdvisor() != null) ? getEvictionAdvisor().getClass().getName() : "None") + "\n" + + "expiry: " + getExpiryPolicy() + "\n" + "resourcePools: " + "\n " + ((resourcePools instanceof HumanReadable) ? ((HumanReadable)resourcePools).readableString() : "").replace("\n", "\n "); } } diff --git a/core/src/main/java/org/ehcache/core/config/CoreConfigurationBuilder.java b/core/src/main/java/org/ehcache/core/config/CoreConfigurationBuilder.java index 54da1a991e..10fc4fa125 100644 --- a/core/src/main/java/org/ehcache/core/config/CoreConfigurationBuilder.java +++ b/core/src/main/java/org/ehcache/core/config/CoreConfigurationBuilder.java @@ -108,7 +108,7 @@ public B withoutCache(String alias) { } @Override - public B updateCache(String alias, UnaryOperator> update) { + public B updateCache(String alias, UnaryOperator> update) { CacheConfiguration existing = getCache(alias); if (existing == null) { throw new IllegalArgumentException("Cache does not exist"); diff --git a/core/src/main/java/org/ehcache/core/config/store/StoreEventSourceConfiguration.java b/core/src/main/java/org/ehcache/core/config/store/StoreEventSourceConfiguration.java index 52e2bf81a4..1e814f673a 100644 --- a/core/src/main/java/org/ehcache/core/config/store/StoreEventSourceConfiguration.java +++ b/core/src/main/java/org/ehcache/core/config/store/StoreEventSourceConfiguration.java @@ -21,9 +21,9 @@ /** * {@link ServiceConfiguration} used by the {@link org.ehcache.core.EhcacheManager} to populate the dispatcher - * concurrency in the {@link StoreConfigurationImpl}. + * concurrency in the {@link org.ehcache.core.store.StoreConfigurationImpl}. */ -public interface StoreEventSourceConfiguration extends ServiceConfiguration { +public interface StoreEventSourceConfiguration extends ServiceConfiguration { /** * Default dispatcher concurrency diff --git a/core/src/main/java/org/ehcache/core/config/store/StoreStatisticsConfiguration.java b/core/src/main/java/org/ehcache/core/config/store/StoreStatisticsConfiguration.java index 473861b995..834ffa6cc6 100644 --- a/core/src/main/java/org/ehcache/core/config/store/StoreStatisticsConfiguration.java +++ b/core/src/main/java/org/ehcache/core/config/store/StoreStatisticsConfiguration.java @@ -27,7 +27,7 @@ * Note that statistics about the store size, mapping and so on are not affected * by this configuration. Only operation statistics (e.g. get/put counts) are disabled. */ -public class StoreStatisticsConfiguration implements ServiceConfiguration { +public class StoreStatisticsConfiguration implements ServiceConfiguration { private final boolean operationStatisticsEnabled; @@ -43,4 +43,14 @@ public boolean isOperationStatisticsEnabled() { public Class getServiceType() { return Store.Provider.class; } + + @Override + public Boolean derive() { + return isOperationStatisticsEnabled(); + } + + @Override + public StoreStatisticsConfiguration build(Boolean enabled) { + return new StoreStatisticsConfiguration(enabled); + } } diff --git a/core/src/main/java/org/ehcache/core/events/CacheEventDispatcherFactory.java b/core/src/main/java/org/ehcache/core/events/CacheEventDispatcherFactory.java index 8bf715ed09..a6781f5216 100644 --- a/core/src/main/java/org/ehcache/core/events/CacheEventDispatcherFactory.java +++ b/core/src/main/java/org/ehcache/core/events/CacheEventDispatcherFactory.java @@ -38,7 +38,7 @@ public interface CacheEventDispatcherFactory extends Service { * * @return the {@link CacheEventDispatcher} */ - CacheEventDispatcher createCacheEventDispatcher(Store store, ServiceConfiguration... serviceConfigs); + CacheEventDispatcher createCacheEventDispatcher(Store store, ServiceConfiguration... serviceConfigs); /** * Releases an instance of {@link CacheEventDispatcher}, causing it to shutdown and release all diff --git a/core/src/main/java/org/ehcache/core/events/CacheEventListenerConfiguration.java b/core/src/main/java/org/ehcache/core/events/CacheEventListenerConfiguration.java index 445c84ebba..18bc84296d 100644 --- a/core/src/main/java/org/ehcache/core/events/CacheEventListenerConfiguration.java +++ b/core/src/main/java/org/ehcache/core/events/CacheEventListenerConfiguration.java @@ -26,7 +26,7 @@ /** * Configuration contract for setting up {@link org.ehcache.event.CacheEvent} system in a cache. */ -public interface CacheEventListenerConfiguration extends ServiceConfiguration { +public interface CacheEventListenerConfiguration extends ServiceConfiguration { /** * Indicates which {@link EventFiring firing mode} to use diff --git a/core/src/main/java/org/ehcache/core/events/CacheEventListenerProvider.java b/core/src/main/java/org/ehcache/core/events/CacheEventListenerProvider.java index dda77e64fa..4c90b67b63 100644 --- a/core/src/main/java/org/ehcache/core/events/CacheEventListenerProvider.java +++ b/core/src/main/java/org/ehcache/core/events/CacheEventListenerProvider.java @@ -35,7 +35,7 @@ public interface CacheEventListenerProvider extends Service { * * @return the CacheEventListener to be registered with the given {@link org.ehcache.Cache} */ - CacheEventListener createEventListener(String alias, ServiceConfiguration serviceConfiguration); + CacheEventListener createEventListener(String alias, ServiceConfiguration serviceConfiguration); /** * Releases a given {@link org.ehcache.event.CacheEventListener} diff --git a/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java b/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java index a14090d6ea..97bf72ed8e 100644 --- a/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java +++ b/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java @@ -97,7 +97,7 @@ public Collection getServicesOfType(Class serviceType) return services.get(serviceType); } - public boolean knowsServiceFor(ServiceConfiguration serviceConfig) { + public boolean knowsServiceFor(ServiceConfiguration serviceConfig) { return services.contains(serviceConfig.getServiceType()); } diff --git a/core/src/main/java/org/ehcache/core/spi/service/DiskResourceService.java b/core/src/main/java/org/ehcache/core/spi/service/DiskResourceService.java index b2afe0c857..cde1fd48d4 100644 --- a/core/src/main/java/org/ehcache/core/spi/service/DiskResourceService.java +++ b/core/src/main/java/org/ehcache/core/spi/service/DiskResourceService.java @@ -31,4 +31,4 @@ public interface DiskResourceService extends PersistableResourceService { * @return a {@link FileBasedPersistenceContext} */ FileBasedPersistenceContext createPersistenceContextWithin(PersistenceSpaceIdentifier identifier, String name) throws CachePersistenceException; -} \ No newline at end of file +} diff --git a/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java b/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java index 65277d90e9..3013339727 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java +++ b/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java @@ -21,10 +21,8 @@ import org.ehcache.spi.service.ServiceProvider; import java.util.Arrays; -import java.util.IdentityHashMap; import java.util.Map; -import static java.util.Collections.synchronizedMap; import static org.ehcache.core.store.StoreSupport.selectStoreProvider; public abstract class AbstractWrapperStoreProvider implements WrapperStore.Provider { @@ -35,7 +33,7 @@ public abstract class AbstractWrapperStoreProvider implements WrapperStore.Provi @Override - public Store createStore(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public Store createStore(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { Store.Provider underlyingStoreProvider = selectStoreProvider(serviceProvider, storeConfig.getResourcePools().getResourceTypeSet(), Arrays.asList(serviceConfigs)); @@ -46,7 +44,7 @@ public Store createStore(Store.Configuration storeConfig, Ser return wrappedStore; } - protected abstract Store wrap(Store store, Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs); + protected abstract Store wrap(Store store, Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs); @Override public void releaseStore(Store resource) { diff --git a/core/src/main/java/org/ehcache/core/spi/store/Store.java b/core/src/main/java/org/ehcache/core/spi/store/Store.java index 2868ffaebb..24d7ffdc09 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/Store.java +++ b/core/src/main/java/org/ehcache/core/spi/store/Store.java @@ -32,7 +32,6 @@ import java.util.Collection; import java.util.Map; import java.util.Set; -import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; @@ -531,7 +530,7 @@ interface Provider extends Service { * @param serviceConfigs the configurations the Provider may need to configure the Store * @return the Store honoring the configurations passed in */ - Store createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs); + Store createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs); /** * Informs this Provider, a Store it created is being disposed (i.e. closed) @@ -557,7 +556,7 @@ interface Provider extends Service { * to handle the resource types specified by {@code resourceTypes}; a rank of 0 indicates the store * can not handle all types specified in {@code resourceTypes} */ - int rank(Set> resourceTypes, Collection> serviceConfigs); + int rank(Set> resourceTypes, Collection> serviceConfigs); } /** diff --git a/core/src/main/java/org/ehcache/core/spi/store/WrapperStore.java b/core/src/main/java/org/ehcache/core/spi/store/WrapperStore.java index 2c7f2f29aa..4002b660b4 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/WrapperStore.java +++ b/core/src/main/java/org/ehcache/core/spi/store/WrapperStore.java @@ -43,7 +43,7 @@ interface Provider extends Store.Provider { * to the ranking * @return a non-negative rank indicating the ability of a {@code WrapperStore} created by this {@code Provider} */ - int wrapperStoreRank(Collection> serviceConfigs); + int wrapperStoreRank(Collection> serviceConfigs); } } diff --git a/core/src/main/java/org/ehcache/core/spi/store/heap/SizeOfEngineProvider.java b/core/src/main/java/org/ehcache/core/spi/store/heap/SizeOfEngineProvider.java index ffa7f6c8eb..28feed15df 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/heap/SizeOfEngineProvider.java +++ b/core/src/main/java/org/ehcache/core/spi/store/heap/SizeOfEngineProvider.java @@ -36,5 +36,5 @@ public interface SizeOfEngineProvider extends Service { * @return {@link SizeOfEngine} instance */ - SizeOfEngine createSizeOfEngine(ResourceUnit resourceUnit, ServiceConfiguration... serviceConfigs); + SizeOfEngine createSizeOfEngine(ResourceUnit resourceUnit, ServiceConfiguration... serviceConfigs); } diff --git a/core/src/main/java/org/ehcache/core/spi/store/tiering/AuthoritativeTier.java b/core/src/main/java/org/ehcache/core/spi/store/tiering/AuthoritativeTier.java index c1c123c431..4cb97c40da 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/tiering/AuthoritativeTier.java +++ b/core/src/main/java/org/ehcache/core/spi/store/tiering/AuthoritativeTier.java @@ -114,7 +114,7 @@ interface Provider extends Service { * @param serviceConfigs a collection of service configurations * @return the new authoritative tier */ - AuthoritativeTier createAuthoritativeTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs); + AuthoritativeTier createAuthoritativeTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs); /** * Releases an {@link AuthoritativeTier}. @@ -146,7 +146,7 @@ interface Provider extends Service { * to handle the resource type specified by {@code authorityResource}; a rank of 0 indicates the authority * can not handle the type specified in {@code authorityResource} */ - int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs); + int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs); } } diff --git a/core/src/main/java/org/ehcache/core/spi/store/tiering/CachingTier.java b/core/src/main/java/org/ehcache/core/spi/store/tiering/CachingTier.java index 371862741d..cdaf58a46d 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/tiering/CachingTier.java +++ b/core/src/main/java/org/ehcache/core/spi/store/tiering/CachingTier.java @@ -145,7 +145,7 @@ interface Provider extends Service { * * @return the new caching tier */ - CachingTier createCachingTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs); + CachingTier createCachingTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs); /** * Releases a {@link CachingTier}. @@ -177,7 +177,7 @@ interface Provider extends Service { * to handle the resource types specified by {@code resourceTypes}; a rank of 0 indicates the caching tier * can not handle the type specified in {@code resourceTypes} */ - int rankCachingTier(Set> resourceTypes, Collection> serviceConfigs); + int rankCachingTier(Set> resourceTypes, Collection> serviceConfigs); } } diff --git a/core/src/main/java/org/ehcache/core/spi/store/tiering/HigherCachingTier.java b/core/src/main/java/org/ehcache/core/spi/store/tiering/HigherCachingTier.java index 4be5992e0a..bda5705091 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/tiering/HigherCachingTier.java +++ b/core/src/main/java/org/ehcache/core/spi/store/tiering/HigherCachingTier.java @@ -77,7 +77,7 @@ interface Provider extends Service { * * @return the new higher caching tier */ - HigherCachingTier createHigherCachingTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs); + HigherCachingTier createHigherCachingTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs); /** * Releases a {@link HigherCachingTier}. diff --git a/core/src/main/java/org/ehcache/core/spi/store/tiering/LowerCachingTier.java b/core/src/main/java/org/ehcache/core/spi/store/tiering/LowerCachingTier.java index 5036b15fb1..d9e2860e01 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/tiering/LowerCachingTier.java +++ b/core/src/main/java/org/ehcache/core/spi/store/tiering/LowerCachingTier.java @@ -124,7 +124,7 @@ interface Provider extends Service { * * @return the new lower caching tier */ - LowerCachingTier createCachingTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs); + LowerCachingTier createCachingTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs); /** * Releases a {@link LowerCachingTier}. diff --git a/core/src/main/java/org/ehcache/core/store/StoreSupport.java b/core/src/main/java/org/ehcache/core/store/StoreSupport.java index e8baca30bd..5194f6741c 100644 --- a/core/src/main/java/org/ehcache/core/store/StoreSupport.java +++ b/core/src/main/java/org/ehcache/core/store/StoreSupport.java @@ -42,7 +42,7 @@ public final class StoreSupport { private StoreSupport() { } - public static Store.Provider selectWrapperStoreProvider(ServiceProvider serviceProvider, Collection> serviceConfigs) { + public static Store.Provider selectWrapperStoreProvider(ServiceProvider serviceProvider, Collection> serviceConfigs) { Collection storeProviders = serviceProvider.getServicesOfType(WrapperStore.Provider.class); Optional> wrapperProvider = storeProviders.stream() .map(provider -> new Tuple<>(provider.wrapperStoreRank(serviceConfigs), provider)) @@ -78,7 +78,7 @@ private static class Tuple { * multiple {@code Store.Provider} implementations return the same top ranking */ public static Store.Provider selectStoreProvider( - ServiceProvider serviceProvider, Set> resourceTypes, Collection> serviceConfigs) { + ServiceProvider serviceProvider, Set> resourceTypes, Collection> serviceConfigs) { Collection storeProviders = serviceProvider.getServicesOfType(Store.Provider.class); List filteredStoreProviders = storeProviders.stream().filter(provider -> !(provider instanceof WrapperStore.Provider)).collect(Collectors.toList()); diff --git a/core/src/test/java/org/ehcache/core/CacheConfigurationChangeListenerTest.java b/core/src/test/java/org/ehcache/core/CacheConfigurationChangeListenerTest.java index 933de8efa3..8b7272811d 100644 --- a/core/src/test/java/org/ehcache/core/CacheConfigurationChangeListenerTest.java +++ b/core/src/test/java/org/ehcache/core/CacheConfigurationChangeListenerTest.java @@ -17,10 +17,9 @@ package org.ehcache.core; import org.ehcache.config.CacheConfiguration; -import org.ehcache.core.config.ResourcePoolsHelper; -import org.ehcache.core.config.BaseCacheConfiguration; import org.ehcache.core.events.CacheEventDispatcher; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.util.TestCacheConfig; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.resilience.ResilienceStrategy; import org.junit.After; @@ -34,6 +33,7 @@ import java.util.List; import java.util.Set; +import static org.ehcache.core.config.ResourcePoolsHelper.createResourcePools; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.mockito.Mockito.mock; @@ -55,7 +55,7 @@ public void setUp() throws Exception { this.eventNotifier = mock(CacheEventDispatcher.class); ResilienceStrategy resilienceStrategy = mock(ResilienceStrategy.class); CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); - this.config = new BaseCacheConfiguration<>(Object.class, Object.class, null, null, null, ResourcePoolsHelper.createHeapDiskPools(2, 10)); + this.config = new TestCacheConfig<>(Object.class, Object.class, createResourcePools(2L)); this.cache = new Ehcache<>(config, store, resilienceStrategy, eventNotifier, LoggerFactory.getLogger(Ehcache.class + "-" + "CacheConfigurationListenerTest"), loaderWriter); cache.init(); @@ -74,7 +74,7 @@ public void testCacheConfigurationChangeFiresEvent () { = new ArrayList<>(); cacheConfigurationChangeListeners.add(configurationListener); this.runtimeConfiguration.addCacheConfigurationListener(cacheConfigurationChangeListeners); - this.cache.getRuntimeConfiguration().updateResourcePools(ResourcePoolsHelper.createHeapOnlyPools(10)); + this.cache.getRuntimeConfiguration().updateResourcePools(createResourcePools(10L)); assertThat(configurationListener.eventSet.size(), is(1) ); } @@ -85,10 +85,10 @@ public void testRemovingCacheConfigurationListener() { = new ArrayList<>(); cacheConfigurationChangeListeners.add(configurationListener); this.runtimeConfiguration.addCacheConfigurationListener(cacheConfigurationChangeListeners); - this.cache.getRuntimeConfiguration().updateResourcePools(ResourcePoolsHelper.createHeapOnlyPools(20)); + this.cache.getRuntimeConfiguration().updateResourcePools(createResourcePools(20L)); assertThat(configurationListener.eventSet.size(), is(1)); this.runtimeConfiguration.removeCacheConfigurationListener(configurationListener); - this.cache.getRuntimeConfiguration().updateResourcePools(ResourcePoolsHelper.createHeapOnlyPools(5)); + this.cache.getRuntimeConfiguration().updateResourcePools(createResourcePools(5L)); assertThat(configurationListener.eventSet.size(), is(1) ); } diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java b/core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java index 72d2e7a985..88f9731644 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java @@ -18,12 +18,11 @@ import org.ehcache.Cache; import org.ehcache.config.CacheConfiguration; -import org.ehcache.core.config.BaseCacheConfiguration; -import org.ehcache.core.config.ResourcePoolsHelper; import org.ehcache.core.events.CacheEventDispatcher; import org.ehcache.core.exceptions.StorePassThroughException; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.events.StoreEventSource; +import org.ehcache.core.util.TestCacheConfig; import org.ehcache.spi.loaderwriter.BulkCacheLoadingException; import org.ehcache.spi.loaderwriter.BulkCacheWritingException; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; @@ -55,7 +54,6 @@ import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; @@ -63,7 +61,6 @@ import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.spy; /** * Provides testing of basic CRUD operations on an {@code Ehcache}. @@ -72,9 +69,7 @@ */ public abstract class EhcacheBasicCrudBase { - protected static final CacheConfiguration CACHE_CONFIGURATION = - new BaseCacheConfiguration<>(String.class, String.class, null, - null, null, ResourcePoolsHelper.createHeapOnlyPools()); + protected static final CacheConfiguration CACHE_CONFIGURATION = new TestCacheConfig<>(String.class, String.class); @Mock protected Store store; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java index c1f4d97bb7..d92c20d9e6 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java @@ -19,11 +19,7 @@ import java.util.EnumSet; import org.ehcache.Status; -import org.ehcache.config.CacheConfiguration; -import org.ehcache.core.config.BaseCacheConfiguration; -import org.ehcache.core.config.ResourcePoolsHelper; import org.ehcache.core.statistics.CacheOperationOutcomes; -import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.spi.resilience.StoreAccessException; import org.hamcrest.Matchers; import org.junit.Test; @@ -171,9 +167,7 @@ public void testPutIfAbsentHasStoreEntryStoreAccessException() throws Exception * @return a new {@code Ehcache} instance */ private Ehcache getEhcache() { - CacheConfiguration config = new BaseCacheConfiguration<>(String.class, String.class, null, null, - ExpiryPolicy.NO_EXPIRY, ResourcePoolsHelper.createHeapOnlyPools()); - final Ehcache ehcache = new Ehcache<>(config, this.store, resilienceStrategy, cacheEventDispatcher, LoggerFactory.getLogger(Ehcache.class + "-" + "EhcacheBasicPutIfAbsentTest")); + final Ehcache ehcache = new Ehcache<>(CACHE_CONFIGURATION, this.store, resilienceStrategy, cacheEventDispatcher, LoggerFactory.getLogger(Ehcache.class + "-" + "EhcacheBasicPutIfAbsentTest")); ehcache.init(); assertThat("cache not initialized", ehcache.getStatus(), Matchers.is(Status.AVAILABLE)); return ehcache; diff --git a/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java b/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java index 0e7d9528c9..67fb3359b9 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java @@ -27,7 +27,6 @@ import org.ehcache.config.Configuration; import org.ehcache.config.ResourcePools; import org.ehcache.config.ResourceType; -import org.ehcache.core.config.BaseCacheConfiguration; import org.ehcache.core.config.DefaultConfiguration; import org.ehcache.core.config.ResourcePoolsHelper; import org.ehcache.core.events.CacheEventDispatcher; @@ -37,6 +36,7 @@ import org.ehcache.core.spi.service.LocalPersistenceService; import org.ehcache.core.spi.store.Store; import org.ehcache.core.util.ClassLoading; +import org.ehcache.core.util.TestCacheConfig; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.loaderwriter.CacheLoaderWriterProvider; import org.ehcache.spi.loaderwriter.WriteBehindProvider; @@ -110,8 +110,7 @@ private List minimumCacheManagerServices() { @Test public void testCanDestroyAndClose() throws Exception { - CacheConfiguration cacheConfiguration = new BaseCacheConfiguration<>(Long.class, String.class, null, - null, null, ResourcePoolsHelper.createHeapOnlyPools(10)); + CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Long.class, String.class); Store.Provider storeProvider = mock(Store.Provider.class); when(storeProvider.rank(any(Set.class), any(Collection.class))).thenReturn(1); @@ -188,7 +187,7 @@ public void testStopAllServicesWhenCacheInitializationFails() { @Test public void testNoClassLoaderSpecified() { Map> caches = newCacheMap(); - caches.put("foo", new BaseCacheConfiguration<>(Object.class, Object.class, null, null, null, ResourcePoolsHelper.createHeapOnlyPools())); + caches.put("foo", new TestCacheConfig<>(Object.class, Object.class)); DefaultConfiguration config = new DefaultConfiguration(caches, null); final Store.Provider storeProvider = mock(Store.Provider.class); @@ -222,9 +221,14 @@ public void testClassLoaderSpecified() { assertNotSame(cl1.getClass(), cl2.getClass()); Map> caches = newCacheMap(); - caches.put("foo1", new BaseCacheConfiguration<>(Object.class, Object.class, null, null, null, ResourcePoolsHelper.createHeapOnlyPools())); - caches.put("foo2", new BaseCacheConfiguration<>(Object.class, Object.class, null, null, null, ResourcePoolsHelper.createHeapOnlyPools())); - caches.put("foo3", new BaseCacheConfiguration<>(Object.class, Object.class, null, cl2, null, ResourcePoolsHelper.createHeapOnlyPools())); + caches.put("foo1", new TestCacheConfig<>(Object.class, Object.class)); + caches.put("foo2", new TestCacheConfig<>(Object.class, Object.class)); + caches.put("foo3", new TestCacheConfig(Object.class, Object.class) { + @Override + public ClassLoader getClassLoader() { + return cl2; + } + }); DefaultConfiguration config = new DefaultConfiguration(caches, cl1); final Store.Provider storeProvider = mock(Store.Provider.class); @@ -259,8 +263,7 @@ public void testReturnsNullForNonExistCache() { @Test public void testThrowsWhenAddingExistingCache() { - CacheConfiguration cacheConfiguration = new BaseCacheConfiguration<>(Object.class, Object.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Object.class, Object.class); final Store.Provider storeProvider = mock(Store.Provider.class); when(storeProvider.rank(any(Set.class), any(Collection.class))).thenReturn(1); final Store mock = mock(Store.class); @@ -302,8 +305,7 @@ public void testThrowsWhenNotInitialized() { when(storeProvider .createStore(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(mock); - final CacheConfiguration cacheConfiguration = new BaseCacheConfiguration<>(Integer.class, String.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + final CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Integer.class, String.class); Map> caches = newCacheMap(); caches.put("bar", cacheConfiguration); DefaultConfiguration config = new DefaultConfiguration(caches, null); @@ -341,8 +343,7 @@ public void testThrowsWhenRetrievingCacheWithWrongTypes() { when(storeProvider .createStore(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(mock); - final CacheConfiguration cacheConfiguration = new BaseCacheConfiguration<>(Integer.class, String.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + final CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Integer.class, String.class); Map> caches = newCacheMap(); caches.put("bar", cacheConfiguration); DefaultConfiguration config = new DefaultConfiguration(caches, null); @@ -371,7 +372,7 @@ public void testThrowsWhenRetrievingCacheWithWrongTypes() { @Test public void testLifeCyclesCacheLoaders() throws Exception { - ResourcePools resourcePools = ResourcePoolsHelper.createHeapOnlyPools(10); + ResourcePools resourcePools = ResourcePoolsHelper.createResourcePools(100L); final CacheLoaderWriterProvider cacheLoaderWriterProvider = mock(CacheLoaderWriterProvider.class); @@ -421,8 +422,7 @@ public void testLifeCyclesCacheLoaders() throws Exception { @Test public void testDoesNotifyAboutCache() { - final CacheConfiguration cacheConfiguration = new BaseCacheConfiguration<>(Object.class, Object.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + final CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Object.class, Object.class); final Store.Provider mock = mock(Store.Provider.class); when(mock.rank(any(Set.class), any(Collection.class))).thenReturn(1); @@ -448,8 +448,7 @@ public void testDoesNotifyAboutCache() { @Test public void testDoesNotNotifyAboutCacheOnInitOrClose() { - final CacheConfiguration cacheConfiguration = new BaseCacheConfiguration<>(Object.class, Object.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + final CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Object.class, Object.class); final Store.Provider mock = mock(Store.Provider.class); when(mock.rank(any(Set.class), any(Collection.class))).thenReturn(1); @@ -476,8 +475,7 @@ public void testDoesNotNotifyAboutCacheOnInitOrClose() { @Test public void testClosesStartedCachesDownWhenInitThrows() { final Set> caches = new HashSet<>(); - final CacheConfiguration cacheConfiguration = new BaseCacheConfiguration<>(Object.class, Object.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + final CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Object.class, Object.class); final Store.Provider storeProvider = mock(Store.Provider.class); when(storeProvider.rank(any(Set.class), any(Collection.class))).thenReturn(1); final Collection services = getServices(storeProvider, null); @@ -497,7 +495,7 @@ InternalCache createNewEhcache(final String alias, final CacheConfi caches.add(ehcache); if(caches.size() == 1) { when(storeProvider.createStore( - ArgumentMatchers.>any(), ArgumentMatchers.>any())) + ArgumentMatchers.>any(), ArgumentMatchers.>any())) .thenThrow(thrown); } return ehcache; @@ -526,8 +524,7 @@ protected void closeEhcache(final String alias, final InternalCache ehcach @Test public void testClosesAllCachesDownWhenCloseThrows() { final Set caches = new HashSet<>(); - final CacheConfiguration cacheConfiguration = new BaseCacheConfiguration<>(Object.class, Object.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + final CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Object.class, Object.class); final Store.Provider storeProvider = mock(Store.Provider.class); when(storeProvider.rank(any(Set.class), any(Collection.class))).thenReturn(1); @@ -589,11 +586,10 @@ public void testDoesNotifyAboutLifecycle() { @Test public void testCloseNoLoaderWriterAndCacheEventListener() throws Exception { - final CacheConfiguration cacheConfiguration = new BaseCacheConfiguration<>(Object.class, Object.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + final CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Object.class, Object.class); final Store.Provider storeProvider = spy(new Store.Provider() { @Override - public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { + public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { return 1; } @@ -616,7 +612,7 @@ public void initStore(Store resource) { } @Override - public Store createStore(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public Store createStore(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { return null; } }); @@ -631,7 +627,7 @@ public void stop() { } @Override - public CacheEventDispatcher createCacheEventDispatcher(Store store, ServiceConfiguration... serviceConfigs) { + public CacheEventDispatcher createCacheEventDispatcher(Store store, ServiceConfiguration... serviceConfigs) { return null; } @@ -677,8 +673,7 @@ public void testChangesToManagerAreReflectedInConfig() { when(store.getConfigurationChangeListeners()).thenReturn(new ArrayList<>()); when(cacheEventNotificationListenerServiceProvider.createCacheEventDispatcher(store)).thenReturn(mock(CacheEventDispatcher.class)); - CacheConfiguration cache1Configuration = new BaseCacheConfiguration<>(Long.class, String.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + CacheConfiguration cache1Configuration = new TestCacheConfig<>(Long.class, String.class); Map> caches = newCacheMap(); caches.put("cache1", cache1Configuration); DefaultConfiguration config = new DefaultConfiguration(caches, null); @@ -694,8 +689,8 @@ public void testChangesToManagerAreReflectedInConfig() { cacheManager.init(); try { - final CacheConfiguration cache2Configuration = new BaseCacheConfiguration<>(Long.class, String.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + final CacheConfiguration cache2Configuration = new TestCacheConfig<>(Long.class, String.class, ResourcePoolsHelper + .createResourcePools(100L)); final Cache cache = cacheManager.createCache("cache2", cache2Configuration); final CacheConfiguration cacheConfiguration = cacheManager.getRuntimeConfiguration() .getCacheConfigurations() @@ -725,8 +720,7 @@ public void testCachesAddedAtRuntimeGetReInited() { when(store.getConfigurationChangeListeners()).thenReturn(new ArrayList<>()); when(cacheEventNotificationListenerServiceProvider.createCacheEventDispatcher(store)).thenReturn(mock(CacheEventDispatcher.class)); - CacheConfiguration cache1Configuration = new BaseCacheConfiguration<>(Long.class, String.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + CacheConfiguration cache1Configuration = new TestCacheConfig<>(Long.class, String.class); Map> caches = newCacheMap(); caches.put("cache1", cache1Configuration); DefaultConfiguration config = new DefaultConfiguration(caches, null); @@ -742,8 +736,7 @@ public void testCachesAddedAtRuntimeGetReInited() { cacheManager.init(); - CacheConfiguration cache2Configuration = new BaseCacheConfiguration<>(Long.class, String.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + CacheConfiguration cache2Configuration = new TestCacheConfig<>(Long.class, String.class, ResourcePoolsHelper.createResourcePools(100L)); cacheManager.createCache("cache2", cache2Configuration); cacheManager.removeCache("cache1"); @@ -777,8 +770,7 @@ public void testCloseWhenRuntimeCacheCreationFails() throws Exception { cacheManager.init(); - CacheConfiguration cacheConfiguration = new BaseCacheConfiguration<>(Long.class, String.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Long.class, String.class); try { cacheManager.createCache("cache", cacheConfiguration); @@ -798,8 +790,7 @@ public void testCloseWhenCacheCreationFailsDuringInitialization() throws Excepti when(storeProvider.rank(any(Set.class), any(Collection.class))).thenReturn(1); doThrow(new Error("Test EhcacheManager close.")).when(storeProvider).createStore(any(Store.Configuration.class), ArgumentMatchers.any()); - CacheConfiguration cacheConfiguration = new BaseCacheConfiguration<>(Long.class, String.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Long.class, String.class); Map> caches = newCacheMap(); caches.put("cache1", cacheConfiguration); DefaultConfiguration config = new DefaultConfiguration(caches, null); diff --git a/core/src/test/java/org/ehcache/core/EhcacheTest.java b/core/src/test/java/org/ehcache/core/EhcacheTest.java index 4f127ddfcc..91d2afda22 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheTest.java @@ -18,11 +18,9 @@ import static org.mockito.Mockito.mock; import org.ehcache.config.CacheConfiguration; -import org.ehcache.core.config.BaseCacheConfiguration; -import org.ehcache.core.config.ResourcePoolsHelper; import org.ehcache.core.events.CacheEventDispatcher; -import org.ehcache.core.resilience.DefaultRecoveryStore; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.util.TestCacheConfig; import org.ehcache.spi.resilience.ResilienceStrategy; import org.slf4j.LoggerFactory; @@ -34,8 +32,7 @@ public class EhcacheTest extends CacheTest { @Override protected InternalCache getCache(Store store) { - final CacheConfiguration config = new BaseCacheConfiguration<>(Object.class, Object.class, null, - null, null, ResourcePoolsHelper.createHeapOnlyPools()); + final CacheConfiguration config = new TestCacheConfig<>(Object.class, Object.class); @SuppressWarnings("unchecked") CacheEventDispatcher cacheEventDispatcher = mock(CacheEventDispatcher.class); @SuppressWarnings("unchecked") diff --git a/core/src/test/java/org/ehcache/core/UserManagedCacheTest.java b/core/src/test/java/org/ehcache/core/UserManagedCacheTest.java index 20e2617c07..3d792887f6 100644 --- a/core/src/test/java/org/ehcache/core/UserManagedCacheTest.java +++ b/core/src/test/java/org/ehcache/core/UserManagedCacheTest.java @@ -18,8 +18,6 @@ import org.ehcache.Status; import org.ehcache.config.CacheConfiguration; -import org.ehcache.core.config.BaseCacheConfiguration; -import org.ehcache.core.config.ResourcePoolsHelper; import org.ehcache.core.events.CacheEventDispatcher; import org.ehcache.core.spi.store.Store; import org.ehcache.StateTransitionException; @@ -44,8 +42,7 @@ public class UserManagedCacheTest { @Test public void testUserManagedCacheDelegatesLifecycleCallsToStore() throws Exception { final Store store = mock(Store.class); - CacheConfiguration config = new BaseCacheConfiguration<>(Object.class, Object.class, null, null, - null, ResourcePoolsHelper.createHeapOnlyPools()); + CacheConfiguration config = mock(CacheConfiguration.class); Ehcache ehcache = new Ehcache(config, store, mock(ResilienceStrategy.class), mock(CacheEventDispatcher.class), LoggerFactory.getLogger(Ehcache.class + "testUserManagedCacheDelegatesLifecycleCallsToStore")); assertCacheDelegatesLifecycleCallsToStore(ehcache); @@ -67,8 +64,7 @@ private void assertCacheDelegatesLifecycleCallsToStore(InternalCache cache) thro @Test public void testUserManagedEhcacheFailingTransitionGoesToLowestStatus() throws Exception { final Store store = mock(Store.class); - CacheConfiguration config = new BaseCacheConfiguration<>(Object.class, Object.class, null, null, null, ResourcePoolsHelper - .createHeapOnlyPools()); + CacheConfiguration config = mock(CacheConfiguration.class); Ehcache ehcache = new Ehcache(config, store, mock(ResilienceStrategy.class), mock(CacheEventDispatcher.class), LoggerFactory.getLogger(Ehcache.class + "testUserManagedEhcacheFailingTransitionGoesToLowestStatus")); assertFailingTransitionGoesToLowestStatus(ehcache); Ehcache ehcacheWithLoaderWriter = new Ehcache(config, store, mock(ResilienceStrategy.class), diff --git a/core/src/test/java/org/ehcache/core/config/ResourcePoolsHelper.java b/core/src/test/java/org/ehcache/core/config/ResourcePoolsHelper.java index c6f1751f74..fc7f023774 100644 --- a/core/src/test/java/org/ehcache/core/config/ResourcePoolsHelper.java +++ b/core/src/test/java/org/ehcache/core/config/ResourcePoolsHelper.java @@ -21,56 +21,60 @@ import org.ehcache.config.ResourceUnit; import org.ehcache.config.SizedResourcePool; import org.ehcache.config.units.EntryUnit; -import org.ehcache.config.units.MemoryUnit; -import java.util.HashMap; -import java.util.Map; +import java.util.Collections; +import java.util.Set; /** * @author Ludovic Orban */ public class ResourcePoolsHelper { - public static ResourcePools createHeapOnlyPools() { - return createHeapOnlyPools(Long.MAX_VALUE); - } + public static ResourcePools createResourcePools(long size) { + return new ResourcePools() { + @Override @SuppressWarnings("unchecked") + public

P getPoolForResource(ResourceType

resourceType) { + if (ResourceType.Core.HEAP.equals(resourceType)) { + return (P) new SizedResourcePool() { + @Override + public long getSize() { + return size; + } - public static ResourcePools createHeapOnlyPools(long heapSize) { - Map, ResourcePool> poolsMap = new HashMap<>(); - poolsMap.put(ResourceType.Core.HEAP, new SizedResourcePoolImpl<>(ResourceType.Core.HEAP, heapSize, EntryUnit.ENTRIES, false)); - return new ResourcePoolsImpl(poolsMap); - } + @Override + public ResourceUnit getUnit() { + return EntryUnit.ENTRIES; + } - public static ResourcePools createHeapOnlyPools(long heapSize, ResourceUnit resourceUnit) { - Map, ResourcePool> poolsMap = new HashMap<>(); - poolsMap.put(ResourceType.Core.HEAP, new SizedResourcePoolImpl<>(ResourceType.Core.HEAP, heapSize, resourceUnit, false)); - return new ResourcePoolsImpl(poolsMap); - } + @Override + public ResourceType getType() { + return ResourceType.Core.HEAP; + } - public static ResourcePools createOffheapOnlyPools(long offheapSizeInMb) { - Map, ResourcePool> poolsMap = new HashMap<>(); - poolsMap.put(ResourceType.Core.OFFHEAP, new SizedResourcePoolImpl<>(ResourceType.Core.OFFHEAP, offheapSizeInMb, MemoryUnit.MB, false)); - return new ResourcePoolsImpl(poolsMap); - } + @Override + public boolean isPersistent() { + return false; + } - public static ResourcePools createDiskOnlyPools(long diskSize, ResourceUnit resourceUnit) { - Map, ResourcePool> poolsMap = new HashMap<>(); - poolsMap.put(ResourceType.Core.DISK, new SizedResourcePoolImpl<>(ResourceType.Core.DISK, diskSize, resourceUnit, false)); - return new ResourcePoolsImpl(poolsMap); - } + @Override + public void validateUpdate(ResourcePool newPool) { + //all updates are okay + } + }; + } else { + return null; + } + } - public static ResourcePools createHeapDiskPools(long heapSize, long diskSizeInMb) { - Map, ResourcePool> poolsMap = new HashMap<>(); - poolsMap.put(ResourceType.Core.HEAP, new SizedResourcePoolImpl<>(ResourceType.Core.HEAP, heapSize, EntryUnit.ENTRIES, false)); - poolsMap.put(ResourceType.Core.DISK, new SizedResourcePoolImpl<>(ResourceType.Core.DISK, diskSizeInMb, MemoryUnit.MB, false)); - return new ResourcePoolsImpl(poolsMap); - } + @Override + public Set> getResourceTypeSet() { + return Collections.singleton(ResourceType.Core.HEAP); + } - public static ResourcePools createHeapDiskPools(long heapSize, ResourceUnit heapResourceUnit, long diskSizeInMb) { - Map, ResourcePool> poolsMap = new HashMap<>(); - poolsMap.put(ResourceType.Core.HEAP, new SizedResourcePoolImpl<>(ResourceType.Core.HEAP, heapSize, heapResourceUnit, false)); - poolsMap.put(ResourceType.Core.DISK, new SizedResourcePoolImpl<>(ResourceType.Core.DISK, diskSizeInMb, MemoryUnit.MB, false)); - return new ResourcePoolsImpl(poolsMap); + @Override + public ResourcePools validateAndMerge(ResourcePools toBeUpdated) throws IllegalArgumentException, UnsupportedOperationException { + return toBeUpdated; + } + }; } - } diff --git a/core/src/test/java/org/ehcache/core/config/store/StoreStatisticsConfigurationTest.java b/core/src/test/java/org/ehcache/core/config/store/StoreStatisticsConfigurationTest.java new file mode 100644 index 0000000000..5b95d8201a --- /dev/null +++ b/core/src/test/java/org/ehcache/core/config/store/StoreStatisticsConfigurationTest.java @@ -0,0 +1,36 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.core.config.store; + +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; + +public class StoreStatisticsConfigurationTest { + + @Test + public void testDeriveDetachesCorrectly() { + StoreStatisticsConfiguration configuration = new StoreStatisticsConfiguration(true); + StoreStatisticsConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.isOperationStatisticsEnabled(), is(configuration.isOperationStatisticsEnabled())); + } +} diff --git a/core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java b/core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java index c2082de08d..4be41d6098 100644 --- a/core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java +++ b/core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java @@ -518,7 +518,7 @@ public void stop() { class YetAnotherCacheProvider implements CacheProvider { @Override - public Ehcache createCache(Class keyClazz, Class valueClazz, ServiceConfiguration... config) { + public Ehcache createCache(Class keyClazz, Class valueClazz, ServiceConfiguration... config) { return null; } diff --git a/core/src/test/java/org/ehcache/core/spi/services/FancyCacheProvider.java b/core/src/test/java/org/ehcache/core/spi/services/FancyCacheProvider.java index 0907e01815..954c5d66bc 100644 --- a/core/src/test/java/org/ehcache/core/spi/services/FancyCacheProvider.java +++ b/core/src/test/java/org/ehcache/core/spi/services/FancyCacheProvider.java @@ -30,7 +30,7 @@ public class FancyCacheProvider implements CacheProvider { public int startStopCounter = 0; @Override - public Ehcache createCache(Class keyClazz, Class valueClazz, ServiceConfiguration... config) { + public Ehcache createCache(Class keyClazz, Class valueClazz, ServiceConfiguration... config) { return null; } diff --git a/core/src/test/java/org/ehcache/core/spi/store/CacheProvider.java b/core/src/test/java/org/ehcache/core/spi/store/CacheProvider.java index 7228e5bdb5..0db6eb7b02 100644 --- a/core/src/test/java/org/ehcache/core/spi/store/CacheProvider.java +++ b/core/src/test/java/org/ehcache/core/spi/store/CacheProvider.java @@ -27,7 +27,7 @@ @PluralService public interface CacheProvider extends Service { - Ehcache createCache(Class keyClazz, Class valueClazz, ServiceConfiguration... config); + Ehcache createCache(Class keyClazz, Class valueClazz, ServiceConfiguration... config); void releaseCache(Ehcache resource); } diff --git a/core/src/test/java/org/ehcache/core/store/StoreSupportTest.java b/core/src/test/java/org/ehcache/core/store/StoreSupportTest.java index 744d5e0797..eb6eb4b48c 100644 --- a/core/src/test/java/org/ehcache/core/store/StoreSupportTest.java +++ b/core/src/test/java/org/ehcache/core/store/StoreSupportTest.java @@ -80,7 +80,7 @@ public void testSelectStoreProvider() throws Exception { final ServiceLocator serviceLocator = dependencySet().with(storeProviders).build(); final Store.Provider selectedProvider = StoreSupport.selectStoreProvider(serviceLocator, Collections.>singleton(anyResourceType), - Collections.>emptyList()); + Collections.>emptyList()); assertThat(selectedProvider, is(Matchers.sameInstance(expectedProvider))); @@ -106,7 +106,7 @@ public void testSelectStoreProviderMultiple() throws Exception { try { StoreSupport.selectStoreProvider(serviceLocator, Collections.>singleton(anyResourceType), - Collections.>emptyList()); + Collections.>emptyList()); fail(); } catch (IllegalStateException e) { // expected @@ -123,7 +123,7 @@ public void testSelectStoreProviderNoProviders() throws Exception { try { StoreSupport.selectStoreProvider(dependencySet().build(), Collections.>singleton(anyResourceType), - Collections.>emptyList()); + Collections.>emptyList()); fail(); } catch (IllegalStateException e) { // expected @@ -163,7 +163,7 @@ public int getTierHeight() { try { StoreSupport.selectStoreProvider(serviceLocator, Collections.>singleton(otherResourceType), - Collections.>emptyList()); + Collections.>emptyList()); fail(); } catch (IllegalStateException e) { // expected @@ -214,7 +214,7 @@ public TestBaseProvider(final int rank) { } @Override - public Store createStore(final Store.Configuration storeConfig, final ServiceConfiguration... serviceConfigs) { + public Store createStore(final Store.Configuration storeConfig, final ServiceConfiguration... serviceConfigs) { throw new UnsupportedOperationException("TestBaseProvider.createStore not implemented"); } @@ -229,7 +229,7 @@ public void initStore(final Store resource) { } @Override - public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { + public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { assertThat(resourceTypes, is(not(nullValue()))); assertThat(serviceConfigs, is(not(nullValue()))); rankAccessCount.incrementAndGet(); diff --git a/core/src/test/java/org/ehcache/core/util/TestCacheConfig.java b/core/src/test/java/org/ehcache/core/util/TestCacheConfig.java new file mode 100644 index 0000000000..7d7ec62d12 --- /dev/null +++ b/core/src/test/java/org/ehcache/core/util/TestCacheConfig.java @@ -0,0 +1,262 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.core.util; + +import org.ehcache.config.CacheConfiguration; +import org.ehcache.config.Eviction; +import org.ehcache.config.EvictionAdvisor; +import org.ehcache.config.FluentCacheConfigurationBuilder; +import org.ehcache.config.ResourcePools; +import org.ehcache.expiry.ExpiryPolicy; +import org.ehcache.spi.copy.Copier; +import org.ehcache.spi.loaderwriter.CacheLoaderWriter; +import org.ehcache.spi.resilience.ResilienceStrategy; +import org.ehcache.spi.serialization.Serializer; +import org.ehcache.spi.service.ServiceConfiguration; + +import java.util.Collection; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +import static java.util.Collections.emptyList; +import static org.ehcache.core.config.ExpiryUtils.convertToExpiry; +import static org.ehcache.core.config.ResourcePoolsHelper.createResourcePools; + +public class TestCacheConfig implements CacheConfiguration { + + private final Class keyType; + private final Class valueType; + private final ResourcePools resources; + + public TestCacheConfig(Class keyType, Class valueType) { + this(keyType, valueType, createResourcePools(100L)); + } + + public TestCacheConfig(Class keyType, Class valueType, ResourcePools resources) { + this.keyType = keyType; + this.valueType = valueType; + this.resources = resources; + } + + @Override + public Collection> getServiceConfigurations() { + return emptyList(); + } + + @Override + public Class getKeyType() { + return keyType; + } + + @Override + public Class getValueType() { + return valueType; + } + + @Override + public EvictionAdvisor getEvictionAdvisor() { + return Eviction.noAdvice(); + } + + @Override + public ClassLoader getClassLoader() { + return null; + } + + @Override @SuppressWarnings("deprecation") + public org.ehcache.expiry.Expiry getExpiry() { + return convertToExpiry(getExpiryPolicy()); + } + + @Override + public ExpiryPolicy getExpiryPolicy() { + return ExpiryPolicy.NO_EXPIRY; + } + + @Override + public ResourcePools getResourcePools() { + return resources; + } + + @Override + public Builder derive() { + return new Builder(); + } + + public class Builder implements FluentCacheConfigurationBuilder { + + @Override + public CacheConfiguration build() { + return TestCacheConfig.this; + } + + @Override + public > Collection getServices(Class configurationType) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withService(ServiceConfiguration config) { + throw new UnsupportedOperationException(); + } + + @Override + public > Builder withoutServices(Class clazz, Predicate predicate) { + throw new UnsupportedOperationException(); + } + + @Override + public > Builder updateServices(Class clazz, UnaryOperator update) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withEvictionAdvisor(EvictionAdvisor evictionAdvisor) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withClassLoader(ClassLoader classLoader) { + return new TestCacheConfig(getKeyType(), getValueType(), resources) { + @Override + public ClassLoader getClassLoader() { + return classLoader; + } + }.derive(); + } + + @Override + public Builder withDefaultClassLoader() { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withResourcePools(ResourcePools resourcePools) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder updateResourcePools(UnaryOperator update) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withExpiry(ExpiryPolicy expiry) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withLoaderWriter(CacheLoaderWriter loaderWriter) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withLoaderWriter(Class> cacheLoaderWriterClass, Object... arguments) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withoutLoaderWriter() { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withResilienceStrategy(ResilienceStrategy resilienceStrategy) { + throw new UnsupportedOperationException(); + } + + @Override @SuppressWarnings("rawtypes") + public Builder withResilienceStrategy(Class resilienceStrategyClass, Object... arguments) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withDefaultResilienceStrategy() { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withKeySerializingCopier() { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withValueSerializingCopier() { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withKeyCopier(Copier keyCopier) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withKeyCopier(Class> keyCopierClass) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withoutKeyCopier() { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withValueCopier(Copier valueCopier) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withValueCopier(Class> valueCopierClass) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withoutValueCopier() { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withKeySerializer(Serializer keySerializer) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withKeySerializer(Class> keySerializerClass) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withDefaultKeySerializer() { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withValueSerializer(Serializer valueSerializer) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withValueSerializer(Class> valueSerializerClass) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder withDefaultValueSerializer() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/impl/src/main/java/org/ehcache/config/builders/CacheConfigurationBuilder.java b/impl/src/main/java/org/ehcache/config/builders/CacheConfigurationBuilder.java index df07cd11be..f5b875f4b7 100644 --- a/impl/src/main/java/org/ehcache/config/builders/CacheConfigurationBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/CacheConfigurationBuilder.java @@ -19,9 +19,10 @@ import org.ehcache.config.Builder; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.EvictionAdvisor; +import org.ehcache.config.FluentCacheConfigurationBuilder; import org.ehcache.config.ResourcePools; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.config.BaseCacheConfiguration; +import org.ehcache.impl.config.BaseCacheConfiguration; import org.ehcache.core.config.store.StoreEventSourceConfiguration; import org.ehcache.core.spi.store.heap.SizeOfEngine; import org.ehcache.expiry.ExpiryPolicy; @@ -44,11 +45,14 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; +import java.util.Iterator; import java.util.List; +import java.util.function.Predicate; +import java.util.function.Supplier; import java.util.function.UnaryOperator; import static java.util.Objects.requireNonNull; -import static java.util.Optional.ofNullable; +import static java.util.stream.Collectors.toList; import static org.ehcache.core.config.ExpiryUtils.convertToExpiryPolicy; import static org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration.DEFAULT_MAX_OBJECT_SIZE; import static org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration.DEFAULT_OBJECT_GRAPH_SIZE; @@ -62,9 +66,9 @@ * instance without modifying the one on which the method was called. * This enables the sharing of builder instances without any risk of seeing them modified by code elsewhere. */ -public class CacheConfigurationBuilder implements Builder> { +public class CacheConfigurationBuilder implements FluentCacheConfigurationBuilder> { - private final Collection> serviceConfigurations = new HashSet<>(); + private final Collection> serviceConfigurations = new HashSet<>(); private ExpiryPolicy expiry; private ClassLoader classLoader = null; private EvictionAdvisor evictionAdvisor; @@ -112,11 +116,14 @@ public static CacheConfigurationBuilder newCacheConfigurationBuilde */ public static CacheConfigurationBuilder newCacheConfigurationBuilder(CacheConfiguration configuration) { CacheConfigurationBuilder builder = newCacheConfigurationBuilder(configuration.getKeyType(), configuration.getValueType(), configuration.getResourcePools()) - .withClassLoader(configuration.getClassLoader()) .withEvictionAdvisor(configuration.getEvictionAdvisor()) .withExpiry(configuration.getExpiryPolicy()); - for (ServiceConfiguration serviceConfig : configuration.getServiceConfigurations()) { - builder = builder.add(serviceConfig); + ClassLoader classLoader = configuration.getClassLoader(); + if (classLoader != null) { + builder = builder.withClassLoader(classLoader); + } + for (ServiceConfiguration serviceConfig : configuration.getServiceConfigurations()) { + builder = builder.withService(serviceConfig); } return builder; } @@ -142,24 +149,21 @@ private CacheConfigurationBuilder(CacheConfigurationBuilder other) { * * @param configuration the service configuration to add * @return a new builder with the added service configuration + * @deprecated in favor of {@link #withService(ServiceConfiguration)} */ - public CacheConfigurationBuilder add(ServiceConfiguration configuration) { - CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this); - - if (getExistingServiceConfiguration(configuration.getClass()) != null) { - if (configuration instanceof DefaultCopierConfiguration) { - DefaultCopierConfiguration copierConfiguration = (DefaultCopierConfiguration) configuration; - otherBuilder.removeExistingCopierConfigFor(copierConfiguration.getType()); - } else if (configuration instanceof DefaultSerializerConfiguration) { - DefaultSerializerConfiguration serializerConfiguration = (DefaultSerializerConfiguration) configuration; - otherBuilder.removeExistingSerializerConfigFor(serializerConfiguration.getType()); - } else if (!(configuration instanceof DefaultCacheEventListenerConfiguration)) { + @Deprecated + public CacheConfigurationBuilder add(ServiceConfiguration configuration) { + if (!getServices(configuration.getClass()).isEmpty()) { + if (configuration instanceof DefaultCopierConfiguration + || configuration instanceof DefaultSerializerConfiguration + || configuration instanceof DefaultCacheEventListenerConfiguration) { + return withService(configuration); + } else { throw new IllegalStateException("Cannot add a generic service configuration when another one already exists. " + - "Rely on specific with* methods or make sure your remove other configuration first."); + "Rely on specific with* methods or make sure your remove other configuration first."); } } - otherBuilder.serviceConfigurations.add(configuration); - return otherBuilder; + return withService(configuration); } /** @@ -169,17 +173,61 @@ public CacheConfigurationBuilder add(ServiceConfiguration configuration * @return a new builder with the added service configuration * * @see #add(ServiceConfiguration) + * @deprecated in favor of {@link #withService(Builder)} */ - public CacheConfigurationBuilder add(Builder> configurationBuilder) { + @Deprecated + public CacheConfigurationBuilder add(Builder> configurationBuilder) { return add(configurationBuilder.build()); } - /** - * Adds an {@link EvictionAdvisor} to the returned builder. - * - * @param evictionAdvisor the eviction advisor to be used - * @return a new builder with the added eviction advisor - */ + @Override + public > Collection getServices(Class configurationType) throws IllegalArgumentException { + return serviceConfigurations.stream().filter(configurationType::isInstance).map(configurationType::cast).collect(toList()); + } + + @Override + public CacheConfigurationBuilder withService(ServiceConfiguration config) { + CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this); + otherBuilder.serviceConfigurations.removeIf(other -> !other.compatibleWith(config) || !config.compatibleWith(other)); + otherBuilder.serviceConfigurations.add(config); + return otherBuilder; + } + + @Override + public CacheConfigurationBuilder withoutServices(Class> clazz) { + CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this); + otherBuilder.serviceConfigurations.removeIf(clazz::isInstance); + return otherBuilder; + } + + @Override + public >CacheConfigurationBuilder withoutServices(Class clazz, Predicate predicate) { + CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this); + otherBuilder.serviceConfigurations.removeIf(c -> clazz.isInstance(c) && predicate.test(clazz.cast(c))); + return otherBuilder; + } + + @Override + public > CacheConfigurationBuilder updateServices(Class clazz, UnaryOperator update) { + Collection> existing = getServices(clazz); + + if (existing.isEmpty()) { + throw new IllegalStateException("Cannot update service configurations. No existing services of type: " + clazz); + } else { + CacheConfigurationBuilder otherBuilder = withoutServices(clazz); + for (ServiceConfiguration configuration : existing) { + ServiceConfiguration replacement = configuration.build(update.apply(configuration.derive())); + if (replacement == null) { + throw new NullPointerException(configuration.getClass().getSimpleName() + ".build(...) returned a null configuration instance"); + } else { + otherBuilder = otherBuilder.withService(replacement); + } + } + return otherBuilder; + } + } + + @Override public CacheConfigurationBuilder withEvictionAdvisor(final EvictionAdvisor evictionAdvisor) { CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this); otherBuilder.evictionAdvisor = evictionAdvisor; @@ -191,8 +239,10 @@ public CacheConfigurationBuilder withEvictionAdvisor(final EvictionAdvisor * * @param configuration the service configuration to remove * @return a new builder without the specified configuration + * @deprecated in favor of {@link #withoutServices(Class)} or {@link #withoutServices(Class, Predicate)} */ - public CacheConfigurationBuilder remove(ServiceConfiguration configuration) { + @Deprecated + public CacheConfigurationBuilder remove(ServiceConfiguration configuration) { CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this); otherBuilder.serviceConfigurations.remove(configuration); return otherBuilder; @@ -202,11 +252,11 @@ public CacheConfigurationBuilder remove(ServiceConfiguration configurat * Clears all {@link ServiceConfiguration}s from the returned builder. * * @return a new builder with no service configurations left + * @deprecated in favor of {@link #withoutServices(Class) withoutServices(ServiceConfiguration.class)} */ + @Deprecated @SuppressWarnings("unchecked") public CacheConfigurationBuilder clearAllServiceConfig() { - CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this); - otherBuilder.serviceConfigurations.clear(); - return otherBuilder; + return withoutServices((Class) ServiceConfiguration.class); } /** @@ -215,14 +265,12 @@ public CacheConfigurationBuilder clearAllServiceConfig() { * @param clazz the service configuration class * @param the type of the service configuration * @return a matching service configuration, or {@code null} if none can be found + * @deprecated in favor of {@link #getService(Class)} */ - public > T getExistingServiceConfiguration(Class clazz) { - for (ServiceConfiguration serviceConfiguration : serviceConfigurations) { - if (clazz.equals(serviceConfiguration.getClass())) { - return clazz.cast(serviceConfiguration); - } - } - return null; + @Deprecated + public > T getExistingServiceConfiguration(Class clazz) { + Iterator iterator = getServices(clazz).iterator(); + return iterator.hasNext() ? iterator.next() : null; } /** @@ -231,39 +279,28 @@ public > T getExistingServiceConfiguration(Cla * @param clazz the service configuration class * @param the type of the service configuration * @return a list with service configurations + * @deprecated in favor of {@link #getServices(Class)} */ - public > List getExistingServiceConfigurations(Class clazz) { - ArrayList results = new ArrayList<>(); - for (ServiceConfiguration serviceConfiguration : serviceConfigurations) { - if (clazz.equals(serviceConfiguration.getClass())) { - results.add(clazz.cast(serviceConfiguration)); - } - } - return results; + @Deprecated + public > List getExistingServiceConfigurations(Class clazz) { + return new ArrayList<>(getServices(clazz)); } - /** - * Adds a {@link ClassLoader} to the returned builder. - *

- * The {@link ClassLoader} will be used for resolving all non Ehcache types. - * - * @param classLoader the class loader to use - * @return a new builder with the added class loader - */ + @Override public CacheConfigurationBuilder withClassLoader(ClassLoader classLoader) { CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this); - otherBuilder.classLoader = classLoader; + otherBuilder.classLoader = requireNonNull(classLoader); return otherBuilder; } - /** - * Adds the {@link ResourcePools} to the returned builder. - *

- * {@link ResourcePools} is what determines the tiering of a cache. - * - * @param resourcePools the resource pools to use - * @return a new builder with the added resource pools - */ + @Override + public CacheConfigurationBuilder withDefaultClassLoader() { + CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this); + otherBuilder.classLoader = null; + return otherBuilder; + } + + @Override public CacheConfigurationBuilder withResourcePools(ResourcePools resourcePools) { if (resourcePools == null) { throw new NullPointerException("Null resource pools"); @@ -273,16 +310,11 @@ public CacheConfigurationBuilder withResourcePools(ResourcePools resourceP return otherBuilder; } - /** - * Convenience method to add a {@link ResourcePools} through a {@link ResourcePoolsBuilder} to the returned builder. - * - * @param resourcePoolsBuilder the builder providing the resource pool - * @return a new builder with the added resource pools - * - * @see #withResourcePools(ResourcePools) - */ - public CacheConfigurationBuilder withResourcePools(ResourcePoolsBuilder resourcePoolsBuilder) { - return withResourcePools(requireNonNull(resourcePoolsBuilder, "Null resource pools builder").build()); + @Override + public CacheConfigurationBuilder updateResourcePools(UnaryOperator update) { + CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this); + otherBuilder.resourcePools = update.apply(resourcePools); + return otherBuilder; } /** @@ -300,14 +332,7 @@ public CacheConfigurationBuilder withExpiry(org.ehcache.expiry.Expiry - * {@code ExpiryPolicy} is what controls data freshness in a cache. - * - * @param expiry the expiry to use - * @return a new builder with the added expiry - */ + @Override public CacheConfigurationBuilder withExpiry(ExpiryPolicy expiry) { if (expiry == null) { throw new NullPointerException("Null expiry"); @@ -326,171 +351,104 @@ public boolean hasConfiguredExpiry() { return expiry != null; } - /** - * Adds a {@link CacheLoaderWriter} to the configured builder. - *

- * Configuration of a {@link CacheLoaderWriter} is what enables cache-through patterns. - * - * @param loaderWriter the loaderwriter to use - * @return a new builder with the added loaderwriter configuration - */ + @Override public CacheConfigurationBuilder withLoaderWriter(CacheLoaderWriter loaderWriter) { - return addOrReplaceConfiguration(new DefaultCacheLoaderWriterConfiguration(requireNonNull(loaderWriter, "Null loaderWriter"))); + return withService(new DefaultCacheLoaderWriterConfiguration(requireNonNull(loaderWriter, "Null loaderWriter"))); } - /** - * Adds a {@link CacheLoaderWriter} configured through a class and optional constructor arguments to the configured - * builder. - *

- * Configuration of a {@link CacheLoaderWriter} is what enables cache-through patterns. - * - * @param loaderWriterClass the loaderwrite class - * @param arguments optional constructor arguments - * @return a new builder with the added loaderwriter configuration - */ + @Override public CacheConfigurationBuilder withLoaderWriter(Class> loaderWriterClass, Object... arguments) { - return addOrReplaceConfiguration(new DefaultCacheLoaderWriterConfiguration(requireNonNull(loaderWriterClass, "Null loaderWriterClass"), arguments)); + return withService(new DefaultCacheLoaderWriterConfiguration(requireNonNull(loaderWriterClass, "Null loaderWriterClass"), arguments)); } - /** - * Adds a {@link ResilienceStrategy} to the configured builder. - * - * @param resilienceStrategy the resilience strategy to use - * @return a new builder with the added resilience strategy configuration - */ + @Override + public CacheConfigurationBuilder withoutLoaderWriter() { + return withoutServices(DefaultCacheLoaderWriterConfiguration.class); + } + + @Override public CacheConfigurationBuilder withResilienceStrategy(ResilienceStrategy resilienceStrategy) { - return addOrReplaceConfiguration(new DefaultResilienceStrategyConfiguration(requireNonNull(resilienceStrategy, "Null resilienceStrategy"))); + return withService(new DefaultResilienceStrategyConfiguration(requireNonNull(resilienceStrategy, "Null resilienceStrategy"))); } - /** - * Adds a {@link ResilienceStrategy} configured through a class and optional constructor arguments to the configured - * builder. - * - * @param resilienceStrategyClass the resilience strategy class - * @param arguments optional constructor arguments - * @return a new builder with the added resilience strategy configuration - */ - @SuppressWarnings("rawtypes") + @Override @SuppressWarnings("rawtypes") public CacheConfigurationBuilder withResilienceStrategy(Class resilienceStrategyClass, Object... arguments) { - return addOrReplaceConfiguration(new DefaultResilienceStrategyConfiguration(requireNonNull(resilienceStrategyClass, "Null resilienceStrategyClass"), arguments)); + return withService(new DefaultResilienceStrategyConfiguration(requireNonNull(resilienceStrategyClass, "Null resilienceStrategyClass"), arguments)); } - /** - * Adds by-value semantic using the cache key serializer for the key on heap. - *

- * {@link Copier}s are what enable control of by-reference / by-value semantics for on-heap tier. - * - * @return a new builder with the added key copier - */ + @Override + public CacheConfigurationBuilder withDefaultResilienceStrategy() { + return withoutServices(DefaultResilienceStrategyConfiguration.class); + } + + @Override public CacheConfigurationBuilder withKeySerializingCopier() { return withKeyCopier(SerializingCopier.asCopierClass()); } - /** - * Adds by-value semantic using the cache value serializer for the value on heap. - *

- * {@link Copier}s are what enable control of by-reference / by-value semantics for on-heap tier. - * - * @return a new builder with the added value copier - */ + @Override public CacheConfigurationBuilder withValueSerializingCopier() { return withValueCopier(SerializingCopier.asCopierClass()); } - /** - * Adds by-value semantic using the provided {@link Copier} for the key on heap. - *

- * {@link Copier}s are what enable control of by-reference / by-value semantics for on-heap tier. - * - * @param keyCopier the key copier to use - * @return a new builder with the added key copier - */ + @Override public CacheConfigurationBuilder withKeyCopier(Copier keyCopier) { - return withCopier(new DefaultCopierConfiguration<>(requireNonNull(keyCopier, "Null key copier"), DefaultCopierConfiguration.Type.KEY)); + return withService(new DefaultCopierConfiguration<>(requireNonNull(keyCopier, "Null key copier"), DefaultCopierConfiguration.Type.KEY)); } - /** - * Adds by-value semantic using the provided {@link Copier} class for the key on heap. - *

- * {@link Copier}s are what enable control of by-reference / by-value semantics for on-heap tier. - * - * @param keyCopierClass the key copier class to use - * @return a new builder with the added key copier - */ + @Override public CacheConfigurationBuilder withKeyCopier(Class> keyCopierClass) { - return withCopier(new DefaultCopierConfiguration<>(requireNonNull(keyCopierClass, "Null key copier class"), DefaultCopierConfiguration.Type.KEY)); + return withService(new DefaultCopierConfiguration<>(requireNonNull(keyCopierClass, "Null key copier class"), DefaultCopierConfiguration.Type.KEY)); } - /** - * Adds by-value semantic using the provided {@link Copier} for the value on heap. - *

- * {@link Copier}s are what enable control of by-reference / by-value semantics for on-heap tier. - * - * @param valueCopier the value copier to use - * @return a new builder with the added value copier - */ + @Override + public CacheConfigurationBuilder withoutKeyCopier() { + return withoutServices(DefaultCopierConfiguration.class, c -> DefaultCopierConfiguration.Type.KEY.equals(c.getType())); + } + + @Override public CacheConfigurationBuilder withValueCopier(Copier valueCopier) { - return withCopier(new DefaultCopierConfiguration<>(requireNonNull(valueCopier, "Null value copier"), DefaultCopierConfiguration.Type.VALUE)); + return withService(new DefaultCopierConfiguration<>(requireNonNull(valueCopier, "Null value copier"), DefaultCopierConfiguration.Type.VALUE)); } - /** - * Adds by-value semantic using the provided {@link Copier} class for the value on heap. - *

- * {@link Copier}s are what enable control of by-reference / by-value semantics for on-heap tier. - * - * @param valueCopierClass the value copier class to use - * @return a new builder with the added value copier - */ + @Override public CacheConfigurationBuilder withValueCopier(Class> valueCopierClass) { - return withCopier(new DefaultCopierConfiguration<>(requireNonNull(valueCopierClass, "Null value copier class"), DefaultCopierConfiguration.Type.VALUE)); + return withService(new DefaultCopierConfiguration<>(requireNonNull(valueCopierClass, "Null value copier class"), DefaultCopierConfiguration.Type.VALUE)); } - /** - * Adds a {@link Serializer} for cache keys to the configured builder. - *

- * {@link Serializer}s are what enables cache storage beyond the heap tier. - * - * @param keySerializer the key serializer to use - * @return a new builder with the added key serializer - */ + @Override + public CacheConfigurationBuilder withoutValueCopier() { + return withoutServices(DefaultCopierConfiguration.class, c -> DefaultCopierConfiguration.Type.VALUE.equals(c.getType())); + } + + @Override public CacheConfigurationBuilder withKeySerializer(Serializer keySerializer) { - return withSerializer(new DefaultSerializerConfiguration<>(requireNonNull(keySerializer, "Null key serializer"), DefaultSerializerConfiguration.Type.KEY)); + return withService(new DefaultSerializerConfiguration<>(requireNonNull(keySerializer, "Null key serializer"), DefaultSerializerConfiguration.Type.KEY)); } - /** - * Adds a {@link Serializer} class for cache keys to the configured builder. - *

- * {@link Serializer}s are what enables cache storage beyond the heap tier. - * - * @param keySerializerClass the key serializer to use - * @return a new builder with the added key serializer - */ + @Override public CacheConfigurationBuilder withKeySerializer(Class> keySerializerClass) { - return withSerializer(new DefaultSerializerConfiguration<>(requireNonNull(keySerializerClass, "Null key serializer class"), DefaultSerializerConfiguration.Type.KEY)); + return withService(new DefaultSerializerConfiguration<>(requireNonNull(keySerializerClass, "Null key serializer class"), DefaultSerializerConfiguration.Type.KEY)); } - /** - * Adds a {@link Serializer} for cache values to the configured builder. - *

- * {@link Serializer}s are what enables cache storage beyond the heap tier. - * - * @param valueSerializer the key serializer to use - * @return a new builder with the added value serializer - */ + @Override + public CacheConfigurationBuilder withDefaultKeySerializer() { + return withoutServices(DefaultSerializerConfiguration.class, config -> DefaultSerializerConfiguration.Type.KEY.equals(config.getType())); + } + + @Override public CacheConfigurationBuilder withValueSerializer(Serializer valueSerializer) { - return withSerializer(new DefaultSerializerConfiguration<>(requireNonNull(valueSerializer, "Null value serializer"), DefaultSerializerConfiguration.Type.VALUE)); + return withService(new DefaultSerializerConfiguration<>(requireNonNull(valueSerializer, "Null value serializer"), DefaultSerializerConfiguration.Type.VALUE)); } - /** - * Adds a {@link Serializer} class for cache values to the configured builder. - *

- * {@link Serializer}s are what enables cache storage beyond the heap tier. - * - * @param valueSerializerClass the key serializer to use - * @return a new builder with the added value serializer - */ + @Override public CacheConfigurationBuilder withValueSerializer(Class> valueSerializerClass) { - return withSerializer(new DefaultSerializerConfiguration<>(requireNonNull(valueSerializerClass, "Null value serializer class"), DefaultSerializerConfiguration.Type.VALUE)); + return withService(new DefaultSerializerConfiguration<>(requireNonNull(valueSerializerClass, "Null value serializer class"), DefaultSerializerConfiguration.Type.VALUE)); + } + + @Override + public CacheConfigurationBuilder withDefaultValueSerializer() { + return withoutServices(DefaultSerializerConfiguration.class, config -> DefaultSerializerConfiguration.Type.VALUE.equals(config.getType())); } /** @@ -499,9 +457,22 @@ public CacheConfigurationBuilder withValueSerializer(Class withDispatcherConcurrency(int dispatcherConcurrency) { - return addOrReplaceConfiguration(new DefaultEventSourceConfiguration(dispatcherConcurrency)); + return withService(new DefaultEventSourceConfiguration(dispatcherConcurrency)); + } + + /** + * Restores the default dispatcher concurrency. + * + * @return a new builder with the default dispatcher concurrency + * + * @see #withDispatcherConcurrency(int) + */ + public CacheConfigurationBuilder withDefaultDispatcherConcurrency() { + return withoutServices(DefaultEventSourceConfiguration.class); } /** @@ -510,9 +481,22 @@ public CacheConfigurationBuilder withDispatcherConcurrency(int dispatcherC * * @param threadPoolAlias the thread pool alias to use * @return a new builder with the added configuration + * + * @see #withDefaultEventListenersThreadPool() */ public CacheConfigurationBuilder withEventListenersThreadPool(String threadPoolAlias) { - return addOrReplaceConfiguration(new DefaultCacheEventDispatcherConfiguration(threadPoolAlias)); + return withService(new DefaultCacheEventDispatcherConfiguration(threadPoolAlias)); + } + + /** + * Restores the default event listener thread pool settings. + * + * @return a new builder with the default event listener thread pool settings + * + * @see #withEventListenersThreadPool(String) + */ + public CacheConfigurationBuilder withDefaultEventListenersThreadPool() { + return withoutServices(DefaultCacheEventDispatcherConfiguration.class); } /** @@ -522,9 +506,25 @@ public CacheConfigurationBuilder withEventListenersThreadPool(String threa * @param threadPoolAlias the thread pool alias * @param concurrency the write concurrency * @return a new builder with the added configuration + * + * @see #withDefaultDiskStoreThreadPool() */ public CacheConfigurationBuilder withDiskStoreThreadPool(String threadPoolAlias, int concurrency) { - return addOrReplaceConfiguration(new OffHeapDiskStoreConfiguration(threadPoolAlias, concurrency)); + return installOrUpdate( + () -> new OffHeapDiskStoreConfiguration(threadPoolAlias, concurrency), + existing -> new OffHeapDiskStoreConfiguration(threadPoolAlias, concurrency, existing.getDiskSegments()) + ); + } + + /** + * Restores the default disk store thread pool settings. + * + * @return a new builder with the default disk store thread pool settings + * + * @see #withDiskStoreThreadPool(String, int) + */ + public CacheConfigurationBuilder withDefaultDiskStoreThreadPool() { + return withoutServices(OffHeapDiskStoreConfiguration.class); } /** @@ -535,11 +535,15 @@ public CacheConfigurationBuilder withDiskStoreThreadPool(String threadPool * * @param size the maximum graph size * @return a new builder with the added / updated configuration + * + * @see #withSizeOfMaxObjectSize(long, MemoryUnit) + * @see #withDefaultSizeOfSettings() */ public CacheConfigurationBuilder withSizeOfMaxObjectGraph(long size) { - return mapServiceConfiguration(DefaultSizeOfEngineConfiguration.class, existing -> ofNullable(existing) - .map(e -> new DefaultSizeOfEngineConfiguration(e.getMaxObjectSize(), e.getUnit(), size)) - .orElse(new DefaultSizeOfEngineConfiguration(DEFAULT_MAX_OBJECT_SIZE, DEFAULT_UNIT, size))); + return installOrUpdate( + () -> new DefaultSizeOfEngineConfiguration(DEFAULT_MAX_OBJECT_SIZE, DEFAULT_UNIT, size), + existing -> new DefaultSizeOfEngineConfiguration(existing.getMaxObjectSize(), existing.getUnit(), size) + ); } /** @@ -551,71 +555,46 @@ public CacheConfigurationBuilder withSizeOfMaxObjectGraph(long size) { * @param size the maximum mapping size * @param unit the memory unit * @return a new builder with the added / updated configuration + * + * @see #withSizeOfMaxObjectGraph(long) + * @see #withDefaultSizeOfSettings() */ public CacheConfigurationBuilder withSizeOfMaxObjectSize(long size, MemoryUnit unit) { - return mapServiceConfiguration(DefaultSizeOfEngineConfiguration.class, existing -> ofNullable(existing) - .map(e -> new DefaultSizeOfEngineConfiguration(size, unit, e.getMaxObjectGraphSize())) - .orElse(new DefaultSizeOfEngineConfiguration(size, unit, DEFAULT_OBJECT_GRAPH_SIZE))); + return installOrUpdate( + () -> new DefaultSizeOfEngineConfiguration(size, unit, DEFAULT_OBJECT_GRAPH_SIZE), + existing -> new DefaultSizeOfEngineConfiguration(size, unit, existing.getMaxObjectGraphSize()) + ); + } + + /** + * Restores the default size-of settings. + * + * @return a new builder with the default size-of settings + * + * @see #withSizeOfMaxObjectGraph(long) + * @see #withSizeOfMaxObjectSize(long, MemoryUnit) + */ + public CacheConfigurationBuilder withDefaultSizeOfSettings() { + return withoutServices(DefaultSizeOfEngineConfiguration.class); } @Override public CacheConfiguration build() { return new BaseCacheConfiguration<>(keyType, valueType, evictionAdvisor, classLoader, expiry, resourcePools, - serviceConfigurations.toArray(new ServiceConfiguration[serviceConfigurations.size()])); + serviceConfigurations.toArray(new ServiceConfiguration[serviceConfigurations.size()])); } - private CacheConfigurationBuilder withSerializer(DefaultSerializerConfiguration configuration) { - CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this); - otherBuilder.removeExistingSerializerConfigFor(configuration.getType()); - otherBuilder.serviceConfigurations.add(configuration); - return otherBuilder; - } + private > CacheConfigurationBuilder installOrUpdate(Supplier supplier, UnaryOperator update) { + C newConfig = supplier.get(); - private void removeExistingSerializerConfigFor(DefaultSerializerConfiguration.Type type) { - @SuppressWarnings({"unchecked","rawtypes"}) - List> existingServiceConfigurations = - (List) getExistingServiceConfigurations(DefaultSerializerConfiguration.class); - for (DefaultSerializerConfiguration configuration : existingServiceConfigurations) { - if (configuration.getType().equals(type)) { - serviceConfigurations.remove(configuration); - } + @SuppressWarnings("unchecked") + Class configType = (Class) newConfig.getClass(); + if (getServices(configType).isEmpty()) { + return withService(newConfig); + } else { + return updateServices(configType, update); } } - private CacheConfigurationBuilder withCopier(DefaultCopierConfiguration configuration) { - CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this); - otherBuilder.removeExistingCopierConfigFor(configuration.getType()); - otherBuilder.serviceConfigurations.add(configuration); - return otherBuilder; - } - - private void removeExistingCopierConfigFor(DefaultCopierConfiguration.Type type) { - @SuppressWarnings({"unchecked","rawtypes"}) - List> existingServiceConfigurations = (List) getExistingServiceConfigurations(DefaultCopierConfiguration.class); - for (DefaultCopierConfiguration configuration : existingServiceConfigurations) { - if (configuration.getType().equals(type)) { - serviceConfigurations.remove(configuration); - } - } - } - - @SuppressWarnings("unchecked") - private > CacheConfigurationBuilder addOrReplaceConfiguration(T configuration) { - return addOrReplaceConfiguration((Class) configuration.getClass(), configuration); - } - - private > CacheConfigurationBuilder addOrReplaceConfiguration(Class configurationType, T configuration) { - return mapServiceConfiguration(configurationType, e -> configuration); - } - - private > CacheConfigurationBuilder mapServiceConfiguration(Class configurationType, UnaryOperator mapper) { - CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this); - T existingServiceConfiguration = otherBuilder.getExistingServiceConfiguration(configurationType); - if (existingServiceConfiguration != null) { - otherBuilder.serviceConfigurations.remove(existingServiceConfiguration); - } - otherBuilder.serviceConfigurations.add(mapper.apply(existingServiceConfiguration)); - return otherBuilder; - } } diff --git a/impl/src/main/java/org/ehcache/config/builders/CacheEventListenerConfigurationBuilder.java b/impl/src/main/java/org/ehcache/config/builders/CacheEventListenerConfigurationBuilder.java index 7db9fe8c33..6a77388099 100644 --- a/impl/src/main/java/org/ehcache/config/builders/CacheEventListenerConfigurationBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/CacheEventListenerConfigurationBuilder.java @@ -35,7 +35,7 @@ * instance without modifying the one on which the method was called. * This enables the sharing of builder instances without any risk of seeing them modified by code elsewhere. */ -public class CacheEventListenerConfigurationBuilder implements Builder { +public class CacheEventListenerConfigurationBuilder implements Builder> { private EventOrdering eventOrdering; private EventFiring eventFiringMode; private Object[] listenerArguments = new Object[0]; diff --git a/impl/src/main/java/org/ehcache/config/builders/ResourcePoolsBuilder.java b/impl/src/main/java/org/ehcache/config/builders/ResourcePoolsBuilder.java index 89e3a06807..3e3d595c5b 100644 --- a/impl/src/main/java/org/ehcache/config/builders/ResourcePoolsBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/ResourcePoolsBuilder.java @@ -20,9 +20,9 @@ import org.ehcache.config.ResourcePool; import org.ehcache.config.SizedResourcePool; import org.ehcache.config.units.EntryUnit; -import org.ehcache.core.config.SizedResourcePoolImpl; +import org.ehcache.impl.config.SizedResourcePoolImpl; import org.ehcache.config.ResourcePools; -import org.ehcache.core.config.ResourcePoolsImpl; +import org.ehcache.impl.config.ResourcePoolsImpl; import org.ehcache.config.ResourceType; import org.ehcache.config.ResourceUnit; import org.ehcache.config.units.MemoryUnit; @@ -32,7 +32,7 @@ import static java.util.Collections.unmodifiableMap; import java.util.HashMap; -import static org.ehcache.core.config.ResourcePoolsImpl.validateResourcePools; +import static org.ehcache.impl.config.ResourcePoolsImpl.validateResourcePools; /** * The {@code ResourcePoolsBuilder} enables building {@link ResourcePools} configurations using a fluent style. diff --git a/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java b/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java index a601146715..a22f9b78ff 100644 --- a/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java @@ -29,7 +29,7 @@ import org.ehcache.core.Ehcache; import org.ehcache.core.InternalCache; import org.ehcache.core.PersistentUserManagedEhcache; -import org.ehcache.core.config.BaseCacheConfiguration; +import org.ehcache.impl.config.BaseCacheConfiguration; import org.ehcache.core.config.ExpiryUtils; import org.ehcache.core.events.CacheEventDispatcher; import org.ehcache.core.events.CacheEventListenerConfiguration; @@ -126,7 +126,7 @@ public class UserManagedCacheBuilder> imp private Serializer keySerializer; private Serializer valueSerializer; private int dispatcherConcurrency = 4; - private List eventListenerConfigurations = new ArrayList<>(); + private List> eventListenerConfigurations = new ArrayList<>(); private ExecutorService unOrderedExecutor; private ExecutorService orderedExecutor; private long objectGraphSize = DEFAULT_OBJECT_GRAPH_SIZE; @@ -157,6 +157,7 @@ private UserManagedCacheBuilder(UserManagedCacheBuilder toCopy) { this.valueSerializer = toCopy.valueSerializer; this.useKeySerializingCopier = toCopy.useKeySerializingCopier; this.useValueSerializingCopier = toCopy.useValueSerializingCopier; + this.dispatcherConcurrency = toCopy.dispatcherConcurrency; this.eventListenerConfigurations = toCopy.eventListenerConfigurations; this.unOrderedExecutor = toCopy.unOrderedExecutor; this.orderedExecutor = toCopy.orderedExecutor; @@ -181,7 +182,7 @@ T build(ServiceLocator.DependencySet serviceLocatorBuilder) throws IllegalStateE throw new IllegalStateException("UserManagedCacheBuilder failed to build.", e); } - List> serviceConfigsList = new ArrayList<>(); + List> serviceConfigsList = new ArrayList<>(); if (keyCopier != null) { serviceConfigsList.add(new DefaultCopierConfiguration<>(keyCopier, DefaultCopierConfiguration.Type.KEY)); @@ -237,7 +238,7 @@ public void close() throws Exception { serviceConfigsList.add(new DefaultSerializerConfiguration<>(this.valueSerializer, DefaultSerializerConfiguration.Type.VALUE)); } - ServiceConfiguration[] serviceConfigs = serviceConfigsList.toArray(new ServiceConfiguration[0]); + ServiceConfiguration[] serviceConfigs = serviceConfigsList.toArray(new ServiceConfiguration[0]); final SerializationProvider serialization = serviceLocator.getService(SerializationProvider.class); if (serialization != null) { try { @@ -365,7 +366,7 @@ private void registerListeners(Cache cache, ServiceProvider servi } else { listenerProvider = new DefaultCacheEventListenerProvider(); } - for (CacheEventListenerConfiguration config : eventListenerConfigurations) { + for (CacheEventListenerConfiguration config : eventListenerConfigurations) { final CacheEventListener listener = listenerProvider.createEventListener(id, config); if (listener != null) { cache.getRuntimeConfiguration().registerCacheEventListener(listener, config.orderingMode(), config.firingMode(), config.fireOn()); @@ -559,7 +560,7 @@ public final UserManagedCacheBuilder withEventListeners(CacheEventListe * @see #withEventExecutors(ExecutorService, ExecutorService) * @see #withEventListeners(CacheEventListenerConfigurationBuilder) */ - public final UserManagedCacheBuilder withEventListeners(CacheEventListenerConfiguration... cacheEventListenerConfigurations) { + public final UserManagedCacheBuilder withEventListeners(CacheEventListenerConfiguration ... cacheEventListenerConfigurations) { UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this); otherBuilder.eventListenerConfigurations.addAll(Arrays.asList(cacheEventListenerConfigurations)); return otherBuilder; diff --git a/impl/src/main/java/org/ehcache/config/builders/WriteBehindConfigurationBuilder.java b/impl/src/main/java/org/ehcache/config/builders/WriteBehindConfigurationBuilder.java index 26d78846e0..612c2bc9c3 100644 --- a/impl/src/main/java/org/ehcache/config/builders/WriteBehindConfigurationBuilder.java +++ b/impl/src/main/java/org/ehcache/config/builders/WriteBehindConfigurationBuilder.java @@ -31,7 +31,7 @@ * instance without modifying the one on which the method was called. * This enables the sharing of builder instances without any risk of seeing them modified by code elsewhere. */ -public abstract class WriteBehindConfigurationBuilder implements Builder { +public abstract class WriteBehindConfigurationBuilder implements Builder> { protected int concurrency = 1; protected int queueSize = Integer.MAX_VALUE; @@ -197,7 +197,7 @@ public BatchedWriteBehindConfigurationBuilder useThreadPool(String alias) { * @return the write behind configuration */ @Override - public WriteBehindConfiguration build() { + public WriteBehindConfiguration build() { return buildWith(new DefaultBatchingConfiguration(maxDelay, maxDelayUnit, batchSize, coalescing)); } } @@ -220,7 +220,7 @@ private UnBatchedWriteBehindConfigurationBuilder(UnBatchedWriteBehindConfigurati * @return the write behind configuration */ @Override - public WriteBehindConfiguration build() { + public WriteBehindConfiguration build() { return buildWith(null); } @@ -261,7 +261,7 @@ public UnBatchedWriteBehindConfigurationBuilder useThreadPool(String alias) { } } - WriteBehindConfiguration buildWith(BatchingConfiguration batching) { + WriteBehindConfiguration buildWith(BatchingConfiguration batching) { return new DefaultWriteBehindConfiguration(threadPoolAlias, concurrency, queueSize, batching); } diff --git a/core/src/main/java/org/ehcache/core/config/AbstractResourcePool.java b/impl/src/main/java/org/ehcache/impl/config/AbstractResourcePool.java similarity index 98% rename from core/src/main/java/org/ehcache/core/config/AbstractResourcePool.java rename to impl/src/main/java/org/ehcache/impl/config/AbstractResourcePool.java index 767590c879..465bcd203e 100644 --- a/core/src/main/java/org/ehcache/core/config/AbstractResourcePool.java +++ b/impl/src/main/java/org/ehcache/impl/config/AbstractResourcePool.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.config; +package org.ehcache.impl.config; import org.ehcache.config.ResourcePool; import org.ehcache.config.ResourceType; diff --git a/core/src/main/java/org/ehcache/core/config/BaseCacheConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/BaseCacheConfiguration.java similarity index 85% rename from core/src/main/java/org/ehcache/core/config/BaseCacheConfiguration.java rename to impl/src/main/java/org/ehcache/impl/config/BaseCacheConfiguration.java index c7089c3c2a..2b9949e977 100644 --- a/core/src/main/java/org/ehcache/core/config/BaseCacheConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/BaseCacheConfiguration.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.config; +package org.ehcache.impl.config; import java.util.Arrays; import java.util.Collection; @@ -23,9 +23,13 @@ import org.ehcache.config.CacheConfiguration; import org.ehcache.config.EvictionAdvisor; import org.ehcache.config.ResourcePools; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.core.config.ExpiryUtils; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.spi.service.ServiceConfiguration; +import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; + /** * Base implementation of {@link CacheConfiguration}. */ @@ -34,7 +38,7 @@ public class BaseCacheConfiguration implements CacheConfiguration { private final Class keyType; private final Class valueType; private final EvictionAdvisor evictionAdvisor; - private final Collection> serviceConfigurations; + private final Collection> serviceConfigurations; private final ClassLoader classLoader; private final ExpiryPolicy expiry; private final ResourcePools resourcePools; @@ -53,7 +57,7 @@ public class BaseCacheConfiguration implements CacheConfiguration { public BaseCacheConfiguration(Class keyType, Class valueType, EvictionAdvisor evictionAdvisor, ClassLoader classLoader, ExpiryPolicy expiry, - ResourcePools resourcePools, ServiceConfiguration... serviceConfigurations) { + ResourcePools resourcePools, ServiceConfiguration... serviceConfigurations) { if (keyType == null) { throw new NullPointerException("keyType cannot be null"); } @@ -80,7 +84,7 @@ public BaseCacheConfiguration(Class keyType, Class valueType, * {@inheritDoc} */ @Override - public Collection> getServiceConfigurations() { + public Collection> getServiceConfigurations() { return serviceConfigurations; } @@ -140,4 +144,9 @@ public ClassLoader getClassLoader() { public ResourcePools getResourcePools() { return resourcePools; } + + @Override + public CacheConfigurationBuilder derive() { + return newCacheConfigurationBuilder(this); + } } diff --git a/core/src/main/java/org/ehcache/core/config/ResourcePoolsImpl.java b/impl/src/main/java/org/ehcache/impl/config/ResourcePoolsImpl.java similarity index 98% rename from core/src/main/java/org/ehcache/core/config/ResourcePoolsImpl.java rename to impl/src/main/java/org/ehcache/impl/config/ResourcePoolsImpl.java index dca19f48ee..8906bcb5b6 100644 --- a/core/src/main/java/org/ehcache/core/config/ResourcePoolsImpl.java +++ b/impl/src/main/java/org/ehcache/impl/config/ResourcePoolsImpl.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.config; +package org.ehcache.impl.config; import org.ehcache.config.ResourcePool; import org.ehcache.config.ResourcePools; @@ -24,7 +24,6 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/core/src/main/java/org/ehcache/core/config/SizedResourcePoolImpl.java b/impl/src/main/java/org/ehcache/impl/config/SizedResourcePoolImpl.java similarity index 98% rename from core/src/main/java/org/ehcache/core/config/SizedResourcePoolImpl.java rename to impl/src/main/java/org/ehcache/impl/config/SizedResourcePoolImpl.java index 60942b37c3..100ba3c23c 100644 --- a/core/src/main/java/org/ehcache/core/config/SizedResourcePoolImpl.java +++ b/impl/src/main/java/org/ehcache/impl/config/SizedResourcePoolImpl.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.config; +package org.ehcache.impl.config; import org.ehcache.config.ResourcePool; import org.ehcache.config.ResourceType; diff --git a/impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopierConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopierConfiguration.java index 2ff4e161c5..00705e60f3 100644 --- a/impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopierConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopierConfiguration.java @@ -25,10 +25,13 @@ * {@link ServiceConfiguration} for the default {@link CopyProvider} implementation. *

* Enables configuring a {@link Copier} for the key or value of a given cache. + *

+ * This class overrides the default {@link ServiceConfiguration#compatibleWith(ServiceConfiguration)} implementation + * to allow for independent configuration of the key and value copiers. * * @param the type which the configured copier can handle */ -public class DefaultCopierConfiguration extends ClassInstanceConfiguration> implements ServiceConfiguration { +public class DefaultCopierConfiguration extends ClassInstanceConfiguration> implements ServiceConfiguration { private final Type type; @@ -67,6 +70,15 @@ public Class getServiceType() { return CopyProvider.class; } + @Override + public boolean compatibleWith(ServiceConfiguration other) { + if (other instanceof DefaultCopierConfiguration) { + return !getType().equals(((DefaultCopierConfiguration) other).getType()); + } else { + return ServiceConfiguration.super.compatibleWith(other); + } + } + /** * Returns the {@link Type} of this configuration * diff --git a/impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfiguration.java index 2bbc11369b..300142b82a 100644 --- a/impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfiguration.java @@ -25,7 +25,7 @@ * Enables configuring the thread pool to be used by a {@link org.ehcache.core.events.CacheEventDispatcher} for * a given cache. */ -public class DefaultCacheEventDispatcherConfiguration implements ServiceConfiguration { +public class DefaultCacheEventDispatcherConfiguration implements ServiceConfiguration { private final String threadPoolAlias; @@ -54,4 +54,14 @@ public Class getServiceType() { public String getThreadPoolAlias() { return threadPoolAlias; } + + @Override + public String derive() { + return getThreadPoolAlias(); + } + + @Override + public DefaultCacheEventDispatcherConfiguration build(String alias) { + return new DefaultCacheEventDispatcherConfiguration(alias); + } } diff --git a/impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventListenerConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventListenerConfiguration.java index cf3edd13d2..91e9720a54 100644 --- a/impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventListenerConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventListenerConfiguration.java @@ -23,6 +23,7 @@ import org.ehcache.event.EventOrdering; import org.ehcache.event.EventType; import org.ehcache.impl.internal.classes.ClassInstanceConfiguration; +import org.ehcache.spi.service.ServiceConfiguration; import java.util.EnumSet; import java.util.Set; @@ -31,9 +32,12 @@ * {@link org.ehcache.spi.service.ServiceConfiguration} for the default {@link CacheEventListenerProvider}. *

* Enables configuring a {@link CacheEventListener} for a given cache. + *

+ * This class overrides the default {@link ServiceConfiguration#compatibleWith(ServiceConfiguration)} implementation + * to allow for the configuration of multiple cache event listeners on the same cache. */ public class DefaultCacheEventListenerConfiguration extends ClassInstanceConfiguration> - implements CacheEventListenerConfiguration { + implements CacheEventListenerConfiguration { private final EnumSet eventsToFireOn; private EventFiring eventFiringMode = EventFiring.ASYNCHRONOUS; @@ -131,4 +135,9 @@ public EventOrdering orderingMode() { public EnumSet fireOn() { return eventsToFireOn; } + + @Override + public boolean compatibleWith(ServiceConfiguration other) { + return true; + } } diff --git a/impl/src/main/java/org/ehcache/impl/config/event/DefaultEventSourceConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/event/DefaultEventSourceConfiguration.java index 3238486a14..1c549db83e 100644 --- a/impl/src/main/java/org/ehcache/impl/config/event/DefaultEventSourceConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/event/DefaultEventSourceConfiguration.java @@ -23,7 +23,7 @@ * {@link org.ehcache.spi.service.ServiceConfiguration} for a {@link org.ehcache.core.spi.store.Store.Provider} * related to {@link org.ehcache.core.spi.store.events.StoreEvent}s. */ -public class DefaultEventSourceConfiguration implements StoreEventSourceConfiguration { +public class DefaultEventSourceConfiguration implements StoreEventSourceConfiguration { private final int dispatcherConcurrency; @@ -53,4 +53,14 @@ public int getDispatcherConcurrency() { public Class getServiceType() { return Store.Provider.class; } + + @Override + public Integer derive() { + return getDispatcherConcurrency(); + } + + @Override + public DefaultEventSourceConfiguration build(Integer concurrency) { + return new DefaultEventSourceConfiguration(concurrency); + } } diff --git a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfiguration.java index 4a50d361f7..4902c4c564 100644 --- a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfiguration.java @@ -25,7 +25,7 @@ /** * {@link ServiceConfiguration} for the default {@link CacheLoaderWriterProvider}. */ -public class DefaultCacheLoaderWriterConfiguration extends ClassInstanceConfiguration> implements CacheLoaderWriterConfiguration { +public class DefaultCacheLoaderWriterConfiguration extends ClassInstanceConfiguration> implements CacheLoaderWriterConfiguration { /** * Creates a new configuration object with the specified {@link CacheLoaderWriter} class and associated constructor @@ -47,4 +47,17 @@ public DefaultCacheLoaderWriterConfiguration(CacheLoaderWriter loaderWrite super(loaderWriter); } + protected DefaultCacheLoaderWriterConfiguration(DefaultCacheLoaderWriterConfiguration configuration) { + super(configuration); + } + + @Override + public DefaultCacheLoaderWriterConfiguration derive() { + return new DefaultCacheLoaderWriterConfiguration(this); + } + + @Override + public DefaultCacheLoaderWriterConfiguration build(DefaultCacheLoaderWriterConfiguration configuration) { + return configuration; + } } diff --git a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/DefaultWriteBehindConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/DefaultWriteBehindConfiguration.java index 57486009ea..7362998bae 100644 --- a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/DefaultWriteBehindConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/DefaultWriteBehindConfiguration.java @@ -22,7 +22,7 @@ /** * {@link org.ehcache.spi.service.ServiceConfiguration} for the default {@link WriteBehindProvider}. */ -public class DefaultWriteBehindConfiguration implements WriteBehindConfiguration { +public class DefaultWriteBehindConfiguration implements WriteBehindConfiguration { private final BatchingConfiguration batchingConfig; private final int concurrency; diff --git a/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfiguration.java index 843514e8b6..4ba945686c 100644 --- a/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfiguration.java @@ -27,7 +27,7 @@ /** * {@link ServiceConfiguration} for the default {@link ResilienceStrategyProvider}. */ -public class DefaultResilienceStrategyConfiguration extends ClassInstanceConfiguration> implements ServiceConfiguration { +public class DefaultResilienceStrategyConfiguration extends ClassInstanceConfiguration> implements ServiceConfiguration { /** * Creates a resilience strategy configuration that instantiates instances of the given class on demand. @@ -61,6 +61,16 @@ public Class getServiceType() { return ResilienceStrategyProvider.class; } + @Override + public DefaultResilienceStrategyConfiguration derive() { + return new DefaultResilienceStrategyConfiguration(this); + } + + @Override + public DefaultResilienceStrategyConfiguration build(DefaultResilienceStrategyConfiguration config) { + return config; + } + /** * Returns a configuration object bound to the given store and cache loader-writer. * diff --git a/impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializerConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializerConfiguration.java index e50a76ad64..33ad82c349 100644 --- a/impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializerConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializerConfiguration.java @@ -23,8 +23,11 @@ /** * {@link ServiceConfiguration} for the default {@link SerializationProvider}. + *

+ * This class overrides the default {@link ServiceConfiguration#compatibleWith(ServiceConfiguration)} implementation + * to allow for independent configuration of the key and value serializers. */ -public class DefaultSerializerConfiguration extends ClassInstanceConfiguration> implements ServiceConfiguration { +public class DefaultSerializerConfiguration extends ClassInstanceConfiguration> implements ServiceConfiguration { private final Type type; @@ -67,6 +70,15 @@ public Type getType() { return type; } + @Override + public boolean compatibleWith(ServiceConfiguration other) { + if (other instanceof DefaultSerializerConfiguration) { + return !getType().equals(((DefaultSerializerConfiguration) other).getType()); + } else { + return ServiceConfiguration.super.compatibleWith(other); + } + } + /** * Serialization provider types */ diff --git a/impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfiguration.java index 828c9ed92e..ad32d7b7d5 100644 --- a/impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfiguration.java @@ -22,7 +22,7 @@ /** * {@link ServiceConfiguration} for the default {@link org.ehcache.core.spi.store.Store off heap disk store}. */ -public class OffHeapDiskStoreConfiguration implements ServiceConfiguration { +public class OffHeapDiskStoreConfiguration implements ServiceConfiguration { public static final int DEFAULT_WRITER_CONCURRENCY = 1; public static final int DEFAULT_DISK_SEGMENTS = 16; @@ -106,4 +106,14 @@ public int getDiskSegments() { public Class getServiceType() { return OffHeapDiskStore.Provider.class; } + + @Override + public OffHeapDiskStoreConfiguration derive() { + return new OffHeapDiskStoreConfiguration(threadPoolAlias, writerConcurrency, diskSegments); + } + + @Override + public OffHeapDiskStoreConfiguration build(OffHeapDiskStoreConfiguration config) { + return config; + } } diff --git a/impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineConfiguration.java b/impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineConfiguration.java index 174fc4966a..d9e3bc89ea 100644 --- a/impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineConfiguration.java +++ b/impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineConfiguration.java @@ -23,7 +23,7 @@ /** * {@link ServiceConfiguration} for the default {@link SizeOfEngineProvider}. */ -public class DefaultSizeOfEngineConfiguration implements ServiceConfiguration { +public class DefaultSizeOfEngineConfiguration implements ServiceConfiguration { /** * Default maximum object graph count after which sizing stops @@ -105,4 +105,14 @@ public MemoryUnit getUnit() { return this.unit; } + + @Override + public DefaultSizeOfEngineConfiguration derive() { + return new DefaultSizeOfEngineConfiguration(maxObjectSize, unit, objectGraphSize); + } + + @Override + public DefaultSizeOfEngineConfiguration build(DefaultSizeOfEngineConfiguration config) { + return config; + } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java b/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java index 1778d208b7..1e41f4313d 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java @@ -87,7 +87,7 @@ protected T newInstance(K alias, CacheConfiguration cacheConfiguration) { return newInstance(alias, config); } - protected T newInstance(K alias, ServiceConfiguration... serviceConfigurations) { + protected T newInstance(K alias, ServiceConfiguration... serviceConfigurations) { C config = null; Iterator iterator = findAmongst(cacheLevelConfig, (Object[]) serviceConfigurations).iterator(); if (iterator.hasNext()) { @@ -96,7 +96,7 @@ protected T newInstance(K alias, ServiceConfiguration... serviceConfiguration return newInstance(alias, config); } - protected T newInstance(K alias, ServiceConfiguration serviceConfiguration) { + protected T newInstance(K alias, ServiceConfiguration serviceConfiguration) { C config = null; if (serviceConfiguration != null && cacheLevelConfig.isAssignableFrom(serviceConfiguration.getClass())) { config = cacheLevelConfig.cast(serviceConfiguration); diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImpl.java b/impl/src/main/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImpl.java index d4b92c7f54..166d1c8f07 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImpl.java +++ b/impl/src/main/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImpl.java @@ -61,7 +61,7 @@ public void stop() { } @Override - public CacheEventDispatcher createCacheEventDispatcher(Store store, ServiceConfiguration... serviceConfigs) { + public CacheEventDispatcher createCacheEventDispatcher(Store store, ServiceConfiguration... serviceConfigs) { String threadPoolAlias = defaultThreadPoolAlias; DefaultCacheEventDispatcherConfiguration config = findSingletonAmongst(DefaultCacheEventDispatcherConfiguration.class, (Object[]) serviceConfigs); if (config != null) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/BatchingLocalHeapWriteBehindQueue.java b/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/BatchingLocalHeapWriteBehindQueue.java index 78ebb88879..4a2dd7b85a 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/BatchingLocalHeapWriteBehindQueue.java +++ b/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/BatchingLocalHeapWriteBehindQueue.java @@ -73,7 +73,7 @@ public class BatchingLocalHeapWriteBehindQueue extends AbstractWriteBehind private volatile Batch openBatch; - public BatchingLocalHeapWriteBehindQueue(ExecutionService executionService, String defaultThreadPool, WriteBehindConfiguration config, CacheLoaderWriter cacheLoaderWriter) { + public BatchingLocalHeapWriteBehindQueue(ExecutionService executionService, String defaultThreadPool, WriteBehindConfiguration config, CacheLoaderWriter cacheLoaderWriter) { super(cacheLoaderWriter); this.cacheLoaderWriter = cacheLoaderWriter; BatchingConfiguration batchingConfig = config.getBatchingConfiguration(); diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/NonBatchingLocalHeapWriteBehindQueue.java b/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/NonBatchingLocalHeapWriteBehindQueue.java index 8c6e64dd74..2fcc075a32 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/NonBatchingLocalHeapWriteBehindQueue.java +++ b/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/NonBatchingLocalHeapWriteBehindQueue.java @@ -44,7 +44,7 @@ public class NonBatchingLocalHeapWriteBehindQueue extends AbstractWriteBeh private final BlockingQueue executorQueue; private final ExecutorService executor; - public NonBatchingLocalHeapWriteBehindQueue(ExecutionService executionService, String defaultThreadPool, WriteBehindConfiguration config, CacheLoaderWriter cacheLoaderWriter) { + public NonBatchingLocalHeapWriteBehindQueue(ExecutionService executionService, String defaultThreadPool, WriteBehindConfiguration config, CacheLoaderWriter cacheLoaderWriter) { super(cacheLoaderWriter); this.cacheLoaderWriter = cacheLoaderWriter; this.executorQueue = new LinkedBlockingQueue<>(config.getMaxQueueSize()); diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/StripedWriteBehind.java b/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/StripedWriteBehind.java index 5f599c172e..af9a99c1f6 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/StripedWriteBehind.java +++ b/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/StripedWriteBehind.java @@ -35,7 +35,7 @@ public class StripedWriteBehind implements WriteBehind { private final List> stripes = new ArrayList<>(); - public StripedWriteBehind(ExecutionService executionService, String defaultThreadPool, WriteBehindConfiguration config, CacheLoaderWriter cacheLoaderWriter) { + public StripedWriteBehind(ExecutionService executionService, String defaultThreadPool, WriteBehindConfiguration config, CacheLoaderWriter cacheLoaderWriter) { int writeBehindConcurrency = config.getConcurrency(); for (int i = 0; i < writeBehindConcurrency; i++) { if (config.getBatchingConfiguration() == null) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java index e60815f3e4..f39185c277 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java @@ -71,7 +71,7 @@ public void start(ServiceProvider serviceProvider) { } @Override - public WriteBehind createWriteBehindLoaderWriter(CacheLoaderWriter cacheLoaderWriter, WriteBehindConfiguration configuration) { + public WriteBehind createWriteBehindLoaderWriter(CacheLoaderWriter cacheLoaderWriter, WriteBehindConfiguration configuration) { if (cacheLoaderWriter == null) { throw new NullPointerException("WriteBehind requires a non null CacheLoaderWriter."); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProvider.java b/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProvider.java index f83d9e94ef..02384cf566 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProvider.java @@ -50,7 +50,7 @@ public void stop() { } @Override - public SizeOfEngine createSizeOfEngine(ResourceUnit resourceUnit, ServiceConfiguration... serviceConfigs) { + public SizeOfEngine createSizeOfEngine(ResourceUnit resourceUnit, ServiceConfiguration... serviceConfigs) { boolean isByteSized = resourceUnit instanceof MemoryUnit; if(!isByteSized) { return new NoopSizeOfEngine(); // Noop Size of Engine diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProvider.java b/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProvider.java index a0e9e75a1e..61530b2352 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProvider.java @@ -46,12 +46,12 @@ public DefaultCopyProvider(DefaultCopyProviderConfiguration configuration) { @Override - public Copier createKeyCopier(final Class clazz, Serializer serializer, ServiceConfiguration... configs) { + public Copier createKeyCopier(final Class clazz, Serializer serializer, ServiceConfiguration... configs) { return createCopier(Type.KEY, clazz, serializer, configs); } @Override - public Copier createValueCopier(final Class clazz, Serializer serializer, ServiceConfiguration... configs) { + public Copier createValueCopier(final Class clazz, Serializer serializer, ServiceConfiguration... configs) { return createCopier(Type.VALUE, clazz, serializer, configs); } @@ -63,7 +63,7 @@ public void releaseCopier(Copier copier) throws Exception { } private Copier createCopier(Type type, Class clazz, - Serializer serializer, ServiceConfiguration... configs) { + Serializer serializer, ServiceConfiguration... configs) { DefaultCopierConfiguration conf = find(type, configs); Copier copier; final DefaultCopierConfiguration preConfigured = preconfigured.get(clazz); @@ -98,7 +98,7 @@ private Copier createCopier(Class clazz, DefaultCopierConfiguration } @SuppressWarnings("unchecked") - private static DefaultCopierConfiguration find(Type type, ServiceConfiguration... serviceConfigurations) { + private static DefaultCopierConfiguration find(Type type, ServiceConfiguration... serviceConfigurations) { DefaultCopierConfiguration result = null; @SuppressWarnings("rawtypes") diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProvider.java b/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProvider.java index e9c7d620b1..e9409a511e 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProvider.java @@ -33,7 +33,7 @@ public DefaultCacheEventListenerProvider() { @SuppressWarnings("unchecked") @Override - public CacheEventListener createEventListener(String alias, ServiceConfiguration serviceConfiguration) { + public CacheEventListener createEventListener(String alias, ServiceConfiguration serviceConfiguration) { return (CacheEventListener) newInstance(alias, serviceConfiguration); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProvider.java b/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProvider.java index d7613234e3..1c1682b805 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProvider.java @@ -50,8 +50,8 @@ public void releaseCacheLoaderWriter(String alias, CacheLoaderWriter cache } @Override - public CacheLoaderWriterConfiguration getPreConfiguredCacheLoaderWriterConfig(String alias) { - return (CacheLoaderWriterConfiguration) getPreconfigured(alias); + public CacheLoaderWriterConfiguration getPreConfiguredCacheLoaderWriterConfig(String alias) { + return getPreconfigured(alias); } @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProvider.java b/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProvider.java index 38e16d1c90..e5bfa39a3a 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProvider.java @@ -71,7 +71,7 @@ public DefaultSerializationProvider(DefaultSerializationProviderConfiguration co } @Override - public Serializer createKeySerializer(Class clazz, ClassLoader classLoader, ServiceConfiguration... configs) throws UnsupportedTypeException { + public Serializer createKeySerializer(Class clazz, ClassLoader classLoader, ServiceConfiguration... configs) throws UnsupportedTypeException { DefaultSerializerConfiguration configuration = find(DefaultSerializerConfiguration.Type.KEY, configs); Serializer serializer = getUserProvidedSerializer(configuration); if (serializer == null) { @@ -83,7 +83,7 @@ public Serializer createKeySerializer(Class clazz, ClassLoader classLo } @Override - public Serializer createValueSerializer(Class clazz, ClassLoader classLoader, ServiceConfiguration... configs) throws UnsupportedTypeException { + public Serializer createValueSerializer(Class clazz, ClassLoader classLoader, ServiceConfiguration... configs) throws UnsupportedTypeException { DefaultSerializerConfiguration configuration = find(DefaultSerializerConfiguration.Type.VALUE, configs); Serializer serializer = getUserProvidedSerializer(configuration); if (serializer == null) { @@ -94,7 +94,7 @@ public Serializer createValueSerializer(Class clazz, ClassLoader class return serializer; } - private Serializer createSerializer(Class clazz, ClassLoader classLoader, DefaultSerializerConfiguration config, ServiceConfiguration... configs) throws UnsupportedTypeException { + private Serializer createSerializer(Class clazz, ClassLoader classLoader, DefaultSerializerConfiguration config, ServiceConfiguration... configs) throws UnsupportedTypeException { Class> klazz = getSerializerClassFor(clazz, config); try { @@ -208,7 +208,7 @@ private static Serializer getUserProvidedSerializer(DefaultSerializerConf } @SuppressWarnings("unchecked") - private static DefaultSerializerConfiguration find(DefaultSerializerConfiguration.Type type, ServiceConfiguration... serviceConfigurations) { + private static DefaultSerializerConfiguration find(DefaultSerializerConfiguration.Type type, ServiceConfiguration... serviceConfigurations) { DefaultSerializerConfiguration result = null; @SuppressWarnings("rawtypes") diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java index 7c7b275866..988f921fc2 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java @@ -68,7 +68,6 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Proxy; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; @@ -315,17 +314,17 @@ protected ResourceType getResourceType() { } @Override - public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { + public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { return resourceTypes.equals(Collections.singleton(getResourceType())) ? 1 : 0; } @Override - public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { + public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { return authorityResource.equals(getResourceType()) ? 1 : 0; } @Override - public OffHeapDiskStore createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public OffHeapDiskStore createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { OffHeapDiskStore store = createStoreInternal(storeConfig, new ThreadLocalStoreEventDispatcher<>(storeConfig.getDispatcherConcurrency()), serviceConfigs); tierOperationStatistics.put(store, new OperationStatistic[] { @@ -336,7 +335,7 @@ public OffHeapDiskStore createStore(Configuration storeConfig return store; } - private OffHeapDiskStore createStoreInternal(Configuration storeConfig, StoreEventDispatcher eventDispatcher, ServiceConfiguration... serviceConfigs) { + private OffHeapDiskStore createStoreInternal(Configuration storeConfig, StoreEventDispatcher eventDispatcher, ServiceConfiguration... serviceConfigs) { if (serviceProvider == null) { throw new NullPointerException("ServiceProvider is null in OffHeapDiskStore.Provider."); } @@ -460,7 +459,7 @@ public void stop() { } @Override - public AuthoritativeTier createAuthoritativeTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public AuthoritativeTier createAuthoritativeTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { OffHeapDiskStore authoritativeTier = createStoreInternal(storeConfig, new ThreadLocalStoreEventDispatcher<>(storeConfig .getDispatcherConcurrency()), serviceConfigs); diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index a137f03f5b..024cd9c19a 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -1631,17 +1631,17 @@ protected ResourceType getResourceType() { } @Override - public int rank(Set> resourceTypes, Collection> serviceConfigs) { + public int rank(Set> resourceTypes, Collection> serviceConfigs) { return resourceTypes.equals(Collections.singleton(getResourceType())) ? 1 : 0; } @Override - public int rankCachingTier(Set> resourceTypes, Collection> serviceConfigs) { + public int rankCachingTier(Set> resourceTypes, Collection> serviceConfigs) { return rank(resourceTypes, serviceConfigs); } @Override - public OnHeapStore createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public OnHeapStore createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { OnHeapStore store = createStoreInternal(storeConfig, new DefaultStoreEventDispatcher<>(storeConfig.getDispatcherConcurrency()), serviceConfigs); tierOperationStatistics.put(store, new OperationStatistic[] { @@ -1652,7 +1652,7 @@ public OnHeapStore createStore(Configuration storeConfig, Ser } public OnHeapStore createStoreInternal(Configuration storeConfig, StoreEventDispatcher eventDispatcher, - ServiceConfiguration... serviceConfigs) { + ServiceConfiguration... serviceConfigs) { TimeSource timeSource = serviceProvider.getService(TimeSourceService.class).getTimeSource(); CopyProvider copyProvider = serviceProvider.getService(CopyProvider.class); Copier keyCopier = copyProvider.createKeyCopier(storeConfig.getKeyType(), storeConfig.getKeySerializer(), serviceConfigs); @@ -1726,7 +1726,7 @@ public void stop() { } @Override - public CachingTier createCachingTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public CachingTier createCachingTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { OnHeapStore cachingTier = createStoreInternal(storeConfig, NullStoreEventDispatcher.nullStoreEventDispatcher(), serviceConfigs); this.tierOperationStatistics.put(cachingTier, new OperationStatistic[] { @@ -1754,7 +1754,7 @@ public void initCachingTier(CachingTier resource) { } @Override - public HigherCachingTier createHigherCachingTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public HigherCachingTier createHigherCachingTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { OnHeapStore higherCachingTier = createStoreInternal(storeConfig, new DefaultStoreEventDispatcher<>(storeConfig .getDispatcherConcurrency()), serviceConfigs); diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java index 46f5688d76..d42f82f2a9 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java @@ -39,8 +39,8 @@ public class LoaderWriterStoreProvider extends AbstractWrapperStoreProvider { private volatile WriteBehindProvider writeBehindProvider; @Override - protected Store wrap(Store store, Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { - WriteBehindConfiguration writeBehindConfiguration = findSingletonAmongst(WriteBehindConfiguration.class, (Object[]) serviceConfigs); + protected Store wrap(Store store, Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + WriteBehindConfiguration writeBehindConfiguration = findSingletonAmongst(WriteBehindConfiguration.class, (Object[]) serviceConfigs); if(writeBehindConfiguration == null) { return new LocalLoaderWriterStore<>(store, storeConfig.getCacheLoaderWriter(), storeConfig.useLoaderInAtomics(), storeConfig.getExpiry()); } else { @@ -73,13 +73,13 @@ public void stop() { } @Override - public int rank(Set> resourceTypes, Collection> serviceConfigs) { + public int rank(Set> resourceTypes, Collection> serviceConfigs) { throw new UnsupportedOperationException("Its a Wrapper store provider, does not support regular ranking"); } @Override - public int wrapperStoreRank(Collection> serviceConfigs) { - CacheLoaderWriterConfiguration loaderWriterConfiguration = findSingletonAmongst(CacheLoaderWriterConfiguration.class, serviceConfigs); + public int wrapperStoreRank(Collection> serviceConfigs) { + CacheLoaderWriterConfiguration loaderWriterConfiguration = findSingletonAmongst(CacheLoaderWriterConfiguration.class, serviceConfigs); if (loaderWriterConfiguration == null) { return 0; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java index b2d3012aa6..196309ee86 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java @@ -141,17 +141,17 @@ protected ResourceType getResourceType() { } @Override - public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { + public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { return resourceTypes.equals(Collections.singleton(ResourceType.Core.OFFHEAP)) ? 1 : 0; } @Override - public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { + public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { return authorityResource.equals(ResourceType.Core.OFFHEAP) ? 1 : 0; } @Override - public OffHeapStore createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public OffHeapStore createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { OffHeapStore store = createStoreInternal(storeConfig, new ThreadLocalStoreEventDispatcher<>(storeConfig.getDispatcherConcurrency()), serviceConfigs); tierOperationStatistics.put(store, new OperationStatistic[] { @@ -162,7 +162,7 @@ public OffHeapStore createStore(Configuration storeConfig, Se return store; } - private OffHeapStore createStoreInternal(Configuration storeConfig, StoreEventDispatcher eventDispatcher, ServiceConfiguration... serviceConfigs) { + private OffHeapStore createStoreInternal(Configuration storeConfig, StoreEventDispatcher eventDispatcher, ServiceConfiguration... serviceConfigs) { if (serviceProvider == null) { throw new NullPointerException("ServiceProvider is null in OffHeapStore.Provider."); } @@ -235,7 +235,7 @@ public void stop() { } @Override - public AuthoritativeTier createAuthoritativeTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public AuthoritativeTier createAuthoritativeTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { OffHeapStore authoritativeTier = createStoreInternal(storeConfig, new ThreadLocalStoreEventDispatcher<>(storeConfig .getDispatcherConcurrency()), serviceConfigs); @@ -258,7 +258,7 @@ public void initAuthoritativeTier(AuthoritativeTier resource) { } @Override - public LowerCachingTier createCachingTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public LowerCachingTier createCachingTier(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { OffHeapStore lowerCachingTier = createStoreInternal(storeConfig, NullStoreEventDispatcher.nullStoreEventDispatcher(), serviceConfigs); tierOperationStatistics.put(lowerCachingTier, new OperationStatistic[] { diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java index 5362fca370..efb2d5f57e 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java @@ -216,7 +216,7 @@ public static class Provider implements CachingTier.Provider { private final ConcurrentMap, Map.Entry> providersMap = new ConcurrentWeakIdentityHashMap<>(); @Override - public CachingTier createCachingTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public CachingTier createCachingTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { if (serviceProvider == null) { throw new RuntimeException("ServiceProvider is null."); } @@ -265,7 +265,7 @@ public void initCachingTier(CachingTier resource) { } @Override - public int rankCachingTier(Set> resourceTypes, Collection> serviceConfigs) { + public int rankCachingTier(Set> resourceTypes, Collection> serviceConfigs) { return resourceTypes.equals(unmodifiableSet(EnumSet.of(HEAP, OFFHEAP))) ? 2 : 0; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java index 6f66efdaa6..a24910d174 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java @@ -383,7 +383,7 @@ public static class Provider implements Store.Provider { private final ConcurrentMap, Map.Entry> providersMap = new ConcurrentWeakIdentityHashMap<>(); @Override - public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { + public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { if (resourceTypes.size() == 1) { return 0; } @@ -426,8 +426,8 @@ private ResourceType getAuthorityResource(Set> resourceTypes) } @Override - public Store createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { - final List> enhancedServiceConfigs = new ArrayList<>(Arrays.asList(serviceConfigs)); + public Store createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + final List> enhancedServiceConfigs = new ArrayList<>(Arrays.asList(serviceConfigs)); final ResourcePools resourcePools = storeConfig.getResourcePools(); if (rank(resourcePools.getResourceTypeSet(), enhancedServiceConfigs) == 0) { @@ -443,8 +443,8 @@ public Store createStore(Configuration storeConfig, ServiceCo CachingTier.Provider cachingTierProvider = getCachingTierProvider(cachingResources, enhancedServiceConfigs); - final ServiceConfiguration[] configurations = - enhancedServiceConfigs.toArray(new ServiceConfiguration[enhancedServiceConfigs.size()]); + final ServiceConfiguration[] configurations = + enhancedServiceConfigs.toArray(new ServiceConfiguration[enhancedServiceConfigs.size()]); CachingTier cachingTier = cachingTierProvider.createCachingTier(storeConfig, configurations); AuthoritativeTier authoritativeTier = authoritativeTierProvider.createAuthoritativeTier(storeConfig, configurations); @@ -453,7 +453,7 @@ public Store createStore(Configuration storeConfig, ServiceCo return store; } - private CachingTier.Provider getCachingTierProvider(Set> cachingResources, List> enhancedServiceConfigs) { + private CachingTier.Provider getCachingTierProvider(Set> cachingResources, List> enhancedServiceConfigs) { CachingTier.Provider cachingTierProvider = null; Collection cachingTierProviders = serviceProvider.getServicesOfType(CachingTier.Provider.class); for (CachingTier.Provider provider : cachingTierProviders) { @@ -468,7 +468,7 @@ private CachingTier.Provider getCachingTierProvider(Set> caching return cachingTierProvider; } - AuthoritativeTier.Provider getAuthoritativeTierProvider(ResourceType authorityResource, List> enhancedServiceConfigs) { + AuthoritativeTier.Provider getAuthoritativeTierProvider(ResourceType authorityResource, List> enhancedServiceConfigs) { AuthoritativeTier.Provider authoritativeTierProvider = null; Collection authorityProviders = serviceProvider.getServicesOfType(AuthoritativeTier.Provider.class); int highestRank = 0; diff --git a/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java b/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java index 9a3ae2ad58..b3e818b95f 100644 --- a/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java @@ -17,8 +17,8 @@ package org.ehcache; import org.ehcache.config.CacheConfiguration; -import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.ResourcePools; +import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.ResourceType; import org.ehcache.config.builders.CacheManagerBuilder; @@ -27,9 +27,6 @@ import org.junit.Rule; import org.junit.Test; -import java.io.File; -import java.io.IOException; - import org.ehcache.config.units.MemoryUnit; import org.junit.rules.TemporaryFolder; diff --git a/impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java b/impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java index 866f64d017..38ded14a0c 100644 --- a/impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java +++ b/impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java @@ -25,37 +25,43 @@ import org.ehcache.impl.config.loaderwriter.DefaultCacheLoaderWriterConfiguration; import org.ehcache.impl.config.resilience.DefaultResilienceStrategyConfiguration; import org.ehcache.impl.config.serializer.DefaultSerializerConfiguration; +import org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration; import org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration; +import org.ehcache.impl.copy.SerializingCopier; import org.ehcache.impl.internal.classes.ClassInstanceConfiguration; import org.ehcache.impl.internal.resilience.RobustResilienceStrategy; +import org.ehcache.impl.serialization.JavaSerializer; import org.ehcache.spi.copy.Copier; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.loaderwriter.CacheLoaderWriterConfiguration; import org.ehcache.spi.resilience.RecoveryStore; import org.ehcache.spi.resilience.ResilienceStrategy; import org.ehcache.spi.serialization.Serializer; -import org.ehcache.spi.serialization.SerializerException; +import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceConfiguration; +import org.ehcache.test.MockitoUtil; import org.hamcrest.Matcher; import org.hamcrest.Matchers; import org.hamcrest.core.IsSame; import org.junit.Test; -import java.nio.ByteBuffer; - +import static java.util.function.UnaryOperator.identity; +import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.ehcache.test.MockitoUtil.mock; +import static org.junit.Assert.fail; public class CacheConfigurationBuilderTest { @Test - public void testEvictionAdvisor() throws Exception { + public void testWithEvictionAdvisor() throws Exception { EvictionAdvisor evictionAdvisor = (key, value) -> false; - CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) .withEvictionAdvisor(evictionAdvisor) .build(); @@ -66,53 +72,33 @@ public void testEvictionAdvisor() throws Exception { } @Test - public void testLoaderWriter() throws Exception { - CacheLoaderWriter loaderWriter = new CacheLoaderWriter() { - @Override - public Object load(Object key) { - return null; - } - - @Override - public void write(Object key, Object value) { - - } + public void testWithLoaderWriter() throws Exception { + CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); - @Override - public void delete(Object key) { - - } - }; - - CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) .withLoaderWriter(loaderWriter) .build(); - CacheLoaderWriterConfiguration cacheLoaderWriterConfiguration = ServiceUtils.findSingletonAmongst(DefaultCacheLoaderWriterConfiguration.class, cacheConfiguration.getServiceConfigurations()); + CacheLoaderWriterConfiguration cacheLoaderWriterConfiguration = ServiceUtils.findSingletonAmongst(DefaultCacheLoaderWriterConfiguration.class, cacheConfiguration.getServiceConfigurations()); Object instance = ((ClassInstanceConfiguration) cacheLoaderWriterConfiguration).getInstance(); assertThat(instance, Matchers.sameInstance(loaderWriter)); } @Test - public void testKeySerializer() throws Exception { - Serializer keySerializer = new Serializer() { - @Override - public ByteBuffer serialize(Object object) throws SerializerException { - return null; - } + public void testWithoutLoaderWriter() { + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withLoaderWriter(mock(CacheLoaderWriter.class)) + .withoutLoaderWriter() + .build(); - @Override - public Object read(ByteBuffer binary) throws ClassNotFoundException, SerializerException { - return null; - } + assertThat(cacheConfiguration.getServiceConfigurations(), not(hasItem(instanceOf(DefaultCacheLoaderWriterConfiguration.class)))); + } - @Override - public boolean equals(Object object, ByteBuffer binary) throws ClassNotFoundException, SerializerException { - return false; - } - }; + @Test + public void testWithKeySerializer() throws Exception { + Serializer keySerializer = mock(Serializer.class); - CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) .withKeySerializer(keySerializer) .build(); @@ -124,25 +110,33 @@ public boolean equals(Object object, ByteBuffer binary) throws ClassNotFoundExce } @Test - public void testValueSerializer() throws Exception { - Serializer valueSerializer = new Serializer() { - @Override - public ByteBuffer serialize(Object object) throws SerializerException { - return null; - } + public void testWithKeySerializerClass() throws Exception { + @SuppressWarnings("unchecked") + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withKeySerializer((Class) JavaSerializer.class) + .build(); - @Override - public Object read(ByteBuffer binary) throws ClassNotFoundException, SerializerException { - return null; - } - @Override - public boolean equals(Object object, ByteBuffer binary) throws ClassNotFoundException, SerializerException { - return false; - } - }; + DefaultSerializerConfiguration serializerConfiguration = ServiceUtils.findSingletonAmongst(DefaultSerializerConfiguration.class, cacheConfiguration.getServiceConfigurations()); + assertThat(serializerConfiguration.getType(), is(DefaultSerializerConfiguration.Type.KEY)); + assertThat(serializerConfiguration.getClazz(), sameInstance(JavaSerializer.class)); + } + + @Test + public void testWithoutKeySerializer() throws Exception { + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withKeySerializer(MockitoUtil.>mock(Serializer.class)) + .withDefaultKeySerializer() + .build(); - CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + assertThat(cacheConfiguration.getServiceConfigurations(), not(hasItem(instanceOf(DefaultSerializerConfiguration.class)))); + } + + @Test + public void testWithValueSerializer() throws Exception { + Serializer valueSerializer = mock(Serializer.class); + + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) .withValueSerializer(valueSerializer) .build(); @@ -154,20 +148,33 @@ public boolean equals(Object object, ByteBuffer binary) throws ClassNotFoundExce } @Test - public void testKeyCopier() throws Exception { - Copier keyCopier = new Copier() { - @Override - public Long copyForRead(Object obj) { - return null; - } + public void testWithValueSerializerClass() throws Exception { + @SuppressWarnings("unchecked") + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withValueSerializer((Class) JavaSerializer.class) + .build(); - @Override - public Long copyForWrite(Object obj) { - return null; - } - }; - CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + DefaultSerializerConfiguration serializerConfiguration = ServiceUtils.findSingletonAmongst(DefaultSerializerConfiguration.class, cacheConfiguration.getServiceConfigurations()); + assertThat(serializerConfiguration.getType(), is(DefaultSerializerConfiguration.Type.VALUE)); + assertThat(serializerConfiguration.getClazz(), sameInstance(JavaSerializer.class)); + } + + @Test + public void testWithoutValueSerializer() throws Exception { + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withValueSerializer(MockitoUtil.>mock(Serializer.class)) + .withDefaultValueSerializer() + .build(); + + assertThat(cacheConfiguration.getServiceConfigurations(), not(hasItem(instanceOf(DefaultSerializerConfiguration.class)))); + } + + @Test + public void testWithKeyCopier() throws Exception { + Copier keyCopier = mock(Copier.class); + + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) .withKeyCopier(keyCopier) .build(); @@ -179,20 +186,32 @@ public Long copyForWrite(Object obj) { } @Test - public void testValueCopier() throws Exception { - Copier valueCopier = new Copier() { - @Override - public Long copyForRead(Object obj) { - return null; - } + public void testWithKeySerializingCopier() { + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withKeySerializingCopier() + .build(); - @Override - public Long copyForWrite(Object obj) { - return null; - } - }; - CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + DefaultCopierConfiguration copierConfiguration = ServiceUtils.findSingletonAmongst(DefaultCopierConfiguration.class, cacheConfiguration.getServiceConfigurations()); + assertThat(copierConfiguration.getType(), is(DefaultCopierConfiguration.Type.KEY)); + assertThat(copierConfiguration.getClazz(), Matchers.sameInstance(SerializingCopier.class)); + } + + @Test + public void testWithoutKeyCopier() { + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withKeyCopier(MockitoUtil.>mock(Copier.class)) + .withoutKeyCopier() + .build(); + + assertThat(cacheConfiguration.getServiceConfigurations(), not(hasItem(instanceOf(DefaultCopierConfiguration.class)))); + } + + @Test + public void testWithValueCopier() throws Exception { + Copier valueCopier = mock(Copier.class); + + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) .withValueCopier(valueCopier) .build(); @@ -203,9 +222,31 @@ public Long copyForWrite(Object obj) { assertThat(instance, Matchers.sameInstance(valueCopier)); } + @Test + public void testWithValueSerializingCopier() { + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withValueSerializingCopier() + .build(); + + + DefaultCopierConfiguration copierConfiguration = ServiceUtils.findSingletonAmongst(DefaultCopierConfiguration.class, cacheConfiguration.getServiceConfigurations()); + assertThat(copierConfiguration.getType(), is(DefaultCopierConfiguration.Type.VALUE)); + assertThat(copierConfiguration.getClazz(), Matchers.sameInstance(SerializingCopier.class)); + } + + @Test + public void testWithoutValueCopier() { + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withValueCopier(MockitoUtil.>mock(Copier.class)) + .withoutValueCopier() + .build(); + + assertThat(cacheConfiguration.getServiceConfigurations(), not(hasItem(instanceOf(DefaultCopierConfiguration.class)))); + } + @Test public void testNothing() { - final CacheConfigurationBuilder builder = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, CharSequence.class, heap(10)); + final CacheConfigurationBuilder builder = newCacheConfigurationBuilder(Long.class, CharSequence.class, heap(10)); final ExpiryPolicy expiry = ExpiryPolicyBuilder.timeToIdleExpiration(ExpiryPolicy.INFINITE); @@ -217,7 +258,7 @@ public void testNothing() { @Test public void testOffheapGetsAddedToCacheConfiguration() { - CacheConfigurationBuilder builder = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, CharSequence.class, + CacheConfigurationBuilder builder = newCacheConfigurationBuilder(Long.class, CharSequence.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES) .offheap(10, MemoryUnit.MB)); @@ -233,7 +274,7 @@ public void testOffheapGetsAddedToCacheConfiguration() { @Test public void testSizeOf() { - CacheConfigurationBuilder builder = CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, String.class, heap(10)); + CacheConfigurationBuilder builder = newCacheConfigurationBuilder(String.class, String.class, heap(10)); builder = builder.withSizeOfMaxObjectSize(10, MemoryUnit.B).withSizeOfMaxObjectGraph(100); CacheConfiguration configuration = builder.build(); @@ -261,16 +302,16 @@ public void testCopyingOfExistingConfiguration() { EvictionAdvisor eviction = mock(EvictionAdvisor.class); @SuppressWarnings("unchecked") ExpiryPolicy expiry = mock(ExpiryPolicy.class); - ServiceConfiguration service = mock(ServiceConfiguration.class); + ServiceConfiguration service = mock(ServiceConfiguration.class); - CacheConfiguration configuration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Integer.class, String.class, heap(10)) + CacheConfiguration configuration = newCacheConfigurationBuilder(Integer.class, String.class, heap(10)) .withClassLoader(loader) .withEvictionAdvisor(eviction) .withExpiry(expiry) - .add(service) + .withService(service) .build(); - CacheConfiguration copy = CacheConfigurationBuilder.newCacheConfigurationBuilder(configuration).build(); + CacheConfiguration copy = newCacheConfigurationBuilder(configuration).build(); assertThat(copy.getKeyType(), equalTo(keyClass)); assertThat(copy.getValueType(), equalTo(valueClass)); @@ -282,10 +323,10 @@ public void testCopyingOfExistingConfiguration() { } @Test - public void testResilienceStrategyInstance() throws Exception { + public void testWithResilienceStrategyInstance() throws Exception { ResilienceStrategy resilienceStrategy = mock(ResilienceStrategy.class); - CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) .withResilienceStrategy(resilienceStrategy) .build(); @@ -295,8 +336,8 @@ public void testResilienceStrategyInstance() throws Exception { } @Test - public void testResilienceStrategyClass() throws Exception { - CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + public void testWithResilienceStrategyClass() throws Exception { + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) .withResilienceStrategy(CustomResilience.class, "Hello World") .build(); @@ -307,10 +348,232 @@ public void testResilienceStrategyClass() throws Exception { } + @Test + public void testWithDefaultResilienceStrategy() { + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withResilienceStrategy(mock(ResilienceStrategy.class)) + .withDefaultResilienceStrategy() + .build(); + + assertThat(cacheConfiguration.getServiceConfigurations(), not(hasItem(instanceOf(DefaultResilienceStrategyConfiguration.class)))); + } + + @Test + public void testWithServiceAddsNewConfiguration() { + CacheConfigurationBuilder oldBuilder = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)); + + ServiceConfiguration serviceConfiguration = new IncompatibleServiceConfig(); + + CacheConfigurationBuilder newBuilder = oldBuilder.withService(serviceConfiguration); + + assertThat(oldBuilder.build().getServiceConfigurations(), not(hasItem(sameInstance(serviceConfiguration)))); + assertThat(newBuilder.build().getServiceConfigurations(), hasItem(sameInstance(serviceConfiguration))); + } + + @Test + public void testIncompatibleServiceRemovesExistingConfiguration() { + ServiceConfiguration oldConfig = new IncompatibleServiceConfig(); + ServiceConfiguration newConfig = new IncompatibleServiceConfig(); + + CacheConfigurationBuilder oldBuilder = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(oldConfig); + + CacheConfigurationBuilder newBuilder = oldBuilder.withService(newConfig); + + assertThat(oldBuilder.build().getServiceConfigurations(), both(hasItem(sameInstance(oldConfig))).and(not(hasItem(sameInstance(newConfig))))); + assertThat(newBuilder.build().getServiceConfigurations(), both(hasItem(sameInstance(newConfig))).and(not(hasItem(sameInstance(oldConfig))))); + } + + @Test + public void testCompatibleServiceJoinsExistingConfiguration() { + ServiceConfiguration oldConfig = new CompatibleServiceConfig(); + ServiceConfiguration newConfig = new CompatibleServiceConfig(); + + CacheConfigurationBuilder oldBuilder = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(oldConfig); + + CacheConfigurationBuilder newBuilder = oldBuilder.withService(newConfig); + + assertThat(oldBuilder.build().getServiceConfigurations(), both(hasItem(sameInstance(oldConfig))).and(not(hasItem(sameInstance(newConfig))))); + assertThat(newBuilder.build().getServiceConfigurations(), both(hasItem(sameInstance(oldConfig))).and(hasItem(sameInstance(newConfig)))); + } + + @Test + public void testUpdateServicesWithNoServicesThrows() { + CacheConfigurationBuilder oldBuilder = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)); + try { + oldBuilder.updateServices(IncompatibleServiceConfig.class, identity()); + fail("Expected IllegalStateException"); + } catch (IllegalStateException e) { + //expected + } + } + + @Test + public void testUpdateServicesWithNullReturnThrows() { + CacheConfigurationBuilder oldBuilder = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withService(new IncompatibleServiceConfig()); + try { + oldBuilder.updateServices(IncompatibleServiceConfig.class, c -> null); + fail("Expected NullPointerException"); + } catch (NullPointerException e) { + //expected + } + } + + + @Test + public void testUpdateServicesHitsAllServices() { + CompatibleServiceConfig configA = new CompatibleServiceConfig(); + CompatibleServiceConfig configB = new CompatibleServiceConfig(); + CacheConfigurationBuilder oldBuilder = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withService(configA) + .withService(configB); + + CompatibleServiceConfig configA2 = new CompatibleServiceConfig(); + CompatibleServiceConfig configB2 = new CompatibleServiceConfig(); + CacheConfigurationBuilder newBuilder = oldBuilder.updateServices(CompatibleServiceConfig.class, c -> { + if (c == configA) { + return configA2; + } else if (c == configB) { + return configB2; + } else { + throw new AssertionError(); + } + }); + + assertThat(oldBuilder.build().getServiceConfigurations(), hasItems(configA, configB)); + assertThat(newBuilder.build().getServiceConfigurations(), hasItems(configA2, configB2)); + } + + @Test + public void testWithClassLoader() { + ClassLoader classLoader = mock(ClassLoader.class); + + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withClassLoader(classLoader) + .build(); + + assertThat(cacheConfiguration.getClassLoader(), sameInstance(classLoader)); + } + + @Test + public void testWithDefaultClassLoader() { + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withClassLoader(mock(ClassLoader.class)) + .withDefaultClassLoader() + .build(); + + assertThat(cacheConfiguration.getClassLoader(), nullValue()); + } + + @Test + public void testWithDiskStoreThreadPool() { + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withDiskStoreThreadPool("banana", 42) + .build(); + + OffHeapDiskStoreConfiguration config = findSingletonAmongst(OffHeapDiskStoreConfiguration.class, cacheConfiguration.getServiceConfigurations()); + + assertThat(config.getWriterConcurrency(), is(42)); + assertThat(config.getThreadPoolAlias(), is("banana")); + } + + @Test + public void testWithDefaultDiskStoreThreadPool() { + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withDiskStoreThreadPool("banana", 42) + .withDefaultDiskStoreThreadPool() + .build(); + + assertThat(cacheConfiguration.getServiceConfigurations(), not(hasItem(instanceOf(OffHeapDiskStoreConfiguration.class)))); + } + + @Test + public void testWithSizeOfConfig() { + CacheConfigurationBuilder builder = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)); + + builder = builder.withSizeOfMaxObjectGraph(42L); + { + CacheConfiguration cacheConfiguration = builder.build(); + DefaultSizeOfEngineConfiguration config = findSingletonAmongst(DefaultSizeOfEngineConfiguration.class, cacheConfiguration.getServiceConfigurations()); + assertThat(config.getMaxObjectGraphSize(), is(42L)); + assertThat(config.getMaxObjectSize(), is(Long.MAX_VALUE)); + assertThat(config.getUnit(), is(MemoryUnit.B)); + } + + builder = builder.withSizeOfMaxObjectSize(1024L, MemoryUnit.KB); + { + CacheConfiguration cacheConfiguration = builder.build(); + DefaultSizeOfEngineConfiguration config = findSingletonAmongst(DefaultSizeOfEngineConfiguration.class, cacheConfiguration.getServiceConfigurations()); + assertThat(config.getMaxObjectGraphSize(), is(42L)); + assertThat(config.getMaxObjectSize(), is(1024L)); + assertThat(config.getUnit(), is(MemoryUnit.KB)); + } + + builder = builder.withSizeOfMaxObjectGraph(43L); + { + CacheConfiguration cacheConfiguration = builder.build(); + DefaultSizeOfEngineConfiguration config = findSingletonAmongst(DefaultSizeOfEngineConfiguration.class, cacheConfiguration.getServiceConfigurations()); + assertThat(config.getMaxObjectGraphSize(), is(43L)); + assertThat(config.getMaxObjectSize(), is(1024L)); + assertThat(config.getUnit(), is(MemoryUnit.KB)); + } + } + + @Test + public void testWithDefaultSizeOfSettings() { + CacheConfiguration cacheConfiguration = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) + .withSizeOfMaxObjectGraph(42L) + .withSizeOfMaxObjectSize(1024L, MemoryUnit.KB) + .withDefaultSizeOfSettings() + .build(); + + assertThat(cacheConfiguration.getServiceConfigurations(), not(hasItem(instanceOf(DefaultSizeOfEngineConfiguration.class)))); + } + static class CustomResilience extends RobustResilienceStrategy { public CustomResilience(RecoveryStore store, String blah) { super(store); } } + + static class IncompatibleServiceConfig implements ServiceConfiguration { + + @Override + public Class getServiceType() { + return Service.class; + } + + @Override + public IncompatibleServiceConfig derive() throws UnsupportedOperationException { + return this; + } + + @Override + public ServiceConfiguration build(IncompatibleServiceConfig representation) throws UnsupportedOperationException { + return representation; + } + } + + static class CompatibleServiceConfig implements ServiceConfiguration { + @Override + public CompatibleServiceConfig derive() throws UnsupportedOperationException { + return this; + } + + @Override + public ServiceConfiguration build(CompatibleServiceConfig representation) throws UnsupportedOperationException { + return representation; + } + + @Override + public Class getServiceType() { + return Service.class; + } + + @Override + public boolean compatibleWith(ServiceConfiguration other) { + return true; + } + } } diff --git a/impl/src/test/java/org/ehcache/config/builders/ResourcePoolsBuilderTest.java b/impl/src/test/java/org/ehcache/config/builders/ResourcePoolsBuilderTest.java index 8dfcc69c7b..f87c8d76cc 100644 --- a/impl/src/test/java/org/ehcache/config/builders/ResourcePoolsBuilderTest.java +++ b/impl/src/test/java/org/ehcache/config/builders/ResourcePoolsBuilderTest.java @@ -20,7 +20,7 @@ import org.ehcache.config.ResourceUnit; import org.ehcache.config.SizedResourcePool; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.config.SizedResourcePoolImpl; +import org.ehcache.impl.config.SizedResourcePoolImpl; import org.hamcrest.Matchers; import org.junit.Test; diff --git a/impl/src/test/java/org/ehcache/docs/GettingStarted.java b/impl/src/test/java/org/ehcache/docs/GettingStarted.java index 19e95e3803..039f967283 100644 --- a/impl/src/test/java/org/ehcache/docs/GettingStarted.java +++ b/impl/src/test/java/org/ehcache/docs/GettingStarted.java @@ -122,7 +122,7 @@ public void testCacheEventListener() { final CacheManager manager = CacheManagerBuilder.newCacheManagerBuilder() .withCache("foo", CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, String.class, ResourcePoolsBuilder.heap(10)) - .add(cacheEventListenerConfiguration) // <3> + .withService(cacheEventListenerConfiguration) // <3> ).build(true); final Cache cache = manager.getCache("foo", String.class, String.class); @@ -160,7 +160,7 @@ public void writeBehindCache() { Cache writeBehindCache = cacheManager.createCache("writeBehindCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10)) .withLoaderWriter(new SampleLoaderWriter<>(singletonMap(41L, "zero"))) // <1> - .add(WriteBehindConfigurationBuilder // <2> + .withService(WriteBehindConfigurationBuilder // <2> .newBatchedWriteBehindConfiguration(1, TimeUnit.SECONDS, 3)// <3> .queueSize(3)// <4> .concurrencyLevel(1) // <5> diff --git a/impl/src/test/java/org/ehcache/docs/ThreadPools.java b/impl/src/test/java/org/ehcache/docs/ThreadPools.java index 523dae4700..9a8e07a2ae 100644 --- a/impl/src/test/java/org/ehcache/docs/ThreadPools.java +++ b/impl/src/test/java/org/ehcache/docs/ThreadPools.java @@ -98,7 +98,7 @@ public void writeBehind() throws Exception { CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES)) .withLoaderWriter(new SampleLoaderWriter<>(singletonMap(41L, "zero"))) - .add(WriteBehindConfigurationBuilder + .withService(WriteBehindConfigurationBuilder .newBatchedWriteBehindConfiguration(1, TimeUnit.SECONDS, 3) .queueSize(3) .concurrencyLevel(1))) @@ -106,7 +106,7 @@ public void writeBehind() throws Exception { CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES)) .withLoaderWriter(new SampleLoaderWriter<>(singletonMap(41L, "zero"))) - .add(WriteBehindConfigurationBuilder + .withService(WriteBehindConfigurationBuilder .newBatchedWriteBehindConfiguration(1, TimeUnit.SECONDS, 3) .useThreadPool("cache2Pool") // <3> .queueSize(3) @@ -135,12 +135,12 @@ public void events() throws Exception { .withCache("cache1", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES)) - .add(CacheEventListenerConfigurationBuilder + .withService(CacheEventListenerConfigurationBuilder .newEventListenerConfiguration(new ListenerObject(), EventType.CREATED, EventType.UPDATED))) .withCache("cache2", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES)) - .add(CacheEventListenerConfigurationBuilder + .withService(CacheEventListenerConfigurationBuilder .newEventListenerConfiguration(new ListenerObject(), EventType.CREATED, EventType.UPDATED)) .withEventListenersThreadPool("cache2Pool")) // <3> .build(true); diff --git a/impl/src/test/java/org/ehcache/docs/Tiering.java b/impl/src/test/java/org/ehcache/docs/Tiering.java index fd48c4b711..69932f5554 100644 --- a/impl/src/test/java/org/ehcache/docs/Tiering.java +++ b/impl/src/test/java/org/ehcache/docs/Tiering.java @@ -112,7 +112,7 @@ public void diskSegments() throws Exception { .withCache("less-segments", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().disk(10, MemoryUnit.MB)) - .add(new OffHeapDiskStoreConfiguration(2)) // <1> + .withService(new OffHeapDiskStoreConfiguration(2)) // <1> ) .build(true); @@ -128,7 +128,7 @@ public void updateResourcesAtRuntime() throws InterruptedException { CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10L, EntryUnit.ENTRIES)) - .add(cacheEventListenerConfiguration) + .withService(cacheEventListenerConfiguration) .build(); CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().withCache("cache", cacheConfiguration) diff --git a/core/src/test/java/org/ehcache/core/config/BaseCacheConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/BaseCacheConfigurationTest.java similarity index 98% rename from core/src/test/java/org/ehcache/core/config/BaseCacheConfigurationTest.java rename to impl/src/test/java/org/ehcache/impl/config/BaseCacheConfigurationTest.java index 8039cb69f8..a91cbbc7ba 100644 --- a/core/src/test/java/org/ehcache/core/config/BaseCacheConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/BaseCacheConfigurationTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.config; +package org.ehcache.impl.config; import org.ehcache.config.ResourcePools; import org.junit.Rule; diff --git a/core/src/test/java/org/ehcache/core/config/ResourcePoolsImplTest.java b/impl/src/test/java/org/ehcache/impl/config/ResourcePoolsImplTest.java similarity index 84% rename from core/src/test/java/org/ehcache/core/config/ResourcePoolsImplTest.java rename to impl/src/test/java/org/ehcache/impl/config/ResourcePoolsImplTest.java index 4c7ca74a7e..0a0ad4f10a 100644 --- a/core/src/test/java/org/ehcache/core/config/ResourcePoolsImplTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/ResourcePoolsImplTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.config; +package org.ehcache.impl.config; import org.ehcache.config.ResourcePool; import org.ehcache.config.ResourcePools; @@ -25,17 +25,18 @@ import org.hamcrest.Matchers; import org.junit.Test; -import java.util.Arrays; import java.util.Collection; -import java.util.Collections; -import java.util.List; +import static java.util.Arrays.asList; +import static java.util.Arrays.stream; +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.toMap; import static org.ehcache.config.ResourceType.Core.HEAP; import static org.ehcache.config.ResourceType.Core.OFFHEAP; import static org.ehcache.config.units.EntryUnit.ENTRIES; import static org.ehcache.config.units.MemoryUnit.KB; import static org.ehcache.config.units.MemoryUnit.MB; -import static org.ehcache.core.config.ResourcePoolsImpl.validateResourcePools; +import static org.ehcache.impl.config.ResourcePoolsImpl.validateResourcePools; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; @@ -238,10 +239,8 @@ public void testMemoryResourceUnequalUnitInversion() { @Test public void testAddingNewTierWhileUpdating() { - ResourcePools existing = new ResourcePoolsImpl(Collections., ResourcePool>singletonMap( - ResourceType.Core.HEAP, new SizedResourcePoolImpl<>(ResourceType.Core.HEAP, 10L, EntryUnit.ENTRIES, false))); - ResourcePools toBeUpdated = new ResourcePoolsImpl(Collections., ResourcePool>singletonMap( - ResourceType.Core.DISK, new SizedResourcePoolImpl<>(ResourceType.Core.DISK, 10L, MemoryUnit.MB, false))); + ResourcePools existing = resources(new SizedResourcePoolImpl<>(ResourceType.Core.HEAP, 10L, EntryUnit.ENTRIES, false)); + ResourcePools toBeUpdated = resources(new SizedResourcePoolImpl<>(ResourceType.Core.DISK, 10L, MemoryUnit.MB, false)); try { existing.validateAndMerge(toBeUpdated); fail(); @@ -252,8 +251,8 @@ public void testAddingNewTierWhileUpdating() { @Test public void testUpdatingOffHeap() { - ResourcePools existing = ResourcePoolsHelper.createOffheapOnlyPools(10); - ResourcePools toBeUpdated = ResourcePoolsHelper.createOffheapOnlyPools(50); + ResourcePools existing = resources(new SizedResourcePoolImpl<>(ResourceType.Core.OFFHEAP, 10L, MemoryUnit.MB, false)); + ResourcePools toBeUpdated = resources(new SizedResourcePoolImpl<>(ResourceType.Core.OFFHEAP, 50L, MemoryUnit.MB, false)); try { existing.validateAndMerge(toBeUpdated); fail(); @@ -264,8 +263,8 @@ public void testUpdatingOffHeap() { @Test public void testUpdatingDisk() { - ResourcePools existing = ResourcePoolsHelper.createDiskOnlyPools(10, MB); - ResourcePools toBeUpdated = ResourcePoolsHelper.createDiskOnlyPools(50, MB); + ResourcePools existing = resources(new SizedResourcePoolImpl<>(ResourceType.Core.DISK, 10L, MemoryUnit.MB, false)); + ResourcePools toBeUpdated = resources(new SizedResourcePoolImpl<>(ResourceType.Core.DISK, 50L, MemoryUnit.MB, false)); try { existing.validateAndMerge(toBeUpdated); fail(); @@ -276,8 +275,13 @@ public void testUpdatingDisk() { @Test public void testUpdateResourceUnitSuccess() { - ResourcePools existing = ResourcePoolsHelper.createHeapDiskPools(200, MB, 4096); - ResourcePools toBeUpdated = ResourcePoolsHelper.createHeapOnlyPools(2, MemoryUnit.GB); + ResourcePools existing = resources( + new SizedResourcePoolImpl<>(ResourceType.Core.HEAP, 200L, MemoryUnit.MB, false), + new SizedResourcePoolImpl<>(ResourceType.Core.DISK, 4096L, MemoryUnit.MB, false) + ); + ResourcePools toBeUpdated = resources( + new SizedResourcePoolImpl<>(ResourceType.Core.HEAP, 2, MemoryUnit.GB, false) + ); existing = existing.validateAndMerge(toBeUpdated); assertThat(existing.getPoolForResource(ResourceType.Core.HEAP).getSize(), Matchers.is(2L)); @@ -286,8 +290,13 @@ public void testUpdateResourceUnitSuccess() { @Test public void testUpdateResourceUnitFailure() { - ResourcePools existing = ResourcePoolsHelper.createHeapDiskPools(20, MB, 200); - ResourcePools toBeUpdated = ResourcePoolsHelper.createHeapOnlyPools(500, EntryUnit.ENTRIES); + ResourcePools existing = resources( + new SizedResourcePoolImpl<>(ResourceType.Core.HEAP, 20L, MemoryUnit.MB, false), + new SizedResourcePoolImpl<>(ResourceType.Core.DISK, 200, MemoryUnit.MB, false) + ); + ResourcePools toBeUpdated = resources( + new SizedResourcePoolImpl<>(ResourceType.Core.HEAP, 500, EntryUnit.ENTRIES, false) + ); try { existing = existing.validateAndMerge(toBeUpdated); @@ -299,10 +308,7 @@ public void testUpdateResourceUnitFailure() { assertThat(existing.getPoolForResource(ResourceType.Core.HEAP).getUnit(), Matchers.is(MemoryUnit.MB)); } - private Collection asList(T value1, T value2) { - @SuppressWarnings("unchecked") - List list = Arrays.asList(value1, value2); - return list; + private static ResourcePoolsImpl resources(ResourcePool ... resources) { + return new ResourcePoolsImpl(stream(resources).collect(toMap(ResourcePool::getType, identity()))); } - } diff --git a/core/src/test/java/org/ehcache/core/config/SizedResourcePoolImplTest.java b/impl/src/test/java/org/ehcache/impl/config/SizedResourcePoolImplTest.java similarity index 93% rename from core/src/test/java/org/ehcache/core/config/SizedResourcePoolImplTest.java rename to impl/src/test/java/org/ehcache/impl/config/SizedResourcePoolImplTest.java index 433effec13..dd15bbd519 100644 --- a/core/src/test/java/org/ehcache/core/config/SizedResourcePoolImplTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/SizedResourcePoolImplTest.java @@ -14,10 +14,9 @@ * limitations under the License. */ -package org.ehcache.core.config; +package org.ehcache.impl.config; import org.ehcache.config.ResourceType; -import org.ehcache.config.SizedResourcePool; import org.ehcache.config.units.EntryUnit; import org.junit.Test; diff --git a/impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfigurationTest.java new file mode 100644 index 0000000000..2b827a021c --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfigurationTest.java @@ -0,0 +1,36 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.config.event; + +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; + +public class DefaultCacheEventDispatcherConfigurationTest { + + @Test + public void testDeriveDetachesProperly() { + DefaultCacheEventDispatcherConfiguration configuration = new DefaultCacheEventDispatcherConfiguration("foobar"); + DefaultCacheEventDispatcherConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getThreadPoolAlias(), is(configuration.getThreadPoolAlias())); + } +} diff --git a/impl/src/test/java/org/ehcache/impl/config/event/DefaultEventSourceConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/event/DefaultEventSourceConfigurationTest.java new file mode 100644 index 0000000000..6aeb51982a --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/config/event/DefaultEventSourceConfigurationTest.java @@ -0,0 +1,36 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.config.event; + +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; + +public class DefaultEventSourceConfigurationTest { + + @Test + public void testDeriveDetachesProperly() { + DefaultEventSourceConfiguration configuration = new DefaultEventSourceConfiguration(42); + DefaultEventSourceConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getDispatcherConcurrency(), is(configuration.getDispatcherConcurrency())); + } +} diff --git a/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfigurationTest.java new file mode 100644 index 0000000000..39ac3e68db --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfigurationTest.java @@ -0,0 +1,39 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.config.loaderwriter; + +import org.ehcache.spi.loaderwriter.CacheLoaderWriter; +import org.junit.Test; + +import static org.ehcache.test.MockitoUtil.mock; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; + +public class DefaultCacheLoaderWriterConfigurationTest { + + @Test + public void testDeriveDetachesCorrectly() { + CacheLoaderWriter mock = mock(CacheLoaderWriter.class); + DefaultCacheLoaderWriterConfiguration configuration = new DefaultCacheLoaderWriterConfiguration(mock); + DefaultCacheLoaderWriterConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getInstance(), sameInstance(configuration.getInstance())); + } +} diff --git a/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java index 2cf35fee69..65d2969c5f 100644 --- a/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java @@ -23,6 +23,8 @@ import static org.ehcache.test.MockitoUtil.mock; import static org.hamcrest.collection.IsArrayContainingInOrder.arrayContaining; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsNull.nullValue; import static org.hamcrest.core.IsSame.sameInstance; import static org.junit.Assert.assertThat; @@ -95,4 +97,14 @@ public void testAlreadyBoundLoaderWriterConfigurationCannotBeBound() { //expected } } + + @Test + public void testDeriveDetachesCorrectly() { + ResilienceStrategy resilienceStrategy = mock(ResilienceStrategy.class); + DefaultResilienceStrategyConfiguration configuration = new DefaultResilienceStrategyConfiguration(resilienceStrategy); + DefaultResilienceStrategyConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getInstance(), sameInstance(configuration.getInstance())); + } } diff --git a/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java b/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java index 1acc4368b0..3275454657 100644 --- a/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java @@ -80,8 +80,8 @@ public void tearDown() { public void testOnHeapPutGet() { Cache cache = cacheManager.createCache("onHeap", newCacheConfigurationBuilder(Long.class, String.class, heap(10)) - .add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.KEY)) - .add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)) + .withService(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.KEY)) + .withService(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)) .build()); cache.put(42L, "TheAnswer!"); @@ -122,8 +122,8 @@ public void testOffHeapPutGet() { public void testOffHeapOnHeapCopyPutGet() { Cache cache = cacheManager.createCache("offHeap", newCacheConfigurationBuilder(Long.class, String.class, newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).offheap(10, MemoryUnit.MB)) - .add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.KEY)) - .add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)) + .withService(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.KEY)) + .withService(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)) .build() ); @@ -146,8 +146,8 @@ public void testOffHeapOnHeapCopyPutGet() { public void testDiskOffHeapOnHeapCopyPutGet() { Cache cache = cacheManager.createCache("offHeap", newCacheConfigurationBuilder(Long.class, String.class, newResourcePoolsBuilder().heap(2, EntryUnit.ENTRIES).offheap(10, MemoryUnit.MB).disk(100, MemoryUnit.MB)) - .add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.KEY)) - .add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)) + .withService(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.KEY)) + .withService(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)) .build() ); diff --git a/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfigurationTest.java new file mode 100644 index 0000000000..903a45a4a3 --- /dev/null +++ b/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfigurationTest.java @@ -0,0 +1,38 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.impl.config.store.disk; + +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; + +public class OffHeapDiskStoreConfigurationTest { + + @Test + public void testDeriveDetachesProperly() { + OffHeapDiskStoreConfiguration configuration = new OffHeapDiskStoreConfiguration("foobar", 16, 42); + OffHeapDiskStoreConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getThreadPoolAlias(), is(configuration.getThreadPoolAlias())); + assertThat(derived.getDiskSegments(), is(configuration.getDiskSegments())); + assertThat(derived.getWriterConcurrency(), is(configuration.getWriterConcurrency())); + } +} diff --git a/impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderTest.java index 520e313652..5c467fcdde 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderTest.java @@ -57,7 +57,7 @@ public void testNewInstanceUsingAliasAndArg() throws Exception { ClassInstanceProvider, TestService> classInstanceProvider = new ClassInstanceProvider<>(null, configClass); classInstanceProvider.preconfigured.put("test stuff", new ClassInstanceConfiguration<>(TestService.class, "test string")); - TestService obj = classInstanceProvider.newInstance("test stuff", (ServiceConfiguration) null); + TestService obj = classInstanceProvider.newInstance("test stuff", (ServiceConfiguration) null); assertThat(obj.theString, equalTo("test string")); } @@ -170,7 +170,7 @@ public static abstract class TestCloseableService implements Service, Closeable } - public static class TestCloaseableServiceConfig extends ClassInstanceConfiguration implements ServiceConfiguration { + public static class TestCloaseableServiceConfig extends ClassInstanceConfiguration implements ServiceConfiguration { public TestCloaseableServiceConfig() { super(TestCloseableService.class); @@ -206,7 +206,7 @@ public void stop() { } } - public static class TestServiceConfiguration extends ClassInstanceConfiguration implements ServiceConfiguration { + public static class TestServiceConfiguration extends ClassInstanceConfiguration implements ServiceConfiguration { public TestServiceConfiguration() { super(TestService.class); } @@ -221,7 +221,7 @@ public Class getServiceType() { } } - public static class TestServiceProviderConfiguration extends ClassInstanceProviderConfiguration> implements ServiceConfiguration { + public static class TestServiceProviderConfiguration extends ClassInstanceProviderConfiguration> implements ServiceConfiguration { @Override public Class getServiceType() { return TestService.class; diff --git a/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehindTestBase.java b/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehindTestBase.java index 1cd33a826d..649e38b655 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehindTestBase.java +++ b/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehindTestBase.java @@ -72,7 +72,7 @@ public void testWriteOrdering() throws Exception { try (CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true)) { Cache testCache = cacheManager.createCache("testWriteOrdering", configurationBuilder() .withLoaderWriter(loaderWriter) - .add(newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 8).build()) + .withService(newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 8).build()) .build()); CountDownLatch countDownLatch = new CountDownLatch(8); @@ -103,7 +103,7 @@ public void testWrites() throws Exception { try (CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true)) { Cache testCache = cacheManager.createCache("testWrites", CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, String.class, heap(10)) .withLoaderWriter(loaderWriter) - .add(newUnBatchedWriteBehindConfiguration().concurrencyLevel(3).queueSize(10).build()) + .withService(newUnBatchedWriteBehindConfiguration().concurrencyLevel(3).queueSize(10).build()) .build()); CountDownLatch countDownLatch = new CountDownLatch(4); @@ -129,7 +129,7 @@ public void testBulkWrites() throws Exception { try (CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true)) { Cache testCache = cacheManager.createCache("testBulkWrites", CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, String.class, heap(100)) .withLoaderWriter(loaderWriter) - .add(newUnBatchedWriteBehindConfiguration().concurrencyLevel(3).queueSize(10).build()) + .withService(newUnBatchedWriteBehindConfiguration().concurrencyLevel(3).queueSize(10).build()) .build()); CountDownLatch countDownLatch = new CountDownLatch(20); @@ -175,7 +175,7 @@ public void testThatAllGetsReturnLatestData() throws Exception { try (CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true)) { Cache testCache = cacheManager.createCache("testThatAllGetsReturnLatestData", configurationBuilder() .withLoaderWriter(loaderWriter) - .add(newUnBatchedWriteBehindConfiguration().concurrencyLevel(3).queueSize(10).build()) + .withService(newUnBatchedWriteBehindConfiguration().concurrencyLevel(3).queueSize(10).build()) .build()); for (int i = 0; i < 10; i++) { @@ -219,7 +219,7 @@ public void testAllGetsReturnLatestDataWithKeyCollision() { try (CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true)) { Cache testCache = cacheManager.createCache("testAllGetsReturnLatestDataWithKeyCollision", configurationBuilder() .withLoaderWriter(loaderWriter) - .add(newUnBatchedWriteBehindConfiguration().concurrencyLevel(3).queueSize(10).build()) + .withService(newUnBatchedWriteBehindConfiguration().concurrencyLevel(3).queueSize(10).build()) .build()); Random random = new Random(); @@ -249,7 +249,7 @@ public void testBatchedDeletedKeyReturnsNull() throws Exception { try (CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true)) { Cache testCache = cacheManager.createCache("testBatchedDeletedKeyReturnsNull", configurationBuilder() .withLoaderWriter(loaderWriter) - .add(newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 2).build()) + .withService(newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 2).build()) .build()); assertThat(testCache.get("key"), is("value")); @@ -277,7 +277,7 @@ public void testUnBatchedDeletedKeyReturnsNull() throws Exception { try { Cache testCache = cacheManager.createCache("testUnBatchedDeletedKeyReturnsNull", configurationBuilder() .withLoaderWriter(loaderWriter) - .add(newUnBatchedWriteBehindConfiguration().build()) + .withService(newUnBatchedWriteBehindConfiguration().build()) .build()); assertThat(testCache.get("key"), is("value")); @@ -301,7 +301,7 @@ public void testBatchedOverwrittenKeyReturnsNewValue() throws Exception { try (CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true)) { Cache testCache = cacheManager.createCache("testBatchedOverwrittenKeyReturnsNewValue", configurationBuilder() .withLoaderWriter(loaderWriter) - .add(newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 2).build()) + .withService(newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 2).build()) .build()); assertThat(testCache.get("key"), is("value")); @@ -329,7 +329,7 @@ public void testUnBatchedOverwrittenKeyReturnsNewValue() throws Exception { try { Cache testCache = cacheManager.createCache("testUnBatchedOverwrittenKeyReturnsNewValue", configurationBuilder() .withLoaderWriter(loaderWriter) - .add(newUnBatchedWriteBehindConfiguration().build()) + .withService(newUnBatchedWriteBehindConfiguration().build()) .build()); assertThat(testCache.get("key"), is("value")); @@ -351,7 +351,7 @@ public void testCoaslecedWritesAreNotSeen() throws InterruptedException { try (CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true)) { Cache testCache = cacheManager.createCache("testCoaslecedWritesAreNotSeen", configurationBuilder() .withLoaderWriter(loaderWriter) - .add(newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 2).enableCoalescing().build()) + .withService(newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 2).enableCoalescing().build()) .build()); CountDownLatch latch = new CountDownLatch(2); @@ -376,7 +376,7 @@ public void testUnBatchedWriteBehindStopWaitsForEmptyQueue() { try (CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true)) { Cache testCache = cacheManager.createCache("testUnBatchedWriteBehindStopWaitsForEmptyQueue", configurationBuilder() .withLoaderWriter(loaderWriter) - .add(newUnBatchedWriteBehindConfiguration().build()) + .withService(newUnBatchedWriteBehindConfiguration().build()) .build()); testCache.put("key", "value"); @@ -392,7 +392,7 @@ public void testBatchedWriteBehindStopWaitsForEmptyQueue() { try (CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true)) { Cache testCache = cacheManager.createCache("testBatchedWriteBehindStopWaitsForEmptyQueue", configurationBuilder() .withLoaderWriter(loaderWriter) - .add(newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 2).build()) + .withService(newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 2).build()) .build()); testCache.put("key", "value"); @@ -415,7 +415,7 @@ public void testUnBatchedWriteBehindBlocksWhenFull() throws Exception { try (CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true)) { final Cache testCache = cacheManager.createCache("testUnBatchedWriteBehindBlocksWhenFull", configurationBuilder() .withLoaderWriter(loaderWriter) - .add(newUnBatchedWriteBehindConfiguration().queueSize(1).build()) + .withService(newUnBatchedWriteBehindConfiguration().queueSize(1).build()) .build()); testCache.put("key1", "value"); @@ -455,7 +455,7 @@ public void testBatchedWriteBehindBlocksWhenFull() throws Exception { try (CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true)) { final Cache testCache = cacheManager.createCache("testBatchedWriteBehindBlocksWhenFull", configurationBuilder() .withLoaderWriter(loaderWriter) - .add(newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 1).queueSize(1).build()) + .withService(newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 1).queueSize(1).build()) .build()); testCache.put("key1", "value"); @@ -488,7 +488,7 @@ public void testFilledBatchedIsWritten() throws Exception { try (CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true)) { Cache testCache = cacheManager.createCache("testFilledBatchedIsWritten", configurationBuilder() .withLoaderWriter(loaderWriter) - .add(newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 2).build()) + .withService(newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 2).build()) .build()); CountDownLatch latch = new CountDownLatch(2); @@ -514,7 +514,7 @@ public void testAgedBatchedIsWritten() throws Exception { try (CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true)) { Cache testCache = cacheManager.createCache("testAgedBatchedIsWritten", configurationBuilder() .withLoaderWriter(loaderWriter) - .add(newBatchedWriteBehindConfiguration(1, SECONDS, 2).build()) + .withService(newBatchedWriteBehindConfiguration(1, SECONDS, 2).build()) .build()); CountDownLatch latch = new CountDownLatch(1); @@ -539,7 +539,7 @@ class TestWriteBehindProvider extends WriteBehindProviderFactory.Provider { @Override @SuppressWarnings("unchecked") - public WriteBehind createWriteBehindLoaderWriter(CacheLoaderWriter cacheLoaderWriter, WriteBehindConfiguration configuration) { + public WriteBehind createWriteBehindLoaderWriter(CacheLoaderWriter cacheLoaderWriter, WriteBehindConfiguration configuration) { this.writeBehind = super.createWriteBehindLoaderWriter(cacheLoaderWriter, configuration); return (WriteBehind) writeBehind; } @@ -554,8 +554,8 @@ public WriteBehind createWriteBehindLoaderWriter(CacheLoaderWriter< try (CacheManager cacheManager = managerBuilder().using(writeBehindProvider).build(true)) { Cache testCache = cacheManager.createCache("testAgedBatchedIsWritten", configurationBuilder() - .add(new DefaultCacheLoaderWriterConfiguration(loaderWriter)) - .add(newBatchedWriteBehindConfiguration(5, SECONDS, 2).build()) + .withService(new DefaultCacheLoaderWriterConfiguration(loaderWriter)) + .withService(newBatchedWriteBehindConfiguration(5, SECONDS, 2).build()) .build()); testCache.put("key1", "value1"); diff --git a/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactoryTest.java b/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactoryTest.java index c5db714bbb..aedfb3b3b4 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactoryTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactoryTest.java @@ -50,7 +50,7 @@ public class WriteBehindProviderFactoryTest { @Test public void testAddingWriteBehindConfigurationAtCacheLevel() { CacheManagerBuilder cacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder(); - WriteBehindConfiguration writeBehindConfiguration = WriteBehindConfigurationBuilder.newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 1) + WriteBehindConfiguration writeBehindConfiguration = WriteBehindConfigurationBuilder.newBatchedWriteBehindConfiguration(Long.MAX_VALUE, SECONDS, 1) .concurrencyLevel(3) .queueSize(10) .build(); @@ -58,12 +58,12 @@ public void testAddingWriteBehindConfigurationAtCacheLevel() { CacheManager cacheManager = cacheManagerBuilder.build(true); final Cache cache = cacheManager.createCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, heap(100)) - .add(writeBehindConfiguration) - .add(new DefaultCacheLoaderWriterConfiguration(klazz)) + .withService(writeBehindConfiguration) + .withService(new DefaultCacheLoaderWriterConfiguration(klazz)) .build()); - Collection> serviceConfiguration = cache.getRuntimeConfiguration() + Collection> serviceConfiguration = cache.getRuntimeConfiguration() .getServiceConfigurations(); - assertThat(serviceConfiguration, IsCollectionContaining.>hasItem(instanceOf(WriteBehindConfiguration.class))); + assertThat(serviceConfiguration, IsCollectionContaining.>hasItem(instanceOf(WriteBehindConfiguration.class))); cacheManager.close(); } diff --git a/impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineConfigurationTest.java index 0a4f62a971..b8872af86b 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineConfigurationTest.java @@ -19,6 +19,9 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsSame.sameInstance; import static org.junit.Assert.fail; import org.ehcache.config.units.MemoryUnit; @@ -61,4 +64,14 @@ public void testValidArguments() { assertThat(configuration.getUnit(), equalTo(MemoryUnit.B)); } + @Test + public void testDeriveDetachesProperly() { + DefaultSizeOfEngineConfiguration configuration = new DefaultSizeOfEngineConfiguration(42L, MemoryUnit.MB, 123L); + DefaultSizeOfEngineConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(not(sameInstance(configuration)))); + assertThat(derived.getMaxObjectSize(), is(configuration.getMaxObjectSize())); + assertThat(derived.getUnit(), is(configuration.getUnit())); + assertThat(derived.getMaxObjectGraphSize(), is(configuration.getMaxObjectGraphSize())); + } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderTest.java index 2a15bcc7a4..73426d0d0b 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderTest.java @@ -55,7 +55,7 @@ public void testCacheConfigUsage() { final CacheManager manager = CacheManagerBuilder.newCacheManagerBuilder() .withCache("foo", CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) - .add(listenerBuilder) + .withService(listenerBuilder) .build()).build(true); final Collection bar = manager.getCache("foo", Object.class, Object.class).getRuntimeConfiguration().getServiceConfigurations(); assertThat(bar.iterator().next().getClass().toString(), is(ListenerObject.object.toString())); @@ -64,16 +64,16 @@ public void testCacheConfigUsage() { @Test public void testAddingCacheEventListenerConfigurationAtCacheLevel() { CacheManagerBuilder cacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder(); - CacheEventListenerConfiguration cacheEventListenerConfiguration = CacheEventListenerConfigurationBuilder + CacheEventListenerConfiguration cacheEventListenerConfiguration = CacheEventListenerConfigurationBuilder .newEventListenerConfiguration(ListenerObject.class, EventType.CREATED).unordered().asynchronous().build(); CacheManager cacheManager = cacheManagerBuilder.build(true); final Cache cache = cacheManager.createCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, heap(100)) - .add(cacheEventListenerConfiguration) + .withService(cacheEventListenerConfiguration) .build()); - Collection> serviceConfiguration = cache.getRuntimeConfiguration() + Collection> serviceConfiguration = cache.getRuntimeConfiguration() .getServiceConfigurations(); - assertThat(serviceConfiguration, IsCollectionContaining.>hasItem(instanceOf(DefaultCacheEventListenerConfiguration.class))); + assertThat(serviceConfiguration, IsCollectionContaining.>hasItem(instanceOf(DefaultCacheEventListenerConfiguration.class))); cacheManager.close(); } diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderTest.java index c788884bf7..0af0a4bee4 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderTest.java @@ -49,7 +49,7 @@ public void testCacheConfigUsage() { final CacheManager manager = CacheManagerBuilder.newCacheManagerBuilder() .withCache("foo", CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) - .add(new DefaultCacheLoaderWriterConfiguration(MyLoader.class)) + .withService(new DefaultCacheLoaderWriterConfiguration(MyLoader.class)) .build()).build(true); final Object foo = manager.getCache("foo", Object.class, Object.class).get(new Object()); assertThat(foo, is(MyLoader.object)); @@ -74,7 +74,7 @@ public void testCacheManagerConfigUsage() { @Test public void testCacheConfigOverridesCacheManagerConfig() { final CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, heap(10)) - .add(new DefaultCacheLoaderWriterConfiguration(MyOtherLoader.class)) + .withService(new DefaultCacheLoaderWriterConfiguration(MyOtherLoader.class)) .build(); final Map> caches = new HashMap<>(); @@ -95,11 +95,11 @@ public void testAddingCacheLoaderWriterConfigurationAtCacheLevel() { CacheManager cacheManager = cacheManagerBuilder.build(true); final Cache cache = cacheManager.createCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, heap(100)) - .add(new DefaultCacheLoaderWriterConfiguration(klazz)) + .withService(new DefaultCacheLoaderWriterConfiguration(klazz)) .build()); - Collection> serviceConfiguration = cache.getRuntimeConfiguration() + Collection> serviceConfiguration = cache.getRuntimeConfiguration() .getServiceConfigurations(); - assertThat(serviceConfiguration, IsCollectionContaining.>hasItem(instanceOf(DefaultCacheLoaderWriterConfiguration.class))); + assertThat(serviceConfiguration, IsCollectionContaining.>hasItem(instanceOf(DefaultCacheLoaderWriterConfiguration.class))); cacheManager.close(); } diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java index 97565385f8..85c545a365 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java @@ -113,8 +113,8 @@ public void before() { CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, heap(10)) .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(TIME_TO_EXPIRATION))) - .add(cacheEventListenerConfiguration) - .add(new StoreStatisticsConfiguration(enableStoreStatistics)) + .withService(cacheEventListenerConfiguration) + .withService(new StoreStatisticsConfiguration(enableStoreStatistics)) .build(); cacheManager = CacheManagerBuilder.newCacheManagerBuilder() diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java index aa73b41f4d..a728828231 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java @@ -51,7 +51,7 @@ public void before() { CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES)) .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(TIME_TO_EXPIRATION))) - .add(new StoreStatisticsConfiguration(true)) // explicitly enable statistics + .withService(new StoreStatisticsConfiguration(true)) // explicitly enable statistics .build(); cacheManager = CacheManagerBuilder.newCacheManagerBuilder() diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java index 84496ef8ff..d9ea7b6075 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java @@ -65,7 +65,7 @@ public class StatsUtilsTest { public void before() { CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, heap(10)) - .add(new StoreStatisticsConfiguration(true)) // explicitly enable statistics + .withService(new StoreStatisticsConfiguration(true)) // explicitly enable statistics .build(); cacheManager = CacheManagerBuilder.newCacheManagerBuilder() diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java index 55e58396b1..96e613a11c 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java @@ -154,13 +154,13 @@ public Class getValueType() { } @Override - public ServiceConfiguration[] getServiceConfigurations() { + public ServiceConfiguration[] getServiceConfigurations() { try { CacheConfiguration cacheConfiguration = mock(CacheConfiguration.class); when(cacheConfiguration.getResourcePools()).thenReturn(newResourcePoolsBuilder().disk(1, MemoryUnit.MB, false).build()); String spaceName = "OffheapDiskStore-" + index.getAndIncrement(); PersistenceSpaceIdentifier space = diskResourceService.getPersistenceSpaceIdentifier(spaceName, cacheConfiguration); - return new ServiceConfiguration[] {space}; + return new ServiceConfiguration[] {space}; } catch (CachePersistenceException e) { throw new RuntimeException(e); } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java index e9f0662e80..2416ec91c2 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java @@ -105,8 +105,8 @@ public Class getValueType() { } @Override - public ServiceConfiguration[] getServiceConfigurations() { - return new ServiceConfiguration[0]; + public ServiceConfiguration[] getServiceConfigurations() { + return new ServiceConfiguration[0]; } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java index d97df7852e..d4aefe3677 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java @@ -113,8 +113,8 @@ public Class getValueType() { } @Override - public ServiceConfiguration[] getServiceConfigurations() { - return new ServiceConfiguration[0]; + public ServiceConfiguration[] getServiceConfigurations() { + return new ServiceConfiguration[0]; } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java index e0924ccd5a..6972cf3fe0 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java @@ -111,8 +111,8 @@ public Class getValueType() { } @Override - public ServiceConfiguration[] getServiceConfigurations() { - return new ServiceConfiguration[0]; + public ServiceConfiguration[] getServiceConfigurations() { + return new ServiceConfiguration[0]; } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java index 4b0edc7b27..5a7ec71121 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java @@ -118,8 +118,8 @@ public Class getValueType() { } @Override - public ServiceConfiguration[] getServiceConfigurations() { - return new ServiceConfiguration[0]; + public ServiceConfiguration[] getServiceConfigurations() { + return new ServiceConfiguration[0]; } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueTest.java index 6d9f5930f0..73f12cc31f 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueTest.java @@ -39,7 +39,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.concurrent.TimeUnit; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.hamcrest.CoreMatchers.instanceOf; @@ -158,7 +157,7 @@ public void testStoreByValue() { final Cache cache2 = cacheManager.createCache("cache2", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, heap(1)) - .add(copierConfiguration) + .withService(copierConfiguration) .build()); performAssertions(cache2, false); diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java index 2210573f6e..eb83cb88c4 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java @@ -102,8 +102,8 @@ public Class getValueType() { } @Override - public ServiceConfiguration[] getServiceConfigurations() { - return new ServiceConfiguration[0]; + public ServiceConfiguration[] getServiceConfigurations() { + return new ServiceConfiguration[0]; } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java index 6145137524..141c559907 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java @@ -111,8 +111,8 @@ public Class getValueType() { } @Override - public ServiceConfiguration[] getServiceConfigurations() { - return new ServiceConfiguration[0]; + public ServiceConfiguration[] getServiceConfigurations() { + return new ServiceConfiguration[0]; } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderTest.java index 30ed69b897..99a82a24bb 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderTest.java @@ -83,7 +83,7 @@ public void testRankCachingTier() throws Exception { private void assertRank(final Store.Provider provider, final int expectedRank, final ResourceType... resources) { assertThat(provider.rank( new HashSet<>(Arrays.asList(resources)), - Collections.>emptyList()), + Collections.>emptyList()), is(expectedRank)); } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java index 81cec2d405..813a7416ae 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java @@ -100,8 +100,8 @@ public Class getValueType() { } @Override - public ServiceConfiguration[] getServiceConfigurations() { - return new ServiceConfiguration[0]; + public ServiceConfiguration[] getServiceConfigurations() { + return new ServiceConfiguration[0]; } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java index 506c20e2da..68ae986c8e 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java @@ -108,8 +108,8 @@ public Class getValueType() { } @Override - public ServiceConfiguration[] getServiceConfigurations() { - return new ServiceConfiguration[0]; + public ServiceConfiguration[] getServiceConfigurations() { + return new ServiceConfiguration[0]; } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java index fb2dd5ed0c..3fbf583177 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java @@ -113,8 +113,8 @@ public Class getValueType() { } @Override - public ServiceConfiguration[] getServiceConfigurations() { - return new ServiceConfiguration[0]; + public ServiceConfiguration[] getServiceConfigurations() { + return new ServiceConfiguration[0]; } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java index 68fbccf19e..fb864759c5 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java @@ -121,7 +121,7 @@ public void testRank() throws Exception { private void assertRank(final Store.Provider provider, final int expectedRank, final ResourceType... resources) { assertThat(provider.rank( new HashSet<>(Arrays.asList(resources)), - Collections.>emptyList()), + Collections.>emptyList()), is(expectedRank)); } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java index 53a26eea87..e2a0bb4a18 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java @@ -118,8 +118,8 @@ public Class getValueType() { } @Override - public ServiceConfiguration[] getServiceConfigurations() { - return new ServiceConfiguration[0]; + public ServiceConfiguration[] getServiceConfigurations() { + return new ServiceConfiguration[0]; } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java index e2a42c16f9..f09cb0874f 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java @@ -40,7 +40,6 @@ import org.junit.rules.TemporaryFolder; import java.io.File; -import java.util.concurrent.TimeUnit; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.core.spi.ServiceLocator.dependencySet; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java index ab75b2da78..4a35704927 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java @@ -64,7 +64,6 @@ import java.util.Collection; import java.util.Map; import java.util.Set; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; @@ -151,7 +150,7 @@ private Store newStore(Long capacity, EvictionAdvisor tieredStore = new TieredStore<>(onHeapStore, diskStore); provider.registerStore(tieredStore, new CachingTier.Provider() { @Override - public CachingTier createCachingTier(final Store.Configuration storeConfig, final ServiceConfiguration... serviceConfigs) { + public CachingTier createCachingTier(final Store.Configuration storeConfig, final ServiceConfiguration... serviceConfigs) { throw new UnsupportedOperationException("Implement me!"); } @@ -166,7 +165,7 @@ public void initCachingTier(final CachingTier resource) { } @Override - public int rankCachingTier(Set> resourceTypes, Collection> serviceConfigs) { + public int rankCachingTier(Set> resourceTypes, Collection> serviceConfigs) { throw new UnsupportedOperationException("Implement me!"); } @@ -181,7 +180,7 @@ public void stop() { } }, new AuthoritativeTier.Provider() { @Override - public AuthoritativeTier createAuthoritativeTier(final Store.Configuration storeConfig, final ServiceConfiguration... serviceConfigs) { + public AuthoritativeTier createAuthoritativeTier(final Store.Configuration storeConfig, final ServiceConfiguration... serviceConfigs) { throw new UnsupportedOperationException("Implement me!"); } @@ -196,7 +195,7 @@ public void initAuthoritativeTier(final AuthoritativeTier resource) { } @Override - public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { + public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { throw new UnsupportedOperationException("Implement me!"); } @@ -266,8 +265,8 @@ public Class getValueType() { } @Override - public ServiceConfiguration[] getServiceConfigurations() { - return new ServiceConfiguration[0]; + public ServiceConfiguration[] getServiceConfigurations() { + return new ServiceConfiguration[0]; } @Override @@ -323,7 +322,7 @@ private ResourcePools buildResourcePools(Comparable capacityConstraint) { public static class FakeCachingTierProvider implements CachingTier.Provider { @Override @SuppressWarnings("unchecked") - public CachingTier createCachingTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public CachingTier createCachingTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { return mock(CachingTier.class); } @@ -338,7 +337,7 @@ public void initCachingTier(CachingTier resource) { } @Override - public int rankCachingTier(Set> resourceTypes, Collection> serviceConfigs) { + public int rankCachingTier(Set> resourceTypes, Collection> serviceConfigs) { throw new UnsupportedOperationException(); } @@ -356,7 +355,7 @@ public void stop() { public static class FakeAuthoritativeTierProvider implements AuthoritativeTier.Provider { @Override @SuppressWarnings("unchecked") - public AuthoritativeTier createAuthoritativeTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public AuthoritativeTier createAuthoritativeTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { return mock(AuthoritativeTier.class); } @@ -371,7 +370,7 @@ public void initAuthoritativeTier(AuthoritativeTier resource) { } @Override - public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { + public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { throw new UnsupportedOperationException(); } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java index 13248fb2ea..f586fcb0ab 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java @@ -67,7 +67,6 @@ import java.util.Collection; import java.util.Map; import java.util.Set; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; @@ -164,7 +163,7 @@ private Store newStore(Long capacity, EvictionAdvisor CachingTier createCachingTier(final Store.Configuration storeConfig, final ServiceConfiguration... serviceConfigs) { + public CachingTier createCachingTier(final Store.Configuration storeConfig, final ServiceConfiguration... serviceConfigs) { throw new UnsupportedOperationException("Implement me!"); } @@ -181,7 +180,7 @@ public void initCachingTier(final CachingTier resource) { } @Override - public int rankCachingTier(Set> resourceTypes, Collection> serviceConfigs) { + public int rankCachingTier(Set> resourceTypes, Collection> serviceConfigs) { throw new UnsupportedOperationException("Implement me!"); } @@ -196,7 +195,7 @@ public void stop() { } }, new AuthoritativeTier.Provider() { @Override - public AuthoritativeTier createAuthoritativeTier(final Store.Configuration storeConfig, final ServiceConfiguration... serviceConfigs) { + public AuthoritativeTier createAuthoritativeTier(final Store.Configuration storeConfig, final ServiceConfiguration... serviceConfigs) { throw new UnsupportedOperationException("Implement me!"); } @@ -211,7 +210,7 @@ public void initAuthoritativeTier(final AuthoritativeTier resource) { } @Override - public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { + public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { throw new UnsupportedOperationException("Implement me!"); } @@ -281,8 +280,8 @@ public Class getValueType() { } @Override - public ServiceConfiguration[] getServiceConfigurations() { - return new ServiceConfiguration[0]; + public ServiceConfiguration[] getServiceConfigurations() { + return new ServiceConfiguration[0]; } @Override @@ -349,7 +348,7 @@ private ResourcePools buildResourcePools(Long capacityConstraint) { public static class FakeCachingTierProvider implements CachingTier.Provider { @Override @SuppressWarnings("unchecked") - public CachingTier createCachingTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public CachingTier createCachingTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { return mock(CachingTier.class); } @@ -364,7 +363,7 @@ public void initCachingTier(CachingTier resource) { } @Override - public int rankCachingTier(Set> resourceTypes, Collection> serviceConfigs) { + public int rankCachingTier(Set> resourceTypes, Collection> serviceConfigs) { throw new UnsupportedOperationException(); } @@ -382,7 +381,7 @@ public void stop() { public static class FakeAuthoritativeTierProvider implements AuthoritativeTier.Provider { @Override @SuppressWarnings("unchecked") - public AuthoritativeTier createAuthoritativeTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public AuthoritativeTier createAuthoritativeTier(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { return mock(AuthoritativeTier.class); } @@ -397,7 +396,7 @@ public void initAuthoritativeTier(AuthoritativeTier resource) { } @Override - public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { + public int rankAuthority(ResourceType authorityResource, Collection> serviceConfigs) { throw new UnsupportedOperationException(); } diff --git a/integration-test/src/test/java/org/ehcache/integration/CacheCopierTest.java b/integration-test/src/test/java/org/ehcache/integration/CacheCopierTest.java index e775bfbb13..ad1340f521 100644 --- a/integration-test/src/test/java/org/ehcache/integration/CacheCopierTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/CacheCopierTest.java @@ -66,7 +66,7 @@ public void tearDown() throws Exception { @Test public void testCopyValueOnRead() throws Exception { CacheConfiguration cacheConfiguration = baseConfig - .add(new DefaultCopierConfiguration<>(PersonOnReadCopier.class, DefaultCopierConfiguration.Type.VALUE)) + .withService(new DefaultCopierConfiguration<>(PersonOnReadCopier.class, DefaultCopierConfiguration.Type.VALUE)) .build(); Cache cache = cacheManager.createCache("cache", cacheConfiguration); @@ -89,7 +89,7 @@ public void testCopyValueOnRead() throws Exception { @Test public void testCopyValueOnWrite() throws Exception { CacheConfiguration cacheConfiguration = baseConfig - .add(new DefaultCopierConfiguration<>(PersonOnWriteCopier.class, DefaultCopierConfiguration.Type.VALUE)) + .withService(new DefaultCopierConfiguration<>(PersonOnWriteCopier.class, DefaultCopierConfiguration.Type.VALUE)) .build(); Cache cache = cacheManager.createCache("cache", cacheConfiguration); @@ -131,8 +131,8 @@ public void testIdentityCopier() throws Exception { @Test public void testSerializingCopier() throws Exception { CacheConfiguration cacheConfiguration = baseConfig - .add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)) - .add(new DefaultSerializerConfiguration<>(PersonSerializer.class, DefaultSerializerConfiguration.Type.VALUE)) + .withService(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)) + .withService(new DefaultSerializerConfiguration<>(PersonSerializer.class, DefaultSerializerConfiguration.Type.VALUE)) .build(); Cache cache = cacheManager.createCache("cache", cacheConfiguration); @@ -155,7 +155,7 @@ public void testSerializingCopier() throws Exception { @Test public void testReadWriteCopier() throws Exception { CacheConfiguration cacheConfiguration = baseConfig - .add(new DefaultCopierConfiguration<>(PersonCopier.class, DefaultCopierConfiguration.Type.VALUE)) + .withService(new DefaultCopierConfiguration<>(PersonCopier.class, DefaultCopierConfiguration.Type.VALUE)) .build(); Cache cache = cacheManager.createCache("cache", cacheConfiguration); diff --git a/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java b/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java index fcb7ca1645..3e3a09aea6 100644 --- a/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java +++ b/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java @@ -519,12 +519,12 @@ public void testRemoveAll_with_store_that_throws() throws Exception { */ private static class CustomStoreProvider implements Store.Provider { @Override - public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { + public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { return Integer.MAX_VALUE; // Ensure this Store.Provider is ranked highest } @Override - public Store createStore(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public Store createStore(Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { ServiceLocator serviceLocator = dependencySet().with(new DefaultSerializationProvider(null)).build(); try { serviceLocator.startAllServices(); diff --git a/integration-test/src/test/java/org/ehcache/integration/ExpiryEventsTest.java b/integration-test/src/test/java/org/ehcache/integration/ExpiryEventsTest.java index 6c8c90d383..30fd427980 100644 --- a/integration-test/src/test/java/org/ehcache/integration/ExpiryEventsTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/ExpiryEventsTest.java @@ -60,7 +60,7 @@ public class ExpiryEventsTest { .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(1))); private static final CacheConfigurationBuilder byValueCacheConfigBuilder = - byRefCacheConfigBuilder.add(new DefaultCopierConfiguration<>( + byRefCacheConfigBuilder.withService(new DefaultCopierConfiguration<>( SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)); private static final TestTimeSource testTimeSource = new TestTimeSource(); diff --git a/integration-test/src/test/java/org/ehcache/integration/LoaderWriterErrorEhcacheTest.java b/integration-test/src/test/java/org/ehcache/integration/LoaderWriterErrorEhcacheTest.java index 58fe1c3c0e..13db25d038 100644 --- a/integration-test/src/test/java/org/ehcache/integration/LoaderWriterErrorEhcacheTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/LoaderWriterErrorEhcacheTest.java @@ -25,7 +25,6 @@ import org.ehcache.spi.loaderwriter.CacheWritingException; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.loaderwriter.CacheLoaderWriterProvider; -import org.ehcache.spi.service.ServiceConfiguration; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java b/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java index 68d4d77026..4f11501ae5 100644 --- a/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java @@ -69,7 +69,7 @@ public void test1TierStoreStatsAvailableInContextManager() throws Exception { try(CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .withCache("threeTieredCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, heap(1)) - .add(new StoreStatisticsConfiguration(true)) // explicitly enable statistics + .withService(new StoreStatisticsConfiguration(true)) // explicitly enable statistics ).build(true)) { Cache cache = cacheManager.getCache("threeTieredCache", Long.class, String.class); diff --git a/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java b/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java index 4ef8df77b7..2d1970bb8d 100644 --- a/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java @@ -66,7 +66,7 @@ public void before() throws Exception { CacheConfigurationBuilder .newCacheConfigurationBuilder(Integer.class, String.class, resources) .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMillis(TIME_TO_EXPIRATION))) - .add(new StoreStatisticsConfiguration(true)) // explicitly enable statistics + .withService(new StoreStatisticsConfiguration(true)) // explicitly enable statistics .build(); StatisticsService statisticsService = new DefaultStatisticsService(); diff --git a/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java b/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java index 8be7ad3201..a8f2e4db6d 100644 --- a/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java @@ -45,7 +45,6 @@ import javax.transaction.Status; import javax.transaction.Transaction; import java.io.File; -import java.io.IOException; import java.time.Duration; import java.util.HashMap; import java.util.Iterator; @@ -114,8 +113,8 @@ public void testEndToEnd() throws Exception { cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) - .withCache("txCache1", cacheConfigurationBuilder.add(new XAStoreConfiguration("txCache1")).build()) - .withCache("txCache2", cacheConfigurationBuilder.add(new XAStoreConfiguration("txCache2")).build()) + .withCache("txCache1", cacheConfigurationBuilder.withService(new XAStoreConfiguration("txCache1")).build()) + .withCache("txCache2", cacheConfigurationBuilder.withService(new XAStoreConfiguration("txCache2")).build()) .withCache("nonTxCache", cacheConfigurationBuilder.build()) .build(true); @@ -177,8 +176,8 @@ public void testRecoveryWithInflightTx() throws Exception { .offheap(10, MemoryUnit.MB)); cacheManager = CacheManagerBuilder.newCacheManagerBuilder() - .withCache("txCache1", cacheConfigurationBuilder.add(new XAStoreConfiguration("txCache1")).build()) - .withCache("txCache2", cacheConfigurationBuilder.add(new XAStoreConfiguration("txCache2")).build()) + .withCache("txCache1", cacheConfigurationBuilder.withService(new XAStoreConfiguration("txCache1")).build()) + .withCache("txCache2", cacheConfigurationBuilder.withService(new XAStoreConfiguration("txCache2")).build()) .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) .build(true); @@ -219,8 +218,8 @@ public void testRecoveryAfterCrash() throws Exception { cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .with(new CacheManagerPersistenceConfiguration(getStoragePath())) - .withCache("txCache1", cacheConfigurationBuilder.add(new XAStoreConfiguration("txCache1")).build()) - .withCache("txCache2", cacheConfigurationBuilder.add(new XAStoreConfiguration("txCache2")).build()) + .withCache("txCache1", cacheConfigurationBuilder.withService(new XAStoreConfiguration("txCache1")).build()) + .withCache("txCache2", cacheConfigurationBuilder.withService(new XAStoreConfiguration("txCache2")).build()) .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) .build(true); @@ -277,8 +276,8 @@ public void testExpiry() throws Exception { .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(1))); cacheManager = CacheManagerBuilder.newCacheManagerBuilder() - .withCache("txCache1", cacheConfigurationBuilder.add(new XAStoreConfiguration("txCache1")).build()) - .withCache("txCache2", cacheConfigurationBuilder.add(new XAStoreConfiguration("txCache2")).build()) + .withCache("txCache1", cacheConfigurationBuilder.withService(new XAStoreConfiguration("txCache1")).build()) + .withCache("txCache2", cacheConfigurationBuilder.withService(new XAStoreConfiguration("txCache2")).build()) .using(new DefaultTimeSourceService(new TimeSourceConfiguration(testTimeSource))) .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) .build(true); @@ -322,15 +321,15 @@ public void testCopiers() throws Exception { cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .with(new CacheManagerPersistenceConfiguration(getStoragePath())) .withCache("txCache1", cacheConfigurationBuilder - .add(new XAStoreConfiguration("txCache1")) - .add(new DefaultCopierConfiguration<>(LongCopier.class, DefaultCopierConfiguration.Type.KEY)) - .add(new DefaultCopierConfiguration<>(StringCopier.class, DefaultCopierConfiguration.Type.VALUE)) + .withService(new XAStoreConfiguration("txCache1")) + .withService(new DefaultCopierConfiguration<>(LongCopier.class, DefaultCopierConfiguration.Type.KEY)) + .withService(new DefaultCopierConfiguration<>(StringCopier.class, DefaultCopierConfiguration.Type.VALUE)) .build() ) .withCache("txCache2", cacheConfigurationBuilder - .add(new XAStoreConfiguration("txCache2")) - .add(new DefaultCopierConfiguration<>(LongCopier.class, DefaultCopierConfiguration.Type.KEY)) - .add(new DefaultCopierConfiguration<>(StringCopier.class, DefaultCopierConfiguration.Type.VALUE)) + .withService(new XAStoreConfiguration("txCache2")) + .withService(new DefaultCopierConfiguration<>(LongCopier.class, DefaultCopierConfiguration.Type.KEY)) + .withService(new DefaultCopierConfiguration<>(StringCopier.class, DefaultCopierConfiguration.Type.VALUE)) .build()) .using(new DefaultTimeSourceService(new TimeSourceConfiguration(testTimeSource))) .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) @@ -373,15 +372,15 @@ public void testTimeout() throws Exception { cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .with(new CacheManagerPersistenceConfiguration(getStoragePath())) .withCache("txCache1", cacheConfigurationBuilder - .add(new XAStoreConfiguration("txCache1")) - .add(new DefaultCopierConfiguration<>(LongCopier.class, DefaultCopierConfiguration.Type.KEY)) - .add(new DefaultCopierConfiguration<>(StringCopier.class, DefaultCopierConfiguration.Type.VALUE)) + .withService(new XAStoreConfiguration("txCache1")) + .withService(new DefaultCopierConfiguration<>(LongCopier.class, DefaultCopierConfiguration.Type.KEY)) + .withService(new DefaultCopierConfiguration<>(StringCopier.class, DefaultCopierConfiguration.Type.VALUE)) .build() ) .withCache("txCache2", cacheConfigurationBuilder - .add(new XAStoreConfiguration("txCache2")) - .add(new DefaultCopierConfiguration<>(LongCopier.class, DefaultCopierConfiguration.Type.KEY)) - .add(new DefaultCopierConfiguration<>(StringCopier.class, DefaultCopierConfiguration.Type.VALUE)) + .withService(new XAStoreConfiguration("txCache2")) + .withService(new DefaultCopierConfiguration<>(LongCopier.class, DefaultCopierConfiguration.Type.KEY)) + .withService(new DefaultCopierConfiguration<>(StringCopier.class, DefaultCopierConfiguration.Type.VALUE)) .build()) .using(new DefaultTimeSourceService(new TimeSourceConfiguration(testTimeSource))) .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) @@ -435,8 +434,8 @@ public void testConcurrentTx() throws Exception { .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(1))); cacheManager = CacheManagerBuilder.newCacheManagerBuilder() - .withCache("txCache1", cacheConfigurationBuilder.add(new XAStoreConfiguration("txCache1")).build()) - .withCache("txCache2", cacheConfigurationBuilder.add(new XAStoreConfiguration("txCache2")).build()) + .withCache("txCache1", cacheConfigurationBuilder.withService(new XAStoreConfiguration("txCache1")).build()) + .withCache("txCache2", cacheConfigurationBuilder.withService(new XAStoreConfiguration("txCache2")).build()) .using(new DefaultTimeSourceService(new TimeSourceConfiguration(testTimeSource))) .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) .build(true); @@ -500,7 +499,7 @@ public void testAtomicsWithoutLoaderWriter() throws Exception { .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(1))); cacheManager = CacheManagerBuilder.newCacheManagerBuilder() - .withCache("txCache1", cacheConfigurationBuilder.add(new XAStoreConfiguration("txCache1")).build()) + .withCache("txCache1", cacheConfigurationBuilder.withService(new XAStoreConfiguration("txCache1")).build()) .using(new DefaultTimeSourceService(new TimeSourceConfiguration(testTimeSource))) .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) .build(true); @@ -529,7 +528,7 @@ public void testAtomicsWithLoaderWriter() throws Exception { .withLoaderWriter(loaderWriter); cacheManager = CacheManagerBuilder.newCacheManagerBuilder() - .withCache("txCache1", cacheConfigurationBuilder.add(new XAStoreConfiguration("txCache1")).build()) + .withCache("txCache1", cacheConfigurationBuilder.withService(new XAStoreConfiguration("txCache1")).build()) .using(new DefaultTimeSourceService(new TimeSourceConfiguration(testTimeSource))) .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) .build(true); @@ -678,7 +677,7 @@ public void testIterate() throws Throwable { .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(1))); cacheManager = CacheManagerBuilder.newCacheManagerBuilder() - .withCache("txCache1", cacheConfigurationBuilder.add(new XAStoreConfiguration("txCache1")).build()) + .withCache("txCache1", cacheConfigurationBuilder.withService(new XAStoreConfiguration("txCache1")).build()) .using(new DefaultTimeSourceService(new TimeSourceConfiguration(testTimeSource))) .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) .build(true); diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java index 4e811216c7..27834e37e2 100755 --- a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java @@ -102,7 +102,7 @@ public void test() throws IOException { CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, resources) .withEvictionAdvisor((key, value) -> key.equals(2L)) - .add(new StoreStatisticsConfiguration(true)) // explicitly enable statistics to make sure they are there even when using only one tier + .withService(new StoreStatisticsConfiguration(true)) // explicitly enable statistics to make sure they are there even when using only one tier .build(); try (CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() diff --git a/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java b/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java index 5d12a7efc8..cbecaf2cf2 100644 --- a/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java +++ b/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java @@ -98,7 +98,7 @@ public void testCanGetContext() { @Test public void descriptorOnHeapTest() { CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, heap(10)) - .add(new StoreStatisticsConfiguration(true)) + .withService(new StoreStatisticsConfiguration(true)) .build(); ManagementRegistryService managementRegistry = new DefaultManagementRegistryService(new DefaultManagementRegistryConfiguration().setCacheManagerAlias("myCM")); @@ -229,7 +229,7 @@ private String getStoragePath() throws IOException { @Test public void testCanGetCapabilities() { CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, heap(10)) - .add(new StoreStatisticsConfiguration(true)) + .withService(new StoreStatisticsConfiguration(true)) .build(); ManagementRegistryService managementRegistry = new DefaultManagementRegistryService(new DefaultManagementRegistryConfiguration().setCacheManagerAlias("myCM")); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java index f5250233c2..f270e60737 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java @@ -137,7 +137,7 @@ public static void testEhcache3AsBundle() { public static void testEhcache3WithSerializationAndClientClass() { CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .withCache("myCache", newCacheConfigurationBuilder(Long.class, Person.class, heap(10)) - .add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)) + .withService(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE)) .withClassLoader(TestMethods.class.getClassLoader()) .build()) .build(true); @@ -151,7 +151,7 @@ public static void testEhcache3WithSerializationAndClientClass() { public static void testCustomCopier() { CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .withCache("myCache", newCacheConfigurationBuilder(Long.class, String.class, heap(10)) - .add(new DefaultCopierConfiguration<>(StringCopier.class, DefaultCopierConfiguration.Type.VALUE)) + .withService(new DefaultCopierConfiguration<>(StringCopier.class, DefaultCopierConfiguration.Type.VALUE)) .withClassLoader(TestMethods.class.getClassLoader()) .build()) .build(true); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java index 5cda12d76d..9c521c27c4 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java @@ -114,7 +114,7 @@ public static void testProgrammaticConfiguration() throws Exception { .withClassLoader(TestMethods.class.getClassLoader()) .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) .withCache("xaCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, heap(10)) - .add(new XAStoreConfiguration("xaCache")).build()).build(true)) { + .withService(new XAStoreConfiguration("xaCache")).build()).build(true)) { Cache xaCache = cacheManager.getCache("xaCache", Long.class, String.class); diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/configuration/XAStoreConfiguration.java b/transactions/src/main/java/org/ehcache/transactions/xa/configuration/XAStoreConfiguration.java index c18a72a256..7b30dd7647 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/configuration/XAStoreConfiguration.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/configuration/XAStoreConfiguration.java @@ -21,7 +21,7 @@ /** * @author Ludovic Orban */ -public class XAStoreConfiguration implements ServiceConfiguration { +public class XAStoreConfiguration implements ServiceConfiguration { private final String uniqueXAResourceId; @@ -37,4 +37,14 @@ public String getUniqueXAResourceId() { public Class getServiceType() { return XAStore.Provider.class; } + + @Override + public String derive() { + return getUniqueXAResourceId(); + } + + @Override + public XAStoreConfiguration build(String xaResourceId) { + return new XAStoreConfiguration(xaResourceId); + } } diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java index 30c43a22ab..2a303d58fd 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java @@ -68,7 +68,6 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiFunction; import java.util.function.Consumer; @@ -769,12 +768,12 @@ public static class Provider implements WrapperStore.Provider { private final Map, CreatedStoreRef> createdStores = new ConcurrentWeakIdentityHashMap<>(); @Override - public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { + public int rank(final Set> resourceTypes, final Collection> serviceConfigs) { throw new UnsupportedOperationException("Its a Wrapper store provider, does not support regular ranking"); } @Override - public Store createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { + public Store createStore(Configuration storeConfig, ServiceConfiguration... serviceConfigs) { Set supportedTypes = EnumSet.allOf(ResourceType.Core.class); Set> configuredTypes = storeConfig.getResourcePools().getResourceTypeSet(); @@ -790,13 +789,13 @@ public Store createStore(Configuration storeConfig, ServiceCo throw new IllegalStateException("XAStore.Provider.createStore called without XAStoreConfiguration"); } - List> serviceConfigList = Arrays.asList(serviceConfigs); + List> serviceConfigList = Arrays.asList(serviceConfigs); Store.Provider underlyingStoreProvider = StoreSupport.selectStoreProvider(serviceProvider, storeConfig.getResourcePools().getResourceTypeSet(), serviceConfigList); String uniqueXAResourceId = xaServiceConfiguration.getUniqueXAResourceId(); - List> underlyingServiceConfigs = new ArrayList<>(serviceConfigList.size() + 5); // pad a bit because we add stuff + List> underlyingServiceConfigs = new ArrayList<>(serviceConfigList.size() + 5); // pad a bit because we add stuff underlyingServiceConfigs.addAll(serviceConfigList); // eviction advisor @@ -935,7 +934,7 @@ public Duration getExpiryForUpdate(K key, Supplier> oldSof Store.Configuration> underlyingStoreConfig = new StoreConfigurationImpl<>(storeConfig.getKeyType(), softLockClass, evictionAdvisor, storeConfig.getClassLoader(), expiry, storeConfig.getResourcePools(), storeConfig.getDispatcherConcurrency(), storeConfig .getKeySerializer(), softLockValueCombinedSerializer); - Store> underlyingStore = underlyingStoreProvider.createStore(underlyingStoreConfig, underlyingServiceConfigs.toArray(new ServiceConfiguration[0])); + Store> underlyingStore = underlyingStoreProvider.createStore(underlyingStoreConfig, underlyingServiceConfigs.toArray(new ServiceConfiguration[0])); // create the XA store TransactionManagerWrapper transactionManagerWrapper = transactionManagerProvider.getTransactionManagerWrapper(); @@ -1014,7 +1013,7 @@ public void stop() { } @Override - public int wrapperStoreRank(Collection> serviceConfigs) { + public int wrapperStoreRank(Collection> serviceConfigs) { XAStoreConfiguration xaServiceConfiguration = findSingletonAmongst(XAStoreConfiguration.class, serviceConfigs); if (xaServiceConfiguration == null) { // An XAStore must be configured for use diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java index 200cb10e80..a3a940631c 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java @@ -56,7 +56,7 @@ public URI getNamespace() { } @Override - public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { + public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { String localName = fragment.getLocalName(); if ("xa-store".equals(localName)) { String uniqueXAResourceId = fragment.getAttribute("unique-XAResource-id"); @@ -73,7 +73,7 @@ public Class getServiceType() { } @Override - public Element unparseServiceConfiguration(ServiceConfiguration serviceConfiguration) { + public Element unparseServiceConfiguration(ServiceConfiguration serviceConfiguration) { return unparseConfig(serviceConfiguration); } diff --git a/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java b/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java index a92cd9c2c7..168e3c0e21 100644 --- a/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java +++ b/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java @@ -20,8 +20,8 @@ import org.ehcache.Cache; import org.ehcache.CacheManager; import org.ehcache.PersistentCacheManager; -import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.Configuration; +import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.impl.config.loaderwriter.DefaultCacheLoaderWriterConfiguration; @@ -83,7 +83,7 @@ public void testSimpleXACache() throws Exception { .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) // <2> .withCache("xaCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, // <3> ResourcePoolsBuilder.heap(10)) // <4> - .add(new XAStoreConfiguration("xaCache")) // <5> + .withService(new XAStoreConfiguration("xaCache")) // <5> .build() ) .build(true); @@ -111,7 +111,7 @@ public void testNonTransactionalAccess() throws Exception { .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) // <2> .withCache("xaCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, // <3> ResourcePoolsBuilder.heap(10)) // <4> - .add(new XAStoreConfiguration("xaCache")) // <5> + .withService(new XAStoreConfiguration("xaCache")) // <5> .build() ) .build(true); @@ -143,8 +143,8 @@ public void testXACacheWithWriteThrough() throws Exception { .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) // <2> .withCache("xaCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, // <3> ResourcePoolsBuilder.heap(10)) // <4> - .add(new XAStoreConfiguration("xaCache")) // <5> - .add(new DefaultCacheLoaderWriterConfiguration(klazz, singletonMap(1L, "eins"))) // <6> + .withService(new XAStoreConfiguration("xaCache")) // <5> + .withService(new DefaultCacheLoaderWriterConfiguration(klazz, singletonMap(1L, "eins"))) // <6> .build() ) .build(true); @@ -178,7 +178,7 @@ public void testXACacheWithThreeTiers() throws Exception { .offheap(10, MemoryUnit.MB) .disk(20, MemoryUnit.MB, true) ) - .add(new XAStoreConfiguration("xaCache")) // <6> + .withService(new XAStoreConfiguration("xaCache")) // <6> .build() ) .build(true); diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/configuration/XAStoreConfigurationTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/configuration/XAStoreConfigurationTest.java new file mode 100644 index 0000000000..c57c4be428 --- /dev/null +++ b/transactions/src/test/java/org/ehcache/transactions/xa/configuration/XAStoreConfigurationTest.java @@ -0,0 +1,36 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.transactions.xa.configuration; + +import org.hamcrest.core.IsNot; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.junit.Assert.assertThat; + +public class XAStoreConfigurationTest { + + @Test + public void testDeriveDetachesProperly() { + XAStoreConfiguration configuration = new XAStoreConfiguration("foobar"); + XAStoreConfiguration derived = configuration.build(configuration.derive()); + + assertThat(derived, is(IsNot.not(sameInstance(configuration)))); + assertThat(derived.getUniqueXAResourceId(), is(configuration.getUniqueXAResourceId())); + } +} diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/integration/StatefulSerializerTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/integration/StatefulSerializerTest.java index ef2896ce32..c88b2d279c 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/integration/StatefulSerializerTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/integration/StatefulSerializerTest.java @@ -63,7 +63,7 @@ public void testXAWithStatefulSerializer() throws Exception { CacheConfigurationBuilder .newCacheConfigurationBuilder(Long.class, Person.class, ResourcePoolsBuilder.heap(5)) - .withExpiry(ExpiryPolicyBuilder.noExpiration()).add(new XAStoreConfiguration("xaCache")) + .withExpiry(ExpiryPolicyBuilder.noExpiration()).withService(new XAStoreConfiguration("xaCache")) .build()) .build(true)) { diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/UnSupportedResourceTypeTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/UnSupportedResourceTypeTest.java index c25904ffcc..e87ece536d 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/UnSupportedResourceTypeTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/UnSupportedResourceTypeTest.java @@ -48,7 +48,7 @@ public void testUnSupportedResourceType() { when(resourcePools.getResourceTypeSet()).thenReturn(resourceTypes); try { - provider.createStore(configuration, (ServiceConfiguration) null); + provider.createStore(configuration, (ServiceConfiguration) null); fail("IllegalStateException expected"); } catch (IllegalStateException e) { diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java index 3a00afd0ca..9bd50e7fed 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java @@ -1454,10 +1454,10 @@ public void testRank() throws Exception { serviceLocator.startAllServices(); - Set> xaStoreConfigs = Collections.singleton(configuration); + Set> xaStoreConfigs = Collections.singleton(configuration); assertThat(provider.wrapperStoreRank(xaStoreConfigs), is(1)); - Set> emptyConfigs = emptySet(); + Set> emptyConfigs = emptySet(); assertThat(provider.wrapperStoreRank(emptyConfigs), is(0)); } diff --git a/xml/src/main/java/org/ehcache/xml/CacheServiceConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/CacheServiceConfigurationParser.java index 49e0fef1ae..52d72aaf3a 100644 --- a/xml/src/main/java/org/ehcache/xml/CacheServiceConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/CacheServiceConfigurationParser.java @@ -34,9 +34,9 @@ public interface CacheServiceConfigurationParser { URI getNamespace(); - ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader); + ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader); Class getServiceType(); - Element unparseServiceConfiguration(ServiceConfiguration serviceConfiguration); + Element unparseServiceConfiguration(ServiceConfiguration serviceConfiguration); } diff --git a/xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java index f0b1b48d4f..94dacb3f23 100644 --- a/xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java @@ -23,7 +23,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.config.SizedResourcePoolImpl; +import org.ehcache.impl.config.SizedResourcePoolImpl; import org.ehcache.xml.exceptions.XmlConfigurationException; import org.ehcache.xml.model.CacheTemplate; import org.ehcache.xml.model.CacheType; diff --git a/xml/src/main/java/org/ehcache/xml/ServiceConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/ServiceConfigurationParser.java index f187c33525..5f53219f96 100644 --- a/xml/src/main/java/org/ehcache/xml/ServiceConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/ServiceConfigurationParser.java @@ -74,7 +74,7 @@ public CacheConfigurationBuilder parseConfiguration(CacheTemplate c if(xmlConfigurationParser == null) { throw new IllegalArgumentException("Can't find parser for namespace: " + namespace); } - cacheBuilder = cacheBuilder.add(xmlConfigurationParser.parseServiceConfiguration(element, cacheClassLoader)); + cacheBuilder = cacheBuilder.withService(xmlConfigurationParser.parseServiceConfiguration(element, cacheClassLoader)); } return cacheBuilder; diff --git a/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java b/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java index 199c3c0177..6e393655a3 100644 --- a/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java +++ b/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java @@ -20,8 +20,8 @@ import org.ehcache.config.Configuration; import org.ehcache.config.ResourcePools; import org.ehcache.config.Builder; -import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.FluentConfigurationBuilder; +import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.core.util.ClassLoading; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.xml.exceptions.XmlConfigurationException; diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParser.java index 6456db5330..4cd2eeae5b 100644 --- a/xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParser.java @@ -56,7 +56,7 @@ public CacheConfigurationBuilder parseServiceConfiguration(CacheTem .newEventListenerConfiguration(cacheEventListenerClass, eventSetToFireOn) .firingMode(EventFiring.valueOf(listener.getEventFiringMode().value())) .eventOrdering(EventOrdering.valueOf(listener.getEventOrderingMode().value())); - cacheBuilder = cacheBuilder.add(listenerBuilder); + cacheBuilder = cacheBuilder.withService(listenerBuilder); } } diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultCopierConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/service/DefaultCopierConfigurationParser.java index 2891906096..8bf44511be 100644 --- a/xml/src/main/java/org/ehcache/xml/service/DefaultCopierConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/service/DefaultCopierConfigurationParser.java @@ -36,12 +36,12 @@ public CacheConfigurationBuilder parseServiceConfiguration(CacheTem CacheConfigurationBuilder cacheBuilder) throws ClassNotFoundException { if (cacheDefinition.keyCopier() != null) { Class keyCopier = getClassForName(cacheDefinition.keyCopier(), cacheClassLoader); - cacheBuilder = cacheBuilder.add(new DefaultCopierConfiguration(keyCopier, DefaultCopierConfiguration.Type.KEY)); + cacheBuilder = cacheBuilder.withService(new DefaultCopierConfiguration(keyCopier, DefaultCopierConfiguration.Type.KEY)); } if (cacheDefinition.valueCopier() != null) { Class valueCopier = getClassForName(cacheDefinition.valueCopier(), cacheClassLoader); - cacheBuilder = cacheBuilder.add(new DefaultCopierConfiguration(valueCopier, DefaultCopierConfiguration.Type.VALUE)); + cacheBuilder = cacheBuilder.withService(new DefaultCopierConfiguration(valueCopier, DefaultCopierConfiguration.Type.VALUE)); } return cacheBuilder; diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultSerializerConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/service/DefaultSerializerConfigurationParser.java index 244a58f3a0..1ca1c1bae8 100644 --- a/xml/src/main/java/org/ehcache/xml/service/DefaultSerializerConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/service/DefaultSerializerConfigurationParser.java @@ -36,12 +36,12 @@ public CacheConfigurationBuilder parseServiceConfiguration(CacheTem CacheConfigurationBuilder cacheBuilder) throws ClassNotFoundException { if (cacheDefinition.keySerializer() != null) { Class keySerializer = getClassForName(cacheDefinition.keySerializer(), cacheClassLoader); - cacheBuilder = cacheBuilder.add(new DefaultSerializerConfiguration(keySerializer, DefaultSerializerConfiguration.Type.KEY)); + cacheBuilder = cacheBuilder.withService(new DefaultSerializerConfiguration(keySerializer, DefaultSerializerConfiguration.Type.KEY)); } if (cacheDefinition.valueSerializer() != null) { Class valueSerializer = getClassForName(cacheDefinition.valueSerializer(), cacheClassLoader); - cacheBuilder = cacheBuilder.add(new DefaultSerializerConfiguration(valueSerializer, DefaultSerializerConfiguration.Type.VALUE)); + cacheBuilder = cacheBuilder.withService(new DefaultSerializerConfiguration(valueSerializer, DefaultSerializerConfiguration.Type.VALUE)); } return cacheBuilder; diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParser.java index 8897fd61cc..daa0a5ed4b 100644 --- a/xml/src/main/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParser.java @@ -19,13 +19,11 @@ import org.ehcache.config.builders.WriteBehindConfigurationBuilder; import org.ehcache.config.builders.WriteBehindConfigurationBuilder.BatchedWriteBehindConfigurationBuilder; import org.ehcache.config.builders.WriteBehindConfigurationBuilder.UnBatchedWriteBehindConfigurationBuilder; -import org.ehcache.impl.config.loaderwriter.writebehind.DefaultWriteBehindConfiguration; import org.ehcache.spi.loaderwriter.WriteBehindConfiguration; import org.ehcache.xml.model.BaseCacheType; import org.ehcache.xml.model.CacheLoaderWriterType; import org.ehcache.xml.model.CacheTemplate; import org.ehcache.xml.model.TimeType; -import org.ehcache.xml.model.TimeUnit; import java.math.BigInteger; @@ -35,10 +33,11 @@ import static org.ehcache.xml.XmlModel.convertToXmlTimeUnit; public class DefaultWriteBehindConfigurationParser - extends SimpleCoreServiceConfigurationParser { + extends SimpleCoreServiceConfigurationParser> { + @SuppressWarnings("unchecked") public DefaultWriteBehindConfigurationParser() { - super(WriteBehindConfiguration.class, + super((Class>) (Class) WriteBehindConfiguration.class, CacheTemplate::writeBehind, config -> ofNullable(config.getBatching()).map(batching -> { BatchedWriteBehindConfigurationBuilder batchedBuilder = newBatchedWriteBehindConfiguration(batching.getMaxWriteDelay().getValue().longValue(), convertToJUCTimeUnit(batching.getMaxWriteDelay().getUnit()), batching.getBatchSize().intValue()); diff --git a/xml/src/main/java/org/ehcache/xml/service/SimpleCoreServiceConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/service/SimpleCoreServiceConfigurationParser.java index 8ee09376ec..32bf3be092 100644 --- a/xml/src/main/java/org/ehcache/xml/service/SimpleCoreServiceConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/service/SimpleCoreServiceConfigurationParser.java @@ -28,7 +28,7 @@ import java.util.function.BinaryOperator; import java.util.function.Function; -class SimpleCoreServiceConfigurationParser> implements CoreServiceConfigurationParser { +class SimpleCoreServiceConfigurationParser> implements CoreServiceConfigurationParser { private final Function extractor; private final Parser parser; @@ -77,7 +77,7 @@ public final CacheConfigurationBuilder parseServiceConfiguration(Ca if (config != null) { U configuration = parser.parse(config, cacheClassLoader); if (configuration != null) { - return cacheBuilder.add(configuration); + return cacheBuilder.withService(configuration); } } return cacheBuilder; diff --git a/xml/src/test/java/org/ehcache/xml/FancyParser.java b/xml/src/test/java/org/ehcache/xml/FancyParser.java index 794f29f63d..7f79e3eb55 100644 --- a/xml/src/test/java/org/ehcache/xml/FancyParser.java +++ b/xml/src/test/java/org/ehcache/xml/FancyParser.java @@ -42,7 +42,7 @@ public Source getXmlSchema() throws IOException { } @Override - public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { + public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { return new FooConfiguration(); } @@ -57,7 +57,7 @@ public Class getServiceType() { } @Override - public Element unparseServiceConfiguration(ServiceConfiguration serviceConfiguration) { + public Element unparseServiceConfiguration(ServiceConfiguration serviceConfiguration) { return null; } diff --git a/xml/src/test/java/org/ehcache/xml/FooConfiguration.java b/xml/src/test/java/org/ehcache/xml/FooConfiguration.java index 00fdd485ca..22cd8611b5 100644 --- a/xml/src/test/java/org/ehcache/xml/FooConfiguration.java +++ b/xml/src/test/java/org/ehcache/xml/FooConfiguration.java @@ -23,7 +23,7 @@ * * @author cdennis */ -class FooConfiguration implements ServiceConfiguration { +class FooConfiguration implements ServiceConfiguration { @Override public Class getServiceType() { diff --git a/xml/src/test/java/org/ehcache/xml/FooParser.java b/xml/src/test/java/org/ehcache/xml/FooParser.java index f4c70a65c5..c193618848 100644 --- a/xml/src/test/java/org/ehcache/xml/FooParser.java +++ b/xml/src/test/java/org/ehcache/xml/FooParser.java @@ -46,7 +46,7 @@ public Source getXmlSchema() throws IOException { } @Override - public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { + public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { return new FooConfiguration(); } @@ -56,7 +56,7 @@ public Class getServiceType() { } @Override - public Element unparseServiceConfiguration(ServiceConfiguration serviceConfiguration) { + public Element unparseServiceConfiguration(ServiceConfiguration serviceConfiguration) { try { Document document = DomUtil.createAndGetDocumentBuilder().newDocument(); return document.createElementNS(NAMESPACE.toString(), "foo:foo"); diff --git a/xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java index d945d747d3..3c5cd03aa5 100644 --- a/xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java @@ -189,7 +189,7 @@ public void testCacheEventListenerThreadPoolName() throws Exception { Configuration configuration = new XmlConfiguration(this.getClass().getResource("/configs/ehcache-cacheEventListener.xml")); CacheConfiguration template1 = configuration.getCacheConfigurations().get("template1"); DefaultCacheEventDispatcherConfiguration eventDispatcherConfig = null; - for (ServiceConfiguration serviceConfiguration : template1.getServiceConfigurations()) { + for (ServiceConfiguration serviceConfiguration : template1.getServiceConfigurations()) { if (serviceConfiguration instanceof DefaultCacheEventDispatcherConfiguration) { eventDispatcherConfig = (DefaultCacheEventDispatcherConfiguration) serviceConfiguration; } @@ -225,8 +225,8 @@ public void testThreadPools() throws Exception { cacheManager.init(); try { Cache cache = cacheManager.createCache("testThreadPools", newCacheConfigurationBuilder(String.class, String.class, heap(10)) - .add(new DefaultCacheLoaderWriterConfiguration(ThreadRememberingLoaderWriter.class)) - .add(newUnBatchedWriteBehindConfiguration().useThreadPool("small")) + .withService(new DefaultCacheLoaderWriterConfiguration(ThreadRememberingLoaderWriter.class)) + .withService(newUnBatchedWriteBehindConfiguration().useThreadPool("small")) .build()); cache.put("foo", "bar"); @@ -246,8 +246,8 @@ public void testThreadPoolsUsingDefaultPool() throws Exception { cacheManager.init(); try { Cache cache = cacheManager.createCache("testThreadPools", newCacheConfigurationBuilder(String.class, String.class, heap(10)) - .add(new DefaultCacheLoaderWriterConfiguration(ThreadRememberingLoaderWriter.class)) - .add(newUnBatchedWriteBehindConfiguration()) + .withService(new DefaultCacheLoaderWriterConfiguration(ThreadRememberingLoaderWriter.class)) + .withService(newUnBatchedWriteBehindConfiguration()) .build()); cache.put("foo", "bar"); diff --git a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java index 0b6c0c5747..e445b8cdf1 100644 --- a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java @@ -421,12 +421,12 @@ public void testDefaultSerializerConfiguration() throws Exception { assertThat(factoryConfiguration.getDefaultSerializers().get(Integer.class), Matchers.equalTo(TestSerializer4.class)); - List> orderedServiceConfigurations = new ArrayList<>(xmlConfig.getCacheConfigurations() + List> orderedServiceConfigurations = new ArrayList<>(xmlConfig.getCacheConfigurations() .get("baz") .getServiceConfigurations()); // order services by class name so the test can rely on some sort of ordering orderedServiceConfigurations.sort(Comparator.comparing(o -> o.getClass().getName())); - Iterator> it = orderedServiceConfigurations.iterator(); + Iterator> it = orderedServiceConfigurations.iterator(); DefaultSerializerConfiguration keySerializationProviderConfiguration = (DefaultSerializerConfiguration) it.next(); assertThat(keySerializationProviderConfiguration.getType(), isIn(new DefaultSerializerConfiguration.Type[] { DefaultSerializerConfiguration.Type.KEY, DefaultSerializerConfiguration.Type.VALUE })); @@ -473,8 +473,8 @@ public void testCacheCopierConfiguration() throws Exception { Matchers.>>equalTo(PersonCopier.class)); - Collection> configs = xmlConfig.getCacheConfigurations().get("baz").getServiceConfigurations(); - for(ServiceConfiguration config: configs) { + Collection> configs = xmlConfig.getCacheConfigurations().get("baz").getServiceConfigurations(); + for(ServiceConfiguration config: configs) { if(config instanceof DefaultCopierConfiguration) { DefaultCopierConfiguration copierConfig = (DefaultCopierConfiguration) config; if(copierConfig.getType() == DefaultCopierConfiguration.Type.KEY) { @@ -486,7 +486,7 @@ public void testCacheCopierConfiguration() throws Exception { } configs = xmlConfig.getCacheConfigurations().get("bak").getServiceConfigurations(); - for(ServiceConfiguration config: configs) { + for(ServiceConfiguration config: configs) { if(config instanceof DefaultCopierConfiguration) { DefaultCopierConfiguration copierConfig = (DefaultCopierConfiguration) config; if(copierConfig.getType() == DefaultCopierConfiguration.Type.KEY) { @@ -530,7 +530,7 @@ public void testWriteBehind() throws Exception { final URL resource = XmlConfigurationTest.class.getResource("/configs/writebehind-cache.xml"); XmlConfiguration xmlConfig = new XmlConfiguration(resource); - Collection> serviceConfiguration = xmlConfig.getCacheConfigurations().get("bar").getServiceConfigurations(); + Collection> serviceConfiguration = xmlConfig.getCacheConfigurations().get("bar").getServiceConfigurations(); assertThat(serviceConfiguration, IsCollectionContaining.hasItem(instanceOf(WriteBehindConfiguration.class))); @@ -538,7 +538,7 @@ public void testWriteBehind() throws Exception { assertThat(serviceConfiguration, IsCollectionContaining.hasItem(instanceOf(WriteBehindConfiguration.class))); - for (ServiceConfiguration configuration : serviceConfiguration) { + for (ServiceConfiguration configuration : serviceConfiguration) { if(configuration instanceof WriteBehindConfiguration) { BatchingConfiguration batchingConfig = ((WriteBehindConfiguration) configuration).getBatchingConfiguration(); assertThat(batchingConfig.getMaxDelay(), is(10L)); @@ -570,7 +570,7 @@ public void testCacheEventListenerThroughTemplate() throws Exception { checkListenerConfigurationExists(cacheConfig.getServiceConfigurations()); CacheConfigurationBuilder templateConfig = xmlConfig.newCacheConfigurationBuilderFromTemplate("example", Number.class, String.class); - assertThat(templateConfig.getExistingServiceConfiguration(DefaultCacheEventListenerConfiguration.class), notNullValue()); + assertThat(templateConfig.getService(DefaultCacheEventListenerConfiguration.class), notNullValue()); } @Test diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventDispatcherConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventDispatcherConfigurationParserTest.java index c698a15ada..13e669db7e 100644 --- a/xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventDispatcherConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventDispatcherConfigurationParserTest.java @@ -43,7 +43,7 @@ public void parseServiceConfiguration() throws Exception { @Test public void unparseServiceConfiguration() { CacheConfiguration cacheConfig = - newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).add(new DefaultCacheEventDispatcherConfiguration("foo")).build(); + newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(new DefaultCacheEventDispatcherConfiguration("foo")).build(); CacheType cacheType = new CacheType(); cacheType = new DefaultCacheEventDispatcherConfigurationParser().unparseServiceConfiguration(cacheConfig, cacheType); diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParserTest.java index a173bc0e24..2ec0aa4b16 100644 --- a/xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParserTest.java @@ -66,7 +66,7 @@ public void unparseServiceConfiguration() { listenerConfig.setEventFiringMode(SYNCHRONOUS); listenerConfig.setEventOrderingMode(UNORDERED); - CacheConfiguration cacheConfig = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).add(listenerConfig).build(); + CacheConfiguration cacheConfig = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(listenerConfig).build(); CacheType cacheType = new CacheType(); cacheType = new DefaultCacheEventListenerConfigurationParser().unparseServiceConfiguration(cacheConfig, cacheType); @@ -86,7 +86,7 @@ public void unparseServiceConfigurationWithInstance() { listenerConfig.setEventFiringMode(SYNCHRONOUS); listenerConfig.setEventOrderingMode(UNORDERED); - CacheConfiguration cacheConfig = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).add(listenerConfig).build(); + CacheConfiguration cacheConfig = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(listenerConfig).build(); CacheType cacheType = new CacheType(); assertThatExceptionOfType(XmlConfigurationException.class).isThrownBy(() -> new DefaultCacheEventListenerConfigurationParser().unparseServiceConfiguration(cacheConfig, cacheType)) diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParserTest.java index c436650932..740f52d293 100644 --- a/xml/src/test/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParserTest.java @@ -46,7 +46,7 @@ public void parseServiceConfiguration() throws Exception { @Test public void unparseServiceConfiguration() { CacheConfiguration cacheConfig = - newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).add(new DefaultCacheLoaderWriterConfiguration(TestCacheLoaderWriter.class)).build(); + newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(new DefaultCacheLoaderWriterConfiguration(TestCacheLoaderWriter.class)).build(); CacheType cacheType = new DefaultCacheLoaderWriterConfigurationParser().unparseServiceConfiguration(cacheConfig, new CacheType()); @@ -57,7 +57,7 @@ public void unparseServiceConfiguration() { public void unparseServiceConfigurationWithInstance() { TestCacheLoaderWriter testCacheLoaderWriter = new TestCacheLoaderWriter(); CacheConfiguration cacheConfig = - newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).add(new DefaultCacheLoaderWriterConfiguration(testCacheLoaderWriter)).build(); + newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(new DefaultCacheLoaderWriterConfiguration(testCacheLoaderWriter)).build(); assertThatExceptionOfType(XmlConfigurationException.class).isThrownBy(() -> new DefaultCacheLoaderWriterConfigurationParser().unparseServiceConfiguration(cacheConfig, new CacheType())) .withMessage("%s", "XML translation for instance based initialization for " + diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultCopierConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/service/DefaultCopierConfigurationParserTest.java index c165afff9a..00a02cc416 100644 --- a/xml/src/test/java/org/ehcache/xml/service/DefaultCopierConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/service/DefaultCopierConfigurationParserTest.java @@ -62,8 +62,8 @@ public void parseServiceConfiguration() throws Exception { public void unparseServiceConfiguration() { @SuppressWarnings({"unchecked", "rawtypes"}) CacheConfiguration cacheConfig = newCacheConfigurationBuilder(Description.class, Person.class, heap(10)) - .add(new DefaultCopierConfiguration(DescriptionCopier.class, DefaultCopierConfiguration.Type.KEY)) - .add(new DefaultCopierConfiguration(PersonCopier.class, DefaultCopierConfiguration.Type.VALUE)) + .withService(new DefaultCopierConfiguration(DescriptionCopier.class, DefaultCopierConfiguration.Type.KEY)) + .withService(new DefaultCopierConfiguration(PersonCopier.class, DefaultCopierConfiguration.Type.VALUE)) .build(); CacheType cacheType = new CacheType(); @@ -90,7 +90,7 @@ public void unparseServiceConfigurationWithInstance() { new DefaultCopierConfiguration<>(personCopier, DefaultCopierConfiguration.Type.VALUE); CacheConfiguration cacheConfig = newCacheConfigurationBuilder(Description.class, Person.class, heap(10)) - .add(config1).add(config2).build(); + .withService(config1).withService(config2).build(); CacheType cacheType = new CacheType(); CacheEntryType keyType = new CacheEntryType(); diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParserTest.java index 5faea257e7..8de81e8c9a 100644 --- a/xml/src/test/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParserTest.java @@ -47,7 +47,7 @@ public void parseServiceConfiguration() throws Exception { @Test public void unparseServiceConfiguration() { CacheConfiguration cacheConfig = - newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).add(new DefaultResilienceStrategyConfiguration(TestResilienceStrategy.class)).build(); + newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(new DefaultResilienceStrategyConfiguration(TestResilienceStrategy.class)).build(); CacheType cacheType = new DefaultResilienceStrategyConfigurationParser().unparseServiceConfiguration(cacheConfig, new CacheType()); assertThat(cacheType.getResilience()).isEqualTo(TestResilienceStrategy.class.getName()); @@ -58,7 +58,7 @@ public void unparseServiceConfiguration() { public void unparseServiceConfigurationWithInstance() { TestResilienceStrategy testObject = new TestResilienceStrategy<>(); CacheConfiguration cacheConfig = - newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).add(new DefaultResilienceStrategyConfiguration(testObject)).build(); + newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(new DefaultResilienceStrategyConfiguration(testObject)).build(); assertThatExceptionOfType(XmlConfigurationException.class).isThrownBy(() -> new DefaultResilienceStrategyConfigurationParser().unparseServiceConfiguration(cacheConfig, new CacheType())) .withMessage("%s", "XML translation for instance based initialization for " + diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultSerializerConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/service/DefaultSerializerConfigurationParserTest.java index f72c030db9..7afffe6edf 100644 --- a/xml/src/test/java/org/ehcache/xml/service/DefaultSerializerConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/service/DefaultSerializerConfigurationParserTest.java @@ -61,8 +61,8 @@ public void parseServiceConfiguration() throws Exception { public void unparseServiceConfiguration() { @SuppressWarnings({"unchecked", "rawtypes"}) CacheConfiguration cacheConfig = newCacheConfigurationBuilder(Description.class, Person.class, heap(10)) - .add(new DefaultSerializerConfiguration(TestSerializer3.class, DefaultSerializerConfiguration.Type.KEY)) - .add(new DefaultSerializerConfiguration(TestSerializer4.class, DefaultSerializerConfiguration.Type.VALUE)) + .withService(new DefaultSerializerConfiguration(TestSerializer3.class, DefaultSerializerConfiguration.Type.KEY)) + .withService(new DefaultSerializerConfiguration(TestSerializer4.class, DefaultSerializerConfiguration.Type.VALUE)) .build(); CacheType cacheType = new CacheType(); @@ -87,7 +87,7 @@ public void unparseServiceConfigurationWithInstance() { DefaultSerializerConfiguration config1 = new DefaultSerializerConfiguration<>(testSerializer3, DefaultSerializerConfiguration.Type.KEY); DefaultSerializerConfiguration config2 = new DefaultSerializerConfiguration<>(testSerializer4, DefaultSerializerConfiguration.Type.VALUE); CacheConfiguration cacheConfig = newCacheConfigurationBuilder(Description.class, Person.class, heap(10)) - .add(config1).add(config2).build(); + .withService(config1).withService(config2).build(); CacheType cacheType = new CacheType(); CacheEntryType keyType = new CacheEntryType(); diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultSizeOfEngineConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/service/DefaultSizeOfEngineConfigurationParserTest.java index 023de7234d..07a4f16365 100644 --- a/xml/src/test/java/org/ehcache/xml/service/DefaultSizeOfEngineConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/service/DefaultSizeOfEngineConfigurationParserTest.java @@ -64,7 +64,7 @@ public void parseServiceConfiguration() throws Exception { @Test public void unparseServiceConfiguration() { CacheConfiguration cacheConfig = - newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).add(new DefaultSizeOfEngineConfiguration(123, MemoryUnit.MB, 987)).build(); + newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(new DefaultSizeOfEngineConfiguration(123, MemoryUnit.MB, 987)).build(); CacheType cacheType = new CacheType(); cacheType = new DefaultSizeOfEngineConfigurationParser().unparseServiceConfiguration(cacheConfig, cacheType); diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParserTest.java index 180e37c82c..92e02443ed 100644 --- a/xml/src/test/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParserTest.java @@ -65,10 +65,10 @@ public void parseServiceConfigurationBatching() throws Exception { @Test public void unparseServiceConfigurationBatched() { - WriteBehindConfiguration writeBehindConfiguration = + WriteBehindConfiguration writeBehindConfiguration = WriteBehindConfigurationBuilder.newBatchedWriteBehindConfiguration(123, TimeUnit.SECONDS, 987) .enableCoalescing().concurrencyLevel(8).useThreadPool("foo").queueSize(16).build(); - CacheConfiguration cacheConfig = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).add(writeBehindConfiguration).build(); + CacheConfiguration cacheConfig = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(writeBehindConfiguration).build(); CacheType cacheType = new CacheType(); cacheType = new DefaultWriteBehindConfigurationParser().unparseServiceConfiguration(cacheConfig, cacheType); diff --git a/xml/src/test/java/org/ehcache/xml/service/OffHeapDiskStoreConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/service/OffHeapDiskStoreConfigurationParserTest.java index 2a52c13955..0cd20ce318 100644 --- a/xml/src/test/java/org/ehcache/xml/service/OffHeapDiskStoreConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/service/OffHeapDiskStoreConfigurationParserTest.java @@ -44,7 +44,7 @@ public void parseServiceConfiguration() throws Exception { @Test public void unparseServiceConfiguration() { CacheConfiguration cacheConfig = - newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).add(new OffHeapDiskStoreConfiguration("foo", 4, 8)).build(); + newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(new OffHeapDiskStoreConfiguration("foo", 4, 8)).build(); CacheType cacheType = new CacheType(); cacheType = new OffHeapDiskStoreConfigurationParser().unparseServiceConfiguration(cacheConfig, cacheType); From 5ba3f96b98866723b6adf4018a5affc350b799a9 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 8 Apr 2019 10:55:14 -0400 Subject: [PATCH 134/372] Issue 2613 : Documentation --- .../client/docs/ConfigurationDerivation.java | 101 ++++++ docs/src/docs/asciidoc/user/common.adoc | 1 + .../src/docs/asciidoc/user/config-derive.adoc | 302 ++++++++++++++++++ .../docs/asciidoc/user/getting-started.adoc | 5 +- docs/src/docs/asciidoc/user/index.adoc | 8 +- docs/src/docs/asciidoc/user/menu.adoc | 2 + .../ehcache/docs/ConfigurationDerivation.java | 226 +++++++++++++ 7 files changed, 636 insertions(+), 9 deletions(-) create mode 100644 clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java create mode 100644 docs/src/docs/asciidoc/user/config-derive.adoc create mode 100644 impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java new file mode 100644 index 0000000000..621b27eac0 --- /dev/null +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java @@ -0,0 +1,101 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered.client.docs; + +import org.ehcache.clustered.client.config.ClusteredResourceType; +import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; +import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; +import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; +import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; +import org.ehcache.clustered.common.Consistency; +import org.ehcache.config.Configuration; +import org.ehcache.config.FluentConfigurationBuilder; +import org.ehcache.config.ResourcePool; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.ConfigurationBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; +import org.ehcache.core.spi.service.ServiceUtils; +import org.ehcache.impl.config.event.DefaultCacheEventListenerConfiguration; +import org.ehcache.impl.config.resilience.DefaultResilienceStrategyConfiguration; +import org.hamcrest.core.Is; +import org.hamcrest.core.IsCollectionContaining; +import org.hamcrest.core.IsInstanceOf; +import org.hamcrest.core.IsNot; +import org.junit.Assert; +import org.junit.Test; + +import java.net.URI; +import java.util.List; +import java.util.stream.Collectors; + +public class ConfigurationDerivation { + + @Test + public void removingServices() { + Configuration configuration = ConfigurationBuilder.newConfigurationBuilder() + .withService(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://example.com/myCacheManager"))) + .withCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, + ResourcePoolsBuilder.heap(1000).with(ClusteredResourcePoolBuilder.clusteredDedicated("offheap", 128, MemoryUnit.MB)))) + .build(); + + //tag::removeService[] + Configuration withoutClustering = configuration.derive() + .updateCaches(cache -> cache // <1> + .withoutServices(ClusteredStoreConfiguration.class) // <2> + .updateResourcePools(existing -> { + ResourcePoolsBuilder poolsBuilder = ResourcePoolsBuilder.newResourcePoolsBuilder(); // <3> + for (ResourcePool pool : existing.getResourceTypeSet().stream() // <4> + .filter(p -> !(p instanceof ClusteredResourceType)) // <5> + .map(existing::getPoolForResource) + .toArray(ResourcePool[]::new)) { + poolsBuilder = poolsBuilder.with(pool); // <6> + } + return poolsBuilder.build(); + })) + .withoutServices(ClusteringServiceConfiguration.class) // <7> + .build(); + //end::removeService[] + + Assert.assertThat(withoutClustering.getServiceCreationConfigurations(), IsNot.not(IsCollectionContaining.hasItem( + IsInstanceOf.instanceOf(ClusteringServiceConfiguration.class)))); + } + + @Test + public void updateService() { + Configuration configuration = ConfigurationBuilder.newConfigurationBuilder() + .withCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10)) + .withService(new ClusteredStoreConfiguration(Consistency.STRONG))) + .build(); + + //tag::updateService[] + Configuration changedConsistency = configuration.derive() + .updateCache("cache", cache -> cache.updateServices( + ClusteredStoreConfiguration.class, + existing -> Consistency.EVENTUAL) + ) + .build(); + //end::updateService[] + + Assert.assertThat(ServiceUtils.findSingletonAmongst(ClusteredStoreConfiguration.class, + configuration.getCacheConfigurations().get("cache").getServiceConfigurations()).getConsistency(), Is.is(Consistency.STRONG)); + + Assert.assertThat(ServiceUtils.findSingletonAmongst(ClusteredStoreConfiguration.class, + changedConsistency.getCacheConfigurations().get("cache").getServiceConfigurations()).getConsistency(), Is.is(Consistency.EVENTUAL)); + } + +} diff --git a/docs/src/docs/asciidoc/user/common.adoc b/docs/src/docs/asciidoc/user/common.adoc index 93311263e2..0a1860612e 100644 --- a/docs/src/docs/asciidoc/user/common.adoc +++ b/docs/src/docs/asciidoc/user/common.adoc @@ -1,6 +1,7 @@ --- --- ifndef::sourcedir37[] +:version: 3.7 :notBuildingForSite: true ifdef::basebackend-html[:outfilesuffix: .html] :source-highlighter: coderay diff --git a/docs/src/docs/asciidoc/user/config-derive.adoc b/docs/src/docs/asciidoc/user/config-derive.adoc new file mode 100644 index 0000000000..bf860630fa --- /dev/null +++ b/docs/src/docs/asciidoc/user/config-derive.adoc @@ -0,0 +1,302 @@ +--- +--- += Configuration Derivation +ifndef::sourcedir37[] +include::common.adoc[] +endif::sourcedir37[] + +ifdef::notBuildingForSite[] +include::menu.adoc[] +endif::notBuildingForSite[] + +== Principles + +The configuration derivation features allows a new Ehcache configuration object to be derived via a transformation on +an existing configuration object. This can be useful for: + + * pre-processing an externally sourced configuration, adding additional settings before creating the cache manager. + * processing the configuration of an existing cache manager to generate a new configuration. + +The basis of the configuration derivation API is the `Configuration.derive()` method that generates a builder seeded +with the configurations values + +[source,java,indent=0] +---- +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=deriveContract] +---- +<1> Creates a builder seeded with the configuration's state. +<2> Configurations built using the builder are then functionally identical to the original configuration. + +== Core Configuration Changes + +The configuration builder returned by the derive method provide direct methods for modifying core configuration concepts: + +.setting a custom classloader: +[source,java,indent=0] +---- +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=customClassLoader] +---- + +.adding a cache: +[source,java,indent=0] +---- +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withCache] +---- +[cols=".^~a,^.^~d,.^~a"] +|=== +|[source,xml] +---- + + +---- +|→ +|[source,xml] +---- + + + Long.class + Object.class + 10 + + +---- +|=== + +.removing a cache: +[source,java,indent=0] +---- +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withoutCache] +---- +[cols=".^~a,^.^~d,.^~a"] +|=== +|[source,xml] +---- + + + Long.class + Object.class + 10 + + +---- +|→ +|[source,xml] +---- + + +---- +|=== + +Updating a cache configuration uses a `UnaryOperator` that is run against a cache configuration +builder seeded using the existing cache configuration. + +.updating a cache, by adding a resource: +[source,java,indent=0] +---- +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=updateCache] +---- +[cols=".^~a,^.^~d,.^~a"] +|=== +|[source,xml] +---- + + + Long.class + Object.class + 10 + + +---- +|→ +|[source,xml] +---- + + + Long.class + Object.class + + 10 + 100 + + + +---- +|=== + +== Extended Configuration Changes + +Ehcache is a pluggable system, so modifying many of the more complex configurations requires modifying both service +creation configurations and service configurations: + +.adding a service creation configuration (constraining the default thread pool) +[source,java,indent=0] +---- +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withServiceCreation] +---- +[cols=".^~a,^.^~d,.^~a"] +|=== +|[source,xml] +---- + + +---- +|→ +|[source,xml] +---- + + + + + +---- +|=== + +.updating a service creation configuration (changing the persistence path) +[source,java,indent=0] +---- +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=updateServiceCreation] +---- +[cols=".^~a,^.^~d,.^~a"] +|=== +|[source,xml] +---- + + + +---- +|→ +|[source,xml] +---- + + + +---- +|=== + +.adding a service configuration (setting a resilience strategy) +[source,java,indent=0] +---- +include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withService] +---- +[cols=".^~a,^.^~d,.^~a"] +|=== +|[source,xml] +---- + + + Long.class + Object.class + 10 + + +---- +|→ +|[source,xml] +---- + + + Long.class + Object.class + 10 + + com.example.ThrowingResilienceStrategy + + + +---- +|=== + +.updating a service configuration (changing a clustered cache's consistency) +[source,java,indent=0] +---- +include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java[tag=updateService] +---- +[cols=".^~a,^.^~d,.^~a"] +|=== +|[source,xml] +---- + + + + + + + + + + 50 + + + + +---- +|→ +|[source,xml] +---- + + + + + + + + + + 50 + + + + +---- +|=== + +=== Removing a service +Removing a service often involves removing both service creation and a service configuration instances since a service +instance its configuration are usually strongly coupled: + +.removing a service (making a cache manager non-clustered) +[source,java,indent=0] +---- +include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java[tag=removeService] +---- +<1> From all cache configurations... +<2> remove any existing `ClusteredStoreConfiguration` instances. +<3> Create a new resource pool builder... +<4> From the existing resource pools... +<5> filter out any clustered resources. +<6> Add all remaining pools to the new resource pools instance +<7> Finally remove the clustering service creation configuration + +[cols=".^~a,^.^~d,.^~a"] +|=== +|[source,xml] +---- + + + + + + + + + + 100 + 50 + + + + +---- +|→ +|[source,xml] +---- + + + + 100 + + + +---- +|=== diff --git a/docs/src/docs/asciidoc/user/getting-started.adoc b/docs/src/docs/asciidoc/user/getting-started.adoc index 7e0d5e9e45..f52d06de15 100644 --- a/docs/src/docs/asciidoc/user/getting-started.adoc +++ b/docs/src/docs/asciidoc/user/getting-started.adoc @@ -1,7 +1,4 @@ ---- -version: 3.7 ---- -= Ehcache 3.7 Documentation += Ehcache {version} Documentation ifndef::sourcedir37[] include::common.adoc[] endif::sourcedir37[] diff --git a/docs/src/docs/asciidoc/user/index.adoc b/docs/src/docs/asciidoc/user/index.adoc index 78fb564d27..46900240ce 100644 --- a/docs/src/docs/asciidoc/user/index.adoc +++ b/docs/src/docs/asciidoc/user/index.adoc @@ -1,7 +1,4 @@ ---- -version: 3.7 ---- -= Ehcache 3.7 Documentation Overview += Ehcache {version} Documentation Overview ifndef::sourcedir37[] include::common.adoc[] endif::sourcedir37[] @@ -12,7 +9,7 @@ endif::notBuildingForSite[] == Table of Contents -The Table of Contents provides an overview of the Ehcache 3.7 documentation on this site. +The Table of Contents provides an overview of the Ehcache {version} documentation on this site. Each topic below corresponds to a menu item at the left. === Basic Topics @@ -57,5 +54,6 @@ Each topic below corresponds to a menu item at the left. |link:eviction-advisor{outfilesuffix}[Eviction Advisor]|Affecting the way entries are chosen for eviction |link:class-loading{outfilesuffix}[Class loading]|Ehcache and `ClassLoader` interactions |link:osgi{outfilesuffix}[OSGi Deployment]|How to use Ehcache in an OSGi Environment +|link:config-derive{outfilesuffix}[Configuration Derivation]|How to derive a new configuration from an existing one |link:performance{outfilesuffix}[Performance Tuning]|Ehcache Performance Tuning |=== diff --git a/docs/src/docs/asciidoc/user/menu.adoc b/docs/src/docs/asciidoc/user/menu.adoc index 0a1c35ac32..b6623d5837 100644 --- a/docs/src/docs/asciidoc/user/menu.adoc +++ b/docs/src/docs/asciidoc/user/menu.adoc @@ -26,6 +26,8 @@ Advanced topics:: - link:./cache-event-listeners{outfilesuffix}[Cache Event Listeners] - link:./eviction-advisor{outfilesuffix}[Eviction Advisor] - link:./class-loading{outfilesuffix}[Class loading in Ehcache] +- link:./osgi{outfilesuffix}[OSGi Deployment] +- link:./config-derive{outfilesuffix}[Configuration Derivation] - link:./performance{outfilesuffix}[Performance Tuning] Not published:: diff --git a/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java b/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java new file mode 100644 index 0000000000..381ef9cc0c --- /dev/null +++ b/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java @@ -0,0 +1,226 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.docs; + +import org.ehcache.config.Configuration; +import org.ehcache.config.FluentConfigurationBuilder; +import org.ehcache.config.ResourceType; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.ConfigurationBuilder; +import org.ehcache.config.builders.ExpiryPolicyBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; +import org.ehcache.core.spi.service.ServiceUtils; +import org.ehcache.core.util.ClassLoading; +import org.ehcache.impl.config.executor.PooledExecutionServiceConfiguration; +import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; +import org.ehcache.impl.config.resilience.DefaultResilienceStrategyConfiguration; +import org.ehcache.impl.config.serializer.DefaultSerializationProviderConfiguration; +import org.ehcache.impl.serialization.PlainJavaSerializer; +import org.ehcache.spi.serialization.Serializer; +import org.ehcache.spi.serialization.SerializerException; +import org.ehcache.test.MockitoUtil; +import org.hamcrest.collection.IsEmptyCollection; +import org.hamcrest.collection.IsIterableContainingInAnyOrder; +import org.hamcrest.collection.IsMapContaining; +import org.hamcrest.core.Is; +import org.hamcrest.core.IsCollectionContaining; +import org.hamcrest.core.IsInstanceOf; +import org.hamcrest.core.IsNot; +import org.hamcrest.core.IsNull; +import org.hamcrest.core.IsSame; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.time.Duration; +import java.util.Date; + +public class ConfigurationDerivation { + + @Test + public void identityTransform() { + Configuration configuration = ConfigurationBuilder.newConfigurationBuilder() + .withCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10)) + .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(10)))) + .build(); + + // tag::deriveContract[] + FluentConfigurationBuilder derivedBuilder = configuration.derive(); // <1> + Configuration configurationCopy = derivedBuilder.build(); // <2> + // end::deriveContract[] + } + + @Test + public void withCustomClassLoader() { + Configuration configuration = ConfigurationBuilder.newConfigurationBuilder() + .withCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))) + .build(); + + ClassLoader classLoader = MockitoUtil.mock(ClassLoader.class); + + // tag::customClassLoader[] + Configuration withClassLoader = configuration.derive() + .withClassLoader(classLoader) + .build(); + // end::customClassLoader[] + + Assert.assertThat(configuration.getClassLoader(), Is.is(IsSame.sameInstance(ClassLoading.getDefaultClassLoader()))); + Assert.assertThat(withClassLoader.getClassLoader(), Is.is(IsSame.sameInstance(classLoader))); + } + + @Test + public void withCache() { + Configuration configuration = ConfigurationBuilder.newConfigurationBuilder().build(); + + //tag::withCache[] + Configuration withCache = configuration.derive() + .withCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder( + Long.class, String.class, ResourcePoolsBuilder.heap(10))) + .build(); + //end::withCache[] + + Assert.assertThat(configuration.getCacheConfigurations().keySet(), Is.is(IsEmptyCollection.empty())); + Assert.assertThat(withCache.getCacheConfigurations().keySet(), IsIterableContainingInAnyOrder.containsInAnyOrder("cache")); + } + + @Test + public void withoutCache() { + Configuration configuration = ConfigurationBuilder.newConfigurationBuilder() + .withCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))) + .build(); + + //tag::withoutCache[] + Configuration withoutCache = configuration.derive() + .withoutCache("cache") + .build(); + //end::withoutCache[] + + Assert.assertThat(configuration.getCacheConfigurations().keySet(), IsIterableContainingInAnyOrder.containsInAnyOrder("cache")); + Assert.assertThat(withoutCache.getCacheConfigurations().keySet(), Is.is(IsEmptyCollection.empty())); + } + + @Test + public void updateCache() { + Configuration configuration = ConfigurationBuilder.newConfigurationBuilder() + .withCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))) + .build(); + + //tag::updateCache[] + Configuration withOffHeap = configuration.derive() + .updateCache("cache", cache -> cache.updateResourcePools( + resources -> ResourcePoolsBuilder.newResourcePoolsBuilder(resources) + .offheap(100, MemoryUnit.MB) + .build())) + .build(); + //end::updateCache[] + + Assert.assertThat(configuration.getCacheConfigurations().get("cache").getResourcePools().getResourceTypeSet(), IsIterableContainingInAnyOrder.containsInAnyOrder(ResourceType.Core.HEAP)); + Assert.assertThat(withOffHeap.getCacheConfigurations().get("cache").getResourcePools().getResourceTypeSet(), IsIterableContainingInAnyOrder.containsInAnyOrder(ResourceType.Core.HEAP, ResourceType.Core.OFFHEAP)); + } + + @Test + public void withServiceCreation() { + Configuration configuration = ConfigurationBuilder.newConfigurationBuilder() + .withCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))) + .build(); + + //tag::withServiceCreation[] + Configuration withBoundedThreads = configuration.derive() + .withService(new PooledExecutionServiceConfiguration() + .addDefaultPool("default", 1, 16)) + .build(); + //end::withServiceCreation[] + + Assert.assertThat(configuration.getServiceCreationConfigurations(), IsNot.not(IsCollectionContaining.hasItem(IsInstanceOf.instanceOf(PooledExecutionServiceConfiguration.class)))); + PooledExecutionServiceConfiguration serviceCreationConfiguration = ServiceUtils.findSingletonAmongst(PooledExecutionServiceConfiguration.class, withBoundedThreads.getServiceCreationConfigurations()); + Assert.assertThat(serviceCreationConfiguration.getDefaultPoolAlias(), Is.is("default")); + Assert.assertThat(serviceCreationConfiguration.getPoolConfigurations().keySet(), IsIterableContainingInAnyOrder.containsInAnyOrder("default")); + PooledExecutionServiceConfiguration.PoolConfiguration pool = serviceCreationConfiguration.getPoolConfigurations().get("default"); + Assert.assertThat(pool.minSize(), Is.is(1)); + Assert.assertThat(pool.maxSize(), Is.is(16)); + } + + @Test + public void updateServiceCreation() { + @SuppressWarnings("unchecked") + Configuration configuration = ConfigurationBuilder.newConfigurationBuilder() + .withService(new DefaultPersistenceConfiguration(new File("temp"))) + .withCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))) + .build(); + + //tag::updateServiceCreation[] + Configuration withUpdatedPersistence = configuration.derive() + .updateServices(DefaultPersistenceConfiguration.class, + existing -> new File("/var/persistence/path")) + .build(); + //end::updateServiceCreation[] + + DefaultPersistenceConfiguration initialPersistenceConfiguration = ServiceUtils.findSingletonAmongst(DefaultPersistenceConfiguration.class, configuration.getServiceCreationConfigurations()); + Assert.assertThat(initialPersistenceConfiguration.getRootDirectory(), Is.is(new File("temp"))); + + DefaultPersistenceConfiguration revisedPersistenceConfiguration = ServiceUtils.findSingletonAmongst(DefaultPersistenceConfiguration.class, withUpdatedPersistence.getServiceCreationConfigurations()); + Assert.assertThat(revisedPersistenceConfiguration.getRootDirectory(), Is.is(new File("/var/persistence/path"))); + } + + @Test + public void withService() { + Configuration configuration = ConfigurationBuilder.newConfigurationBuilder() + .withCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))) + .build(); + + //tag::withService[] + Configuration withThrowingStrategy = configuration.derive() + .updateCache("cache", existing -> existing.withService( + new DefaultResilienceStrategyConfiguration(new ThrowingResilienceStrategy<>()) + )) + .build(); + //end::withService[] + + + Assert.assertThat(configuration.getServiceCreationConfigurations(), IsNot.not(IsCollectionContaining.hasItem( + IsInstanceOf.instanceOf(DefaultResilienceStrategyConfiguration.class)))); + + DefaultResilienceStrategyConfiguration resilienceStrategyConfiguration = + ServiceUtils.findSingletonAmongst(DefaultResilienceStrategyConfiguration.class, + withThrowingStrategy.getCacheConfigurations().get("cache").getServiceConfigurations()); + Assert.assertThat(resilienceStrategyConfiguration.getInstance(), IsInstanceOf.instanceOf(ThrowingResilienceStrategy.class)); + } + + public static final class OptimizedDateSerializer implements Serializer { + + public OptimizedDateSerializer(ClassLoader classLoader) {} + + @Override + public ByteBuffer serialize(Date object) throws SerializerException { + ByteBuffer buffer = ByteBuffer.allocate(8); + return (ByteBuffer) buffer.putLong(object.getTime()).flip(); + } + + @Override + public Date read(ByteBuffer binary) throws ClassNotFoundException, SerializerException { + return new Date(binary.getLong()); + } + + @Override + public boolean equals(Date object, ByteBuffer binary) throws ClassNotFoundException, SerializerException { + return binary.getLong() == object.getTime(); + } + } +} From c63c4b655279f7739b5201b5f7844ab2909f3195 Mon Sep 17 00:00:00 2001 From: Tathagata Chakraborty Date: Thu, 16 May 2019 14:02:06 +0530 Subject: [PATCH 135/372] Version bump --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index c40ab04242..636eede533 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.3-pre1 +terracottaPlatformVersion = 5.7.3-pre2 terracottaApisVersion = 1.6.1 -terracottaCoreVersion = 5.6.4-pre1 +terracottaCoreVersion = 5.6.4-pre2 terracottaPassthroughTestingVersion = 1.6.1 # Test lib versions From 20ec19c308629cb24fa7365f17f0869721fdbaa2 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 21 May 2019 19:21:18 -0400 Subject: [PATCH 136/372] Fixes #2652 : Ensure expiry events are fired correctly when triggered by 'real' operations --- clustered/client/build.gradle | 1 + .../client/internal/store/ClusteredStore.java | 44 ++-- .../clustered/client/ClusteredEventsTest.java | 205 ++++++++++++++++++ ...tedCombinationsWithClusteredCacheTest.java | 27 --- .../store/ClusteredStoreEventsTest.java | 79 ++++--- 5 files changed, 268 insertions(+), 88 deletions(-) create mode 100644 clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java diff --git a/clustered/client/build.gradle b/clustered/client/build.gradle index 941c7151ea..bf9bcf2598 100644 --- a/clustered/client/build.gradle +++ b/clustered/client/build.gradle @@ -45,4 +45,5 @@ dependencies { } testImplementation 'org.xmlunit:xmlunit-core:2.6.0' testImplementation 'org.xmlunit:xmlunit-matchers:2.6.0' + testImplementation "org.awaitility:awaitility:3.1.6" } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index 0da2ae3234..a6d702553c 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -36,6 +36,7 @@ import org.ehcache.clustered.common.internal.store.operations.PutOperation; import org.ehcache.clustered.common.internal.store.operations.RemoveOperation; import org.ehcache.clustered.common.internal.store.operations.ReplaceOperation; +import org.ehcache.clustered.common.internal.store.operations.TimestampOperation; import org.ehcache.clustered.common.internal.store.operations.codecs.OperationsCodec; import org.ehcache.config.ResourceType; import org.ehcache.config.builders.ExpiryPolicyBuilder; @@ -629,10 +630,6 @@ private ClusteredStore createStoreInternal(Configuration stor // Forget it. Never. throw new IllegalStateException("Synchronous CacheEventListener is not supported with clustered tiers"); } - if (eventListenerConfiguration.orderingMode() == EventOrdering.ORDERED) { - // this could be supported, but at least expiration events would need to be reordered - throw new IllegalStateException("Ordered CacheEventListener is not supported with clustered tiers"); - } } if (clusteringService == null) { @@ -774,30 +771,23 @@ public void onAppend(Chain beforeAppend, ByteBuffer appended) { K key = operation.getKey(); PutOperation resolvedBefore = clusteredStore.resolver.resolve(beforeAppend, key); - PutOperation resolvedAfter = clusteredStore.resolver.applyOperation(key, resolvedBefore, operation); + PutOperation resolvedNow = clusteredStore.resolver.applyOperation(key, resolvedBefore, + new TimestampOperation<>(key, operation.timeStamp())); + PutOperation resolvedAfter = clusteredStore.resolver.applyOperation(key, resolvedNow, operation); + + /* + * If the old value was expired then we *must* fire expiry before the other event + */ + if (resolvedBefore != null && resolvedNow == null) { + sink.expired(key, resolvedBefore::getValue); + } - if (resolvedBefore == null) { - if (resolvedAfter == null) { - //a non-event - } else { - sink.created(key, resolvedAfter.getValue()); - } - } else { - if (resolvedAfter != null) { - if (resolvedAfter == resolvedBefore) { - //non-event - } else { - sink.updated(key, resolvedBefore::getValue, resolvedAfter.getValue()); - } - } else { - switch (operation.getOpCode()) { - case TIMESTAMP: - sink.expired(key, resolvedBefore::getValue); - break; - default: - sink.removed(key, resolvedBefore::getValue); - } - } + if (resolvedNow == null && resolvedAfter != null) { + sink.created(key, resolvedAfter.getValue()); + } else if (resolvedNow != null && resolvedAfter == null) { + sink.removed(key, resolvedNow::getValue); + } else if (resolvedAfter != resolvedNow) { + sink.updated(key, resolvedNow::getValue, resolvedAfter.getValue()); } clusteredStore.storeEventDispatcher.releaseEventSink(sink); } catch (Exception e) { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java new file mode 100644 index 0000000000..b24bca5f4f --- /dev/null +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java @@ -0,0 +1,205 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered.client; + +import org.ehcache.Cache; +import org.ehcache.PersistentCacheManager; +import org.ehcache.clustered.client.internal.UnitTestConnectionService; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.config.units.MemoryUnit; +import org.ehcache.event.CacheEvent; +import org.ehcache.event.EventFiring; +import org.ehcache.event.EventOrdering; +import org.ehcache.event.EventType; +import org.ehcache.impl.internal.TimeSourceConfiguration; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import java.net.URI; +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import static java.util.EnumSet.allOf; +import static org.awaitility.Awaitility.await; +import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; +import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; +import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; +import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; +import static org.ehcache.config.builders.ExpiryPolicyBuilder.timeToLiveExpiration; +import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.collection.IsIterableContainingInOrder.contains; +import static org.hamcrest.core.IsNull.nullValue; +import static org.junit.Assert.assertThat; + +public class ClusteredEventsTest { + + private static final URI CLUSTER_URI = URI.create("terracotta://example.com:9540/my-application"); + + @Rule + public final TestName runningTest = new TestName(); + + @Before + public void definePassthroughServer() { + UnitTestConnectionService.add(CLUSTER_URI, + new UnitTestConnectionService.PassthroughServerBuilder() + .resource("primary-server-resource", 32, MemoryUnit.MB) + .build()); + } + + @After + public void removePassthroughServer() { + UnitTestConnectionService.remove(CLUSTER_URI); + } + + @Test + public void testNonExpiringEventSequence() { + CacheManagerBuilder clusteredCacheManagerBuilder = + newCacheManagerBuilder() + .with(cluster(CLUSTER_URI).autoCreate().defaultServerResource("primary-server-resource")) + .withCache(runningTest.getMethodName(), newCacheConfigurationBuilder(Long.class, String.class, + newResourcePoolsBuilder().with(clusteredDedicated(16, MemoryUnit.MB)))); + + try (PersistentCacheManager driver = clusteredCacheManagerBuilder.build(true)) { + Cache driverCache = driver.getCache(runningTest.getMethodName(), Long.class, String.class); + try (PersistentCacheManager observer = clusteredCacheManagerBuilder.build(true)) { + Cache observerCache = observer.getCache(runningTest.getMethodName(), Long.class, String.class); + + List> driverEvents = new ArrayList<>(); + driverCache.getRuntimeConfiguration().registerCacheEventListener(driverEvents::add, EventOrdering.ORDERED, EventFiring.ASYNCHRONOUS, allOf(EventType.class)); + + List> observerEvents = new ArrayList<>(); + observerCache.getRuntimeConfiguration().registerCacheEventListener(observerEvents::add, EventOrdering.ORDERED, EventFiring.ASYNCHRONOUS, allOf(EventType.class)); + + + driverCache.put(1L, "foo"); + driverCache.put(1L, "bar"); + driverCache.remove(1L); + driverCache.putIfAbsent(1L, "baz"); + driverCache.replace(1L, "bat"); + driverCache.replace(1L, "bat", "bag"); + driverCache.remove(1L, "bag"); + + @SuppressWarnings("unchecked") + Matcher>> expectedSequence = contains( + created(1L, "foo"), + updated(1L, "foo", "bar"), + removed(1L, "bar"), + created(1L, "baz"), + updated(1L, "baz", "bat"), + updated(1L, "bat", "bag"), + removed(1L, "bag")); + + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + assertThat(driverEvents, expectedSequence); + assertThat(observerEvents, expectedSequence); + }); + } + } + } + + @Test + public void testExpiringEventSequence() { + TestTimeSource timeSource = new TestTimeSource(); + + CacheManagerBuilder clusteredCacheManagerBuilder = + newCacheManagerBuilder() + .using(new TimeSourceConfiguration(timeSource)) + .with(cluster(CLUSTER_URI).autoCreate().defaultServerResource("primary-server-resource")) + .withCache(runningTest.getMethodName(), newCacheConfigurationBuilder(Long.class, String.class, + newResourcePoolsBuilder().with(clusteredDedicated(16, MemoryUnit.MB))) + .withExpiry(timeToLiveExpiration(Duration.ofMillis(1000)))); + + try (PersistentCacheManager driver = clusteredCacheManagerBuilder.build(true)) { + Cache driverCache = driver.getCache(runningTest.getMethodName(), Long.class, String.class); + try (PersistentCacheManager observer = clusteredCacheManagerBuilder.build(true)) { + Cache observerCache = observer.getCache(runningTest.getMethodName(), Long.class, String.class); + + List> driverEvents = new ArrayList<>(); + driverCache.getRuntimeConfiguration().registerCacheEventListener(driverEvents::add, EventOrdering.ORDERED, EventFiring.ASYNCHRONOUS, allOf(EventType.class)); + + List> observerEvents = new ArrayList<>(); + observerCache.getRuntimeConfiguration().registerCacheEventListener(observerEvents::add, EventOrdering.ORDERED, EventFiring.ASYNCHRONOUS, allOf(EventType.class)); + + + driverCache.put(1L, "foo"); + timeSource.advanceTime(1100); + driverCache.putIfAbsent(1L, "bar"); + timeSource.advanceTime(1100); + driverCache.remove(1L); + driverCache.put(1L, "baz"); + timeSource.advanceTime(1100); + assertThat(driverCache.get(1L), nullValue()); + + @SuppressWarnings("unchecked") + Matcher>> expectedSequence = contains( + created(1L, "foo"), + expired(1L, "foo"), + created(1L, "bar"), + expired(1L, "bar"), + created(1L, "baz"), + expired(1L, "baz")); + + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + assertThat(driverEvents, expectedSequence); + assertThat(observerEvents, expectedSequence); + }); + } + } + } + + private static Matcher> created(K key, V value) { + return event(EventType.CREATED, key, null, value); + } + + private static Matcher> updated(K key, V oldValue, V newValue) { + return event(EventType.UPDATED, key, oldValue, newValue); + } + + private static Matcher> removed(K key, V value) { + return event(EventType.REMOVED, key, value, null); + } + + private static Matcher> expired(K key, V value) { + return event(EventType.EXPIRED, key, value, null); + } + + private static Matcher> event(EventType type, K key, V oldValue, V newValue) { + return new TypeSafeMatcher>() { + @Override + protected boolean matchesSafely(CacheEvent item) { + return type.equals(item.getType()) && key.equals(item.getKey()) + && Objects.equals(oldValue, item.getOldValue()) + && Objects.equals(newValue, item.getNewValue()); + } + + @Override + public void describeTo(Description description) { + description.appendText(" on '").appendValue(key).appendText("' ").appendValue(type) + .appendText(" [").appendValue(oldValue).appendText(" => ").appendValue(newValue).appendText("]"); + } + }; + } +} diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java index 87ec3b5126..887bed53dc 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java @@ -67,33 +67,6 @@ public void removePassthroughServer() throws Exception { UnitTestConnectionService.remove("terracotta://localhost/my-application"); } - @Test - public void testClusteredCacheWithOrderedEventListeners() { - CacheEventListenerConfigurationBuilder cacheEventListenerConfiguration = CacheEventListenerConfigurationBuilder - .newEventListenerConfiguration(new TestEventListener(), EventType.CREATED, EventType.UPDATED) - .ordered().asynchronous(); - - final CacheManagerBuilder clusteredCacheManagerBuilder - = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .autoCreate()); - final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); - - try { - CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, - ResourcePoolsBuilder.newResourcePoolsBuilder() - .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) - .add(cacheEventListenerConfiguration) - .build(); - - cacheManager.createCache("test", config); - fail("IllegalStateException expected"); - } catch (IllegalStateException e){ - assertThat(e.getCause().getMessage(), is("Ordered CacheEventListener is not supported with clustered tiers")); - } - cacheManager.close(); - } - @Test public void testClusteredCacheWithSynchronousEventListeners() { CacheEventListenerConfigurationBuilder cacheEventListenerConfiguration = CacheEventListenerConfigurationBuilder diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java index 96e0a38079..b9dddfd405 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java @@ -49,10 +49,13 @@ import org.ehcache.impl.serialization.StringSerializer; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.serialization.Serializer; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; import org.terracotta.connection.Connection; import java.net.URI; @@ -62,13 +65,14 @@ import java.util.Properties; import java.util.function.Supplier; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import static org.mockito.hamcrest.MockitoHamcrest.argThat; public class ClusteredStoreEventsTest { @@ -186,28 +190,22 @@ public void testOnAppend_PutAfterNothingFiresCreatedEvent() { verifyNoMoreInteractions(storeEventSink); } - @SuppressWarnings("unchecked") @Test public void testOnAppend_PutAfterPutFiresUpdatedEvent() { Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); serverCallback.onAppend(beforeAppend, op(new PutOperation<>(1L, "one-bis", testTimeSource.getTimeMillis()))); - ArgumentCaptor> supplierArgumentCaptor = ArgumentCaptor.forClass(Supplier.class); - verify(storeEventSink).updated(eq(1L), supplierArgumentCaptor.capture(), eq("one-bis")); + verify(storeEventSink).updated(eq(1L), argThat(supplies("one")), eq("one-bis")); verifyNoMoreInteractions(storeEventSink); - assertThat(supplierArgumentCaptor.getValue().get(), is("one")); } - @SuppressWarnings("unchecked") @Test public void testOnAppend_RemoveAfterPutFiresRemovedEvent() { Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); serverCallback.onAppend(beforeAppend, op(new RemoveOperation<>(1L, testTimeSource.getTimeMillis()))); - ArgumentCaptor> supplierArgumentCaptor = ArgumentCaptor.forClass(Supplier.class); - verify(storeEventSink).removed(eq(1L), supplierArgumentCaptor.capture()); + verify(storeEventSink).removed(eq(1L), argThat(supplies("one"))); verifyNoMoreInteractions(storeEventSink); - assertThat(supplierArgumentCaptor.getValue().get(), is("one")); } @Test @@ -218,16 +216,13 @@ public void testOnAppend_RemoveAfterNothingFiresNoEvent() { verifyNoMoreInteractions(storeEventSink); } - @SuppressWarnings("unchecked") @Test public void testOnAppend_ReplaceAfterPutFiresUpdatedEvent() { Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); serverCallback.onAppend(beforeAppend, op(new ReplaceOperation<>(1L, "one-bis", testTimeSource.getTimeMillis()))); - ArgumentCaptor> supplierArgumentCaptor = ArgumentCaptor.forClass(Supplier.class); - verify(storeEventSink).updated(eq(1L), supplierArgumentCaptor.capture(), eq("one-bis")); + verify(storeEventSink).updated(eq(1L), argThat(supplies("one")), eq("one-bis")); verifyNoMoreInteractions(storeEventSink); - assertThat(supplierArgumentCaptor.getValue().get(), is("one")); } @Test @@ -255,16 +250,13 @@ public void testOnAppend_PutIfAbsentAfterPutFiresNoEvent() { verifyNoMoreInteractions(storeEventSink); } - @SuppressWarnings("unchecked") @Test public void testOnAppend_SuccessfulReplaceConditionalAfterPutFiresUpdatedEvent() { Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); serverCallback.onAppend(beforeAppend, op(new ConditionalReplaceOperation<>(1L, "one", "one-bis", testTimeSource.getTimeMillis()))); - ArgumentCaptor> supplierArgumentCaptor = ArgumentCaptor.forClass(Supplier.class); - verify(storeEventSink).updated(eq(1L), supplierArgumentCaptor.capture(), eq("one-bis")); + verify(storeEventSink).updated(eq(1L), argThat(supplies("one")), eq("one-bis")); verifyNoMoreInteractions(storeEventSink); - assertThat(supplierArgumentCaptor.getValue().get(), is("one")); } @Test @@ -283,16 +275,13 @@ public void testOnAppend_ReplaceConditionalAfterNothingFiresNoEvent() { verifyNoMoreInteractions(storeEventSink); } - @SuppressWarnings("unchecked") @Test public void testOnAppend_SuccessfulRemoveConditionalAfterPutFiresUpdatedEvent() { Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); serverCallback.onAppend(beforeAppend, op(new ConditionalRemoveOperation<>(1L, "one", testTimeSource.getTimeMillis()))); - ArgumentCaptor> supplierArgumentCaptor = ArgumentCaptor.forClass(Supplier.class); - verify(storeEventSink).removed(eq(1L), supplierArgumentCaptor.capture()); + verify(storeEventSink).removed(eq(1L), argThat(supplies("one"))); verifyNoMoreInteractions(storeEventSink); - assertThat(supplierArgumentCaptor.getValue().get(), is("one")); } @Test @@ -311,17 +300,14 @@ public void testOnAppend_RemoveConditionalAfterNothingFiresNoEvent() { verifyNoMoreInteractions(storeEventSink); } - @SuppressWarnings("unchecked") @Test public void testOnAppend_timestampAfterExpiryFiresExpiredEvent() { Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "wrong-one", testTimeSource.getTimeMillis())), op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); testTimeSource.advanceTime(1100L); serverCallback.onAppend(beforeAppend, op(new TimestampOperation<>(1L, testTimeSource.getTimeMillis()))); - ArgumentCaptor> supplierArgumentCaptor = ArgumentCaptor.forClass(Supplier.class); - verify(storeEventSink).expired(eq(1L), supplierArgumentCaptor.capture()); + verify(storeEventSink).expired(eq(1L), argThat(supplies("one"))); verifyNoMoreInteractions(storeEventSink); - assertThat(supplierArgumentCaptor.getValue().get(), is("one")); } @Test @@ -341,19 +327,26 @@ public void testOnAppend_timestampAfterNoExpiryFiresNoEvent() { verifyNoMoreInteractions(storeEventSink); } - @SuppressWarnings("unchecked") + @Test + public void testOnAppend_putIfAbsentAfterExpiredPutFiresCorrectly() { + Chain beforeAppend = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis()))); + testTimeSource.advanceTime(1100L); + serverCallback.onAppend(beforeAppend, op(new PutIfAbsentOperation<>(1L, "one-bis", testTimeSource.getTimeMillis()))); + + InOrder inOrder = inOrder(storeEventSink); + inOrder.verify(storeEventSink).expired(eq(1L), argThat(supplies("one"))); + inOrder.verify(storeEventSink).created(1L, "one-bis"); + inOrder.verifyNoMoreInteractions(); + } + @Test public void testOnInvalidateHash_chainFiresEvictedEvents() { Chain evictedChain = ChainUtils.chainOf(op(new PutOperation<>(1L, "one", testTimeSource.getTimeMillis())), op(new PutOperation<>(2L, "two", testTimeSource.getTimeMillis()))); serverCallback.onInvalidateHash(1L, evictedChain); - ArgumentCaptor> supplierArgumentCaptor1 = ArgumentCaptor.forClass(Supplier.class); - ArgumentCaptor> supplierArgumentCaptor2 = ArgumentCaptor.forClass(Supplier.class); - verify(storeEventSink).evicted(eq(1L), supplierArgumentCaptor1.capture()); - verify(storeEventSink).evicted(eq(2L), supplierArgumentCaptor2.capture()); + verify(storeEventSink).evicted(eq(1L), argThat(supplies("one"))); + verify(storeEventSink).evicted(eq(2L), argThat(supplies("two"))); verifyNoMoreInteractions(storeEventSink); - assertThat(supplierArgumentCaptor1.getValue().get(), is("one")); - assertThat(supplierArgumentCaptor2.getValue().get(), is("two")); } @Test @@ -362,4 +355,22 @@ public void testOnInvalidateHash_noChainFiresNoEvent() { verifyNoMoreInteractions(storeEventSink); } + + private static Matcher> supplies(T value) { + return supplies(equalTo(value)); + } + + private static Matcher> supplies(Matcher matcher) { + return new TypeSafeMatcher>() { + @Override + protected boolean matchesSafely(Supplier item) { + return matcher.matches(item.get()); + } + + @Override + public void describeTo(Description description) { + description.appendValue(" supplier of ").appendDescriptionOf(matcher); + } + }; + } } From 04e3cb963de889bd001e78518205366a17b6a487 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Mon, 3 Jun 2019 10:28:35 -0700 Subject: [PATCH 137/372] Bump dependency versions tc-core and tc-platform --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 636eede533..5b5e8e9cc1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.3-pre2 +terracottaPlatformVersion = 5.7.3-pre3 terracottaApisVersion = 1.6.1 -terracottaCoreVersion = 5.6.4-pre2 +terracottaCoreVersion = 5.6.4-pre3 terracottaPassthroughTestingVersion = 1.6.1 # Test lib versions From 515d7a36bcdc00d542f83faee9593d8013212694 Mon Sep 17 00:00:00 2001 From: Ludovic Orban Date: Mon, 3 Jun 2019 18:05:33 +0200 Subject: [PATCH 138/372] change doc to remove note that states clustered caches don't support event listeners --- docs/src/docs/asciidoc/user/cache-event-listeners.adoc | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/src/docs/asciidoc/user/cache-event-listeners.adoc b/docs/src/docs/asciidoc/user/cache-event-listeners.adoc index 31fc3fe051..d446fd3a38 100644 --- a/docs/src/docs/asciidoc/user/cache-event-listeners.adoc +++ b/docs/src/docs/asciidoc/user/cache-event-listeners.adoc @@ -9,8 +9,6 @@ ifdef::notBuildingForSite[] include::menu.adoc[] endif::notBuildingForSite[] -NOTE: Clustering is not yet compatible with event listeners. - [[introduction]] == Introduction From bfdb993d9c00dfc260adecd1758bf2613bb4cbaa Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 4 Jun 2019 11:45:12 -0400 Subject: [PATCH 139/372] Use component selection to reject non-public releases as baselines --- build.gradle | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/build.gradle b/build.gradle index 75809cbb98..58d40b4af2 100644 --- a/build.gradle +++ b/build.gradle @@ -258,6 +258,17 @@ subprojects { transitive = false } } + configurations.baseline { + resolutionStrategy { + componentSelection { + all { selection -> + if (!selection.candidate.version.matches(/\d+(?:\.\d+)*/)) { + selection.reject("Only full releases can be used as OSGi baselines") + } + } + } + } + } } } From 483d75744f175f6acb159d9043f6ea4bce76fdd8 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Wed, 5 Jun 2019 09:26:17 -0700 Subject: [PATCH 140/372] tc-core version bump --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 5b5e8e9cc1..bf968693d3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ jaxbVersion = 2.3.1 # Terracotta clustered terracottaPlatformVersion = 5.7.3-pre3 terracottaApisVersion = 1.6.1 -terracottaCoreVersion = 5.6.4-pre3 +terracottaCoreVersion = 5.6.4-pre4 terracottaPassthroughTestingVersion = 1.6.1 # Test lib versions From 0c9e97f1df1b9e7265539556fb24094543e690fc Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 5 Jun 2019 11:36:50 -0400 Subject: [PATCH 141/372] Add support for running OSGi tests in Java 11 --- osgi-test/build.gradle | 12 +++---- .../ehcache/osgi/ByteSizedOnHeapOsgiTest.java | 3 +- .../java/org/ehcache/osgi/Jsr107OsgiTest.java | 5 +-- .../org/ehcache/osgi/OffHeapOsgiTest.java | 5 +-- .../java/org/ehcache/osgi/OsgiTestUtils.java | 34 +++++++++++++++---- .../java/org/ehcache/osgi/SimpleOsgiTest.java | 7 ++-- .../ehcache/osgi/TransactionalOsgiTest.java | 18 ++++------ 7 files changed, 51 insertions(+), 33 deletions(-) diff --git a/osgi-test/build.gradle b/osgi-test/build.gradle index ad9dc637c7..0da7259f08 100644 --- a/osgi-test/build.gradle +++ b/osgi-test/build.gradle @@ -37,9 +37,10 @@ dependencies { osgiModule "org.slf4j:slf4j-simple:$parent.slf4jVersion" osgiModule 'org.apache.felix:org.apache.felix.scr:2.1.6' + osgiModule 'com.sun.activation:javax.activation:1.2.0' + osgiModule 'org.glassfish.hk2:osgi-resource-locator:1.0.2' - - testImplementation 'org.apache.felix:org.apache.felix.framework:6.0.1' + testImplementation 'org.apache.felix:org.apache.felix.framework:6.0.3' testImplementation ('org.ops4j.pax.exam:pax-exam-junit4:4.12.0') { exclude group:'org.slf4j', module:'slf4j-api' } @@ -50,7 +51,7 @@ dependencies { testRuntimeOnly ('org.ops4j.pax.exam:pax-exam-link-mvn:4.12.0') { exclude group:'org.slf4j', module:'slf4j-api' } - testRuntimeOnly ("org.ops4j.pax.url:pax-url-wrap:2.4.5") { + testRuntimeOnly ("org.ops4j.pax.url:pax-url-wrap:2.6.1") { exclude group:'org.slf4j', module:'slf4j-api' } } @@ -60,6 +61,7 @@ configurations.all { force 'org.ops4j.base:ops4j-base-lang:1.5.0' force 'org.ops4j.base:ops4j-base-net:1.5.0' force 'org.ops4j.base:ops4j-base-util-property:1.5.0' + force 'org.ops4j.pax.url:pax-url-commons:2.6.1' } } @@ -76,14 +78,10 @@ configurations.osgiModule.dependencies.withType(ProjectDependency).forEach { test { if (testJava.javaVersion.isJava9Compatible()) { - //Deploying the jaxb-runtime as an OSGi module is currently impossible - don't ask... sigh. - jvmArgs += ['--add-modules', 'java.xml.bind'] //https://issues.apache.org/jira/browse/FELIX-5727 - framework extensions in Java 9 are ugly jvmArgs += ['--add-opens=java.base/jdk.internal.loader=ALL-UNNAMED'] } }.doFirst { - if (testJava.javaVersion.isJava11Compatible()) throw new StopExecutionException("OSGi Tests Not Working in Java 11") - configurations.osgiModule.resolvedConfiguration.resolvedArtifacts.forEach({ systemProperty "$it.moduleVersion.id.module:osgi-path", it.file }) diff --git a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java index 12790ea81e..67fc5940b4 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java @@ -20,6 +20,7 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; +import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.ops4j.pax.exam.CoreOptions.options; @@ -57,7 +58,7 @@ public Option[] individualModules() { @Configuration public Option[] uberJar() { return options( - gradleBundle("org.ehcache:dist"), + gradleBundle("org.ehcache:dist"), jaxbConfiguration(), baseConfiguration("ByteSizedOnHeapOsgiTest", "uberJar") ); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java index ebd32b7579..c1ed3c4b1e 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java @@ -42,6 +42,7 @@ import static java.util.stream.StreamSupport.stream; import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; +import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.hamcrest.core.IsCollectionContaining.hasItems; import static org.junit.Assert.assertEquals; @@ -59,7 +60,7 @@ public class Jsr107OsgiTest { public Option[] individualModules() { return options( gradleBundle("org.ehcache.modules:impl"), - gradleBundle("org.ehcache.modules:xml"), + gradleBundle("org.ehcache.modules:xml"), jaxbConfiguration(), gradleBundle("org.ehcache.modules:107"), gradleBundle("org.ehcache.modules:core"), gradleBundle("org.ehcache.modules:api"), @@ -76,7 +77,7 @@ public Option[] individualModules() { @Configuration public Option[] uberJar() { return options( - gradleBundle("org.ehcache:dist"), + gradleBundle("org.ehcache:dist"), jaxbConfiguration(), gradleBundle("javax.cache:cache-api"), baseConfiguration("Jsr107OsgiTest", "uberJar") diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java index 7083d7c67a..9160c585e5 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java @@ -36,6 +36,7 @@ import static org.ehcache.core.osgi.EhcacheActivator.OSGI_LOADING; import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; +import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -64,7 +65,7 @@ public Option[] individualModules() { @Configuration public Option[] uberJarWithOsgiServiceLoading() { return options( - gradleBundle("org.ehcache:dist"), + gradleBundle("org.ehcache:dist"), jaxbConfiguration(), baseConfiguration("OffHeapOsgiTest", "uberJarWithOsgiServiceLoading") ); @@ -75,7 +76,7 @@ public Option[] uberJarWithJdkServiceLoading() { return options( frameworkProperty(OSGI_LOADING).value("false"), - gradleBundle("org.ehcache:dist"), + gradleBundle("org.ehcache:dist"), jaxbConfiguration(), baseConfiguration("OffHeapOsgiTest", "uberJarWithJdkServiceLoading") ); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java index 476d2efc41..9c2620b433 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -24,7 +24,9 @@ import java.nio.file.Path; import java.nio.file.Paths; +import static java.lang.Integer.parseInt; import static java.lang.String.join; +import static java.lang.System.getProperty; import static java.nio.file.Files.isRegularFile; import static java.util.Objects.requireNonNull; import static org.ops4j.pax.exam.CoreOptions.bundle; @@ -44,17 +46,37 @@ public static Option baseConfiguration(String ... path) { gradleBundle("org.slf4j:slf4j-simple").noStart(), gradleBundle("org.apache.felix:org.apache.felix.scr"), systemProperty("pax.exam.osgi.unresolved.fail").value("true"), - systemPackages( - "javax.xml.bind;version=2.3.0", - "javax.xml.bind.annotation;version=2.3.0", - "javax.xml.bind.annotation.adapters;version=2.3.0" - ), cleanCaches(true), workingDirectory(join(File.separator, "build", "osgi-container", join(File.separator, path))), junitBundles() ); } + public static Option jaxbConfiguration() { + if (parseInt(getProperty("java.version").split("[^\\d]+")[0]) >= 9) { + return composite( + gradleBundle("org.glassfish.hk2:osgi-resource-locator"), + gradleBundle("javax.xml.bind:jaxb-api"), + gradleBundle("com.sun.activation:javax.activation"), + wrappedGradleBundle("org.glassfish.jaxb:jaxb-runtime"), + gradleBundle("com.sun.istack:istack-commons-runtime") + ); + } else { + return systemPackages( + "javax.xml.bind;version=2.3.0", + "javax.xml.bind.annotation;version=2.3.0", + "javax.xml.bind.annotation.adapters;version=2.3.0" + ); + } + } + + public static Option jtaConfiguration() { + return composite( + wrappedGradleBundle("javax.transaction:jta").instructions("Fragment-Host=org.apache.felix.framework"), + wrappedGradleBundle("org.codehaus.btm:btm") + ); + } + public static UrlProvisionOption gradleBundle(String module) { return bundle(artifact(module).toUri().toString()); } @@ -64,7 +86,7 @@ public static WrappedUrlProvisionOption wrappedGradleBundle(String module) { } private static Path artifact(String module) { - Path path = Paths.get(requireNonNull(System.getProperty(module + ":osgi-path"), module + " not available")); + Path path = Paths.get(requireNonNull(getProperty(module + ":osgi-path"), module + " not available")); if (isRegularFile(path)) { return path; } else { diff --git a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java index f270e60737..458b6ef2a5 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java @@ -47,6 +47,7 @@ import static org.ehcache.core.osgi.EhcacheActivator.OSGI_LOADING; import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; +import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.hamcrest.core.IsCollectionContaining.hasItems; import static org.junit.Assert.assertEquals; @@ -65,7 +66,7 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:api"), gradleBundle("org.ehcache.modules:core"), gradleBundle("org.ehcache.modules:impl"), - gradleBundle("org.ehcache.modules:xml"), + gradleBundle("org.ehcache.modules:xml"), jaxbConfiguration(), wrappedGradleBundle("org.terracotta:statistics"), wrappedGradleBundle("org.ehcache:sizeof"), @@ -78,7 +79,7 @@ public Option[] individualModules() { @Configuration public Option[] uberJarWithOsgiServiceLoading() { return options( - gradleBundle("org.ehcache:dist"), + gradleBundle("org.ehcache:dist"), jaxbConfiguration(), baseConfiguration("SimpleOsgiTest", "uberJarWithOsgiServiceLoading") ); @@ -89,7 +90,7 @@ public Option[] uberJarWithJdkServiceLoading() { return options( frameworkProperty(OSGI_LOADING).value("false"), - gradleBundle("org.ehcache:dist"), + gradleBundle("org.ehcache:dist"), jaxbConfiguration(), baseConfiguration("SimpleOsgiTest", "uberJarWithJdkServiceLoading") ); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java index 9c521c27c4..e303ed29a9 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java @@ -41,6 +41,8 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; +import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; +import static org.ehcache.osgi.OsgiTestUtils.jtaConfiguration; import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.ops4j.pax.exam.CoreOptions.options; @@ -54,17 +56,13 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:api"), gradleBundle("org.ehcache.modules:core"), gradleBundle("org.ehcache.modules:impl"), - gradleBundle("org.ehcache.modules:xml"), - gradleBundle("org.ehcache:transactions"), + gradleBundle("org.ehcache.modules:xml"), jaxbConfiguration(), + gradleBundle("org.ehcache:transactions"), jtaConfiguration(), wrappedGradleBundle("org.terracotta:statistics"), wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), - wrappedGradleBundle("javax.transaction:jta") - .instructions("Fragment-Host=org.apache.felix.framework"), - wrappedGradleBundle("org.codehaus.btm:btm"), - baseConfiguration("TransactionalOsgiTest", "individualModules") ); } @@ -72,12 +70,8 @@ public Option[] individualModules() { @Configuration public Option[] uberJar() { return options( - gradleBundle("org.ehcache:dist"), - gradleBundle("org.ehcache:transactions"), - - wrappedGradleBundle("javax.transaction:jta") - .instructions("Fragment-Host=org.apache.felix.framework"), - wrappedGradleBundle("org.codehaus.btm:btm"), + gradleBundle("org.ehcache:dist"), jaxbConfiguration(), + gradleBundle("org.ehcache:transactions"), jtaConfiguration(), baseConfiguration("TransactionalOsgiTest", "uberJar") ); From 9b4f48eb6771d045d433866ab805218b9bad3dae Mon Sep 17 00:00:00 2001 From: mobasherul Date: Mon, 17 Jun 2019 03:25:22 -0700 Subject: [PATCH 142/372] version bump for core and platform --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index bf968693d3..869c1d8c31 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.3-pre3 +terracottaPlatformVersion = 5.7.3-pre4 terracottaApisVersion = 1.6.1 -terracottaCoreVersion = 5.6.4-pre4 +terracottaCoreVersion = 5.6.4-pre5 terracottaPassthroughTestingVersion = 1.6.1 # Test lib versions From 37a251bd7b0907b1b919f7ba3fc41b2493429a85 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Tue, 18 Jun 2019 19:09:46 -0700 Subject: [PATCH 143/372] Bump dependency versions --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 869c1d8c31..2788587973 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.3-pre4 +terracottaPlatformVersion = 5.7.3-pre6 terracottaApisVersion = 1.6.1 -terracottaCoreVersion = 5.6.4-pre5 +terracottaCoreVersion = 5.6.4-pre9 terracottaPassthroughTestingVersion = 1.6.1 # Test lib versions From be24e4d443170d82613b28b7a3c0a2ae01841043 Mon Sep 17 00:00:00 2001 From: akomakom Date: Thu, 20 Jun 2019 10:05:20 -0400 Subject: [PATCH 144/372] Adding for checkmarx scans --- Jenkinsfile | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000000..23e7e47f70 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,18 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + //See Jenkins wiki pages for info +checkmarxBuild() From 040e7af3f56f930910294defee08321ae68be970 Mon Sep 17 00:00:00 2001 From: akomakom Date: Thu, 20 Jun 2019 10:06:46 -0400 Subject: [PATCH 145/372] correcting project name --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 23e7e47f70..ab6247ebda 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -15,4 +15,4 @@ */ //See Jenkins wiki pages for info -checkmarxBuild() +checkmarxBuild checkmarx_project_name: 'Terracotta DB (TDB) Ehcache OSS' From dec49185e1d9828b61ef5d5c7a035f1ce40b9ac6 Mon Sep 17 00:00:00 2001 From: Abhilash Date: Thu, 2 May 2019 23:41:13 +0530 Subject: [PATCH 146/372] Rope in all stats api in core --- 107/build.gradle | 1 - .../jsr107/Eh107CacheStatisticsMXBean.java | 5 +- buildSrc/build.gradle | 2 +- buildSrc/src/main/groovy/EhDistribute.groovy | 7 +- clustered/client/build.gradle | 2 +- .../DelegatingLoaderWriterStore.java | 4 +- .../client/internal/store/ClusteredStore.java | 13 +- .../client/BasicClusteredCacheTest.java | 2 +- .../client/ClusteredCacheExpirationTest.java | 2 +- clustered/integration-test/build.gradle | 17 +- .../clustered/BasicEntityInteractionTest.java | 2 +- .../clustered/TerminatedServerTest.java | 2 +- .../AbstractClusteringManagementTest.java | 2 + .../ClusteredStatisticsCountTest.java | 12 +- .../org/ehcache/osgi/ClusteredOsgiTest.java | 3 + .../PoolStatisticsManagementProvider.java | 2 +- ...rverStoreStatisticsManagementProvider.java | 2 +- core/build.gradle | 4 +- .../core/spi/service/StatisticsService.java | 51 ++++ .../core/statistics/CacheStatistics.java | 10 - .../core/statistics/ChainedObserver.java | 19 ++ .../statistics/ChainedOperationObserver.java | 24 ++ .../statistics/DefaultCacheStatistics.java | 38 ++- .../statistics/DefaultStatisticsService.java | 224 ++++++++++++++++++ .../DefaultStatisticsServiceFactory.java | 2 +- .../statistics/DefaultTierStatistics.java | 9 +- .../DelegatedMappedOperationStatistics.java | 107 +++++++++ .../DelegatingOperationObserver.java | 35 +++ .../DelegatingOperationStatistic.java | 103 ++++++++ .../core/statistics/Jsr107LatencyMonitor.java | 45 ++++ .../LatencyHistogramConfiguration.java | 6 +- .../core/statistics/OperationObserver.java | 47 ++++ .../core/statistics/OperationStatistic.java | 54 +++++ .../core/statistics/SourceStatistic.java | 42 ++++ .../ehcache/core}/statistics/StatsUtils.java | 13 +- .../statistics/SuppliedValueStatistic.java | 59 +++++ .../core/statistics/ValueStatistic.java | 35 +++ .../statistics/ZeroOperationStatistic.java | 75 ++++++ gradle.properties | 3 +- impl/build.gradle | 5 +- .../statistics/DefaultStatisticsService.java | 121 ---------- .../internal/store/disk/OffHeapDiskStore.java | 8 +- .../impl/internal/store/heap/OnHeapStore.java | 17 +- .../loaderwriter/LocalLoaderWriterStore.java | 7 +- .../store/offheap/AbstractOffHeapStore.java | 33 +-- .../internal/store/offheap/OffHeapStore.java | 7 +- .../store/tiering/CompoundCachingTier.java | 6 +- .../internal/store/tiering/TieredStore.java | 6 +- .../org/ehcache/impl/store/BaseStore.java | 51 ++-- ...rg.ehcache.core.spi.service.ServiceFactory | 2 +- .../DefaultCacheStatisticsTest.java | 5 +- .../DefaultStatisticsServiceTest.java | 1 + .../DefaultTierStatisticsDisabledTest.java | 1 + .../statistics/DefaultTierStatisticsTest.java | 1 + .../internal/statistics/StatsUtilsTest.java | 2 +- .../ehcache/integration/EhcacheBaseTest.java | 2 +- .../statistics/CacheCalculationTest.java | 2 +- .../statistics/TierCalculationTest.java | 2 +- management/build.gradle | 4 +- ...anagementRegistryServiceConfiguration.java | 2 +- .../statistics/EhcacheStatisticsProvider.java | 6 +- .../statistics/StandardEhcacheStatistics.java | 47 ++-- .../registry/DefaultCollectorService.java | 11 +- ...efaultManagementRegistryConfiguration.java | 2 +- .../DefaultManagementRegistryService.java | 6 +- .../EhcacheStatisticsProviderTest.java | 2 +- .../LatencyHistogramConfigurationTest.java | 1 + .../StandardEhcacheStatisticsTest.java | 3 +- .../ehcache/osgi/ByteSizedOnHeapOsgiTest.java | 3 + .../java/org/ehcache/osgi/Jsr107OsgiTest.java | 3 + .../org/ehcache/osgi/OffHeapOsgiTest.java | 3 + .../java/org/ehcache/osgi/SimpleOsgiTest.java | 3 + .../ehcache/osgi/TransactionalOsgiTest.java | 3 + transactions/build.gradle | 1 - .../transactions/xa/internal/XAStore.java | 4 +- 75 files changed, 1127 insertions(+), 341 deletions(-) create mode 100644 core/src/main/java/org/ehcache/core/statistics/ChainedObserver.java create mode 100644 core/src/main/java/org/ehcache/core/statistics/ChainedOperationObserver.java rename {impl/src/main/java/org/ehcache/impl/internal => core/src/main/java/org/ehcache/core}/statistics/DefaultCacheStatistics.java (85%) create mode 100644 core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java rename {impl/src/main/java/org/ehcache/impl/internal => core/src/main/java/org/ehcache/core}/statistics/DefaultStatisticsServiceFactory.java (96%) rename {impl/src/main/java/org/ehcache/impl/internal => core/src/main/java/org/ehcache/core}/statistics/DefaultTierStatistics.java (96%) create mode 100644 core/src/main/java/org/ehcache/core/statistics/DelegatedMappedOperationStatistics.java create mode 100644 core/src/main/java/org/ehcache/core/statistics/DelegatingOperationObserver.java create mode 100644 core/src/main/java/org/ehcache/core/statistics/DelegatingOperationStatistic.java create mode 100644 core/src/main/java/org/ehcache/core/statistics/Jsr107LatencyMonitor.java rename {management/src/main/java/org/ehcache/management/providers => core/src/main/java/org/ehcache/core}/statistics/LatencyHistogramConfiguration.java (93%) create mode 100644 core/src/main/java/org/ehcache/core/statistics/OperationObserver.java create mode 100644 core/src/main/java/org/ehcache/core/statistics/OperationStatistic.java create mode 100644 core/src/main/java/org/ehcache/core/statistics/SourceStatistic.java rename {impl/src/main/java/org/ehcache/impl/internal => core/src/main/java/org/ehcache/core}/statistics/StatsUtils.java (93%) create mode 100644 core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java create mode 100644 core/src/main/java/org/ehcache/core/statistics/ValueStatistic.java create mode 100644 core/src/main/java/org/ehcache/core/statistics/ZeroOperationStatistic.java delete mode 100644 impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsService.java diff --git a/107/build.gradle b/107/build.gradle index b7c07985e2..93609d3c0e 100644 --- a/107/build.gradle +++ b/107/build.gradle @@ -37,7 +37,6 @@ dependencies { implementation project(':impl') implementation project(':xml') - implementation "org.terracotta:statistics:$parent.statisticVersion" compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java b/107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java index 0c94c9b47f..4da6c83076 100644 --- a/107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java +++ b/107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java @@ -18,10 +18,9 @@ import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.statistics.CacheOperationOutcomes; import org.ehcache.core.statistics.CacheStatistics; -import org.terracotta.statistics.derived.latency.Jsr107LatencyMonitor; +import org.ehcache.core.statistics.Jsr107LatencyMonitor; import java.net.URI; -import java.util.EnumSet; /** * @author Ludovic Orban @@ -45,7 +44,7 @@ class Eh107CacheStatisticsMXBean extends Eh107MXBean implements javax.cache.mana } private > Jsr107LatencyMonitor registerDerivedStatistics(Class outcome, String name) { - Jsr107LatencyMonitor monitor = new Jsr107LatencyMonitor<>(EnumSet.allOf(outcome), 1.0); + Jsr107LatencyMonitor monitor = new Jsr107LatencyMonitor<>(outcome, 1.0); CacheStatistics cacheStatistics = this.cacheStatistics; cacheStatistics.registerDerivedStatistic(outcome, name, monitor); return monitor; diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 005e117967..b9fee4365a 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -20,5 +20,5 @@ repositories { jcenter() } dependencies { compile gradleApi() compile localGroovy() - compile 'com.github.jengelman.gradle.plugins:shadow:4.0.3' + compile 'com.github.jengelman.gradle.plugins:shadow:5.0.0' } diff --git a/buildSrc/src/main/groovy/EhDistribute.groovy b/buildSrc/src/main/groovy/EhDistribute.groovy index 6850a414ed..5ee312158e 100644 --- a/buildSrc/src/main/groovy/EhDistribute.groovy +++ b/buildSrc/src/main/groovy/EhDistribute.groovy @@ -1,7 +1,6 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.ProjectDependency -import org.gradle.api.plugins.osgi.OsgiPluginConvention import scripts.Utils /* @@ -51,7 +50,13 @@ class EhDistribute implements Plugin { dependencies { exclude({ rdep -> !['org.ehcache', 'org.terracotta'].any({ prefix -> rdep.moduleGroup.startsWith(prefix) })}) } + relocate ('org.terracotta.statistics.', 'org.ehcache.shadow.org.terracotta.statistics.') + relocate ('org.terracotta.offheapstore.', 'org.ehcache.shadow.org.terracotta.offheapstore.') + relocate ('org.terracotta.context.', 'org.ehcache.shadow.org.terracotta.context.') + mergeServiceFiles() + + } project.jar { diff --git a/clustered/client/build.gradle b/clustered/client/build.gradle index bf9bcf2598..f336936d60 100644 --- a/clustered/client/build.gradle +++ b/clustered/client/build.gradle @@ -21,7 +21,6 @@ dependencies { compileOnly project(':impl') compileOnly project(':xml') implementation project(':clustered:common') - implementation "org.terracotta:statistics:$parent.statisticVersion" providedImplementation "org.terracotta:entity-client-api:$terracottaApisVersion" providedImplementation "org.terracotta:runnel:$terracottaPlatformVersion" providedImplementation "org.terracotta:lease-api:$terracottaPlatformVersion" @@ -46,4 +45,5 @@ dependencies { testImplementation 'org.xmlunit:xmlunit-core:2.6.0' testImplementation 'org.xmlunit:xmlunit-matchers:2.6.0' testImplementation "org.awaitility:awaitility:3.1.6" + testImplementation ("org.terracotta:statistics:$parent.statisticVersion") } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java index 0d71b775e3..4560537abb 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java @@ -21,8 +21,8 @@ import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.WrapperStore; import org.ehcache.core.spi.store.events.StoreEventSource; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.spi.resilience.StoreAccessException; -import org.terracotta.context.ContextManager; import java.util.Collections; import java.util.List; @@ -39,7 +39,7 @@ public class DelegatingLoaderWriterStore implements WrapperStore { public DelegatingLoaderWriterStore(Store store) { this.delegate = store; - ContextManager.associate(delegate).withParent(this); + DefaultStatisticsService.registerWithParent(delegate, this); } @Override diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index 54613f3466..bcce02aade 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -51,6 +51,11 @@ import org.ehcache.core.spi.store.events.StoreEventFilter; import org.ehcache.core.spi.store.events.StoreEventListener; import org.ehcache.core.spi.store.events.StoreEventSource; +import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.statistics.OperationObserver; +import org.ehcache.core.statistics.OperationStatistic; +import org.ehcache.impl.store.BaseStore; +import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.core.spi.time.TimeSourceService; @@ -62,10 +67,8 @@ import org.ehcache.event.EventOrdering; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.store.DefaultStoreEventDispatcher; -import org.ehcache.impl.store.BaseStore; import org.ehcache.impl.store.HashUtils; import org.ehcache.spi.persistence.StateRepository; -import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.spi.serialization.Serializer; import org.ehcache.spi.serialization.StatefulSerializer; import org.ehcache.spi.service.Service; @@ -74,9 +77,6 @@ import org.ehcache.spi.service.ServiceProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.terracotta.statistics.OperationStatistic; -import org.terracotta.statistics.StatisticsManager; -import org.terracotta.statistics.observer.OperationObserver; import java.nio.ByteBuffer; import java.util.Collection; @@ -595,7 +595,6 @@ public static class Provider extends BaseStoreProvider implements AuthoritativeT CLUSTER_RESOURCES = Collections.unmodifiableSet(resourceTypes); } - private volatile ServiceProvider serviceProvider; private volatile ClusteringService clusteringService; protected volatile ExecutionService executionService; @@ -693,7 +692,7 @@ public void releaseStore(Store resource) { } ClusteredStore clusteredStore = (ClusteredStore) resource; this.clusteringService.releaseServerStoreProxy(clusteredStore.storeProxy, false); - StatisticsManager.nodeFor(clusteredStore).clean(); + DefaultStatisticsService.cleanForNode(clusteredStore); tierOperationStatistics.remove(clusteredStore); } finally { connectLock.unlock(); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java index 6311fc33e1..7cbdd6315a 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java @@ -26,7 +26,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.impl.internal.statistics.DefaultStatisticsService; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java index f0b460f036..3ebe5fb4cf 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java @@ -32,7 +32,7 @@ import org.ehcache.core.statistics.TierStatistics; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.TimeSourceConfiguration; -import org.ehcache.impl.internal.statistics.DefaultStatisticsService; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index 3b60a3411c..0d6291791d 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -20,21 +20,20 @@ configurations { dependencies { // not required by gradle but required by the IDE because 'dist' does not have any transitive dependencies - testCompileOnly project(':clustered:client') - testCompileOnly project(':clustered:common') - testCompileOnly project(':impl') - testCompileOnly project(':xml') - testCompileOnly "org.terracotta.internal:client-runtime:$terracottaCoreVersion" - testCompileOnly "org.terracotta:runnel:$terracottaPlatformVersion" - testCompileOnly "org.terracotta:lease-api:$terracottaPlatformVersion" + testCompile project(':clustered:client') + testCompile project(':clustered:common') + testCompile project(':impl') + testCompile project(':xml') + testCompile project(':107') + testCompile "org.terracotta.internal:client-runtime:$terracottaCoreVersion" + testCompile "org.terracotta:runnel:$terracottaPlatformVersion" + testCompile "org.terracotta:lease-api:$terracottaPlatformVersion" testImplementation project(':management') testImplementation "org.terracotta.management.dist:mnm-nms:$terracottaPlatformVersion" testImplementation "org.terracotta.management.dist:mnm-nms-agent:$terracottaPlatformVersion" testImplementation "com.fasterxml.jackson.core:jackson-databind:2.8.0" testImplementation "org.awaitility:awaitility:3.1.6" - testRuntimeOnly project(':clustered:clustered-dist') - testRuntimeOnly project(':dist') testRuntimeOnly "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java index a42bafbc4d..34b3f306f2 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java @@ -29,7 +29,7 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.impl.internal.statistics.DefaultStatisticsService; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.management.cluster.DefaultClusteringManagementService; import org.hamcrest.Matchers; import org.junit.BeforeClass; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java index 7a49a8bb61..52c46d8b83 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java @@ -33,7 +33,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.spi.service.StatisticsService; -import org.ehcache.impl.internal.statistics.DefaultStatisticsService; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 976dd9e7d6..07ea06c233 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -269,6 +269,8 @@ public static void createNmsService() throws ConnectionException, EntityConfigur } public static void createNmsService(Cluster cluster) throws ConnectionException, EntityConfigurationException { + String classpathStr = System.getProperty("java.class.path"); + System.out.print("CLASSPATH" + classpathStr); managementConnection = cluster.newConnection(); NmsEntityFactory entityFactory = new NmsEntityFactory(managementConnection, AbstractClusteringManagementTest.class.getName()); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java index 7e6be02a7c..cab6b27705 100755 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java @@ -19,8 +19,12 @@ import org.junit.Assert; import org.junit.Test; import org.terracotta.management.model.stats.ContextualStatistics; +import org.terracotta.statistics.registry.Statistic; +import java.io.Serializable; import java.util.List; +import java.util.Map; +import java.util.Set; import static org.hamcrest.CoreMatchers.is; @@ -61,10 +65,12 @@ public void countTest() throws Exception { if (stat.getContext().contains("cacheName") && stat.getContext().get("cacheName").equals("dedicated-cache-1")) { // please leave it there - it's really useful to see what's coming - /*System.out.println("stats:"); - for (Map.ChainEntry> entry : stat.getStatistics().entrySet()) { + System.out.println("stats:"); + + Set>> entries = stat.getStatistics().entrySet(); + for (Map.Entry> entry : entries) { System.out.println(" - " + entry.getKey() + " : " + entry.getValue()); - }*/ + } cacheHitCount = stat.getLatestSampleValue("Cache:HitCount").get(); clusteredHitCount = stat.getLatestSampleValue("Clustered:HitCount").get(); diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java index 3171facb43..177015e2dd 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java @@ -84,6 +84,9 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:xml"), gradleBundle("org.ehcache:clustered-dist"), + gradleBundle("org.terracotta.management:management-model"), + gradleBundle("org.terracotta.management:sequence-generator"), + wrappedGradleBundle("org.terracotta:statistics"), wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/management/PoolStatisticsManagementProvider.java b/clustered/server/src/main/java/org/ehcache/clustered/server/management/PoolStatisticsManagementProvider.java index 47dbf004b8..867674a8a5 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/management/PoolStatisticsManagementProvider.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/management/PoolStatisticsManagementProvider.java @@ -17,11 +17,11 @@ import org.ehcache.clustered.server.state.EhcacheStateService; import org.terracotta.management.model.context.Context; +import org.terracotta.management.model.stats.StatisticRegistry; import org.terracotta.management.registry.Named; import org.terracotta.management.registry.RequiredContext; import org.terracotta.management.registry.ExposedObject; import org.terracotta.management.registry.collect.StatisticProvider; -import org.terracotta.management.registry.collect.StatisticRegistry; import org.terracotta.management.service.monitoring.registry.provider.AbstractExposedStatistics; import org.terracotta.management.service.monitoring.registry.provider.AbstractStatisticsManagementProvider; diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/management/ServerStoreStatisticsManagementProvider.java b/clustered/server/src/main/java/org/ehcache/clustered/server/management/ServerStoreStatisticsManagementProvider.java index 0d67ccaaa2..c5696c8016 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/management/ServerStoreStatisticsManagementProvider.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/management/ServerStoreStatisticsManagementProvider.java @@ -16,10 +16,10 @@ package org.ehcache.clustered.server.management; import org.terracotta.management.model.context.Context; +import org.terracotta.management.model.stats.StatisticRegistry; import org.terracotta.management.registry.Named; import org.terracotta.management.registry.RequiredContext; import org.terracotta.management.registry.collect.StatisticProvider; -import org.terracotta.management.registry.collect.StatisticRegistry; import org.terracotta.management.service.monitoring.registry.provider.AbstractExposedStatistics; import org.terracotta.management.service.monitoring.registry.provider.AbstractStatisticsManagementProvider; diff --git a/core/build.gradle b/core/build.gradle index 40fa709263..0f8d6b5bcf 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -19,8 +19,10 @@ apply plugin: 'biz.aQute.bnd.builder' dependencies { api project(':api') - api "org.terracotta:statistics:$parent.statisticVersion" + implementation "org.terracotta:statistics:$parent.statisticVersion" + implementation "org.terracotta.management:management-model:$terracottaPlatformVersion" compileOnly 'org.osgi:osgi.core:6.0.0' + compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':spi-tester') } diff --git a/core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java b/core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java index f207415b5e..edf4d1cc1d 100644 --- a/core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java +++ b/core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java @@ -16,8 +16,17 @@ package org.ehcache.core.spi.service; +import org.ehcache.Cache; import org.ehcache.core.statistics.CacheStatistics; +import org.ehcache.core.statistics.LatencyHistogramConfiguration; import org.ehcache.spi.service.Service; +import org.terracotta.management.model.capabilities.descriptors.StatisticDescriptor; +import org.terracotta.management.model.stats.Statistic; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Map; +import java.util.function.LongSupplier; /** * Service providing raw statistics for cache and tier usage. @@ -31,4 +40,46 @@ public interface StatisticsService extends Service { * @return all the cache statistics */ CacheStatistics getCacheStatistics(String cacheName); + + /** + * + * @param cacheName + * @param cache + * @param timeSource + */ + void createCacheRegistry(String cacheName, Cache cache, LongSupplier timeSource); + + /** + * + * @param cacheName + */ + void registerCacheStatistics(String cacheName); + + /** + * + * @param cacheName + * @return + */ + Collection getCacheDescriptors(String cacheName); + + /** + * @param + * @param cacheName + * @param cache + * @param statName + * @param outcome + * @param derivedName + * @param configuration + */ + , K, V> void registerDerivedStatistics(String cacheName, Cache cache, String statName, T outcome, String derivedName, LatencyHistogramConfiguration configuration); + + /** + * + * @param cacheName + * @param statisticNames + * @param since + * @return + */ + Map> collectStatistics(String cacheName, Collection statisticNames, long since); + } diff --git a/core/src/main/java/org/ehcache/core/statistics/CacheStatistics.java b/core/src/main/java/org/ehcache/core/statistics/CacheStatistics.java index 48f74a1e8a..a115c2a5cf 100644 --- a/core/src/main/java/org/ehcache/core/statistics/CacheStatistics.java +++ b/core/src/main/java/org/ehcache/core/statistics/CacheStatistics.java @@ -16,9 +16,6 @@ package org.ehcache.core.statistics; -import org.terracotta.statistics.ValueStatistic; -import org.terracotta.statistics.observer.ChainedOperationObserver; - import java.util.Map; /** @@ -26,13 +23,6 @@ */ public interface CacheStatistics { - /** - * List of statistics tracked on this cache - * - * @return a map of statistics per name - */ - Map> getKnownStatistics(); - /** * Map of tier statistics on this cache. Per tier name * diff --git a/core/src/main/java/org/ehcache/core/statistics/ChainedObserver.java b/core/src/main/java/org/ehcache/core/statistics/ChainedObserver.java new file mode 100644 index 0000000000..19b0cbac93 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/statistics/ChainedObserver.java @@ -0,0 +1,19 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.statistics; + +public interface ChainedObserver { +} diff --git a/core/src/main/java/org/ehcache/core/statistics/ChainedOperationObserver.java b/core/src/main/java/org/ehcache/core/statistics/ChainedOperationObserver.java new file mode 100644 index 0000000000..1dc95ff0dc --- /dev/null +++ b/core/src/main/java/org/ehcache/core/statistics/ChainedOperationObserver.java @@ -0,0 +1,24 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.statistics; + +public interface ChainedOperationObserver> extends ChainedObserver { + + void begin(long time); + + void end(long time, long latency, T result); + +} diff --git a/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultCacheStatistics.java b/core/src/main/java/org/ehcache/core/statistics/DefaultCacheStatistics.java similarity index 85% rename from impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultCacheStatistics.java rename to core/src/main/java/org/ehcache/core/statistics/DefaultCacheStatistics.java index 875708c5f8..288c021d01 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultCacheStatistics.java +++ b/core/src/main/java/org/ehcache/core/statistics/DefaultCacheStatistics.java @@ -14,17 +14,13 @@ * limitations under the License. */ -package org.ehcache.impl.internal.statistics; +package org.ehcache.core.statistics; import org.ehcache.core.InternalCache; -import org.ehcache.core.statistics.BulkOps; import org.ehcache.core.statistics.CacheOperationOutcomes.GetOutcome; import org.ehcache.core.statistics.CacheOperationOutcomes.PutOutcome; -import org.ehcache.core.statistics.CacheStatistics; -import org.ehcache.core.statistics.TierStatistics; -import org.terracotta.statistics.OperationStatistic; import org.terracotta.statistics.ValueStatistic; -import org.terracotta.statistics.observer.ChainedOperationObserver; +import org.terracotta.statistics.derived.OperationResultFilter; import java.util.Collections; import java.util.EnumSet; @@ -35,31 +31,31 @@ import static org.ehcache.core.statistics.CacheOperationOutcomes.PutIfAbsentOutcome; import static org.ehcache.core.statistics.CacheOperationOutcomes.RemoveOutcome; import static org.ehcache.core.statistics.CacheOperationOutcomes.ReplaceOutcome; -import static org.ehcache.impl.internal.statistics.StatsUtils.findLowestTier; -import static org.ehcache.impl.internal.statistics.StatsUtils.findOperationStatisticOnChildren; -import static org.ehcache.impl.internal.statistics.StatsUtils.findTiers; +import static org.ehcache.core.statistics.StatsUtils.findLowestTier; +import static org.ehcache.core.statistics.StatsUtils.findOperationStatisticOnChildren; +import static org.ehcache.core.statistics.StatsUtils.findTiers; import static org.terracotta.statistics.ValueStatistics.counter; /** * Contains usage statistics relative to a given cache. */ -class DefaultCacheStatistics implements CacheStatistics { +public class DefaultCacheStatistics implements CacheStatistics { private volatile CompensatingCounters compensatingCounters = CompensatingCounters.empty(); - private final OperationStatistic get; - private final OperationStatistic put; - private final OperationStatistic remove; - private final OperationStatistic putIfAbsent; - private final OperationStatistic replace; - private final OperationStatistic conditionalRemove; + private final org.terracotta.statistics.OperationStatistic get; + private final org.terracotta.statistics.OperationStatistic put; + private final org.terracotta.statistics.OperationStatistic remove; + private final org.terracotta.statistics.OperationStatistic putIfAbsent; + private final org.terracotta.statistics.OperationStatistic replace; + private final org.terracotta.statistics.OperationStatistic conditionalRemove; private final InternalCache cache; private final Map tierStatistics; private final TierStatistics lowestTier; - private final Map> knownStatistics; + private final Map> knownStatistics; public DefaultCacheStatistics(InternalCache cache) { this.cache = cache; @@ -89,13 +85,14 @@ public DefaultCacheStatistics(InternalCache cache) { knownStatistics = createKnownStatistics(); } + @Override public , S extends ChainedOperationObserver> void registerDerivedStatistic(Class outcomeClass, String statName, S derivedStatistic) { - OperationStatistic stat = findOperationStatisticOnChildren(cache, outcomeClass, statName); + OperationStatistic stat = new DelegatingOperationStatistic<>(findOperationStatisticOnChildren(cache, outcomeClass, statName)); stat.addDerivedStatistic(derivedStatistic); } private Map> createKnownStatistics() { - Map> knownStatistics = new HashMap<>(30); + Map> knownStatistics = new HashMap<>(30); knownStatistics.put("Cache:HitCount", counter(this::getCacheHits)); knownStatistics.put("Cache:MissCount", counter(this::getCacheMisses)); knownStatistics.put("Cache:PutCount", counter(this::getCachePuts)); @@ -110,8 +107,7 @@ private Map> createKnownStatistics() { return Collections.unmodifiableMap(knownStatistics); } - @Override - public Map> getKnownStatistics() { + public Map> getKnownStatistics() { return knownStatistics; } diff --git a/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java b/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java new file mode 100644 index 0000000000..b312cfa7b8 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java @@ -0,0 +1,224 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.core.statistics; + +import org.ehcache.Cache; +import org.ehcache.Status; +import org.ehcache.config.CacheConfiguration; +import org.ehcache.core.InternalCache; +import org.ehcache.core.events.CacheManagerListener; +import org.ehcache.core.spi.service.CacheManagerProviderService; +import org.ehcache.core.spi.service.StatisticsService; +import org.ehcache.core.spi.store.InternalCacheManager; +import org.ehcache.core.spi.store.Store; +import org.ehcache.spi.service.Service; +import org.ehcache.spi.service.ServiceDependencies; +import org.ehcache.spi.service.ServiceProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.terracotta.management.model.capabilities.descriptors.StatisticDescriptor; +import org.terracotta.management.model.stats.Statistic; +import org.terracotta.management.model.stats.StatisticRegistry; +import org.terracotta.management.model.stats.StatisticType; +import org.terracotta.statistics.MappedOperationStatistic; +import org.terracotta.statistics.OperationStatistic; +import org.terracotta.statistics.StatisticsManager; +import org.terracotta.statistics.derived.OperationResultFilter; +import org.terracotta.statistics.derived.latency.DefaultLatencyHistogramStatistic; + +import java.io.Serializable; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.function.LongSupplier; +import java.util.function.Supplier; + +import static org.ehcache.core.statistics.StatsUtils.findOperationStatisticOnChildren; +import static org.terracotta.statistics.StatisticBuilder.operation; + +/** + * Default implementation using the statistics calculated by the observers set on the caches. + */ +@ServiceDependencies(CacheManagerProviderService.class) +public class DefaultStatisticsService implements StatisticsService, CacheManagerListener { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultStatisticsService.class); + + private final ConcurrentMap cacheStatistics = new ConcurrentHashMap<>(); + private final ConcurrentMap statisticRegistries = new ConcurrentHashMap<>(); + + private volatile InternalCacheManager cacheManager; + private volatile boolean started = false; + + public CacheStatistics getCacheStatistics(String cacheName) { + CacheStatistics stats = cacheStatistics.get(cacheName); + if (stats == null) { + throw new IllegalArgumentException("Unknown cache: " + cacheName); + } + return stats; + } + + public static void registerWithParent(Object toAssociate, Object parent) { + StatisticsManager.associate(toAssociate).withParent(parent); + } + + public static , T extends Enum> org.ehcache.core.statistics.OperationStatistic registerStoreStatistics(Store store, String targetName, int tierHeight, String tag, Map> translation, String statisticName) { + + Class outcomeType = getOutcomeType(translation); + + // If the original stat doesn't exist, we do not need to translate it + if (StatsUtils.hasOperationStat(store, outcomeType, targetName)) { + + MappedOperationStatistic operationStatistic = new MappedOperationStatistic<>(store, translation, statisticName, tierHeight, targetName, tag); + StatisticsManager.associate(operationStatistic).withParent(store); + org.ehcache.core.statistics.OperationStatistic stat = new DelegatedMappedOperationStatistics<>(operationStatistic); + return stat; + } + return ZeroOperationStatistic.get(); + } + + /** + * From the Map of translation, we extract one of the items to get the declaring class of the enum. + * + * @param translation translation map + * @param type of the outcome + * @param type of the possible translations + * @return the outcome type + */ + private static , T extends Enum> Class getOutcomeType(Map> translation) { + Map.Entry> first = translation.entrySet().iterator().next(); + Class outcomeType = first.getValue().iterator().next().getDeclaringClass(); + return outcomeType; + } + + public static void deRegisterFromParent(Object toDessociate, Object parent) { + StatisticsManager.dissociate(toDessociate).fromParent(parent); + } + + public static void cleanForNode(Object node) { + StatisticsManager.nodeFor(node).clean(); + } + + @Override + public void createCacheRegistry(String cacheName, Cache cache, LongSupplier timeSource) { + statisticRegistries.put(cacheName, new StatisticRegistry(cache, timeSource)); + } + + @Override + public void registerCacheStatistics(String cacheName) { + cacheStatistics.get(cacheName).getKnownStatistics().forEach(statisticRegistries.get(cacheName)::registerStatistic); + } + + @Override + public Collection getCacheDescriptors(String cacheName) { + return statisticRegistries.get(cacheName).getDescriptors(); + } + + @Override + public , K, V> void registerDerivedStatistics(String cacheName, Cache cache, String statName, T outcome, String derivedName, LatencyHistogramConfiguration configuration) { + DefaultLatencyHistogramStatistic histogram = new DefaultLatencyHistogramStatistic(configuration.getPhi(), configuration.getBucketCount(), configuration.getWindow()); + + @SuppressWarnings("unchecked") + Class outcomeClass = (Class) outcome.getClass(); + OperationStatistic stat = findOperationStatisticOnChildren(cache, outcomeClass, statName); + stat.addDerivedStatistic(new OperationResultFilter<>(EnumSet.of(outcome), histogram)); + + statisticRegistries.get(cacheName).registerStatistic(derivedName + "#50", histogram.medianStatistic()); + statisticRegistries.get(cacheName).registerStatistic(derivedName + "#95", histogram.percentileStatistic(0.95)); + statisticRegistries.get(cacheName).registerStatistic(derivedName + "#99", histogram.percentileStatistic(0.99)); + statisticRegistries.get(cacheName).registerStatistic(derivedName + "#100", histogram.maximumStatistic()); + } + + @Override + public Map> collectStatistics(String cacheName, Collection statisticNames, long since) { + return StatisticRegistry.collect(statisticRegistries.get(cacheName), statisticNames, since); + } + + public static void registerStatistic(Object context, String name, StatisticType type, Set tags, Supplier valueSupplier) { + StatisticsManager.createPassThroughStatistic(context, name, tags, StatisticType.convert(type), valueSupplier); + } + + public static > OperationObserver createOperationStatistics(String name, Class outcome, String tag, Object context) { + return new DelegatingOperationObserver<>(operation(outcome).named(name).of(context).tag(tag).build()); + } + + public boolean isStarted() { + return started; + } + + @Override + public void start(ServiceProvider serviceProvider) { + LOGGER.debug("Starting service"); + + CacheManagerProviderService cacheManagerProviderService = serviceProvider.getService(CacheManagerProviderService.class); + cacheManager = cacheManagerProviderService.getCacheManager(); + cacheManager.registerListener(this); + + started = true; + } + + @Override + public void stop() { + LOGGER.debug("Stopping service"); + cacheManager.deregisterListener(this); + cacheStatistics.clear(); + started = false; + } + + @Override + public void stateTransition(Status from, Status to) { + LOGGER.debug("Moving from " + from + " to " + to); + switch (to) { + case AVAILABLE: + registerAllCaches(); + break; + case UNINITIALIZED: + cacheManager.deregisterListener(this); + cacheStatistics.clear(); + break; + case MAINTENANCE: + throw new IllegalStateException("Should not be started in maintenance mode"); + default: + throw new AssertionError("Unsupported state: " + to); + } + } + + private void registerAllCaches() { + for (Map.Entry> entry : cacheManager.getRuntimeConfiguration().getCacheConfigurations().entrySet()) { + String alias = entry.getKey(); + CacheConfiguration configuration = entry.getValue(); + Cache cache = cacheManager.getCache(alias, configuration.getKeyType(), configuration.getValueType()); + cacheAdded(alias, cache); + } + } + + @Override + public void cacheAdded(String alias, Cache cache) { + LOGGER.debug("Cache added " + alias); + cacheStatistics.put(alias, new DefaultCacheStatistics((InternalCache) cache)); + } + + @Override + public void cacheRemoved(String alias, Cache cache) { + LOGGER.debug("Cache removed " + alias); + cacheStatistics.remove(alias); + } + +} diff --git a/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceFactory.java b/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsServiceFactory.java similarity index 96% rename from impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceFactory.java rename to core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsServiceFactory.java index ba2a2ecff4..b0aa724f19 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceFactory.java +++ b/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsServiceFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.impl.internal.statistics; +package org.ehcache.core.statistics; import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.core.spi.service.StatisticsService; diff --git a/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultTierStatistics.java b/core/src/main/java/org/ehcache/core/statistics/DefaultTierStatistics.java similarity index 96% rename from impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultTierStatistics.java rename to core/src/main/java/org/ehcache/core/statistics/DefaultTierStatistics.java index 565811498f..5bd4431e92 100755 --- a/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultTierStatistics.java +++ b/core/src/main/java/org/ehcache/core/statistics/DefaultTierStatistics.java @@ -14,12 +14,9 @@ * limitations under the License. */ -package org.ehcache.impl.internal.statistics; +package org.ehcache.core.statistics; import org.ehcache.Cache; -import org.ehcache.core.statistics.StoreOperationOutcomes; -import org.ehcache.core.statistics.TierOperationOutcomes; -import org.ehcache.core.statistics.TierStatistics; import org.terracotta.statistics.OperationStatistic; import org.terracotta.statistics.ValueStatistic; import org.terracotta.statistics.ZeroOperationStatistic; @@ -31,14 +28,14 @@ import java.util.Optional; import java.util.function.Supplier; -import static org.ehcache.impl.internal.statistics.StatsUtils.findStatisticOnDescendants; +import static org.ehcache.core.statistics.StatsUtils.findStatisticOnDescendants; import static org.terracotta.statistics.ValueStatistics.counter; import static org.terracotta.statistics.ValueStatistics.gauge; /** * Contains usage statistics relative to a given tier. */ -class DefaultTierStatistics implements TierStatistics { +public class DefaultTierStatistics implements TierStatistics { private volatile CompensatingCounters compensatingCounters = CompensatingCounters.empty(); diff --git a/core/src/main/java/org/ehcache/core/statistics/DelegatedMappedOperationStatistics.java b/core/src/main/java/org/ehcache/core/statistics/DelegatedMappedOperationStatistics.java new file mode 100644 index 0000000000..3b4ff273f2 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/statistics/DelegatedMappedOperationStatistics.java @@ -0,0 +1,107 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.statistics; + +import org.terracotta.statistics.MappedOperationStatistic; + +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collectors; + +public class DelegatedMappedOperationStatistics, D extends Enum> implements OperationStatistic { + + private final MappedOperationStatistic delegate; + + public DelegatedMappedOperationStatistics(MappedOperationStatistic operationStatistic) { + this.delegate = operationStatistic; + } + + @Override + public Class type() { + return delegate.type(); + } + + @Override + public long count(D type) { + return delegate.count(type); + } + + @Override + public long sum(Set types) { + return delegate.sum(types); + } + + @Override + public long sum() { + return delegate.sum(); + } + + @Override + public void begin() { + delegate.begin(); + } + + @Override + public void end(D result) { + delegate.end(result); + } + + @Override + public void addDerivedStatistic(ChainedOperationObserver derived) { + delegate.addDerivedStatistic(convert(derived)); + } + + @Override + public void removeDerivedStatistic(ChainedOperationObserver derived) { + delegate.removeDerivedStatistic(convert(derived)); + } + + @Override + public Collection> getDerivedStatistics() { + Collection> derivedStatistics = delegate.getDerivedStatistics(); + return derivedStatistics.stream().map(this::revert).collect(Collectors.toSet()); + } + + private ChainedOperationObserver revert(org.terracotta.statistics.observer.ChainedOperationObserver observer) { + return new ChainedOperationObserver() { + @Override + public void begin(long time) { + observer.begin(time); + } + + @Override + public void end(long time, long latency, D result) { + observer.end(time, latency, result); + } + }; + } + + private org.terracotta.statistics.observer.ChainedOperationObserver convert(ChainedOperationObserver observer) { + return new org.terracotta.statistics.observer.ChainedOperationObserver() { + @Override + public void begin(long time) { + observer.begin(time); + } + + @Override + public void end(long time, long latency, D result) { + observer.end(time, latency, result); + } + }; + } + + +} diff --git a/core/src/main/java/org/ehcache/core/statistics/DelegatingOperationObserver.java b/core/src/main/java/org/ehcache/core/statistics/DelegatingOperationObserver.java new file mode 100644 index 0000000000..1ec14b5e40 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/statistics/DelegatingOperationObserver.java @@ -0,0 +1,35 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.statistics; + +public class DelegatingOperationObserver> implements OperationObserver { + + private final org.terracotta.statistics.observer.OperationObserver observer; + + public DelegatingOperationObserver(org.terracotta.statistics.observer.OperationObserver operationObserver) { + this.observer = operationObserver; + } + + @Override + public void begin() { + this.observer.begin(); + } + + @Override + public void end(T result) { + this.observer.end(result); + } +} diff --git a/core/src/main/java/org/ehcache/core/statistics/DelegatingOperationStatistic.java b/core/src/main/java/org/ehcache/core/statistics/DelegatingOperationStatistic.java new file mode 100644 index 0000000000..c79d379755 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/statistics/DelegatingOperationStatistic.java @@ -0,0 +1,103 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.statistics; + +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collectors; + +public class DelegatingOperationStatistic> implements OperationStatistic { + + private final org.terracotta.statistics.OperationStatistic delegate; + + public DelegatingOperationStatistic(org.terracotta.statistics.OperationStatistic statistic) { + this.delegate = statistic; + } + + @Override + public Class type() { + return delegate.type(); + } + + @Override + public long count(T type) { + return delegate.count(type); + } + + @Override + public long sum(Set types) { + return delegate.sum(types); + } + + @Override + public long sum() { + return delegate.sum(); + } + + @Override + public void begin() { + delegate.begin(); + } + + @Override + public void end(T result) { + delegate.end(result); + } + + @Override + public void addDerivedStatistic(ChainedOperationObserver derived) { + delegate.addDerivedStatistic(convert(derived)); + } + + @Override + public void removeDerivedStatistic(ChainedOperationObserver derived) { + delegate.removeDerivedStatistic(convert(derived)); + } + + @Override + public Collection> getDerivedStatistics() { + Collection> derivedStatistics = delegate.getDerivedStatistics(); + return derivedStatistics.stream().map(this::revert).collect(Collectors.toSet()); + } + + private ChainedOperationObserver revert(org.terracotta.statistics.observer.ChainedOperationObserver observer) { + return new ChainedOperationObserver() { + @Override + public void begin(long time) { + observer.begin(time); + } + + @Override + public void end(long time, long latency, T result) { + observer.end(time, latency, result); + } + }; + } + + private org.terracotta.statistics.observer.ChainedOperationObserver convert(ChainedOperationObserver observer) { + return new org.terracotta.statistics.observer.ChainedOperationObserver() { + @Override + public void begin(long time) { + observer.begin(time); + } + + @Override + public void end(long time, long latency, T result) { + observer.end(time, latency, result); + } + }; + } +} diff --git a/core/src/main/java/org/ehcache/core/statistics/Jsr107LatencyMonitor.java b/core/src/main/java/org/ehcache/core/statistics/Jsr107LatencyMonitor.java new file mode 100644 index 0000000000..9be1c34fbc --- /dev/null +++ b/core/src/main/java/org/ehcache/core/statistics/Jsr107LatencyMonitor.java @@ -0,0 +1,45 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.statistics; + +import java.util.EnumSet; + +public class Jsr107LatencyMonitor> implements ChainedOperationObserver { + + private final org.terracotta.statistics.derived.latency.Jsr107LatencyMonitor delegate; + + public Jsr107LatencyMonitor(Class outcome, double sampling) { + delegate = new org.terracotta.statistics.derived.latency.Jsr107LatencyMonitor<>(EnumSet.allOf(outcome), 1.0); + } + + public double average() { + return delegate.average(); + } + + public void clear() { + delegate.clear(); + } + + @Override + public void begin(long time) { + delegate.begin(time); + } + + @Override + public void end(long time, long latency, T result) { + delegate.end(time, latency, result); + } +} diff --git a/management/src/main/java/org/ehcache/management/providers/statistics/LatencyHistogramConfiguration.java b/core/src/main/java/org/ehcache/core/statistics/LatencyHistogramConfiguration.java similarity index 93% rename from management/src/main/java/org/ehcache/management/providers/statistics/LatencyHistogramConfiguration.java rename to core/src/main/java/org/ehcache/core/statistics/LatencyHistogramConfiguration.java index b15a088044..85b9d9eda4 100644 --- a/management/src/main/java/org/ehcache/management/providers/statistics/LatencyHistogramConfiguration.java +++ b/core/src/main/java/org/ehcache/core/statistics/LatencyHistogramConfiguration.java @@ -13,17 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.management.providers.statistics; - -import org.terracotta.statistics.derived.latency.DefaultLatencyHistogramStatistic; +package org.ehcache.core.statistics; import java.time.Duration; import java.util.Objects; /** * Configuration of all latency histograms. - * - * @see DefaultLatencyHistogramStatistic */ public class LatencyHistogramConfiguration { diff --git a/core/src/main/java/org/ehcache/core/statistics/OperationObserver.java b/core/src/main/java/org/ehcache/core/statistics/OperationObserver.java new file mode 100644 index 0000000000..55fb6700c5 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/statistics/OperationObserver.java @@ -0,0 +1,47 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.core.statistics; + +/** + * Operation observers track the occurrence of processes which take a finite time + * and can potential terminate in different ways. + *

+ * Operations must have an associated enum type that represents their possible + * outcomes. An example of such an enum type would be: + *

+ * enum PlaneFlight {
+ *   LAND, CRASH;
+ * }
+ * 
+ * + * @param Enum type representing the possible operations 'results' + */ +public interface OperationObserver> { + + /** + * Called immediately prior to the operation beginning. + */ + void begin(); + + /** + * Called immediately after the operation completes with no interesting parameters, and with the same thread the called {{@link #begin()}} before. + * + * @param result the operation result + */ + void end(T result); + +} diff --git a/core/src/main/java/org/ehcache/core/statistics/OperationStatistic.java b/core/src/main/java/org/ehcache/core/statistics/OperationStatistic.java new file mode 100644 index 0000000000..afd1aabdf7 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/statistics/OperationStatistic.java @@ -0,0 +1,54 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.core.statistics; + +import java.util.Set; + +import static org.ehcache.core.statistics.SuppliedValueStatistic.counter; + + +public interface OperationStatistic> extends OperationObserver, SourceStatistic> { + + Class type(); + + /** + * Return a {@link ValueStatistic} returning the count for the given result. + * + * @param result the result of interest + * @return a {@code ValueStatistic} instance + */ + default ValueStatistic statistic(T result) { + return counter(() -> count(result)); + } + + default ValueStatistic statistic(Set results) { + return counter(() -> sum(results)); + } + + /** + * Return the count of operations with the given type. + * + * @param type the result type + * @return the operation count + */ + long count(T type); + + long sum(Set types); + + long sum(); + +} diff --git a/core/src/main/java/org/ehcache/core/statistics/SourceStatistic.java b/core/src/main/java/org/ehcache/core/statistics/SourceStatistic.java new file mode 100644 index 0000000000..b9472ab6f5 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/statistics/SourceStatistic.java @@ -0,0 +1,42 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.statistics; + +import java.util.Collection; + +public interface SourceStatistic { + + /** + * Register the given {@code Observer} to be called by this {@code SourceStatistic} + * + * @param derived statistic to be registered + */ + void addDerivedStatistic(T derived); + + /** + * Remove the given registered {@code Observer} from this {@code SourceStatistic}. + * + * @param derived statistic to be removed + */ + void removeDerivedStatistic(T derived); + + /** + * Retrieve all registered statistics. + * + * @return an unmodifiable collection of all derived statistics + */ + Collection getDerivedStatistics(); +} diff --git a/impl/src/main/java/org/ehcache/impl/internal/statistics/StatsUtils.java b/core/src/main/java/org/ehcache/core/statistics/StatsUtils.java similarity index 93% rename from impl/src/main/java/org/ehcache/impl/internal/statistics/StatsUtils.java rename to core/src/main/java/org/ehcache/core/statistics/StatsUtils.java index 4e23231adb..12dc4bcbee 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/statistics/StatsUtils.java +++ b/core/src/main/java/org/ehcache/core/statistics/StatsUtils.java @@ -14,21 +14,23 @@ * limitations under the License. */ -package org.ehcache.impl.internal.statistics; +package org.ehcache.core.statistics; import java.util.Collections; +import java.util.EnumSet; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.function.Consumer; import org.ehcache.Cache; -import org.ehcache.core.statistics.StoreOperationOutcomes; import org.terracotta.context.ContextManager; import org.terracotta.context.TreeNode; import org.terracotta.context.query.Matcher; import org.terracotta.context.query.Matchers; import org.terracotta.context.query.Query; import org.terracotta.statistics.OperationStatistic; +import org.terracotta.statistics.derived.OperationResultFilter; import static org.terracotta.context.query.Matchers.*; import static org.terracotta.context.query.QueryBuilder.queryBuilder; @@ -252,4 +254,11 @@ protected boolean matchesSafely(OperationStatistic object) { return !result.isEmpty(); } + + public static void registerClearNotification(String alias, Cache cache, Consumer cacheClear) { + OperationStatistic clear = StatsUtils.findOperationStatisticOnChildren(cache, + CacheOperationOutcomes.ClearOutcome.class, "clear"); + clear.addDerivedStatistic(new OperationResultFilter<>(EnumSet.of(CacheOperationOutcomes.ClearOutcome.SUCCESS), + (time, latency) -> cacheClear.accept(alias))); + } } diff --git a/core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java b/core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java new file mode 100644 index 0000000000..feb2d57680 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java @@ -0,0 +1,59 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.core.statistics; + +import org.terracotta.management.model.stats.StatisticType; + +import java.io.Serializable; +import java.util.Objects; +import java.util.function.Supplier; + + +/** + * This class can be used to create a {@link ValueStatistic} with a specific {@link StatisticType} + * which value is given by a provided {@link Supplier} + * + * @author Mathieu Carbou + */ +public class SuppliedValueStatistic implements ValueStatistic { + + private final Supplier supplier; + private final StatisticType type; + + public SuppliedValueStatistic(StatisticType type, Supplier supplier) { + this.type = Objects.requireNonNull(type); + this.supplier = Objects.requireNonNull(supplier); + } + + @Override + public T value() { + return supplier.get(); + } + + @Override + public StatisticType type() { + return type; + } + + public static ValueStatistic counter(Supplier supplier) { + return supply(StatisticType.COUNTER, supplier); + } + + public static ValueStatistic supply(StatisticType type, Supplier supplier) { + return new SuppliedValueStatistic<>(type, supplier); + } +} diff --git a/core/src/main/java/org/ehcache/core/statistics/ValueStatistic.java b/core/src/main/java/org/ehcache/core/statistics/ValueStatistic.java new file mode 100644 index 0000000000..51101ae11d --- /dev/null +++ b/core/src/main/java/org/ehcache/core/statistics/ValueStatistic.java @@ -0,0 +1,35 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.core.statistics; + +import org.terracotta.management.model.stats.StatisticType; + +import java.io.Serializable; + +public interface ValueStatistic { + + /** + * @return The statistic type + */ + StatisticType type(); + + /** + * @return The current statistic value + */ + T value(); + +} diff --git a/core/src/main/java/org/ehcache/core/statistics/ZeroOperationStatistic.java b/core/src/main/java/org/ehcache/core/statistics/ZeroOperationStatistic.java new file mode 100644 index 0000000000..7a09e6cebc --- /dev/null +++ b/core/src/main/java/org/ehcache/core/statistics/ZeroOperationStatistic.java @@ -0,0 +1,75 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.statistics; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +public class ZeroOperationStatistic> implements OperationStatistic { + + private static final OperationStatistic INSTANCE = new ZeroOperationStatistic<>(); + + @SuppressWarnings("unchecked") + public static > OperationStatistic get() { + return (OperationStatistic) INSTANCE; + } + + @Override + public Class type() { + return null; + } + + @Override + public long count(T type) { + return 0; + } + + @Override + public long sum(Set types) { + return 0; + } + + @Override + public long sum() { + return 0; + } + + @Override + public void addDerivedStatistic(ChainedOperationObserver derived) { + + } + + @Override + public void removeDerivedStatistic(ChainedOperationObserver derived) { + + } + + @Override + public Collection> getDerivedStatistics() { + return Collections.emptyList(); + } + + @Override + public void begin() { + + } + + @Override + public void end(T result) { + + } +} diff --git a/gradle.properties b/gradle.properties index 2788587973..6bd52981e1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.3-pre6 +terracottaPlatformVersion = 5.7-SNAPSHOT terracottaApisVersion = 1.6.1 terracottaCoreVersion = 5.6.4-pre9 terracottaPassthroughTestingVersion = 1.6.1 @@ -35,3 +35,4 @@ deployUrl = https://oss.sonatype.org/service/local/staging/deploy/maven2/ # Enable the daemon by adding org.gradle.daemon in USER_HOME/.gradle/gradle.properties org.gradle.parallel=true +mvnlocal=true diff --git a/impl/build.gradle b/impl/build.gradle index 0808a31050..573c6e4146 100644 --- a/impl/build.gradle +++ b/impl/build.gradle @@ -32,11 +32,14 @@ dependencies { implementation (group: 'org.ehcache', name: 'sizeof', version: parent.sizeofVersion) { exclude group:'org.slf4j', module:'slf4j-api' } - implementation ("org.terracotta:statistics:$parent.statisticVersion") + implementation ("org.terracotta.management:management-model:$terracottaPlatformVersion") { + exclude group:'org.terracotta', module:'statistics' + } compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':core-spi-test') testImplementation 'org.ow2.asm:asm:6.2' testImplementation 'org.ow2.asm:asm-commons:6.2' + testImplementation ("org.terracotta:statistics:$parent.statisticVersion") unsafeImplementation project(':api') unsafeCompileOnly "com.github.spotbugs:spotbugs-annotations:$parent.spotbugsVersion" diff --git a/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsService.java b/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsService.java deleted file mode 100644 index c17de6e887..0000000000 --- a/impl/src/main/java/org/ehcache/impl/internal/statistics/DefaultStatisticsService.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.ehcache.impl.internal.statistics; - -import org.ehcache.Cache; -import org.ehcache.Status; -import org.ehcache.config.CacheConfiguration; -import org.ehcache.core.InternalCache; -import org.ehcache.core.events.CacheManagerListener; -import org.ehcache.core.spi.service.CacheManagerProviderService; -import org.ehcache.core.spi.service.StatisticsService; -import org.ehcache.core.spi.store.InternalCacheManager; -import org.ehcache.core.statistics.CacheStatistics; -import org.ehcache.spi.service.Service; -import org.ehcache.spi.service.ServiceDependencies; -import org.ehcache.spi.service.ServiceProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * Default implementation using the statistics calculated by the observers set on the caches. - */ -@ServiceDependencies(CacheManagerProviderService.class) -public class DefaultStatisticsService implements StatisticsService, CacheManagerListener { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultStatisticsService.class); - - private final ConcurrentMap cacheStatistics = new ConcurrentHashMap<>(); - - private volatile InternalCacheManager cacheManager; - private volatile boolean started = false; - - public CacheStatistics getCacheStatistics(String cacheName) { - CacheStatistics stats = cacheStatistics.get(cacheName); - if (stats == null) { - throw new IllegalArgumentException("Unknown cache: " + cacheName); - } - return stats; - } - - public boolean isStarted() { - return started; - } - - @Override - public void start(ServiceProvider serviceProvider) { - LOGGER.debug("Starting service"); - - CacheManagerProviderService cacheManagerProviderService = serviceProvider.getService(CacheManagerProviderService.class); - cacheManager = cacheManagerProviderService.getCacheManager(); - cacheManager.registerListener(this); - - started = true; - } - - @Override - public void stop() { - LOGGER.debug("Stopping service"); - cacheManager.deregisterListener(this); - cacheStatistics.clear(); - started = false; - } - - @Override - public void stateTransition(Status from, Status to) { - LOGGER.debug("Moving from " + from + " to " + to); - switch (to) { - case AVAILABLE: - registerAllCaches(); - break; - case UNINITIALIZED: - cacheManager.deregisterListener(this); - cacheStatistics.clear(); - break; - case MAINTENANCE: - throw new IllegalStateException("Should not be started in maintenance mode"); - default: - throw new AssertionError("Unsupported state: " + to); - } - } - - private void registerAllCaches() { - for (Map.Entry> entry : cacheManager.getRuntimeConfiguration().getCacheConfigurations().entrySet()) { - String alias = entry.getKey(); - CacheConfiguration configuration = entry.getValue(); - Cache cache = cacheManager.getCache(alias, configuration.getKeyType(), configuration.getValueType()); - cacheAdded(alias, cache); - } - } - - @Override - public void cacheAdded(String alias, Cache cache) { - LOGGER.debug("Cache added " + alias); - cacheStatistics.put(alias, new DefaultCacheStatistics((InternalCache) cache)); - } - - @Override - public void cacheRemoved(String alias, Cache cache) { - LOGGER.debug("Cache removed " + alias); - cacheStatistics.remove(alias); - } - -} diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java index 988f921fc2..975d6c3e6b 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java @@ -22,6 +22,9 @@ import org.ehcache.config.EvictionAdvisor; import org.ehcache.config.ResourceType; import org.ehcache.core.spi.service.DiskResourceService; +import org.ehcache.core.spi.service.StatisticsService; +import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.statistics.OperationStatistic; import org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.events.StoreEventDispatcher; @@ -58,8 +61,6 @@ import org.terracotta.offheapstore.disk.storage.FileBackedStorageEngine; import org.terracotta.offheapstore.storage.portability.Portability; import org.terracotta.offheapstore.util.Factory; -import org.terracotta.statistics.OperationStatistic; -import org.terracotta.statistics.StatisticsManager; import java.io.File; import java.io.FileInputStream; @@ -297,7 +298,6 @@ public static class Provider extends BaseStoreProvider implements AuthoritativeT private final Map, OperationStatistic[]> tierOperationStatistics = new ConcurrentWeakIdentityHashMap<>(); private final Map, PersistenceSpaceIdentifier> createdStores = new ConcurrentWeakIdentityHashMap<>(); private final String defaultThreadPool; - private volatile ServiceProvider serviceProvider; private volatile DiskResourceService diskPersistenceService; public Provider() { @@ -386,7 +386,7 @@ public void releaseStore(Store resource) { try { OffHeapDiskStore offHeapDiskStore = (OffHeapDiskStore)resource; close(offHeapDiskStore); - StatisticsManager.nodeFor(offHeapDiskStore).clean(); + DefaultStatisticsService.cleanForNode(offHeapDiskStore); tierOperationStatistics.remove(offHeapDiskStore); } catch (IOException e) { throw new RuntimeException(e); diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index 024cd9c19a..515b870c3c 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -29,6 +29,10 @@ import org.ehcache.core.config.ExpiryUtils; import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.core.events.StoreEventSink; +import org.ehcache.core.spi.service.StatisticsService; +import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.statistics.OperationObserver; +import org.ehcache.core.statistics.OperationStatistic; import org.ehcache.impl.internal.concurrent.EvictingConcurrentMap; import org.ehcache.impl.store.BaseStore; import org.ehcache.spi.resilience.StoreAccessException; @@ -70,9 +74,7 @@ import org.ehcache.core.statistics.TierOperationOutcomes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.terracotta.statistics.OperationStatistic; -import org.terracotta.statistics.StatisticsManager; -import org.terracotta.statistics.observer.OperationObserver; +import org.terracotta.management.model.stats.StatisticType; import java.time.Duration; import java.util.ArrayList; @@ -99,8 +101,6 @@ import static org.ehcache.config.Eviction.noAdvice; import static org.ehcache.core.config.ExpiryUtils.isExpiryDurationInfinite; import static org.ehcache.core.exceptions.StorePassThroughException.handleException; -import static org.terracotta.statistics.StatisticType.COUNTER; -import static org.terracotta.statistics.StatisticType.GAUGE; /** * {@link Store} and {@link HigherCachingTier} implementation for on heap. @@ -261,9 +261,9 @@ public OnHeapStore(Configuration config, TimeSource timeSource, Copier silentInvalidateAllWithHashObserver = createObserver("silentInvalidateAllWithHash", HigherCachingTierOperationOutcomes.SilentInvalidateAllWithHashOutcome.class, true); Set tags = new HashSet<>(Arrays.asList(getStatisticsTag(), "tier")); - registerStatistic("mappings", COUNTER, tags, () -> map.mappingCount()); + registerStatistic("mappings", StatisticType.COUNTER, tags, () -> map.mappingCount()); if (byteSized) { - registerStatistic("occupiedMemory", GAUGE, tags, () -> map.byteSize()); + registerStatistic("occupiedMemory", StatisticType.GAUGE, tags, () -> map.byteSize()); } } @@ -1621,7 +1621,6 @@ void fireOnExpirationEvent(K mappedKey, ValueHolder mappedValue, StoreEventSi @ServiceDependencies({TimeSourceService.class, CopyProvider.class, SizeOfEngineProvider.class}) public static class Provider extends BaseStoreProvider implements CachingTier.Provider, HigherCachingTier.Provider { - private volatile ServiceProvider serviceProvider; private final Map, List>> createdStores = new ConcurrentWeakIdentityHashMap<>(); private final Map, OperationStatistic[]> tierOperationStatistics = new ConcurrentWeakIdentityHashMap<>(); @@ -1676,7 +1675,7 @@ public void releaseStore(Store resource) { } OnHeapStore onHeapStore = (OnHeapStore)resource; close(onHeapStore); - StatisticsManager.nodeFor(onHeapStore).clean(); + DefaultStatisticsService.cleanForNode(onHeapStore); tierOperationStatistics.remove(onHeapStore); CopyProvider copyProvider = serviceProvider.getService(CopyProvider.class); diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java index 3673f38047..101833046d 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java @@ -19,6 +19,7 @@ import org.ehcache.core.CacheConfigurationChangeListener; import org.ehcache.core.Ehcache; import org.ehcache.core.exceptions.StorePassThroughException; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.util.CollectionUtil; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.WrapperStore; @@ -27,12 +28,9 @@ import org.ehcache.spi.loaderwriter.BulkCacheLoadingException; import org.ehcache.spi.loaderwriter.BulkCacheWritingException; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; -import org.ehcache.spi.loaderwriter.WriteBehindConfiguration; import org.ehcache.spi.resilience.StoreAccessException; -import org.ehcache.spi.service.ServiceConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.terracotta.context.ContextManager; import java.time.Duration; import java.util.Collection; @@ -50,7 +48,6 @@ import static org.ehcache.core.exceptions.ExceptionFactory.newCacheLoadingException; import static org.ehcache.core.exceptions.ExceptionFactory.newCacheWritingException; -import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; public class LocalLoaderWriterStore implements WrapperStore { @@ -68,7 +65,7 @@ public LocalLoaderWriterStore(Store delegate, CacheLoaderWriter extends BaseStore implements AuthoritativeTier, LowerCachingTier { @@ -136,17 +135,17 @@ public AbstractOffHeapStore(Configuration config, TimeSource timeSource, S this.installMappingObserver= createObserver("installMapping", LowerCachingTierOperationsOutcome.InstallMappingOutcome.class, true); Set tags = tags(getStatisticsTag(), "tier"); - registerStatistic("allocatedMemory", GAUGE, tags, EhcacheOffHeapBackingMap::allocatedMemory); - registerStatistic("occupiedMemory", GAUGE, tags, EhcacheOffHeapBackingMap::occupiedMemory); - registerStatistic("dataAllocatedMemory", GAUGE, tags, EhcacheOffHeapBackingMap::dataAllocatedMemory); - registerStatistic("dataOccupiedMemory", GAUGE, tags, EhcacheOffHeapBackingMap::dataOccupiedMemory); - registerStatistic("dataSize", GAUGE, tags, EhcacheOffHeapBackingMap::dataSize); - registerStatistic("dataVitalMemory", GAUGE, tags, EhcacheOffHeapBackingMap::dataVitalMemory); - registerStatistic("mappings", GAUGE, tags, EhcacheOffHeapBackingMap::longSize); - registerStatistic("vitalMemory", GAUGE, tags, EhcacheOffHeapBackingMap::vitalMemory); - registerStatistic("removedSlotCount", GAUGE, tags, EhcacheOffHeapBackingMap::removedSlotCount); - registerStatistic("usedSlotCount", GAUGE, tags, EhcacheOffHeapBackingMap::usedSlotCount); - registerStatistic("tableCapacity", GAUGE, tags, EhcacheOffHeapBackingMap::tableCapacity); + registerStatistic("allocatedMemory", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::allocatedMemory); + registerStatistic("occupiedMemory", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::occupiedMemory); + registerStatistic("dataAllocatedMemory", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::dataAllocatedMemory); + registerStatistic("dataOccupiedMemory", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::dataOccupiedMemory); + registerStatistic("dataSize", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::dataSize); + registerStatistic("dataVitalMemory", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::dataVitalMemory); + registerStatistic("mappings", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::longSize); + registerStatistic("vitalMemory", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::vitalMemory); + registerStatistic("removedSlotCount", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::removedSlotCount); + registerStatistic("usedSlotCount", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::usedSlotCount); + registerStatistic("tableCapacity", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::tableCapacity); this.mapEvictionListener = new BackingMapEvictionListener<>(eventDispatcher, evictionObserver); } @@ -161,6 +160,8 @@ private void registerStatistic(String name, StatisticTy }); } + private static Set tags(String... tags) {return new HashSet<>(Arrays.asList(tags));} + @Override public Store.ValueHolder get(K key) throws StoreAccessException { checkKey(key); diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java index 196309ee86..5932e3200f 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java @@ -22,6 +22,8 @@ import org.ehcache.config.ResourceType; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.events.StoreEventDispatcher; +import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.statistics.OperationStatistic; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.events.NullStoreEventDispatcher; import org.ehcache.impl.internal.events.ThreadLocalStoreEventDispatcher; @@ -51,8 +53,6 @@ import org.terracotta.offheapstore.storage.PointerSize; import org.terracotta.offheapstore.storage.portability.Portability; import org.terracotta.offheapstore.util.Factory; -import org.terracotta.statistics.OperationStatistic; -import org.terracotta.statistics.StatisticsManager; import java.util.Collection; import java.util.Collections; @@ -131,7 +131,6 @@ public static class Provider extends BaseStoreProvider implements AuthoritativeT private static final Logger LOGGER = LoggerFactory.getLogger(Provider.class); - private volatile ServiceProvider serviceProvider; private final Set> createdStores = Collections.newSetFromMap(new ConcurrentWeakIdentityHashMap<>()); private final Map, OperationStatistic[]> tierOperationStatistics = new ConcurrentWeakIdentityHashMap<>(); @@ -188,7 +187,7 @@ public void releaseStore(Store resource) { } OffHeapStore offHeapStore = (OffHeapStore) resource; close(offHeapStore); - StatisticsManager.nodeFor(offHeapStore).clean(); + DefaultStatisticsService.cleanForNode(offHeapStore); tierOperationStatistics.remove(offHeapStore); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java index efb2d5f57e..96502c7953 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java @@ -19,6 +19,7 @@ import org.ehcache.core.CacheConfigurationChangeListener; import org.ehcache.core.collections.ConcurrentWeakIdentityHashMap; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.store.tiering.CachingTier; import org.ehcache.core.spi.store.tiering.HigherCachingTier; @@ -29,7 +30,6 @@ import org.ehcache.spi.service.ServiceProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.terracotta.statistics.StatisticsManager; import java.util.AbstractMap; import java.util.ArrayList; @@ -68,8 +68,8 @@ public CompoundCachingTier(HigherCachingTier higher, final LowerCachingTie } }); - StatisticsManager.associate(higher).withParent(this); - StatisticsManager.associate(lower).withParent(this); + DefaultStatisticsService.registerWithParent(higher, this); + DefaultStatisticsService.registerWithParent(lower, this); } private void notifyInvalidation(K key, Store.ValueHolder p) { diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java index a24910d174..6b0169c35c 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java @@ -22,6 +22,7 @@ import org.ehcache.core.collections.ConcurrentWeakIdentityHashMap; import org.ehcache.core.exceptions.StorePassThroughException; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.store.events.StoreEventSource; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; @@ -30,7 +31,6 @@ import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.spi.service.ServiceProvider; -import org.terracotta.statistics.StatisticsManager; import java.util.AbstractMap; import java.util.ArrayList; @@ -79,8 +79,8 @@ public void invalidateAllWithHash(long hash) throws StoreAccessException { } }); - StatisticsManager.associate(cachingTier).withParent(this); - StatisticsManager.associate(authoritativeTier).withParent(this); + DefaultStatisticsService.registerWithParent(cachingTier, this); + DefaultStatisticsService.registerWithParent(authoritativeTier, this); } @Override diff --git a/impl/src/main/java/org/ehcache/impl/store/BaseStore.java b/impl/src/main/java/org/ehcache/impl/store/BaseStore.java index a2198dbcc6..f59f1f650f 100644 --- a/impl/src/main/java/org/ehcache/impl/store/BaseStore.java +++ b/impl/src/main/java/org/ehcache/impl/store/BaseStore.java @@ -18,14 +18,17 @@ import org.ehcache.config.ResourceType; import org.ehcache.core.config.store.StoreStatisticsConfiguration; +import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.Store; -import org.ehcache.impl.internal.statistics.StatsUtils; -import org.terracotta.statistics.MappedOperationStatistic; -import org.terracotta.statistics.OperationStatistic; -import org.terracotta.statistics.StatisticType; -import org.terracotta.statistics.StatisticsManager; -import org.terracotta.statistics.ZeroOperationStatistic; -import org.terracotta.statistics.observer.OperationObserver; +import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.statistics.DelegatedMappedOperationStatistics; +import org.ehcache.core.statistics.OperationObserver; +import org.ehcache.core.statistics.OperationStatistic; +import org.ehcache.core.statistics.StatsUtils; +import org.ehcache.core.statistics.ZeroOperationStatistic; +import org.ehcache.spi.service.Service; +import org.ehcache.spi.service.ServiceProvider; +import org.terracotta.management.model.stats.StatisticType; import java.io.Serializable; import java.util.Map; @@ -33,8 +36,6 @@ import java.util.Set; import java.util.function.Supplier; -import static org.terracotta.statistics.StatisticBuilder.operation; - /** * Base class to most stores. It provides functionality common to stores in general. A given store implementation is not required to extend * it but the implementor might find it easier to do so. @@ -83,11 +84,11 @@ protected > OperationObserver createObserver(String name, C if(!operationStatisticsEnabled && canBeDisabled) { return ZeroOperationStatistic.get(); } - return operation(outcome).named(name).of(this).tag(getStatisticsTag()).build(); + return DefaultStatisticsService.createOperationStatistics(name, outcome, getStatisticsTag(), this); } protected void registerStatistic(String name, StatisticType type, Set tags, Supplier valueSupplier) { - StatisticsManager.createPassThroughStatistic(this, name, tags, type, valueSupplier); + DefaultStatisticsService.registerStatistic(this, name, type, tags, valueSupplier); } protected abstract String getStatisticsTag(); @@ -95,32 +96,10 @@ protected void registerStatistic(String name, Statistic protected static abstract class BaseStoreProvider implements Store.Provider { - protected , T extends Enum> OperationStatistic createTranslatedStatistic(BaseStore store, String statisticName, Map> translation, String targetName) { - Class outcomeType = getOutcomeType(translation); - - // If the original stat doesn't exist, we do not need to translate it - if (StatsUtils.hasOperationStat(store, outcomeType, targetName)) { - int tierHeight = getResourceType().getTierHeight(); - OperationStatistic stat = new MappedOperationStatistic<>(store, translation, statisticName, tierHeight, targetName, store - .getStatisticsTag()); - StatisticsManager.associate(stat).withParent(store); - return stat; - } - return ZeroOperationStatistic.get(); - } + protected volatile ServiceProvider serviceProvider; - /** - * From the Map of translation, we extract one of the items to get the declaring class of the enum. - * - * @param translation translation map - * @param type of the outcome - * @param type of the possible translations - * @return the outcome type - */ - private static , T extends Enum> Class getOutcomeType(Map> translation) { - Map.Entry> first = translation.entrySet().iterator().next(); - Class outcomeType = first.getValue().iterator().next().getDeclaringClass(); - return outcomeType; + protected , T extends Enum> OperationStatistic createTranslatedStatistic(BaseStore store, String statisticName, Map> translation, String targetName) { + return DefaultStatisticsService.registerStoreStatistics(store, targetName, getResourceType().getTierHeight(), store.getStatisticsTag(), translation, statisticName); } protected abstract ResourceType getResourceType(); diff --git a/impl/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory b/impl/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory index b7a4bc98f6..cd8eb5c2ec 100644 --- a/impl/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory +++ b/impl/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory @@ -16,5 +16,5 @@ org.ehcache.impl.internal.loaderwriter.writebehind.WriteBehindProviderFactory org.ehcache.impl.internal.events.CacheEventNotificationListenerServiceProviderFactory org.ehcache.impl.internal.spi.copy.DefaultCopyProviderFactory org.ehcache.impl.internal.sizeof.DefaultSizeOfEngineProviderFactory -org.ehcache.impl.internal.statistics.DefaultStatisticsServiceFactory +org.ehcache.core.statistics.DefaultStatisticsServiceFactory org.ehcache.impl.internal.spi.resilience.DefaultResilienceStrategyProviderFactory diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java index 85c545a365..5ba0e4406f 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java @@ -26,6 +26,8 @@ import org.ehcache.core.InternalCache; import org.ehcache.core.config.store.StoreStatisticsConfiguration; import org.ehcache.core.statistics.CacheOperationOutcomes; +import org.ehcache.core.statistics.ChainedOperationObserver; +import org.ehcache.core.statistics.DefaultCacheStatistics; import org.ehcache.event.CacheEvent; import org.ehcache.event.CacheEventListener; import org.ehcache.event.EventType; @@ -36,7 +38,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import org.terracotta.statistics.observer.ChainedOperationObserver; import java.time.Duration; import java.util.ArrayList; @@ -212,7 +213,7 @@ public void getExpirations() throws Exception { @Test public void registerDerivedStatistics() { AtomicBoolean endCalled = new AtomicBoolean(); - ChainedOperationObserver derivedStatistic = new ChainedOperationObserver() { + ChainedOperationObserver derivedStatistic = new org.ehcache.core.statistics.ChainedOperationObserver() { @Override public void begin(long time) { diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java index 353d465fe4..2e5f8c4005 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java @@ -22,6 +22,7 @@ import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.spi.test.After; import org.junit.Before; import org.junit.Rule; diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsDisabledTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsDisabledTest.java index 8bbc683176..1eebd1e1b9 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsDisabledTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsDisabledTest.java @@ -23,6 +23,7 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; +import org.ehcache.core.statistics.DefaultTierStatistics; import org.ehcache.impl.internal.TimeSourceConfiguration; import org.ehcache.internal.TestTimeSource; import org.junit.After; diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java index a728828231..cf12e539fb 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java @@ -25,6 +25,7 @@ import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.core.config.store.StoreStatisticsConfiguration; +import org.ehcache.core.statistics.DefaultTierStatistics; import org.ehcache.impl.internal.TimeSourceConfiguration; import org.ehcache.internal.TestTimeSource; import org.junit.After; diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java index d9ea7b6075..ad36a9f990 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java @@ -45,7 +45,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; -import static org.ehcache.impl.internal.statistics.StatsUtils.*; +import static org.ehcache.core.statistics.StatsUtils.*; import static org.terracotta.context.query.Matchers.attributes; import static org.terracotta.context.query.Matchers.context; import static org.terracotta.context.query.Matchers.hasAttribute; diff --git a/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java b/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java index 7772f1e9de..f317efd20b 100644 --- a/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java @@ -28,7 +28,7 @@ import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; import org.ehcache.impl.internal.TimeSourceConfiguration; -import org.ehcache.impl.internal.statistics.DefaultStatisticsService; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.integration.statistics.AbstractCacheCalculationTest; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.service.Service; diff --git a/integration-test/src/test/java/org/ehcache/integration/statistics/CacheCalculationTest.java b/integration-test/src/test/java/org/ehcache/integration/statistics/CacheCalculationTest.java index ca1d07ff7c..c0999c7790 100644 --- a/integration-test/src/test/java/org/ehcache/integration/statistics/CacheCalculationTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/statistics/CacheCalculationTest.java @@ -30,7 +30,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; -import org.ehcache.impl.internal.statistics.DefaultStatisticsService; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java b/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java index 2d1970bb8d..4c97c4a5fc 100644 --- a/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java @@ -33,7 +33,7 @@ import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; import org.ehcache.impl.internal.TimeSourceConfiguration; -import org.ehcache.impl.internal.statistics.DefaultStatisticsService; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.integration.TestTimeSource; import org.junit.After; import org.junit.Before; diff --git a/management/build.gradle b/management/build.gradle index c1cb9330c0..44a5bbd437 100644 --- a/management/build.gradle +++ b/management/build.gradle @@ -23,7 +23,9 @@ dependencies { // optional: if we want to use the clustered management layer compileOnly project(':clustered:client') compileOnly "org.terracotta:entity-client-api:$terracottaApisVersion" - compileOnly "org.terracotta.management.dist:mnm-nms-agent:$terracottaPlatformVersion" + compileOnly ("org.terracotta.management.dist:mnm-nms-agent:$terracottaPlatformVersion") { + exclude group:'org.terracotta', module:'statistics' + } compileOnly project(':api') compileOnly project(':core') diff --git a/management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java b/management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java index a17532326f..a6552dc361 100644 --- a/management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java +++ b/management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java @@ -15,7 +15,7 @@ */ package org.ehcache.management; -import org.ehcache.management.providers.statistics.LatencyHistogramConfiguration; +import org.ehcache.core.statistics.LatencyHistogramConfiguration; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.terracotta.management.model.context.Context; diff --git a/management/src/main/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProvider.java b/management/src/main/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProvider.java index 23d04bd1c1..e4b1793eb0 100644 --- a/management/src/main/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProvider.java +++ b/management/src/main/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProvider.java @@ -24,10 +24,9 @@ import org.terracotta.management.model.capabilities.descriptors.Descriptor; import org.terracotta.management.model.capabilities.descriptors.StatisticDescriptor; import org.terracotta.management.model.context.Context; -import org.terracotta.management.registry.DefaultStatisticsManagementProvider; +import org.terracotta.management.model.stats.Statistic; import org.terracotta.management.registry.Named; import org.terracotta.management.registry.collect.StatisticProvider; -import org.terracotta.statistics.registry.Statistic; import java.io.Serializable; import java.util.Collection; @@ -72,8 +71,7 @@ public Map> collectStatistics(Context if (exposedObject == null) { return Collections.emptyMap(); } - return DefaultStatisticsManagementProvider.collect(exposedObject.getStatisticRegistry(), statisticNames, since); - + return exposedObject.collectStatistics(statisticNames, since); } } diff --git a/management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java b/management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java index 481dac90fc..88875ad9c4 100644 --- a/management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java +++ b/management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java @@ -15,62 +15,55 @@ */ package org.ehcache.management.providers.statistics; +import org.ehcache.Cache; import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.core.statistics.CacheOperationOutcomes; -import org.ehcache.core.statistics.CacheStatistics; +import org.ehcache.core.statistics.LatencyHistogramConfiguration; import org.ehcache.management.ManagementRegistryServiceConfiguration; import org.ehcache.management.providers.CacheBinding; import org.ehcache.management.providers.ExposedCacheBinding; import org.terracotta.management.model.capabilities.descriptors.StatisticDescriptor; -import org.terracotta.management.registry.collect.StatisticRegistry; -import org.terracotta.statistics.derived.OperationResultFilter; -import org.terracotta.statistics.derived.latency.DefaultLatencyHistogramStatistic; +import org.terracotta.management.model.stats.Statistic; +import java.io.Serializable; import java.util.Collection; -import java.util.EnumSet; +import java.util.Map; public class StandardEhcacheStatistics extends ExposedCacheBinding { - private final StatisticRegistry statisticRegistry; + private final String cacheAlias; + private final StatisticsService statisticsService; StandardEhcacheStatistics(ManagementRegistryServiceConfiguration registryConfiguration, CacheBinding cacheBinding, StatisticsService statisticsService, TimeSource timeSource) { super(registryConfiguration, cacheBinding); - this.statisticRegistry = new StatisticRegistry(cacheBinding.getCache(), timeSource::getTimeMillis); + this.cacheAlias = cacheBinding.getAlias(); + this.statisticsService = statisticsService; - String cacheName = cacheBinding.getAlias(); - CacheStatistics cacheStatistics = statisticsService.getCacheStatistics(cacheName); + statisticsService.createCacheRegistry(this.cacheAlias, cacheBinding.getCache(), timeSource::getTimeMillis); - cacheStatistics.getKnownStatistics().forEach(statisticRegistry::registerStatistic); + statisticsService.registerCacheStatistics(this.cacheAlias); LatencyHistogramConfiguration latencyHistogramConfiguration = registryConfiguration.getLatencyHistogramConfiguration(); // We want some latency statistics as well, so let's register them - registerDerivedStatistics(cacheStatistics, "get", CacheOperationOutcomes.GetOutcome.HIT, "Cache:GetHitLatency", latencyHistogramConfiguration); - registerDerivedStatistics(cacheStatistics, "get", CacheOperationOutcomes.GetOutcome.MISS, "Cache:GetMissLatency", latencyHistogramConfiguration); - registerDerivedStatistics(cacheStatistics, "put", CacheOperationOutcomes.PutOutcome.PUT, "Cache:PutLatency", latencyHistogramConfiguration); - registerDerivedStatistics(cacheStatistics, "remove", CacheOperationOutcomes.RemoveOutcome.SUCCESS, "Cache:RemoveLatency", latencyHistogramConfiguration); + registerDerivedStatistics(cacheBinding.getCache(), "get", CacheOperationOutcomes.GetOutcome.HIT, "Cache:GetHitLatency", latencyHistogramConfiguration); + registerDerivedStatistics(cacheBinding.getCache(),"get", CacheOperationOutcomes.GetOutcome.MISS, "Cache:GetMissLatency", latencyHistogramConfiguration); + registerDerivedStatistics(cacheBinding.getCache(),"put", CacheOperationOutcomes.PutOutcome.PUT, "Cache:PutLatency", latencyHistogramConfiguration); + registerDerivedStatistics(cacheBinding.getCache(),"remove", CacheOperationOutcomes.RemoveOutcome.SUCCESS, "Cache:RemoveLatency", latencyHistogramConfiguration); } - private > void registerDerivedStatistics(CacheStatistics cacheStatistics, String statName, T outcome, String derivedName, LatencyHistogramConfiguration configuration) { - @SuppressWarnings("unchecked") - Class outcomeClass = (Class) outcome.getClass(); - DefaultLatencyHistogramStatistic histogram = new DefaultLatencyHistogramStatistic(configuration.getPhi(), configuration.getBucketCount(), configuration.getWindow()); - cacheStatistics.registerDerivedStatistic(outcomeClass, statName, new OperationResultFilter<>(EnumSet.of(outcome), histogram)); - - statisticRegistry.registerStatistic(derivedName + "#50", histogram.medianStatistic()); - statisticRegistry.registerStatistic(derivedName + "#95", histogram.percentileStatistic(0.95)); - statisticRegistry.registerStatistic(derivedName + "#99", histogram.percentileStatistic(0.99)); - statisticRegistry.registerStatistic(derivedName + "#100", histogram.maximumStatistic()); + private , K, V> void registerDerivedStatistics(Cache cache, String statName, T outcome, String derivedName, LatencyHistogramConfiguration configuration) { + this.statisticsService.registerDerivedStatistics(this.cacheAlias, cache , statName, outcome, derivedName, configuration); } @Override public Collection getDescriptors() { - return statisticRegistry.getDescriptors(); + return statisticsService.getCacheDescriptors(cacheAlias); } - StatisticRegistry getStatisticRegistry() { - return statisticRegistry; + Map> collectStatistics(Collection statisticNames, long since) { + return this.statisticsService.collectStatistics(this.cacheAlias, statisticNames, since); } } diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultCollectorService.java b/management/src/main/java/org/ehcache/management/registry/DefaultCollectorService.java index 5a901770df..633f11356e 100644 --- a/management/src/main/java/org/ehcache/management/registry/DefaultCollectorService.java +++ b/management/src/main/java/org/ehcache/management/registry/DefaultCollectorService.java @@ -23,7 +23,7 @@ import org.ehcache.core.spi.store.InternalCacheManager; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.core.spi.time.TimeSourceService; -import org.ehcache.impl.internal.statistics.StatsUtils; +import org.ehcache.core.statistics.StatsUtils; import org.ehcache.management.CollectorService; import org.ehcache.management.ManagementRegistryService; import org.ehcache.management.ManagementRegistryServiceConfiguration; @@ -32,11 +32,7 @@ import org.ehcache.spi.service.ServiceProvider; import org.terracotta.management.model.notification.ContextualNotification; import org.terracotta.management.registry.collect.DefaultStatisticCollector; -import org.ehcache.core.statistics.CacheOperationOutcomes.ClearOutcome; -import org.terracotta.statistics.OperationStatistic; -import org.terracotta.statistics.derived.OperationResultFilter; -import java.util.EnumSet; import java.util.concurrent.ScheduledExecutorService; import static org.ehcache.impl.internal.executor.ExecutorUtil.shutdownNow; @@ -129,10 +125,7 @@ private void cacheCleared(String alias) { } private void registerClearNotification(String alias, Cache cache) { - OperationStatistic clear = StatsUtils.findOperationStatisticOnChildren(cache, - ClearOutcome.class, "clear"); - clear.addDerivedStatistic(new OperationResultFilter<>(EnumSet.of(ClearOutcome.SUCCESS), - (time, latency) -> cacheCleared(alias))); + StatsUtils.registerClearNotification(alias, cache, this::cacheCleared); } @Override diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java index e2af78f386..26c515c315 100644 --- a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java +++ b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java @@ -17,7 +17,7 @@ import org.ehcache.management.ManagementRegistryService; import org.ehcache.management.ManagementRegistryServiceConfiguration; -import org.ehcache.management.providers.statistics.LatencyHistogramConfiguration; +import org.ehcache.core.statistics.LatencyHistogramConfiguration; import org.terracotta.management.model.context.Context; import java.util.Arrays; diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java index d9bb1d4f79..6e819bf5f1 100644 --- a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java +++ b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java @@ -24,6 +24,7 @@ import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.InternalCacheManager; import org.ehcache.core.spi.time.TimeSourceService; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.management.ManagementRegistryService; import org.ehcache.management.ManagementRegistryServiceConfiguration; import org.ehcache.management.cluster.Clustering; @@ -40,7 +41,6 @@ import org.ehcache.spi.service.ServiceProvider; import org.terracotta.management.model.context.ContextContainer; import org.terracotta.management.registry.DefaultManagementRegistry; -import org.terracotta.statistics.StatisticsManager; import java.util.ArrayList; import java.util.Collection; @@ -105,7 +105,7 @@ public void stop() { @Override public void cacheAdded(String alias, Cache cache) { - StatisticsManager.associate(cache).withParent(cacheManager); + DefaultStatisticsService.registerWithParent(cache, cacheManager); register(new CacheBinding(alias, cache)); } @@ -114,7 +114,7 @@ public void cacheAdded(String alias, Cache cache) { public void cacheRemoved(String alias, Cache cache) { unregister(new CacheBinding(alias, cache)); - StatisticsManager.dissociate(cache).fromParent(cacheManager); + DefaultStatisticsService.deRegisterFromParent(cache, cacheManager); } @Override diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java index 5e138956f2..d396f031cc 100644 --- a/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java @@ -19,7 +19,7 @@ import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.time.SystemTimeSource; import org.ehcache.core.spi.time.TimeSource; -import org.ehcache.impl.internal.statistics.DefaultStatisticsService; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.management.ManagementRegistryServiceConfiguration; import org.ehcache.management.providers.CacheBinding; import org.ehcache.management.providers.ExposedCacheBinding; diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/LatencyHistogramConfigurationTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/LatencyHistogramConfigurationTest.java index 89bba0ce9d..ccd906ef38 100644 --- a/management/src/test/java/org/ehcache/management/providers/statistics/LatencyHistogramConfigurationTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/LatencyHistogramConfigurationTest.java @@ -15,6 +15,7 @@ */ package org.ehcache.management.providers.statistics; +import org.ehcache.core.statistics.LatencyHistogramConfiguration; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java index 68f8eb19d5..e4683f1ad1 100755 --- a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java @@ -25,6 +25,7 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.statistics.CacheOperationOutcomes; +import org.ehcache.core.statistics.LatencyHistogramConfiguration; import org.ehcache.management.ManagementRegistryService; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; import org.ehcache.management.registry.DefaultManagementRegistryService; @@ -51,7 +52,7 @@ import java.util.stream.IntStream; import static org.assertj.core.api.Assertions.assertThat; -import static org.ehcache.impl.internal.statistics.StatsUtils.findOperationStatisticOnChildren; +import static org.ehcache.core.statistics.StatsUtils.findOperationStatisticOnChildren; public class StandardEhcacheStatisticsTest { diff --git a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java index 67fc5940b4..34603e7af0 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java @@ -47,6 +47,9 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:core"), gradleBundle("org.ehcache.modules:api"), + gradleBundle("org.terracotta.management:management-model"), + gradleBundle("org.terracotta.management:sequence-generator"), + wrappedGradleBundle("org.terracotta:statistics"), wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), diff --git a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java index c1ed3c4b1e..042267c7b1 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java @@ -66,6 +66,9 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:api"), gradleBundle("javax.cache:cache-api"), + gradleBundle("org.terracotta.management:management-model"), + gradleBundle("org.terracotta.management:sequence-generator"), + wrappedGradleBundle("org.terracotta:statistics"), wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java index 9160c585e5..7f0fe5bda9 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java @@ -54,6 +54,9 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:core"), gradleBundle("org.ehcache.modules:impl"), + gradleBundle("org.terracotta.management:management-model"), + gradleBundle("org.terracotta.management:sequence-generator"), + wrappedGradleBundle("org.terracotta:statistics"), wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), diff --git a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java index 458b6ef2a5..697a2ed0f7 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java @@ -68,6 +68,9 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:impl"), gradleBundle("org.ehcache.modules:xml"), jaxbConfiguration(), + gradleBundle("org.terracotta.management:management-model"), + gradleBundle("org.terracotta.management:sequence-generator"), + wrappedGradleBundle("org.terracotta:statistics"), wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), diff --git a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java index e303ed29a9..ba1fa31f58 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java @@ -59,6 +59,9 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:xml"), jaxbConfiguration(), gradleBundle("org.ehcache:transactions"), jtaConfiguration(), + gradleBundle("org.terracotta.management:management-model"), + gradleBundle("org.terracotta.management:sequence-generator"), + wrappedGradleBundle("org.terracotta:statistics"), wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), diff --git a/transactions/build.gradle b/transactions/build.gradle index 1b6ea31bb8..e57de17458 100644 --- a/transactions/build.gradle +++ b/transactions/build.gradle @@ -25,7 +25,6 @@ dependencies { api project(':core') implementation project(':impl') implementation project(':xml') - implementation "org.terracotta:statistics:$parent.statisticVersion" implementation (group: 'org.codehaus.btm', name: 'btm', version: '2.1.4') { exclude group:'org.slf4j', module:'slf4j-api' } diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java index 2a303d58fd..93c55d4f8b 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java @@ -22,6 +22,7 @@ import org.ehcache.config.EvictionAdvisor; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.store.WrapperStore; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.core.store.StoreSupport; import org.ehcache.impl.store.BaseStore; @@ -52,7 +53,6 @@ import org.ehcache.core.collections.ConcurrentWeakIdentityHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.terracotta.context.ContextManager; import java.io.IOException; import java.time.Duration; @@ -115,7 +115,7 @@ public XAStore(Class keyType, Class valueType, Store> under this.recoveryXaResource = new EhcacheXAResource<>(underlyingStore, journal, transactionContextFactory); this.eventSourceWrapper = new StoreEventSourceWrapper<>(underlyingStore.getStoreEventSource()); - ContextManager.associate(underlyingStore).withParent(this); + DefaultStatisticsService.registerWithParent(underlyingStore, this); } private static boolean isInDoubt(SoftLock softLock) { From 2cf61673c961ed7defbbf4518e15dcc5fffd6308 Mon Sep 17 00:00:00 2001 From: Abhilash Date: Wed, 12 Jun 2019 12:07:58 +0530 Subject: [PATCH 147/372] Remove all static methods from DefaultStatisticsService --- .../jsr107/Eh107CacheStatisticsMXBean.java | 2 +- buildSrc/src/main/groovy/EhDistribute.groovy | 2 - .../ClusteredLoaderWriterStore.java | 11 +- .../DelegatingLoaderWriterStore.java | 2 - .../DelegatingLoaderWriterStoreProvider.java | 3 +- .../ClusteredWriteBehindStore.java | 7 +- .../client/internal/store/ClusteredStore.java | 25 +++-- .../ClusteredLoaderWriterStoreTest.java | 43 ++++---- .../store/ClusteredStoreEventsTest.java | 3 +- .../store/ClusteredStoreProviderTest.java | 4 + .../internal/store/ClusteredStoreTest.java | 39 +++---- clustered/integration-test/build.gradle | 2 +- .../AbstractClusteringManagementTest.java | 2 - .../ClusteredStatisticsCountTest.java | 7 +- core/build.gradle | 4 +- .../core/spi/service/StatisticsService.java | 101 ++++++++++++++---- .../store/AbstractWrapperStoreProvider.java | 4 + .../statistics/DefaultStatisticsService.java | 30 ++++-- .../core/statistics/Jsr107LatencyMonitor.java | 2 +- gradle.properties | 3 +- impl/build.gradle | 3 - .../internal/store/disk/OffHeapDiskStore.java | 26 ++--- .../impl/internal/store/heap/OnHeapStore.java | 35 +++--- .../LoaderWriterStoreProvider.java | 6 +- .../loaderwriter/LocalLoaderWriterStore.java | 2 - .../store/offheap/AbstractOffHeapStore.java | 32 +++--- .../internal/store/offheap/OffHeapStore.java | 26 +++-- .../store/tiering/CompoundCachingTier.java | 8 +- .../internal/store/tiering/TieredStore.java | 8 +- .../org/ehcache/impl/store/BaseStore.java | 36 +++++-- .../ehcache/core/spi/ServiceProviderTest.java | 3 + .../disk/OffHeapDiskStoreProviderTest.java | 5 +- .../store/disk/OffHeapDiskStoreSPITest.java | 3 +- .../store/disk/OffHeapDiskStoreTest.java | 37 ++++--- .../ByteSizedOnHeapStoreByRefSPITest.java | 3 +- .../ByteSizedOnHeapStoreByValueSPITest.java | 3 +- .../heap/CountSizedOnHeapStoreByRefTest.java | 3 +- .../CountSizedOnHeapStoreByValueTest.java | 3 +- .../heap/OnHeapStoreBulkMethodsTest.java | 8 +- .../store/heap/OnHeapStoreByRefSPITest.java | 4 +- .../store/heap/OnHeapStoreByValueSPITest.java | 3 +- .../OnHeapStoreCachingTierByRefSPITest.java | 4 +- .../OnHeapStoreCachingTierByValueSPITest.java | 4 +- .../store/heap/OnHeapStoreEvictionTest.java | 9 +- .../store/heap/OnHeapStoreKeyCopierTest.java | 4 +- .../heap/OnHeapStoreValueCopierTest.java | 4 +- .../heap/bytesized/ByteAccountingTest.java | 3 +- .../ByteSizedOnHeapStoreByRefTest.java | 4 +- .../ByteSizedOnHeapStoreByValueTest.java | 3 +- .../bytesized/OnHeapStoreBulkMethodsTest.java | 5 +- .../OnHeapStoreCachingTierByRefSPITest.java | 3 +- .../OnHeapStoreCachingTierByValueSPITest.java | 3 +- .../store/offheap/OffHeapStoreSPITest.java | 3 +- .../store/offheap/OffHeapStoreTest.java | 5 +- .../tiering/CompoundCachingTierSPITest.java | 5 +- .../TieredStoreFlushWhileShutdownTest.java | 4 + .../store/tiering/TieredStoreMutatorTest.java | 3 +- .../store/tiering/TieredStoreSPITest.java | 6 +- .../store/tiering/TieredStoreTest.java | 8 +- .../tiering/TieredStoreWith3TiersSPITest.java | 8 +- .../integration/EhcacheBulkMethodsITest.java | 3 +- management/build.gradle | 1 + .../DefaultManagementRegistryService.java | 8 +- .../transactions/xa/internal/XAStore.java | 11 +- .../xa/internal/XAStoreProviderTest.java | 3 + .../transactions/xa/internal/XAStoreTest.java | 40 +++---- 66 files changed, 429 insertions(+), 278 deletions(-) diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java b/107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java index 4da6c83076..55ba63389e 100644 --- a/107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java +++ b/107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java @@ -44,7 +44,7 @@ class Eh107CacheStatisticsMXBean extends Eh107MXBean implements javax.cache.mana } private > Jsr107LatencyMonitor registerDerivedStatistics(Class outcome, String name) { - Jsr107LatencyMonitor monitor = new Jsr107LatencyMonitor<>(outcome, 1.0); + Jsr107LatencyMonitor monitor = new Jsr107LatencyMonitor<>(outcome); CacheStatistics cacheStatistics = this.cacheStatistics; cacheStatistics.registerDerivedStatistic(outcome, name, monitor); return monitor; diff --git a/buildSrc/src/main/groovy/EhDistribute.groovy b/buildSrc/src/main/groovy/EhDistribute.groovy index 5ee312158e..ac75663663 100644 --- a/buildSrc/src/main/groovy/EhDistribute.groovy +++ b/buildSrc/src/main/groovy/EhDistribute.groovy @@ -55,8 +55,6 @@ class EhDistribute implements Plugin { relocate ('org.terracotta.context.', 'org.ehcache.shadow.org.terracotta.context.') mergeServiceFiles() - - } project.jar { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java index 66d4457ffb..e549782e08 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java @@ -32,6 +32,7 @@ import org.ehcache.config.ResourceType; import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.core.exceptions.StorePassThroughException; +import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.core.spi.time.TimeSourceService; @@ -57,8 +58,8 @@ public class ClusteredLoaderWriterStore extends ClusteredStore imple private final boolean useLoaderInAtomics; public ClusteredLoaderWriterStore(Configuration config, OperationsCodec codec, ChainResolver resolver, TimeSource timeSource, - CacheLoaderWriter loaderWriter, boolean useLoaderInAtomics, StoreEventDispatcher storeEventDispatcher) { - super(config, codec, resolver, timeSource, storeEventDispatcher); + CacheLoaderWriter loaderWriter, boolean useLoaderInAtomics, StoreEventDispatcher storeEventDispatcher, StatisticsService statisticsService) { + super(config, codec, resolver, timeSource, storeEventDispatcher, statisticsService); this.cacheLoaderWriter = loaderWriter; this.useLoaderInAtomics = useLoaderInAtomics; } @@ -67,8 +68,8 @@ public ClusteredLoaderWriterStore(Configuration config, OperationsCodec config, OperationsCodec codec, EternalChainResolver resolver, - ServerStoreProxy proxy, TimeSource timeSource, CacheLoaderWriter loaderWriter) { - super(config, codec, resolver, proxy, timeSource, null); + ServerStoreProxy proxy, TimeSource timeSource, CacheLoaderWriter loaderWriter, StatisticsService statisticsService) { + super(config, codec, resolver, proxy, timeSource, null, statisticsService); this.cacheLoaderWriter = loaderWriter; this.useLoaderInAtomics = true; } @@ -304,7 +305,7 @@ protected ClusteredStore createStore(Configuration storeConfi Object[] serviceConfigs) { StoreEventDispatcher storeEventDispatcher = new DefaultStoreEventDispatcher<>(storeConfig.getDispatcherConcurrency()); return new ClusteredLoaderWriterStore<>(storeConfig, codec, resolver, timeSource, - storeConfig.getCacheLoaderWriter(), useLoaderInAtomics, storeEventDispatcher); + storeConfig.getCacheLoaderWriter(), useLoaderInAtomics, storeEventDispatcher, getServiceProvider().getService(StatisticsService.class)); } @Override diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java index 4560537abb..920ea16c42 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java @@ -21,7 +21,6 @@ import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.WrapperStore; import org.ehcache.core.spi.store.events.StoreEventSource; -import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.spi.resilience.StoreAccessException; import java.util.Collections; @@ -39,7 +38,6 @@ public class DelegatingLoaderWriterStore implements WrapperStore { public DelegatingLoaderWriterStore(Store store) { this.delegate = store; - DefaultStatisticsService.registerWithParent(delegate, this); } @Override diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java index 2856814131..7a5bb4846d 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java @@ -34,7 +34,8 @@ public class DelegatingLoaderWriterStoreProvider extends AbstractWrapperStorePro @Override protected Store wrap(Store store, Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { - return new DelegatingLoaderWriterStore<>(store); + DelegatingLoaderWriterStore loaderWriterStore = new DelegatingLoaderWriterStore<>(store); + return loaderWriterStore; } @Override diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java index c96c622e78..2b61f0465a 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java @@ -33,6 +33,7 @@ import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.config.ResourceType; import org.ehcache.core.events.StoreEventDispatcher; +import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.core.spi.time.TimeSourceService; @@ -64,8 +65,8 @@ private ClusteredWriteBehindStore(Configuration config, TimeSource timeSource, CacheLoaderWriter loaderWriter, ExecutorService executorService, - StoreEventDispatcher storeEventDispatcher) { - super(config, codec, resolver, timeSource, storeEventDispatcher); + StoreEventDispatcher storeEventDispatcher, StatisticsService statisticsService) { + super(config, codec, resolver, timeSource, storeEventDispatcher, statisticsService); this.cacheLoaderWriter = loaderWriter; this.clusteredWriteBehind = new ClusteredWriteBehind<>(this, executorService, resolver, @@ -268,7 +269,7 @@ protected ClusteredStore createStore(Configuration storeConfi timeSource, storeConfig.getCacheLoaderWriter(), executorService, - storeEventDispatcher); + storeEventDispatcher, getServiceProvider().getService(StatisticsService.class)); } throw new AssertionError(); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index bcce02aade..fc63097d35 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -47,11 +47,11 @@ import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.core.events.StoreEventSink; import org.ehcache.core.spi.service.ExecutionService; +import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.events.StoreEventFilter; import org.ehcache.core.spi.store.events.StoreEventListener; import org.ehcache.core.spi.store.events.StoreEventSource; -import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.statistics.OperationObserver; import org.ehcache.core.statistics.OperationStatistic; import org.ehcache.impl.store.BaseStore; @@ -64,7 +64,6 @@ import org.ehcache.core.statistics.StoreOperationOutcomes.EvictionOutcome; import org.ehcache.core.statistics.TierOperationOutcomes; import org.ehcache.event.EventFiring; -import org.ehcache.event.EventOrdering; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.store.DefaultStoreEventDispatcher; import org.ehcache.impl.store.HashUtils; @@ -131,8 +130,8 @@ public class ClusteredStore extends BaseStore implements Authoritati private final OperationObserver getAndFaultObserver; - protected ClusteredStore(Configuration config, OperationsCodec codec, ChainResolver resolver, TimeSource timeSource, StoreEventDispatcher storeEventDispatcher) { - super(config); + protected ClusteredStore(Configuration config, OperationsCodec codec, ChainResolver resolver, TimeSource timeSource, StoreEventDispatcher storeEventDispatcher, StatisticsService statisticsService) { + super(config, statisticsService); this.chainCompactionLimit = Integer.getInteger(CHAIN_COMPACTION_THRESHOLD_PROP, DEFAULT_CHAIN_COMPACTION_THRESHOLD); this.codec = codec; @@ -154,8 +153,8 @@ protected ClusteredStore(Configuration config, OperationsCodec codec /** * For tests */ - protected ClusteredStore(Configuration config, OperationsCodec codec, ChainResolver resolver, ServerStoreProxy proxy, TimeSource timeSource, StoreEventDispatcher storeEventDispatcher) { - this(config, codec, resolver, timeSource, storeEventDispatcher); + protected ClusteredStore(Configuration config, OperationsCodec codec, ChainResolver resolver, ServerStoreProxy proxy, TimeSource timeSource, StoreEventDispatcher storeEventDispatcher, StatisticsService statisticsService) { + this(config, codec, resolver, timeSource, storeEventDispatcher, statisticsService); this.storeProxy = proxy; } @@ -652,7 +651,7 @@ private ClusteredStore createStoreInternal(Configuration stor } ClusteredCacheIdentifier cacheId = findSingletonAmongst(ClusteredCacheIdentifier.class, serviceConfigs); - TimeSource timeSource = serviceProvider.getService(TimeSourceService.class).getTimeSource(); + TimeSource timeSource = getServiceProvider().getService(TimeSourceService.class).getTimeSource(); OperationsCodec codec = new OperationsCodec<>(storeConfig.getKeySerializer(), storeConfig.getValueSerializer()); @@ -680,7 +679,7 @@ protected ClusteredStore createStore(Configuration storeConfi boolean useLoaderInAtomics, Object[] serviceConfigs) { StoreEventDispatcher storeEventDispatcher = new DefaultStoreEventDispatcher<>(storeConfig.getDispatcherConcurrency()); - return new ClusteredStore<>(storeConfig, codec, resolver, timeSource, storeEventDispatcher); + return new ClusteredStore<>(storeConfig, codec, resolver, timeSource, storeEventDispatcher, getServiceProvider().getService(StatisticsService.class)); } @Override @@ -692,7 +691,7 @@ public void releaseStore(Store resource) { } ClusteredStore clusteredStore = (ClusteredStore) resource; this.clusteringService.releaseServerStoreProxy(clusteredStore.storeProxy, false); - DefaultStatisticsService.cleanForNode(clusteredStore); + getServiceProvider().getService(StatisticsService.class).cleanForNode(clusteredStore); tierOperationStatistics.remove(clusteredStore); } finally { connectLock.unlock(); @@ -864,9 +863,9 @@ public int rankAuthority(ResourceType authorityResource, Collection serviceProvider) { connectLock.lock(); try { - this.serviceProvider = serviceProvider; - this.clusteringService = this.serviceProvider.getService(ClusteringService.class); - this.executionService = this.serviceProvider.getService(ExecutionService.class); + super.start(serviceProvider); + this.clusteringService = getServiceProvider().getService(ClusteringService.class); + this.executionService = getServiceProvider().getService(ExecutionService.class); } finally { connectLock.unlock(); } @@ -876,10 +875,10 @@ public void start(final ServiceProvider serviceProvider) { public void stop() { connectLock.lock(); try { - this.serviceProvider = null; createdStores.clear(); } finally { connectLock.unlock(); + super.stop(); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java index 5eb1fc8781..d57b40d31e 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java @@ -25,6 +25,7 @@ import org.ehcache.clustered.loaderWriter.TestCacheLoaderWriter; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.time.TimeSource; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.impl.serialization.LongSerializer; import org.ehcache.impl.serialization.StringSerializer; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; @@ -63,7 +64,7 @@ public void testGetValueAbsentInSOR() throws Exception { CacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); when(storeProxy.get(eq(1L))).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); assertThat(store.get(1L), is(nullValue())); } @@ -74,7 +75,7 @@ public void testGetValuePresentInSOR() throws Exception { loaderWriter.storeMap.put(1L, "one"); when(storeProxy.get(eq(1L))).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); assertThat(store.get(1L).get(), equalTo("one")); } @@ -87,7 +88,7 @@ public void testGetValuePresentInCache() throws Exception { ServerStoreProxy.ChainEntry toReturn = entryOf(codec.encode(operation)); when(storeProxy.get(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); assertThat(store.get(1L).get(), equalTo("one")); verify(loaderWriter, times(0)).load(anyLong()); verifyZeroInteractions(loaderWriter); @@ -98,7 +99,7 @@ public void testPut() throws Exception { ServerStoreProxy storeProxy = mock(LockingServerStoreProxyImpl.class); TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); assertThat(loaderWriter.storeMap.containsKey(1L), is(false)); assertThat(store.put(1L, "one"), is(Store.PutStatus.PUT)); assertThat(loaderWriter.storeMap.containsKey(1L), is(true)); @@ -110,7 +111,7 @@ public void testRemoveValueAbsentInCachePresentInSOR() throws Exception { TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); loaderWriter.storeMap.put(1L, "one"); assertThat(store.remove(1L), is(false)); assertThat(loaderWriter.storeMap.containsKey(1L), is(false)); @@ -125,7 +126,7 @@ public void testRemoveValuePresentInCachePresentInSOR() throws Exception { when(storeProxy.lock(anyLong())).thenReturn(toReturn); when(storeProxy.get(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); loaderWriter.storeMap.put(1L, "one"); assertThat(store.get(1L).get(), equalTo("one")); assertThat(store.remove(1L), is(true)); @@ -139,7 +140,7 @@ public void testRemoveValueAbsentInCacheAbsentInSOR() throws Exception { CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); assertThat(store.remove(1L), is(false)); verify(loaderWriter, times(1)).delete(anyLong()); } @@ -150,7 +151,7 @@ public void testPufIfAbsentValueAbsentInCacheAbsentInSOR() throws Exception { TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); assertThat(loaderWriter.storeMap.isEmpty(), is(true)); assertThat(store.putIfAbsent(1L, "one", null), is(nullValue())); assertThat(loaderWriter.storeMap.get(1L), equalTo("one")); @@ -162,7 +163,7 @@ public void testPufIfAbsentValueAbsentInCachePresentInSOR() throws Exception { TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); loaderWriter.storeMap.put(1L, "one"); assertThat(store.putIfAbsent(1L, "Again", null).get(), equalTo("one")); verify(storeProxy, times(0)).append(anyLong(), ArgumentMatchers.any(ByteBuffer.class)); @@ -177,7 +178,7 @@ public void testPufIfAbsentValuePresentInCachePresentInSOR() throws Exception { ServerStoreProxy.ChainEntry toReturn = entryOf(codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); loaderWriter.storeMap.put(1L, "one"); assertThat(store.putIfAbsent(1L, "Again", null).get(), equalTo("one")); verify(storeProxy, times(0)).append(anyLong(), ArgumentMatchers.any(ByteBuffer.class)); @@ -190,7 +191,7 @@ public void testReplaceValueAbsentInCacheAbsentInSOR() throws Exception { TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); assertThat(loaderWriter.storeMap.isEmpty(), is(true)); assertThat(store.replace(1L, "one"), is(nullValue())); assertThat(loaderWriter.storeMap.isEmpty(), is(true)); @@ -203,7 +204,7 @@ public void testReplaceValueAbsentInCachePresentInSOR() throws Exception { TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); loaderWriter.storeMap.put(1L, "one"); assertThat(store.replace(1L, "Again").get(), equalTo("one")); verify(storeProxy, times(1)).append(anyLong(), ArgumentMatchers.any(ByteBuffer.class)); @@ -218,7 +219,7 @@ public void testReplaceValuePresentInCachePresentInSOR() throws Exception { ServerStoreProxy.ChainEntry toReturn = entryOf(codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); loaderWriter.storeMap.put(1L, "one"); assertThat(store.replace(1L, "Again").get(), equalTo("one")); verify(storeProxy, times(1)).append(anyLong(), ArgumentMatchers.any(ByteBuffer.class)); @@ -232,7 +233,7 @@ public void testRemove2ArgsValueAbsentInCacheAbsentInSOR() throws Exception { CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); assertThat(store.remove(1L, "one"), is(Store.RemoveStatus.KEY_MISSING)); verify(storeProxy, times(0)).append(anyLong(), ArgumentMatchers.any(ByteBuffer.class)); } @@ -243,7 +244,7 @@ public void testRemove2ArgsValueAbsentInCachePresentInSOR() throws Exception { TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); loaderWriter.storeMap.put(1L, "one"); assertThat(store.remove(1L, "one"), is(Store.RemoveStatus.REMOVED)); verify(storeProxy, times(1)).append(anyLong(), ArgumentMatchers.any(ByteBuffer.class)); @@ -259,7 +260,7 @@ public void testRemove2ArgsValuePresentInCachePresentInSOR() throws Exception { ServerStoreProxy.ChainEntry toReturn = entryOf(codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); assertThat(store.remove(1L, "one"), is(Store.RemoveStatus.REMOVED)); verify(storeProxy, times(1)).append(anyLong(), ArgumentMatchers.any(ByteBuffer.class)); verify(loaderWriter, times(0)).load(anyLong()); @@ -272,7 +273,7 @@ public void testRemove2ArgsValueAbsentInCacheDiffValuePresentInSOR() throws Exce TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); loaderWriter.storeMap.put(1L, "one"); assertThat(store.remove(1L, "Again"), is(Store.RemoveStatus.KEY_PRESENT)); verify(storeProxy, times(0)).append(anyLong(), ArgumentMatchers.any(ByteBuffer.class)); @@ -286,7 +287,7 @@ public void testReplace2ArgsValueAbsentInCacheAbsentInSOR() throws Exception { CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); assertThat(store.replace(1L, "one", "Again"), is(Store.ReplaceStatus.MISS_NOT_PRESENT)); verify(storeProxy, times(0)).append(anyLong(), ArgumentMatchers.any(ByteBuffer.class)); verify(loaderWriter, times(1)).load(anyLong()); @@ -299,7 +300,7 @@ public void testReplace2ArgsValueAbsentInCachePresentInSOR() throws Exception { TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); loaderWriter.storeMap.put(1L, "one"); assertThat(store.replace(1L, "one", "Again"), is(Store.ReplaceStatus.HIT)); verify(storeProxy, times(1)).append(anyLong(), ArgumentMatchers.any(ByteBuffer.class)); @@ -315,7 +316,7 @@ public void testReplace2ArgsValuePresentInCachePresentInSOR() throws Exception { ServerStoreProxy.ChainEntry toReturn = entryOf(codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); assertThat(store.replace(1L, "one", "Again"), is(Store.ReplaceStatus.HIT)); verify(storeProxy, times(1)).append(anyLong(), ArgumentMatchers.any(ByteBuffer.class)); verify(loaderWriter, times(0)).load(anyLong()); @@ -328,7 +329,7 @@ public void testReplace2ArgsValueAbsentInCacheDiffValueInSOR() throws Exception TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); when(storeProxy.lock(anyLong())).thenReturn(entryOf()); ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, - timeSource, loaderWriter); + timeSource, loaderWriter, new DefaultStatisticsService()); loaderWriter.storeMap.put(1L, "one"); assertThat(store.replace(1L, "Again", "one"), is(Store.ReplaceStatus.MISS_PRESENT)); verify(storeProxy, times(0)).append(anyLong(), ArgumentMatchers.any(ByteBuffer.class)); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java index b9dddfd405..4cc3a11cdb 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java @@ -44,6 +44,7 @@ import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.core.events.StoreEventSink; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.serialization.LongSerializer; import org.ehcache.impl.serialization.StringSerializer; @@ -167,7 +168,7 @@ public void setup() throws Exception { storeEventSink = mock(StoreEventSink.class); when(storeEventDispatcher.eventSink()).thenReturn(storeEventSink); - ClusteredStore store = new ClusteredStore<>(config, codec, resolver, serverStoreProxy, testTimeSource, storeEventDispatcher); + ClusteredStore store = new ClusteredStore<>(config, codec, resolver, serverStoreProxy, testTimeSource, storeEventDispatcher, new DefaultStatisticsService()); serverCallback = new ClusteredStore.Provider().getServerCallback(store); } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java index 93ccf19544..e585eb7cd3 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java @@ -27,6 +27,7 @@ import org.ehcache.config.ResourceType; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.spi.service.CacheManagerProviderService; import org.ehcache.impl.config.ResourcePoolsImpl; import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.service.DiskResourceService; @@ -42,6 +43,8 @@ import org.ehcache.spi.serialization.Serializer; import org.ehcache.spi.service.ServiceConfiguration; import org.junit.Test; +import org.mockito.Answers; +import org.mockito.Mockito; import java.util.Arrays; import java.util.Collections; @@ -89,6 +92,7 @@ public void testRankTiered() throws Exception { .with(new OffHeapStore.Provider()) .with(new OffHeapDiskStore.Provider()) .with(mock(DiskResourceService.class)) + .with(Mockito.mock(CacheManagerProviderService.class, Answers.RETURNS_DEEP_STUBS)) .with(mock(ClusteringService.class)).build(); serviceLocator.startAllServices(); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java index ad510ac903..d828ecf52b 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java @@ -34,6 +34,7 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.Ehcache; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.store.DefaultStoreEventDispatcher; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; @@ -166,7 +167,7 @@ public void setup() throws Exception { OperationsCodec codec = new OperationsCodec<>(new LongSerializer(), new StringSerializer()); EternalChainResolver resolver = new EternalChainResolver<>(codec); - store = new ClusteredStore<>(config, codec, resolver, serverStoreProxy, testTimeSource, new DefaultStoreEventDispatcher<>(8)); + store = new ClusteredStore<>(config, codec, resolver, serverStoreProxy, testTimeSource, new DefaultStoreEventDispatcher<>(8), new DefaultStatisticsService()); } @After @@ -196,7 +197,7 @@ public void testPutTimeout() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); doThrow(TimeoutException.class).when(proxy).append(anyLong(), isNull()); - ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null, new DefaultStatisticsService()); assertTimeoutOccurred(() -> store.put(1L, "one")); } @@ -219,7 +220,7 @@ public void testGetThrowsOnlySAE() throws Exception { ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.get(anyLong())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null, new DefaultStatisticsService()); store.get(1L); } @@ -229,7 +230,7 @@ public void testGetTimeout() throws Exception { ServerStoreProxy proxy = mock(ServerStoreProxy.class); long longKey = HashUtils.intHashToLong(new Long(1L).hashCode()); when(proxy.get(longKey)).thenThrow(TimeoutException.class); - ClusteredStore store = new ClusteredStore<>(config,null, null, proxy, null, null); + ClusteredStore store = new ClusteredStore<>(config,null, null, proxy, null, null, new DefaultStatisticsService()); assertThat(store.get(1L), nullValue()); validateStats(store, EnumSet.of(StoreOperationOutcomes.GetOutcome.TIMEOUT)); } @@ -252,7 +253,7 @@ public void testContainsKeyThrowsOnlySAE() throws Exception { ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.get(anyLong())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null, new DefaultStatisticsService()); store.containsKey(1L); } @@ -277,7 +278,7 @@ public void testRemoveThrowsOnlySAE() throws Exception { when(serverStoreProxy.getAndAppend(anyLong(), any())).thenThrow(theException); TestTimeSource testTimeSource = new TestTimeSource(); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null, new DefaultStatisticsService()); assertThatExceptionOfType(StoreAccessException.class) .isThrownBy(() -> store.remove(1L)) .withCause(theException); @@ -290,7 +291,7 @@ public void testRemoveTimeout() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); when(proxy.getAndAppend(anyLong(), isNull())).thenThrow(TimeoutException.class); - ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null, new DefaultStatisticsService()); assertTimeoutOccurred(() -> store.remove(1L)); } @@ -322,7 +323,7 @@ public void testClearThrowsOnlySAE() throws Exception { ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); doThrow(new RuntimeException()).when(serverStoreProxy).clear(); TestTimeSource testTimeSource = mock(TestTimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null, new DefaultStatisticsService()); store.clear(); } @@ -333,7 +334,7 @@ public void testClearTimeout() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); doThrow(TimeoutException.class).when(proxy).clear(); - ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null, new DefaultStatisticsService()); assertTimeoutOccurred(() -> store.clear()); } @@ -355,7 +356,7 @@ public void testPutIfAbsentThrowsOnlySAE() throws Exception { ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.getAndAppend(anyLong(), any())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null, new DefaultStatisticsService()); store.putIfAbsent(1L, "one", b -> {}); } @@ -366,7 +367,7 @@ public void testPutIfAbsentTimeout() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); when(proxy.getAndAppend(anyLong(), isNull())).thenThrow(TimeoutException.class); - ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null, new DefaultStatisticsService()); assertTimeoutOccurred(() -> store.putIfAbsent(1L, "one", b -> {})); } @@ -392,7 +393,7 @@ public void testConditionalRemoveThrowsOnlySAE() throws Exception { ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.getAndAppend(anyLong(), any())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null, new DefaultStatisticsService()); store.remove(1L, "one"); } @@ -403,7 +404,7 @@ public void testConditionalRemoveTimeout() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); when(proxy.getAndAppend(anyLong(), isNull())).thenThrow(TimeoutException.class); - ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null, new DefaultStatisticsService()); assertTimeoutOccurred(() -> store.remove(1L, "one")); } @@ -426,7 +427,7 @@ public void testReplaceThrowsOnlySAE() throws Exception { ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.getAndAppend(anyLong(), any())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null, new DefaultStatisticsService()); store.replace(1L, "one"); } @@ -437,7 +438,7 @@ public void testReplaceTimeout() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); when(proxy.getAndAppend(anyLong(), isNull())).thenThrow(TimeoutException.class); - ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null, new DefaultStatisticsService()); assertTimeoutOccurred(() -> store.replace(1L, "one")); } @@ -464,7 +465,7 @@ public void testConditionalReplaceThrowsOnlySAE() throws Exception { ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class); when(serverStoreProxy.getAndAppend(anyLong(), any())).thenThrow(new RuntimeException()); TestTimeSource testTimeSource = mock(TestTimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, chainResolver, serverStoreProxy, testTimeSource, null, new DefaultStatisticsService()); store.replace(1L, "one", "another one"); } @@ -475,7 +476,7 @@ public void testConditionalReplaceTimeout() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); when(proxy.getAndAppend(anyLong(), isNull())).thenThrow(TimeoutException.class); - ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, null, proxy, timeSource, null, new DefaultStatisticsService()); assertTimeoutOccurred(() -> store.replace(1L, "one", "another one")); } @@ -560,7 +561,7 @@ public void testExpirationIsSentToHigherTiers() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource, null, new DefaultStatisticsService()); Store.ValueHolder vh = store.get(1L); @@ -585,7 +586,7 @@ public void testNoExpireIsSentToHigherTiers() throws Exception { OperationsCodec codec = mock(OperationsCodec.class); TimeSource timeSource = mock(TimeSource.class); - ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource, null); + ClusteredStore store = new ClusteredStore<>(config, codec, resolver, proxy, timeSource, null, new DefaultStatisticsService()); Store.ValueHolder vh = store.get(1L); diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index 0d6291791d..e1e224a8e8 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -19,7 +19,6 @@ configurations { } dependencies { - // not required by gradle but required by the IDE because 'dist' does not have any transitive dependencies testCompile project(':clustered:client') testCompile project(':clustered:common') testCompile project(':impl') @@ -36,6 +35,7 @@ dependencies { testImplementation "org.awaitility:awaitility:3.1.6" testRuntimeOnly "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" + testRuntimeOnly project(':clustered:clustered-dist') testImplementation (group:'org.terracotta.internal', name:'galvan-support', version: terracottaCoreVersion) testImplementation (group:'com.google.code.tempus-fugit', name:'tempus-fugit', version:'1.1') { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 07ea06c233..976dd9e7d6 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -269,8 +269,6 @@ public static void createNmsService() throws ConnectionException, EntityConfigur } public static void createNmsService(Cluster cluster) throws ConnectionException, EntityConfigurationException { - String classpathStr = System.getProperty("java.class.path"); - System.out.print("CLASSPATH" + classpathStr); managementConnection = cluster.newConnection(); NmsEntityFactory entityFactory = new NmsEntityFactory(managementConnection, AbstractClusteringManagementTest.class.getName()); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java index cab6b27705..daeb48aa5c 100755 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java @@ -19,12 +19,8 @@ import org.junit.Assert; import org.junit.Test; import org.terracotta.management.model.stats.ContextualStatistics; -import org.terracotta.statistics.registry.Statistic; -import java.io.Serializable; import java.util.List; -import java.util.Map; -import java.util.Set; import static org.hamcrest.CoreMatchers.is; @@ -65,12 +61,13 @@ public void countTest() throws Exception { if (stat.getContext().contains("cacheName") && stat.getContext().get("cacheName").equals("dedicated-cache-1")) { // please leave it there - it's really useful to see what's coming + /* System.out.println("stats:"); Set>> entries = stat.getStatistics().entrySet(); for (Map.Entry> entry : entries) { System.out.println(" - " + entry.getKey() + " : " + entry.getValue()); - } + }*/ cacheHitCount = stat.getLatestSampleValue("Cache:HitCount").get(); clusteredHitCount = stat.getLatestSampleValue("Clustered:HitCount").get(); diff --git a/core/build.gradle b/core/build.gradle index 0f8d6b5bcf..b08f7270f9 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -20,7 +20,9 @@ apply plugin: 'biz.aQute.bnd.builder' dependencies { api project(':api') implementation "org.terracotta:statistics:$parent.statisticVersion" - implementation "org.terracotta.management:management-model:$terracottaPlatformVersion" + api ("org.terracotta.management:management-model:$terracottaPlatformVersion") { + exclude group:'org.terracotta', module:'statistics' + } compileOnly 'org.osgi:osgi.core:6.0.0' compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':spi-tester') diff --git a/core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java b/core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java index edf4d1cc1d..3cb0166c4d 100644 --- a/core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java +++ b/core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java @@ -17,16 +17,21 @@ package org.ehcache.core.spi.service; import org.ehcache.Cache; +import org.ehcache.core.spi.store.Store; import org.ehcache.core.statistics.CacheStatistics; import org.ehcache.core.statistics.LatencyHistogramConfiguration; +import org.ehcache.core.statistics.OperationObserver; import org.ehcache.spi.service.Service; import org.terracotta.management.model.capabilities.descriptors.StatisticDescriptor; import org.terracotta.management.model.stats.Statistic; +import org.terracotta.management.model.stats.StatisticType; import java.io.Serializable; import java.util.Collection; import java.util.Map; +import java.util.Set; import java.util.function.LongSupplier; +import java.util.function.Supplier; /** * Service providing raw statistics for cache and tier usage. @@ -42,44 +47,98 @@ public interface StatisticsService extends Service { CacheStatistics getCacheStatistics(String cacheName); /** - * - * @param cacheName - * @param cache - * @param timeSource + * Create statistics registry + * @param cacheName name (alias) of the cache + * @param cache the {@link Cache} associated with the given alias + * @param timeSource source of time for statistics maintenance */ void createCacheRegistry(String cacheName, Cache cache, LongSupplier timeSource); /** - * - * @param cacheName + * Registers a cache for statistics + * @param cacheName name (alias) of the cache */ void registerCacheStatistics(String cacheName); /** - * - * @param cacheName - * @return + * Returns the Statistics descriptor for the cache with the given alias + * @param cacheName name (alias) of the cache + * @return the collection of {@link StatisticDescriptor}s of the cache */ Collection getCacheDescriptors(String cacheName); /** - * @param - * @param cacheName - * @param cache - * @param statName - * @param outcome - * @param derivedName - * @param configuration + * Registers derived statistics for the cache + * @param the generic type of statistics + * @param cacheName name (alias) of the cache + * @param cache the cache associated with the given alias + * @param statName name of the statistic + * @param outcome Class of the type of statistics + * @param derivedName visible name of the statistics + * @param configuration the histogram configuration for statistics */ , K, V> void registerDerivedStatistics(String cacheName, Cache cache, String statName, T outcome, String derivedName, LatencyHistogramConfiguration configuration); /** - * - * @param cacheName - * @param statisticNames - * @param since - * @return + * Returns the statistics for the cache + * @param cacheName name (alias) of the cache + * @param statisticNames names of the statistics + * @param since time since statistics needs to be collected + * @return map of statisticNames and statistics */ Map> collectStatistics(String cacheName, Collection statisticNames, long since); + /** + * Registers the object to parent + * @param toAssociate object to associate + * @param parent to which object is associated + */ + void registerWithParent(Object toAssociate, Object parent); + + /** + * Registers store of the cache for statistics + * @param store {@link Store} of the cache to be registered + * @param targetName statistics name after translation + * @param tierHeight of the store + * @param tag with which the statistics is associated + * @param translation relationship among maintained statistics + * @param statisticName name of the statistic + * @return statistics for the store + */ + , T extends Enum> org.ehcache.core.statistics.OperationStatistic registerStoreStatistics(Store store, String targetName, int tierHeight, String tag, Map> translation, String statisticName); + + /** + * De-registers object from the parent + * @param toDeassociate object to dissociate + * @param parent to which object is associated + */ + void deRegisterFromParent(Object toDeassociate, Object parent); + + /** + * Clears all associations + * @param node for which all associations are cleared + */ + void cleanForNode(Object node); + + /** + * Register statistics with value supplier + * @param context association object + * @param name of the statistics + * @param type StatisticType to be registered + * @param tags with which the statistics is associated + * @param valueSupplier supplies the value to maintain statistics + * @param the generic type + */ + void registerStatistic(Object context, String name, StatisticType type, Set tags, Supplier valueSupplier); + + /** + * Create operation statistic for provided type + * @param name of the operation observer + * @param outcome Class of the type of statistic + * @param tag with which the statistics is associated + * @param context association object + * @return the observer for the provided statistics + */ + > OperationObserver createOperationStatistics(String name, Class outcome, String tag, Object context); + } diff --git a/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java b/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java index 3013339727..44f630fd7c 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java +++ b/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java @@ -16,8 +16,10 @@ package org.ehcache.core.spi.store; import org.ehcache.core.collections.ConcurrentWeakIdentityHashMap; +import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceConfiguration; +import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.spi.service.ServiceProvider; import java.util.Arrays; @@ -25,6 +27,7 @@ import static org.ehcache.core.store.StoreSupport.selectStoreProvider; +@ServiceDependencies({StatisticsService.class}) public abstract class AbstractWrapperStoreProvider implements WrapperStore.Provider { private volatile ServiceProvider serviceProvider; @@ -40,6 +43,7 @@ public Store createStore(Store.Configuration storeConfig, Ser Store store = underlyingStoreProvider.createStore(storeConfig, serviceConfigs); Store wrappedStore = wrap(store, storeConfig, serviceConfigs); + serviceProvider.getService(StatisticsService.class).registerWithParent(store, wrappedStore); createdStores.put(wrappedStore, new StoreReference<>(store, underlyingStoreProvider)); return wrappedStore; } diff --git a/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java b/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java index b312cfa7b8..6c0d202c49 100644 --- a/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java +++ b/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java @@ -25,8 +25,8 @@ import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.InternalCacheManager; import org.ehcache.core.spi.store.Store; +import org.ehcache.spi.service.OptionalServiceDependencies; import org.ehcache.spi.service.Service; -import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.spi.service.ServiceProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,7 +56,7 @@ /** * Default implementation using the statistics calculated by the observers set on the caches. */ -@ServiceDependencies(CacheManagerProviderService.class) +@OptionalServiceDependencies({"org.ehcache.core.spi.service.CacheManagerProviderService"}) public class DefaultStatisticsService implements StatisticsService, CacheManagerListener { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultStatisticsService.class); @@ -75,11 +75,13 @@ public CacheStatistics getCacheStatistics(String cacheName) { return stats; } - public static void registerWithParent(Object toAssociate, Object parent) { + @Override + public void registerWithParent(Object toAssociate, Object parent) { StatisticsManager.associate(toAssociate).withParent(parent); } - public static , T extends Enum> org.ehcache.core.statistics.OperationStatistic registerStoreStatistics(Store store, String targetName, int tierHeight, String tag, Map> translation, String statisticName) { + @Override + public , T extends Enum> org.ehcache.core.statistics.OperationStatistic registerStoreStatistics(Store store, String targetName, int tierHeight, String tag, Map> translation, String statisticName) { Class outcomeType = getOutcomeType(translation); @@ -108,11 +110,13 @@ private static , T extends Enum> Class getOutcomeType(Ma return outcomeType; } - public static void deRegisterFromParent(Object toDessociate, Object parent) { - StatisticsManager.dissociate(toDessociate).fromParent(parent); + @Override + public void deRegisterFromParent(Object toDeassociate, Object parent) { + StatisticsManager.dissociate(toDeassociate).fromParent(parent); } - public static void cleanForNode(Object node) { + @Override + public void cleanForNode(Object node) { StatisticsManager.nodeFor(node).clean(); } @@ -151,11 +155,13 @@ public Map> collectStatistics(String c return StatisticRegistry.collect(statisticRegistries.get(cacheName), statisticNames, since); } - public static void registerStatistic(Object context, String name, StatisticType type, Set tags, Supplier valueSupplier) { + @Override + public void registerStatistic(Object context, String name, StatisticType type, Set tags, Supplier valueSupplier) { StatisticsManager.createPassThroughStatistic(context, name, tags, StatisticType.convert(type), valueSupplier); } - public static > OperationObserver createOperationStatistics(String name, Class outcome, String tag, Object context) { + @Override + public > OperationObserver createOperationStatistics(String name, Class outcome, String tag, Object context) { return new DelegatingOperationObserver<>(operation(outcome).named(name).of(context).tag(tag).build()); } @@ -168,8 +174,10 @@ public void start(ServiceProvider serviceProvider) { LOGGER.debug("Starting service"); CacheManagerProviderService cacheManagerProviderService = serviceProvider.getService(CacheManagerProviderService.class); - cacheManager = cacheManagerProviderService.getCacheManager(); - cacheManager.registerListener(this); + if (cacheManagerProviderService != null) { + cacheManager = cacheManagerProviderService.getCacheManager(); + cacheManager.registerListener(this); + } started = true; } diff --git a/core/src/main/java/org/ehcache/core/statistics/Jsr107LatencyMonitor.java b/core/src/main/java/org/ehcache/core/statistics/Jsr107LatencyMonitor.java index 9be1c34fbc..30366c1f34 100644 --- a/core/src/main/java/org/ehcache/core/statistics/Jsr107LatencyMonitor.java +++ b/core/src/main/java/org/ehcache/core/statistics/Jsr107LatencyMonitor.java @@ -21,7 +21,7 @@ public class Jsr107LatencyMonitor> implements ChainedOperation private final org.terracotta.statistics.derived.latency.Jsr107LatencyMonitor delegate; - public Jsr107LatencyMonitor(Class outcome, double sampling) { + public Jsr107LatencyMonitor(Class outcome) { delegate = new org.terracotta.statistics.derived.latency.Jsr107LatencyMonitor<>(EnumSet.allOf(outcome), 1.0); } diff --git a/gradle.properties b/gradle.properties index 6bd52981e1..f9063c57fa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7-SNAPSHOT +terracottaPlatformVersion = 5.7.3-pre7 terracottaApisVersion = 1.6.1 terracottaCoreVersion = 5.6.4-pre9 terracottaPassthroughTestingVersion = 1.6.1 @@ -35,4 +35,3 @@ deployUrl = https://oss.sonatype.org/service/local/staging/deploy/maven2/ # Enable the daemon by adding org.gradle.daemon in USER_HOME/.gradle/gradle.properties org.gradle.parallel=true -mvnlocal=true diff --git a/impl/build.gradle b/impl/build.gradle index 573c6e4146..048ae0d77e 100644 --- a/impl/build.gradle +++ b/impl/build.gradle @@ -32,9 +32,6 @@ dependencies { implementation (group: 'org.ehcache', name: 'sizeof', version: parent.sizeofVersion) { exclude group:'org.slf4j', module:'slf4j-api' } - implementation ("org.terracotta.management:management-model:$terracottaPlatformVersion") { - exclude group:'org.terracotta', module:'statistics' - } compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':core-spi-test') testImplementation 'org.ow2.asm:asm:6.2' diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java index 975d6c3e6b..7d23042e2c 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java @@ -23,7 +23,6 @@ import org.ehcache.config.ResourceType; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.service.StatisticsService; -import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.statistics.OperationStatistic; import org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration; import org.ehcache.config.units.MemoryUnit; @@ -114,8 +113,8 @@ public class OffHeapDiskStore extends AbstractOffHeapStore implement public OffHeapDiskStore(FileBasedPersistenceContext fileBasedPersistenceContext, ExecutionService executionService, String threadPoolAlias, int writerConcurrency, int diskSegments, - final Configuration config, TimeSource timeSource, StoreEventDispatcher eventDispatcher, long sizeInBytes) { - super(config, timeSource, eventDispatcher); + final Configuration config, TimeSource timeSource, StoreEventDispatcher eventDispatcher, long sizeInBytes, StatisticsService statisticsService) { + super(config, timeSource, eventDispatcher, statisticsService); this.fileBasedPersistenceContext = fileBasedPersistenceContext; this.executionService = executionService; this.threadPoolAlias = threadPoolAlias; @@ -336,11 +335,11 @@ public OffHeapDiskStore createStore(Configuration storeConfig } private OffHeapDiskStore createStoreInternal(Configuration storeConfig, StoreEventDispatcher eventDispatcher, ServiceConfiguration... serviceConfigs) { - if (serviceProvider == null) { + if (getServiceProvider() == null) { throw new NullPointerException("ServiceProvider is null in OffHeapDiskStore.Provider."); } - TimeSource timeSource = serviceProvider.getService(TimeSourceService.class).getTimeSource(); - ExecutionService executionService = serviceProvider.getService(ExecutionService.class); + TimeSource timeSource = getServiceProvider().getService(TimeSourceService.class).getTimeSource(); + ExecutionService executionService = getServiceProvider().getService(ExecutionService.class); SizedResourcePool diskPool = storeConfig.getResourcePools().getPoolForResource(getResourceType()); if (!(diskPool.getUnit() instanceof MemoryUnit)) { @@ -370,7 +369,7 @@ private OffHeapDiskStore createStoreInternal(Configuration st OffHeapDiskStore offHeapStore = new OffHeapDiskStore<>(persistenceContext, executionService, threadPoolAlias, writerConcurrency, diskSegments, - storeConfig, timeSource, eventDispatcher, unit.toBytes(diskPool.getSize())); + storeConfig, timeSource, eventDispatcher, unit.toBytes(diskPool.getSize()), getServiceProvider().getService(StatisticsService.class)); createdStores.put(offHeapStore, space); return offHeapStore; } catch (CachePersistenceException cpex) { @@ -386,7 +385,7 @@ public void releaseStore(Store resource) { try { OffHeapDiskStore offHeapDiskStore = (OffHeapDiskStore)resource; close(offHeapDiskStore); - DefaultStatisticsService.cleanForNode(offHeapDiskStore); + getServiceProvider().getService(StatisticsService.class).cleanForNode(offHeapDiskStore); tierOperationStatistics.remove(offHeapDiskStore); } catch (IOException e) { throw new RuntimeException(e); @@ -444,7 +443,7 @@ static void init(final OffHeapDiskStore resource) { @Override public void start(ServiceProvider serviceProvider) { - this.serviceProvider = serviceProvider; + super.start(serviceProvider); diskPersistenceService = serviceProvider.getService(DiskResourceService.class); if (diskPersistenceService == null) { throw new IllegalStateException("Unable to find file based persistence service"); @@ -453,9 +452,12 @@ public void start(ServiceProvider serviceProvider) { @Override public void stop() { - this.serviceProvider = null; - createdStores.clear(); - diskPersistenceService = null; + try { + createdStores.clear(); + diskPersistenceService = null; + } finally { + super.stop(); + } } @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index 515b870c3c..f8dba08972 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -30,7 +30,6 @@ import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.core.events.StoreEventSink; import org.ehcache.core.spi.service.StatisticsService; -import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.statistics.OperationObserver; import org.ehcache.core.statistics.OperationStatistic; import org.ehcache.impl.internal.concurrent.EvictingConcurrentMap; @@ -54,7 +53,6 @@ import org.ehcache.sizeof.annotations.IgnoreSizeOf; import org.ehcache.spi.serialization.Serializer; import org.ehcache.spi.serialization.StatefulSerializer; -import org.ehcache.spi.service.ServiceProvider; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.events.StoreEventSource; import org.ehcache.core.spi.store.tiering.CachingTier; @@ -62,7 +60,6 @@ import org.ehcache.impl.internal.store.BinaryValueHolder; import org.ehcache.spi.copy.Copier; import org.ehcache.spi.copy.CopyProvider; -import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.core.spi.store.heap.SizeOfEngine; @@ -201,13 +198,13 @@ public void cacheConfigurationChange(CacheConfigurationChangeEvent event) { private static final Supplier REPLACE_EQUALS_TRUE = () -> Boolean.TRUE; - public OnHeapStore(Configuration config, TimeSource timeSource, Copier keyCopier, Copier valueCopier, SizeOfEngine sizeOfEngine, StoreEventDispatcher eventDispatcher) { - this(config, timeSource, keyCopier, valueCopier, sizeOfEngine, eventDispatcher, ConcurrentHashMap::new); + public OnHeapStore(Configuration config, TimeSource timeSource, Copier keyCopier, Copier valueCopier, SizeOfEngine sizeOfEngine, StoreEventDispatcher eventDispatcher, StatisticsService statisticsService) { + this(config, timeSource, keyCopier, valueCopier, sizeOfEngine, eventDispatcher, ConcurrentHashMap::new, statisticsService); } public OnHeapStore(Configuration config, TimeSource timeSource, Copier keyCopier, Copier valueCopier, - SizeOfEngine sizeOfEngine, StoreEventDispatcher eventDispatcher, Supplier> backingMapSupplier) { - super(config); + SizeOfEngine sizeOfEngine, StoreEventDispatcher eventDispatcher, Supplier> backingMapSupplier, StatisticsService statisticsService) { + super(config, statisticsService); Objects.requireNonNull(keyCopier, "keyCopier must not be null"); @@ -1652,17 +1649,17 @@ public OnHeapStore createStore(Configuration storeConfig, Ser public OnHeapStore createStoreInternal(Configuration storeConfig, StoreEventDispatcher eventDispatcher, ServiceConfiguration... serviceConfigs) { - TimeSource timeSource = serviceProvider.getService(TimeSourceService.class).getTimeSource(); - CopyProvider copyProvider = serviceProvider.getService(CopyProvider.class); + TimeSource timeSource = getServiceProvider().getService(TimeSourceService.class).getTimeSource(); + CopyProvider copyProvider = getServiceProvider().getService(CopyProvider.class); Copier keyCopier = copyProvider.createKeyCopier(storeConfig.getKeyType(), storeConfig.getKeySerializer(), serviceConfigs); Copier valueCopier = copyProvider.createValueCopier(storeConfig.getValueType(), storeConfig.getValueSerializer(), serviceConfigs); List> copiers = Arrays.asList(keyCopier, valueCopier); - SizeOfEngineProvider sizeOfEngineProvider = serviceProvider.getService(SizeOfEngineProvider.class); + SizeOfEngineProvider sizeOfEngineProvider = getServiceProvider().getService(SizeOfEngineProvider.class); SizeOfEngine sizeOfEngine = sizeOfEngineProvider.createSizeOfEngine( storeConfig.getResourcePools().getPoolForResource(ResourceType.Core.HEAP).getUnit(), serviceConfigs); - OnHeapStore onHeapStore = new OnHeapStore<>(storeConfig, timeSource, keyCopier, valueCopier, sizeOfEngine, eventDispatcher, ConcurrentHashMap::new); + OnHeapStore onHeapStore = new OnHeapStore<>(storeConfig, timeSource, keyCopier, valueCopier, sizeOfEngine, eventDispatcher, ConcurrentHashMap::new, getServiceProvider().getService(StatisticsService.class)); createdStores.put(onHeapStore, copiers); return onHeapStore; } @@ -1675,10 +1672,10 @@ public void releaseStore(Store resource) { } OnHeapStore onHeapStore = (OnHeapStore)resource; close(onHeapStore); - DefaultStatisticsService.cleanForNode(onHeapStore); + getServiceProvider().getService(StatisticsService.class).cleanForNode(onHeapStore); tierOperationStatistics.remove(onHeapStore); - CopyProvider copyProvider = serviceProvider.getService(CopyProvider.class); + CopyProvider copyProvider = getServiceProvider().getService(CopyProvider.class); for (Copier copier: copiers) { try { copyProvider.releaseCopier(copier); @@ -1713,15 +1710,13 @@ private void checkResource(Object resource) { } } - @Override - public void start(ServiceProvider serviceProvider) { - this.serviceProvider = serviceProvider; - } - @Override public void stop() { - this.serviceProvider = null; - createdStores.clear(); + try { + createdStores.clear(); + } finally { + super.stop(); + } } @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java index d42f82f2a9..4ba520285f 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java @@ -41,12 +41,14 @@ public class LoaderWriterStoreProvider extends AbstractWrapperStoreProvider { @Override protected Store wrap(Store store, Store.Configuration storeConfig, ServiceConfiguration... serviceConfigs) { WriteBehindConfiguration writeBehindConfiguration = findSingletonAmongst(WriteBehindConfiguration.class, (Object[]) serviceConfigs); + LocalLoaderWriterStore loaderWriterStore; if(writeBehindConfiguration == null) { - return new LocalLoaderWriterStore<>(store, storeConfig.getCacheLoaderWriter(), storeConfig.useLoaderInAtomics(), storeConfig.getExpiry()); + loaderWriterStore = new LocalLoaderWriterStore<>(store, storeConfig.getCacheLoaderWriter(), storeConfig.useLoaderInAtomics(), storeConfig.getExpiry()); } else { CacheLoaderWriter writeBehindLoaderWriter = writeBehindProvider.createWriteBehindLoaderWriter(storeConfig.getCacheLoaderWriter(), writeBehindConfiguration); - return new LocalWriteBehindLoaderWriterStore<>(store, writeBehindLoaderWriter, storeConfig.useLoaderInAtomics(), storeConfig.getExpiry()); + loaderWriterStore = new LocalWriteBehindLoaderWriterStore<>(store, writeBehindLoaderWriter, storeConfig.useLoaderInAtomics(), storeConfig.getExpiry()); } + return loaderWriterStore; } @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java index 101833046d..066bf01033 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java @@ -19,7 +19,6 @@ import org.ehcache.core.CacheConfigurationChangeListener; import org.ehcache.core.Ehcache; import org.ehcache.core.exceptions.StorePassThroughException; -import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.util.CollectionUtil; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.WrapperStore; @@ -65,7 +64,6 @@ public LocalLoaderWriterStore(Store delegate, CacheLoaderWriter extends BaseStore implements AuthoritativeTier, LowerCachingTier { @@ -104,8 +106,8 @@ public abstract class AbstractOffHeapStore extends BaseStore impleme @SuppressWarnings("unchecked") private volatile CachingTier.InvalidationListener invalidationListener = (CachingTier.InvalidationListener) NULL_INVALIDATION_LISTENER; - public AbstractOffHeapStore(Configuration config, TimeSource timeSource, StoreEventDispatcher eventDispatcher) { - super(config); + public AbstractOffHeapStore(Configuration config, TimeSource timeSource, StoreEventDispatcher eventDispatcher, StatisticsService statisticsService) { + super(config, statisticsService); expiry = config.getExpiry(); @@ -134,18 +136,18 @@ public AbstractOffHeapStore(Configuration config, TimeSource timeSource, S this.getAndRemoveObserver= createObserver("getAndRemove", LowerCachingTierOperationsOutcome.GetAndRemoveOutcome.class, true); this.installMappingObserver= createObserver("installMapping", LowerCachingTierOperationsOutcome.InstallMappingOutcome.class, true); - Set tags = tags(getStatisticsTag(), "tier"); - registerStatistic("allocatedMemory", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::allocatedMemory); - registerStatistic("occupiedMemory", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::occupiedMemory); - registerStatistic("dataAllocatedMemory", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::dataAllocatedMemory); - registerStatistic("dataOccupiedMemory", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::dataOccupiedMemory); - registerStatistic("dataSize", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::dataSize); - registerStatistic("dataVitalMemory", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::dataVitalMemory); - registerStatistic("mappings", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::longSize); - registerStatistic("vitalMemory", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::vitalMemory); - registerStatistic("removedSlotCount", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::removedSlotCount); - registerStatistic("usedSlotCount", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::usedSlotCount); - registerStatistic("tableCapacity", StatisticType.GAUGE, tags, EhcacheOffHeapBackingMap::tableCapacity); + Set tags = new HashSet<>(Arrays.asList(getStatisticsTag(), "tier")); + registerStatistic("allocatedMemory", GAUGE, tags, EhcacheOffHeapBackingMap::allocatedMemory); + registerStatistic("occupiedMemory", GAUGE, tags, EhcacheOffHeapBackingMap::occupiedMemory); + registerStatistic("dataAllocatedMemory", GAUGE, tags, EhcacheOffHeapBackingMap::dataAllocatedMemory); + registerStatistic("dataOccupiedMemory", GAUGE, tags, EhcacheOffHeapBackingMap::dataOccupiedMemory); + registerStatistic("dataSize", GAUGE, tags, EhcacheOffHeapBackingMap::dataSize); + registerStatistic("dataVitalMemory", GAUGE, tags, EhcacheOffHeapBackingMap::dataVitalMemory); + registerStatistic("mappings", GAUGE, tags, EhcacheOffHeapBackingMap::longSize); + registerStatistic("vitalMemory", GAUGE, tags, EhcacheOffHeapBackingMap::vitalMemory); + registerStatistic("removedSlotCount", GAUGE, tags, EhcacheOffHeapBackingMap::removedSlotCount); + registerStatistic("usedSlotCount", GAUGE, tags, EhcacheOffHeapBackingMap::usedSlotCount); + registerStatistic("tableCapacity", GAUGE, tags, EhcacheOffHeapBackingMap::tableCapacity); this.mapEvictionListener = new BackingMapEvictionListener<>(eventDispatcher, evictionObserver); } @@ -160,8 +162,6 @@ private void registerStatistic(String name, StatisticTy }); } - private static Set tags(String... tags) {return new HashSet<>(Arrays.asList(tags));} - @Override public Store.ValueHolder get(K key) throws StoreAccessException { checkKey(key); diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java index 5932e3200f..0e153e1ddc 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java @@ -22,7 +22,7 @@ import org.ehcache.config.ResourceType; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.events.StoreEventDispatcher; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.statistics.OperationStatistic; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.events.NullStoreEventDispatcher; @@ -75,8 +75,8 @@ public class OffHeapStore extends AbstractOffHeapStore { private volatile EhcacheConcurrentOffHeapClockCache> map; - public OffHeapStore(final Configuration config, TimeSource timeSource, StoreEventDispatcher eventDispatcher, long sizeInBytes) { - super(config, timeSource, eventDispatcher); + public OffHeapStore(final Configuration config, TimeSource timeSource, StoreEventDispatcher eventDispatcher, long sizeInBytes, StatisticsService statisticsService) { + super(config, timeSource, eventDispatcher, statisticsService); EvictionAdvisor evictionAdvisor = config.getEvictionAdvisor(); if (evictionAdvisor != null) { this.evictionAdvisor = wrap(evictionAdvisor); @@ -162,10 +162,10 @@ public OffHeapStore createStore(Configuration storeConfig, Se } private OffHeapStore createStoreInternal(Configuration storeConfig, StoreEventDispatcher eventDispatcher, ServiceConfiguration... serviceConfigs) { - if (serviceProvider == null) { + if (getServiceProvider() == null) { throw new NullPointerException("ServiceProvider is null in OffHeapStore.Provider."); } - TimeSource timeSource = serviceProvider.getService(TimeSourceService.class).getTimeSource(); + TimeSource timeSource = getServiceProvider().getService(TimeSourceService.class).getTimeSource(); SizedResourcePool offHeapPool = storeConfig.getResourcePools().getPoolForResource(getResourceType()); if (!(offHeapPool.getUnit() instanceof MemoryUnit)) { @@ -175,7 +175,7 @@ private OffHeapStore createStoreInternal(Configuration storeC OffHeapStore offHeapStore = new OffHeapStore<>(storeConfig, timeSource, eventDispatcher, unit.toBytes(offHeapPool - .getSize())); + .getSize()), getServiceProvider().getService(StatisticsService.class)); createdStores.add(offHeapStore); return offHeapStore; } @@ -187,7 +187,7 @@ public void releaseStore(Store resource) { } OffHeapStore offHeapStore = (OffHeapStore) resource; close(offHeapStore); - DefaultStatisticsService.cleanForNode(offHeapStore); + getServiceProvider().getService(StatisticsService.class).cleanForNode(offHeapStore); tierOperationStatistics.remove(offHeapStore); } @@ -222,15 +222,13 @@ static void init(final OffHeapStore resource) { resource.map = resource.createBackingMap(resource.sizeInBytes, resource.keySerializer, resource.valueSerializer, resource.evictionAdvisor); } - @Override - public void start(ServiceProvider serviceProvider) { - this.serviceProvider = serviceProvider; - } - @Override public void stop() { - this.serviceProvider = null; - createdStores.clear(); + try { + createdStores.clear(); + } finally { + super.stop(); + } } @Override diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java index 96502c7953..16bb266442 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java @@ -18,8 +18,8 @@ import org.ehcache.config.ResourceType; import org.ehcache.core.CacheConfigurationChangeListener; import org.ehcache.core.collections.ConcurrentWeakIdentityHashMap; +import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.Store; -import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.store.tiering.CachingTier; import org.ehcache.core.spi.store.tiering.HigherCachingTier; @@ -68,8 +68,6 @@ public CompoundCachingTier(HigherCachingTier higher, final LowerCachingTie } }); - DefaultStatisticsService.registerWithParent(higher, this); - DefaultStatisticsService.registerWithParent(lower, this); } private void notifyInvalidation(K key, Store.ValueHolder p) { @@ -210,7 +208,7 @@ public List getConfigurationChangeListeners() } - @ServiceDependencies({HigherCachingTier.Provider.class, LowerCachingTier.Provider.class}) + @ServiceDependencies({HigherCachingTier.Provider.class, LowerCachingTier.Provider.class, StatisticsService.class}) public static class Provider implements CachingTier.Provider { private volatile ServiceProvider serviceProvider; private final ConcurrentMap, Map.Entry> providersMap = new ConcurrentWeakIdentityHashMap<>(); @@ -236,6 +234,8 @@ public CachingTier createCachingTier(Store.Configuration stor LowerCachingTier lowerCachingTier = lowerProvider.createCachingTier(storeConfig, serviceConfigs); CompoundCachingTier compoundCachingTier = new CompoundCachingTier<>(higherCachingTier, lowerCachingTier); + serviceProvider.getService(StatisticsService.class).registerWithParent(higherCachingTier, compoundCachingTier); + serviceProvider.getService(StatisticsService.class).registerWithParent(lowerCachingTier, compoundCachingTier); providersMap.put(compoundCachingTier, new AbstractMap.SimpleEntry<>(higherProvider, lowerProvider)); return compoundCachingTier; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java index 6b0169c35c..9ed58e7dae 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java @@ -21,8 +21,8 @@ import org.ehcache.core.CacheConfigurationChangeListener; import org.ehcache.core.collections.ConcurrentWeakIdentityHashMap; import org.ehcache.core.exceptions.StorePassThroughException; +import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.Store; -import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.store.events.StoreEventSource; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; @@ -79,8 +79,6 @@ public void invalidateAllWithHash(long hash) throws StoreAccessException { } }); - DefaultStatisticsService.registerWithParent(cachingTier, this); - DefaultStatisticsService.registerWithParent(authoritativeTier, this); } @Override @@ -376,7 +374,7 @@ private ValueHolder handleStoreAccessException(StoreAccessException ce) throw throw new RuntimeException("Unexpected checked exception wrapped in StoreAccessException", cause); } - @ServiceDependencies({CachingTier.Provider.class, AuthoritativeTier.Provider.class}) + @ServiceDependencies({CachingTier.Provider.class, AuthoritativeTier.Provider.class, StatisticsService.class}) public static class Provider implements Store.Provider { private volatile ServiceProvider serviceProvider; @@ -449,6 +447,8 @@ public Store createStore(Configuration storeConfig, ServiceCo AuthoritativeTier authoritativeTier = authoritativeTierProvider.createAuthoritativeTier(storeConfig, configurations); TieredStore store = new TieredStore<>(cachingTier, authoritativeTier); + serviceProvider.getService(StatisticsService.class).registerWithParent(cachingTier, store); + serviceProvider.getService(StatisticsService.class).registerWithParent(authoritativeTier, store); registerStore(store, cachingTierProvider, authoritativeTierProvider); return store; } diff --git a/impl/src/main/java/org/ehcache/impl/store/BaseStore.java b/impl/src/main/java/org/ehcache/impl/store/BaseStore.java index f59f1f650f..9bb1229995 100644 --- a/impl/src/main/java/org/ehcache/impl/store/BaseStore.java +++ b/impl/src/main/java/org/ehcache/impl/store/BaseStore.java @@ -20,13 +20,11 @@ import org.ehcache.core.config.store.StoreStatisticsConfiguration; import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.Store; -import org.ehcache.core.statistics.DefaultStatisticsService; -import org.ehcache.core.statistics.DelegatedMappedOperationStatistics; import org.ehcache.core.statistics.OperationObserver; import org.ehcache.core.statistics.OperationStatistic; -import org.ehcache.core.statistics.StatsUtils; import org.ehcache.core.statistics.ZeroOperationStatistic; import org.ehcache.spi.service.Service; +import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.spi.service.ServiceProvider; import org.terracotta.management.model.stats.StatisticType; @@ -48,15 +46,17 @@ public abstract class BaseStore implements Store { protected final Class valueType; /** Tells if this store is by itself or in a tiered setup */ protected final boolean operationStatisticsEnabled; + protected final StatisticsService statisticsService; - public BaseStore(Configuration config) { - this(config.getKeyType(), config.getValueType(), config.isOperationStatisticsEnabled()); + public BaseStore(Configuration config, StatisticsService statisticsService) { + this(config.getKeyType(), config.getValueType(), config.isOperationStatisticsEnabled(), statisticsService); } - public BaseStore(Class keyType, Class valueType, boolean operationStatisticsEnabled) { + public BaseStore(Class keyType, Class valueType, boolean operationStatisticsEnabled, StatisticsService statisticsService) { this.keyType = keyType; this.valueType = valueType; this.operationStatisticsEnabled = operationStatisticsEnabled; + this.statisticsService = statisticsService; } protected void checkKey(K keyObject) { @@ -84,22 +84,38 @@ protected > OperationObserver createObserver(String name, C if(!operationStatisticsEnabled && canBeDisabled) { return ZeroOperationStatistic.get(); } - return DefaultStatisticsService.createOperationStatistics(name, outcome, getStatisticsTag(), this); + return statisticsService.createOperationStatistics(name, outcome, getStatisticsTag(), this); } protected void registerStatistic(String name, StatisticType type, Set tags, Supplier valueSupplier) { - DefaultStatisticsService.registerStatistic(this, name, type, tags, valueSupplier); + statisticsService.registerStatistic(this, name, type, tags, valueSupplier); } protected abstract String getStatisticsTag(); + @ServiceDependencies({StatisticsService.class}) protected static abstract class BaseStoreProvider implements Store.Provider { - protected volatile ServiceProvider serviceProvider; + private volatile ServiceProvider serviceProvider; protected , T extends Enum> OperationStatistic createTranslatedStatistic(BaseStore store, String statisticName, Map> translation, String targetName) { - return DefaultStatisticsService.registerStoreStatistics(store, targetName, getResourceType().getTierHeight(), store.getStatisticsTag(), translation, statisticName); + StatisticsService statisticsService = serviceProvider.getService(StatisticsService.class); + return statisticsService.registerStoreStatistics(store, targetName, getResourceType().getTierHeight(), store.getStatisticsTag(), translation, statisticName); + } + + @Override + public void start(ServiceProvider serviceProvider) { + this.serviceProvider = serviceProvider; + } + + @Override + public void stop() { + this.serviceProvider = null; + } + + protected ServiceProvider getServiceProvider() { + return this.serviceProvider; } protected abstract ResourceType getResourceType(); diff --git a/impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java b/impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java index 03be2c5d0a..5d8809d0f2 100644 --- a/impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java +++ b/impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java @@ -16,6 +16,7 @@ package org.ehcache.core.spi; +import org.ehcache.core.spi.service.CacheManagerProviderService; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.impl.internal.store.disk.OffHeapDiskStore; import org.ehcache.impl.internal.store.heap.OnHeapStore; @@ -25,6 +26,7 @@ import org.hamcrest.core.IsCollectionContaining; import org.hamcrest.core.IsSame; import org.junit.Test; +import org.mockito.Answers; import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.junit.Assert.assertThat; @@ -48,6 +50,7 @@ public void testSupportsMultipleAuthoritativeTierProviders() throws Exception { dependencySet.with(authoritativeTierProvider); dependencySet.with(diskStoreProvider); dependencySet.with(mock(DiskResourceService.class)); + dependencySet.with(mock(CacheManagerProviderService.class, Answers.RETURNS_DEEP_STUBS)); ServiceLocator serviceLocator = dependencySet.build(); serviceLocator.startAllServices(); diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java index 10f4c84cba..03ac8a82ba 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java @@ -26,8 +26,10 @@ import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.spi.ServiceLocator; +import org.ehcache.core.spi.service.CacheManagerProviderService; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.DefaultTimeSourceService; import org.ehcache.impl.serialization.LongSerializer; @@ -65,7 +67,8 @@ public class OffHeapDiskStoreProviderTest { public void testStatisticsAssociations() throws Exception { OffHeapDiskStore.Provider provider = new OffHeapDiskStore.Provider(); - ServiceLocator serviceLocator = dependencySet().with(mock(SerializationProvider.class)) + ServiceLocator serviceLocator = dependencySet().with(mock(SerializationProvider.class)).with(new DefaultStatisticsService()) + .with(mock(CacheManagerProviderService.class)) .with(new DefaultTimeSourceService(null)).with(mock(DiskResourceService.class)).build(); provider.start(serviceLocator); diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java index 96e613a11c..c93f088128 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java @@ -23,6 +23,7 @@ import org.ehcache.config.SizedResourcePool; import org.ehcache.config.units.MemoryUnit; import org.ehcache.CachePersistenceException; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; @@ -122,7 +123,7 @@ private AuthoritativeTier newStore(Long capacity, EvictionAdviso new OnDemandExecutionService(), null, DEFAULT_WRITER_CONCURRENCY, DEFAULT_DISK_SEGMENTS, config, timeSource, new TestStoreEventDispatcher<>(), - unit.toBytes(diskPool.getSize())); + unit.toBytes(diskPool.getSize()), new DefaultStatisticsService()); OffHeapDiskStore.Provider.init(store); createdStores.put(store, spaceName); return store; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java index bc1a0b00ce..38310e0b2e 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java @@ -25,6 +25,8 @@ import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.spi.service.CacheManagerProviderService; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.statistics.LowerCachingTierOperationsOutcome; @@ -50,9 +52,12 @@ import org.ehcache.spi.serialization.UnsupportedTypeException; import org.ehcache.core.spi.service.FileBasedPersistenceContext; import org.ehcache.spi.persistence.PersistableResourceService.PersistenceSpaceIdentifier; +import org.ehcache.test.MockitoUtil; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import org.mockito.Answers; +import org.mockito.Mockito; import org.terracotta.context.query.Matcher; import org.terracotta.context.query.Query; import org.terracotta.context.query.QueryBuilder; @@ -90,6 +95,7 @@ import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.terracotta.context.ContextManager.nodeFor; import static org.terracotta.context.query.Matchers.attributes; @@ -123,16 +129,17 @@ public void testRecovery() throws StoreAccessException, IOException { @Test public void testRecoveryFailureWhenValueTypeChangesToIncompatibleClass() throws Exception { OffHeapDiskStore.Provider provider = new OffHeapDiskStore.Provider(); - ServiceLocator serviceLocator = dependencySet().with(diskResourceService).with(provider).build(); + ServiceLocator serviceLocator = dependencySet().with(diskResourceService).with(provider) + .with(mock(CacheManagerProviderService.class, Answers.RETURNS_DEEP_STUBS)).build(); serviceLocator.startAllServices(); - CacheConfiguration cacheConfiguration = mock(CacheConfiguration.class); + CacheConfiguration cacheConfiguration = MockitoUtil.mock(CacheConfiguration.class); when(cacheConfiguration.getResourcePools()).thenReturn(newResourcePoolsBuilder().disk(1, MemoryUnit.MB, false).build()); PersistenceSpaceIdentifier space = diskResourceService.getPersistenceSpaceIdentifier("cache", cacheConfiguration); { @SuppressWarnings("unchecked") - Store.Configuration storeConfig1 = mock(Store.Configuration.class); + Store.Configuration storeConfig1 = MockitoUtil.mock(Store.Configuration.class); when(storeConfig1.getKeyType()).thenReturn(Long.class); when(storeConfig1.getValueType()).thenReturn(String.class); when(storeConfig1.getResourcePools()).thenReturn(ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -148,7 +155,7 @@ public void testRecoveryFailureWhenValueTypeChangesToIncompatibleClass() throws { @SuppressWarnings("unchecked") - Store.Configuration storeConfig2 = mock(Store.Configuration.class); + Store.Configuration storeConfig2 = MockitoUtil.mock(Store.Configuration.class); when(storeConfig2.getKeyType()).thenReturn(Long.class); when(storeConfig2.getValueType()).thenReturn(Serializable.class); when(storeConfig2.getResourcePools()).thenReturn(ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -173,16 +180,17 @@ public void testRecoveryFailureWhenValueTypeChangesToIncompatibleClass() throws @Test public void testRecoveryWithArrayType() throws Exception { OffHeapDiskStore.Provider provider = new OffHeapDiskStore.Provider(); - ServiceLocator serviceLocator = dependencySet().with(diskResourceService).with(provider).build(); + ServiceLocator serviceLocator = dependencySet().with(diskResourceService).with(provider) + .with(mock(CacheManagerProviderService.class, Answers.RETURNS_DEEP_STUBS)).build(); serviceLocator.startAllServices(); - CacheConfiguration cacheConfiguration = mock(CacheConfiguration.class); + CacheConfiguration cacheConfiguration = MockitoUtil.mock(CacheConfiguration.class); when(cacheConfiguration.getResourcePools()).thenReturn(newResourcePoolsBuilder().disk(1, MemoryUnit.MB, false).build()); PersistenceSpaceIdentifier space = diskResourceService.getPersistenceSpaceIdentifier("cache", cacheConfiguration); { @SuppressWarnings("unchecked") - Store.Configuration storeConfig1 = mock(Store.Configuration.class); + Store.Configuration storeConfig1 = MockitoUtil.mock(Store.Configuration.class); when(storeConfig1.getKeyType()).thenReturn(Long.class); when(storeConfig1.getValueType()).thenReturn(Object[].class); when(storeConfig1.getResourcePools()).thenReturn(ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -198,7 +206,7 @@ public void testRecoveryWithArrayType() throws Exception { { @SuppressWarnings("unchecked") - Store.Configuration storeConfig2 = mock(Store.Configuration.class); + Store.Configuration storeConfig2 = MockitoUtil.mock(Store.Configuration.class); when(storeConfig2.getKeyType()).thenReturn(Long.class); when(storeConfig2.getValueType()).thenReturn(Object[].class); when(storeConfig2.getResourcePools()).thenReturn(ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -218,15 +226,16 @@ public void testRecoveryWithArrayType() throws Exception { @Test public void testProvidingOffHeapDiskStoreConfiguration() throws Exception { OffHeapDiskStore.Provider provider = new OffHeapDiskStore.Provider(); - ServiceLocator serviceLocator = dependencySet().with(diskResourceService).with(provider).build(); + ServiceLocator serviceLocator = dependencySet().with(diskResourceService).with(provider) + .with(mock(CacheManagerProviderService.class, Answers.RETURNS_DEEP_STUBS)).build(); serviceLocator.startAllServices(); - CacheConfiguration cacheConfiguration = mock(CacheConfiguration.class); + CacheConfiguration cacheConfiguration = MockitoUtil.mock(CacheConfiguration.class); when(cacheConfiguration.getResourcePools()).thenReturn(newResourcePoolsBuilder().disk(1, MemoryUnit.MB, false).build()); PersistenceSpaceIdentifier space = diskResourceService.getPersistenceSpaceIdentifier("cache", cacheConfiguration); @SuppressWarnings("unchecked") - Store.Configuration storeConfig1 = mock(Store.Configuration.class); + Store.Configuration storeConfig1 = MockitoUtil.mock(Store.Configuration.class); when(storeConfig1.getKeyType()).thenReturn(Long.class); when(storeConfig1.getValueType()).thenReturn(Object[].class); when(storeConfig1.getResourcePools()).thenReturn(ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -256,7 +265,7 @@ protected OffHeapDiskStore createAndInitStore(final TimeSource t new OnDemandExecutionService(), null, DEFAULT_WRITER_CONCURRENCY, DEFAULT_DISK_SEGMENTS, storeConfiguration, timeSource, new TestStoreEventDispatcher<>(), - MB.toBytes(1)) { + MB.toBytes(1), new DefaultStatisticsService()) { @Override protected OffHeapValueHolderPortability createValuePortability(Serializer serializer) { return new AssertingOffHeapValueHolderPortability<>(serializer); @@ -284,7 +293,7 @@ protected OffHeapDiskStore createAndInitStore(TimeSource timeSou new OnDemandExecutionService(), null, DEFAULT_WRITER_CONCURRENCY, DEFAULT_DISK_SEGMENTS, storeConfiguration, timeSource, new TestStoreEventDispatcher<>(), - MB.toBytes(1)) { + MB.toBytes(1), new DefaultStatisticsService()) { @Override protected OffHeapValueHolderPortability createValuePortability(Serializer serializer) { return new AssertingOffHeapValueHolderPortability<>(serializer); @@ -351,7 +360,7 @@ private void assertRank(final Store.Provider provider, final int expectedRank, f private FileBasedPersistenceContext getPersistenceContext() { try { - CacheConfiguration cacheConfiguration = mock(CacheConfiguration.class); + CacheConfiguration cacheConfiguration = MockitoUtil.mock(CacheConfiguration.class); when(cacheConfiguration.getResourcePools()).thenReturn(newResourcePoolsBuilder().disk(1, MB, false).build()); PersistenceSpaceIdentifier space = diskResourceService.getPersistenceSpaceIdentifier("cache", cacheConfiguration); return diskResourceService.createPersistenceContextWithin(space, "store"); diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java index 2416ec91c2..fe44f8c421 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java @@ -20,6 +20,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.IdentityCopier; @@ -78,7 +79,7 @@ private Store newStore(Long capacity, EvictionAdvisor config = new StoreConfigurationImpl<>(getKeyType(), getValueType(), evictionAdvisor, getClass().getClassLoader(), expiry, resourcePools, 0, null, null); return new OnHeapStore<>(config, timeSource, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), - new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), new TestStoreEventDispatcher<>()); + new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), new TestStoreEventDispatcher<>(), new DefaultStatisticsService()); } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java index d4aefe3677..c65e210c89 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java @@ -20,6 +20,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.SerializingCopier; @@ -86,7 +87,7 @@ private Store newStore(Long capacity, EvictionAdvisor(getSystemClassLoader()), new JavaSerializer<>(getSystemClassLoader())); return new OnHeapStore<>(config, timeSource, defaultCopier, defaultCopier, - new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), new TestStoreEventDispatcher<>()); + new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), new TestStoreEventDispatcher<>(), new DefaultStatisticsService()); } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByRefTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByRefTest.java index 42076cec32..2367f15248 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByRefTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByRefTest.java @@ -22,6 +22,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.units.EntryUnit; import org.ehcache.core.events.StoreEventDispatcher; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.impl.internal.sizeof.NoopSizeOfEngine; @@ -98,7 +99,7 @@ public int getDispatcherConcurrency() { public CacheLoaderWriter getCacheLoaderWriter() { return null; } - }, timeSource, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), new NoopSizeOfEngine(), (StoreEventDispatcher) eventDispatcher); + }, timeSource, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), new NoopSizeOfEngine(), (StoreEventDispatcher) eventDispatcher, new DefaultStatisticsService()); } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByValueTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByValueTest.java index 618295b60e..7d032735c4 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByValueTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByValueTest.java @@ -22,6 +22,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.units.EntryUnit; import org.ehcache.core.events.StoreEventDispatcher; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.sizeof.NoopSizeOfEngine; import org.ehcache.core.spi.time.TimeSource; @@ -103,7 +104,7 @@ public int getDispatcherConcurrency() { public CacheLoaderWriter getCacheLoaderWriter() { return null; } - }, timeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher); + }, timeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher, new DefaultStatisticsService()); } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java index f9a0386304..01ccf44d80 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java @@ -18,6 +18,7 @@ import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.core.events.NullStoreEventDispatcher; @@ -62,7 +63,7 @@ protected Store.Configuration mockStoreConfig() { protected OnHeapStore newStore() { Store.Configuration configuration = mockStoreConfig(); return new OnHeapStore<>(configuration, SystemTimeSource.INSTANCE, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), - new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher()); + new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()); } @Test @@ -76,7 +77,7 @@ public void testBulkComputeFunctionGetsValuesOfEntries() throws Exception { when(config.getResourcePools()).thenReturn(newResourcePoolsBuilder().heap(Long.MAX_VALUE, EntryUnit.ENTRIES).build()); OnHeapStore store = new OnHeapStore<>(config, SystemTimeSource.INSTANCE, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), - new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher()); + new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()); store.put(1, 2); store.put(2, 3); store.put(3, 4); @@ -155,7 +156,8 @@ public void testBulkComputeStoreRemovesValueWhenFunctionReturnsNullMappings() th Store.Configuration configuration = mockStoreConfig(); @SuppressWarnings("unchecked") - OnHeapStore store = new OnHeapStore<>(configuration, SystemTimeSource.INSTANCE, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher()); + OnHeapStore store = new OnHeapStore<>(configuration, SystemTimeSource.INSTANCE, IdentityCopier.identityCopier(), + IdentityCopier.identityCopier(), new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()); store.put(1, "one"); store.put(2, "two"); store.put(3, "three"); diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java index 6972cf3fe0..e3bcdcc536 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java @@ -20,6 +20,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.IdentityCopier; @@ -83,7 +84,8 @@ private Store newStore(Long capacity, EvictionAdvisor config = new StoreConfigurationImpl<>(getKeyType(), getValueType(), evictionAdvisor, getClass().getClassLoader(), expiry, resourcePools, 0, null, null); - return new OnHeapStore<>(config, timeSource, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), new NoopSizeOfEngine(), new TestStoreEventDispatcher<>()); + return new OnHeapStore<>(config, timeSource, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), + new NoopSizeOfEngine(), new TestStoreEventDispatcher<>(), new DefaultStatisticsService()); } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java index 5a7ec71121..29bda73d6e 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java @@ -20,6 +20,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.SerializingCopier; @@ -91,7 +92,7 @@ private Store newStore(Long capacity, EvictionAdvisor config = new StoreConfigurationImpl<>(getKeyType(), getValueType(), evictionAdvisor, getClass().getClassLoader(), expiry, resourcePools, 0, new JavaSerializer<>(getSystemClassLoader()), new JavaSerializer<>(getSystemClassLoader())); - return new OnHeapStore<>(config, timeSource, defaultCopier, defaultCopier, new NoopSizeOfEngine(), new TestStoreEventDispatcher<>()); + return new OnHeapStore<>(config, timeSource, defaultCopier, defaultCopier, new NoopSizeOfEngine(), new TestStoreEventDispatcher<>(), new DefaultStatisticsService()); } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java index eb83cb88c4..a137d0c675 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java @@ -19,6 +19,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.core.events.NullStoreEventDispatcher; @@ -70,7 +71,8 @@ private CachingTier newCachingTier(Long capacity) { Store.Configuration config = new StoreConfigurationImpl<>(getKeyType(), getValueType(), null, ClassLoader.getSystemClassLoader(), ExpiryPolicyBuilder.noExpiration(), buildResourcePools(capacity), 0, null, null); - return new OnHeapStore<>(config, SystemTimeSource.INSTANCE, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher()); + return new OnHeapStore<>(config, SystemTimeSource.INSTANCE, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), + new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()); } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java index 141c559907..493f267c51 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java @@ -19,6 +19,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.SerializingCopier; import org.ehcache.core.events.NullStoreEventDispatcher; @@ -77,7 +78,8 @@ private CachingTier newCachingTier(Long capacity) { ClassLoader.getSystemClassLoader(), ExpiryPolicyBuilder.noExpiration(), buildResourcePools(capacity), 0, new JavaSerializer<>(getSystemClassLoader()), new JavaSerializer<>(getSystemClassLoader())); - return new OnHeapStore<>(config, SystemTimeSource.INSTANCE, defaultCopier, defaultCopier, new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher()); + return new OnHeapStore<>(config, SystemTimeSource.INSTANCE, defaultCopier, defaultCopier, new NoopSizeOfEngine(), + NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()); } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java index 60c530f358..a2be9cdb12 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java @@ -19,6 +19,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.spi.resilience.StoreAccessException; @@ -115,7 +116,7 @@ String.class, String.class, noAdvice(), } }); OnHeapStore store = new OnHeapStore<>(configuration, timeSource, - new IdentityCopier<>(), new IdentityCopier<>(), new NoopSizeOfEngine(), eventDispatcher); + new IdentityCopier<>(), new IdentityCopier<>(), new NoopSizeOfEngine(), eventDispatcher, new DefaultStatisticsService()); timeSource.advanceTime(10000L); store.put(firstKey, "daValue"); timeSource.advanceTime(10000L); @@ -182,11 +183,13 @@ public CacheLoaderWriter getCacheLoaderWriter() { public static class OnHeapStoreForTests extends OnHeapStore { public OnHeapStoreForTests(final Configuration config, final TimeSource timeSource) { - super(config, timeSource, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher()); + super(config, timeSource, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), new NoopSizeOfEngine(), + NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()); } public OnHeapStoreForTests(final Configuration config, final TimeSource timeSource, final SizeOfEngine engine) { - super(config, timeSource, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), engine, NullStoreEventDispatcher.nullStoreEventDispatcher()); + super(config, timeSource, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), engine, + NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()); } private boolean enforceCapacityWasCalled = false; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java index 7f179eb96e..8065e479a8 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java @@ -19,6 +19,7 @@ import org.ehcache.Cache; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.impl.copy.IdentityCopier; @@ -101,7 +102,8 @@ public Key copyForWrite(Key obj) { } }; - store = new OnHeapStore<>(configuration, SystemTimeSource.INSTANCE, keyCopier, IdentityCopier.identityCopier(), new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher()); + store = new OnHeapStore<>(configuration, SystemTimeSource.INSTANCE, keyCopier, IdentityCopier.identityCopier(), + new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()); } @Test diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java index 0c1107b609..d3d1af5239 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java @@ -19,6 +19,7 @@ import org.ehcache.Cache; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.impl.copy.IdentityCopier; @@ -103,7 +104,8 @@ public Value copyForWrite(Value obj) { } }; - store = new OnHeapStore<>(configuration, SystemTimeSource.INSTANCE, new IdentityCopier<>(), valueCopier, new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher()); + store = new OnHeapStore<>(configuration, SystemTimeSource.INSTANCE, new IdentityCopier<>(), valueCopier, new NoopSizeOfEngine(), + NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()); } @Test diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java index 7fbb27cce3..8c4b652c66 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java @@ -20,6 +20,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.event.EventType; import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; @@ -538,7 +539,7 @@ static class OnHeapStoreForTests extends OnHeapStore { @SuppressWarnings("unchecked") OnHeapStoreForTests(final Configuration config, final TimeSource timeSource, final SizeOfEngine engine, StoreEventDispatcher eventDispatcher) { - super(config, timeSource, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), engine, eventDispatcher); + super(config, timeSource, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), engine, eventDispatcher, new DefaultStatisticsService()); } long getCurrentUsageInBytes() { diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByRefTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByRefTest.java index 45ca0e16c2..b6feb1e813 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByRefTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByRefTest.java @@ -23,6 +23,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.events.StoreEventDispatcher; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.impl.internal.sizeof.DefaultSizeOfEngine; @@ -103,7 +104,8 @@ public int getDispatcherConcurrency() { public CacheLoaderWriter getCacheLoaderWriter() { return null; } - }, timeSource, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), (StoreEventDispatcher) eventDispatcher); + }, timeSource, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), + new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), (StoreEventDispatcher) eventDispatcher, new DefaultStatisticsService()); } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByValueTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByValueTest.java index 2d305c6f01..c9119f5605 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByValueTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByValueTest.java @@ -22,6 +22,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.events.StoreEventDispatcher; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.sizeof.DefaultSizeOfEngine; import org.ehcache.impl.internal.store.heap.OnHeapStore; @@ -108,7 +109,7 @@ public int getDispatcherConcurrency() { public CacheLoaderWriter getCacheLoaderWriter() { return null; } - }, timeSource, keyCopier, valueCopier, new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), eventDispatcher); + }, timeSource, keyCopier, valueCopier, new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), eventDispatcher, new DefaultStatisticsService()); } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java index 3c2f30c6d6..784d51b1ce 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java @@ -18,6 +18,7 @@ import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.ehcache.core.events.NullStoreEventDispatcher; @@ -58,7 +59,7 @@ protected Store.Configuration mockStoreConfig() { protected OnHeapStore newStore() { Store.Configuration configuration = mockStoreConfig(); return new OnHeapStore<>(configuration, SystemTimeSource.INSTANCE, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), - new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), NullStoreEventDispatcher.nullStoreEventDispatcher()); + new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()); } @SuppressWarnings("unchecked") @@ -73,7 +74,7 @@ public void testBulkComputeFunctionGetsValuesOfEntries() throws Exception { Store.Configuration configuration = config; OnHeapStore store = new OnHeapStore<>(configuration, SystemTimeSource.INSTANCE, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), - new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), NullStoreEventDispatcher.nullStoreEventDispatcher()); + new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()); store.put(1, 2); store.put(2, 3); store.put(3, 4); diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java index 813a7416ae..95d160874c 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java @@ -19,6 +19,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.core.events.NullStoreEventDispatcher; @@ -69,7 +70,7 @@ private CachingTier newCachingTier(Long capacity) { ClassLoader.getSystemClassLoader(), ExpiryPolicyBuilder.noExpiration(), buildResourcePools(capacity), 0, null, null); return new OnHeapStore<>(config, SystemTimeSource.INSTANCE, IdentityCopier.identityCopier(), IdentityCopier.identityCopier(), - new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), NullStoreEventDispatcher.nullStoreEventDispatcher()); + new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()); } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java index 68ae986c8e..1351e71396 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java @@ -19,6 +19,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.SerializingCopier; import org.ehcache.core.events.NullStoreEventDispatcher; @@ -75,7 +76,7 @@ private CachingTier newCachingTier(Long capacity) { ClassLoader.getSystemClassLoader(), ExpiryPolicyBuilder.noExpiration(), buildResourcePools(capacity), 0, new JavaSerializer<>(getSystemClassLoader()), new JavaSerializer<>(getSystemClassLoader())); return new OnHeapStore<>(config, SystemTimeSource.INSTANCE, defaultCopier, defaultCopier, - new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), NullStoreEventDispatcher.nullStoreEventDispatcher()); + new DefaultSizeOfEngine(Long.MAX_VALUE, Long.MAX_VALUE), NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()); } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java index 3fbf583177..f6aab61a20 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java @@ -22,6 +22,7 @@ import org.ehcache.config.SizedResourcePool; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.events.TestStoreEventDispatcher; @@ -85,7 +86,7 @@ private AuthoritativeTier newStore(Long capacity, EvictionAdviso Store.Configuration config = new StoreConfigurationImpl<>(getKeyType(), getValueType(), evictionAdvisor, getClass().getClassLoader(), expiry, resourcePools, 0, keySerializer, valueSerializer); OffHeapStore store = new OffHeapStore<>(config, timeSource, new TestStoreEventDispatcher<>(), unit - .toBytes(offheapPool.getSize())); + .toBytes(offheapPool.getSize()), new DefaultStatisticsService()); OffHeapStore.Provider.init(store); return store; } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java index fb864759c5..788230cfae 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java @@ -20,6 +20,7 @@ import org.ehcache.config.ResourceType; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.events.TestStoreEventDispatcher; @@ -56,7 +57,7 @@ protected OffHeapStore createAndInitStore(TimeSource timeSource, StoreConfigurationImpl storeConfiguration = new StoreConfigurationImpl<>(String.class, String.class, null, classLoader, expiry, null, 0, keySerializer, valueSerializer); OffHeapStore offHeapStore = new OffHeapStore(storeConfiguration, timeSource, new TestStoreEventDispatcher<>(), MemoryUnit.MB - .toBytes(1)) { + .toBytes(1), new DefaultStatisticsService()) { @Override protected OffHeapValueHolderPortability createValuePortability(Serializer serializer) { return new AssertingOffHeapValueHolderPortability<>(serializer); @@ -80,7 +81,7 @@ protected OffHeapStore createAndInitStore(TimeSource timeSource, StoreConfigurationImpl storeConfiguration = new StoreConfigurationImpl<>(String.class, byte[].class, evictionAdvisor, getClass().getClassLoader(), expiry, null, 0, keySerializer, valueSerializer); OffHeapStore offHeapStore = new OffHeapStore(storeConfiguration, timeSource, new TestStoreEventDispatcher<>(), MemoryUnit.MB - .toBytes(1)) { + .toBytes(1), new DefaultStatisticsService()) { @Override protected OffHeapValueHolderPortability createValuePortability(Serializer serializer) { return new AssertingOffHeapValueHolderPortability<>(serializer); diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java index e2a0bb4a18..5ee162a2ce 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java @@ -21,6 +21,7 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.events.StoreEventDispatcher; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.core.events.NullStoreEventDispatcher; @@ -80,10 +81,10 @@ private CachingTier newCachingTier(Long capacity) { ClassLoader.getSystemClassLoader(), ExpiryPolicyBuilder.noExpiration(), buildResourcePools(capacity), 0, new JavaSerializer<>(getSystemClassLoader()), new JavaSerializer<>(getSystemClassLoader())); StoreEventDispatcher eventDispatcher = NullStoreEventDispatcher.nullStoreEventDispatcher(); - OffHeapStore offHeapStore = new OffHeapStore<>(config, SystemTimeSource.INSTANCE, eventDispatcher, 10 * 1024 * 1024); + OffHeapStore offHeapStore = new OffHeapStore<>(config, SystemTimeSource.INSTANCE, eventDispatcher, 10 * 1024 * 1024, new DefaultStatisticsService()); OffHeapStoreLifecycleHelper.init(offHeapStore); IdentityCopier copier = new IdentityCopier<>(); - OnHeapStore onHeapStore = new OnHeapStore<>(config, SystemTimeSource.INSTANCE, copier, copier, new NoopSizeOfEngine(), eventDispatcher); + OnHeapStore onHeapStore = new OnHeapStore<>(config, SystemTimeSource.INSTANCE, copier, copier, new NoopSizeOfEngine(), eventDispatcher, new DefaultStatisticsService()); CompoundCachingTier compoundCachingTier = new CompoundCachingTier<>(onHeapStore, offHeapStore); map.put(compoundCachingTier, offHeapStore); return compoundCachingTier; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java index f09cb0874f..7cd315ebaf 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java @@ -20,6 +20,7 @@ import org.ehcache.config.EvictionAdvisor; import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; +import org.ehcache.core.spi.service.CacheManagerProviderService; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; @@ -38,6 +39,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import org.mockito.Answers; +import org.mockito.Mockito; import java.io.File; @@ -167,6 +170,7 @@ private ServiceLocator getServiceLocator(File location) throws Exception { dependencySet.with(diskResourceService); dependencySet.with(new OnHeapStore.Provider()); dependencySet.with(new OffHeapDiskStore.Provider()); + dependencySet.with(Mockito.mock(CacheManagerProviderService.class, Answers.RETURNS_DEEP_STUBS)); return dependencySet.build(); } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java index b583861545..4cdd522f7b 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java @@ -20,6 +20,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; @@ -179,7 +180,7 @@ public void setUp() throws Exception { // Here again, all parameters are useless, we only care about the beforeCompletingTheFault implementation CachingTier cachingTier = new OnHeapStore<>(config, SystemTimeSource.INSTANCE, StringCopier.copier(), StringCopier.copier(), new NoopSizeOfEngine(), NullStoreEventDispatcher. - nullStoreEventDispatcher()); + nullStoreEventDispatcher(), new DefaultStatisticsService()); tieredStore = new TieredStore<>(cachingTier, authoritativeTier); } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java index 4a35704927..e51e7f849f 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java @@ -26,6 +26,7 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.CachePersistenceException; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; @@ -129,7 +130,8 @@ private Store newStore(Long capacity, EvictionAdvisor defaultCopier = IdentityCopier.identityCopier(); - OnHeapStore onHeapStore = new OnHeapStore<>(config, timeSource, defaultCopier, defaultCopier, new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher()); + OnHeapStore onHeapStore = new OnHeapStore<>(config, timeSource, defaultCopier, defaultCopier, + new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()); try { CacheConfiguration cacheConfiguration = mock(CacheConfiguration.class); when(cacheConfiguration.getResourcePools()).thenReturn(newResourcePoolsBuilder().disk(1, MB, false).build()); @@ -146,7 +148,7 @@ private Store newStore(Long capacity, EvictionAdvisor(), - sizeInBytes); + sizeInBytes, new DefaultStatisticsService()); TieredStore tieredStore = new TieredStore<>(onHeapStore, diskStore); provider.registerStore(tieredStore, new CachingTier.Provider() { @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java index cea579a1bc..eeec9a8fe6 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java @@ -21,10 +21,13 @@ import org.ehcache.config.SizedResourcePool; import org.ehcache.core.exceptions.StorePassThroughException; import org.ehcache.core.spi.ServiceLocator; +import org.ehcache.core.spi.service.CacheManagerProviderService; import org.ehcache.core.spi.service.DiskResourceService; +import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.Store.RemoveStatus; import org.ehcache.core.spi.store.Store.ReplaceStatus; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; import org.ehcache.core.spi.store.tiering.CachingTier; @@ -36,6 +39,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.mockito.Answers; import org.mockito.ArgumentMatchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -603,6 +607,7 @@ public void testReleaseStoreFlushes() throws Exception { when(serviceProvider.getService(OffHeapStore.Provider.class)).thenReturn(offHeapStoreProvider); when(serviceProvider.getServicesOfType(AuthoritativeTier.Provider.class)).thenReturn(authorities); when(serviceProvider.getServicesOfType(CachingTier.Provider.class)).thenReturn(cachingTiers); + when(serviceProvider.getService(StatisticsService.class)).thenReturn(new DefaultStatisticsService()); tieredStoreProvider.start(serviceProvider); final Store tieredStore = tieredStoreProvider.createStore(configuration); @@ -614,7 +619,8 @@ public void testReleaseStoreFlushes() throws Exception { @Test public void testRank() throws Exception { TieredStore.Provider provider = new TieredStore.Provider(); - ServiceLocator serviceLocator = dependencySet().with(provider).with(mock(DiskResourceService.class)).build(); + ServiceLocator serviceLocator = dependencySet().with(provider).with(mock(DiskResourceService.class)) + .with(mock(CacheManagerProviderService.class, Answers.RETURNS_DEEP_STUBS)).build(); serviceLocator.startAllServices(); assertRank(provider, 0, ResourceType.Core.DISK); diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java index f586fcb0ab..6474aef6cc 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java @@ -27,6 +27,7 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.CachePersistenceException; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; @@ -132,12 +133,13 @@ private Store newStore(Long capacity, EvictionAdvisor defaultCopier = new IdentityCopier<>(); StoreEventDispatcher noOpEventDispatcher = NullStoreEventDispatcher.nullStoreEventDispatcher(); - final OnHeapStore onHeapStore = new OnHeapStore<>(config, timeSource, defaultCopier, defaultCopier, new NoopSizeOfEngine(), noOpEventDispatcher); + final OnHeapStore onHeapStore = new OnHeapStore<>(config, timeSource, defaultCopier, defaultCopier, + new NoopSizeOfEngine(), noOpEventDispatcher, new DefaultStatisticsService()); SizedResourcePool offheapPool = config.getResourcePools().getPoolForResource(ResourceType.Core.OFFHEAP); long offheapSize = ((MemoryUnit) offheapPool.getUnit()).toBytes(offheapPool.getSize()); - final OffHeapStore offHeapStore = new OffHeapStore<>(config, timeSource, noOpEventDispatcher, offheapSize); + final OffHeapStore offHeapStore = new OffHeapStore<>(config, timeSource, noOpEventDispatcher, offheapSize, new DefaultStatisticsService()); try { CacheConfiguration cacheConfiguration = mock(CacheConfiguration.class); @@ -154,7 +156,7 @@ private Store newStore(Long capacity, EvictionAdvisor(), - diskSize); + diskSize, new DefaultStatisticsService()); CompoundCachingTier compoundCachingTier = new CompoundCachingTier<>(onHeapStore, offHeapStore); diff --git a/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java b/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java index 3e3a09aea6..6aaec4556d 100644 --- a/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java +++ b/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java @@ -21,6 +21,7 @@ import org.ehcache.config.ResourceType; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.spi.loaderwriter.BulkCacheLoadingException; import org.ehcache.spi.loaderwriter.BulkCacheWritingException; import org.ehcache.spi.resilience.StoreAccessException; @@ -532,7 +533,7 @@ public Store createStore(Store.Configuration storeConfig, Ser throw new RuntimeException(e); } final Copier defaultCopier = new IdentityCopier(); - return new OnHeapStore(storeConfig, SystemTimeSource.INSTANCE, defaultCopier, defaultCopier, new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher()) { + return new OnHeapStore(storeConfig, SystemTimeSource.INSTANCE, defaultCopier, defaultCopier, new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()) { @Override public Map> bulkCompute(Set keys, Function>, Iterable>> remappingFunction) throws StoreAccessException { throw new StoreAccessException("Problem trying to bulk compute"); diff --git a/management/build.gradle b/management/build.gradle index 44a5bbd437..51076cbc5b 100644 --- a/management/build.gradle +++ b/management/build.gradle @@ -24,6 +24,7 @@ dependencies { compileOnly project(':clustered:client') compileOnly "org.terracotta:entity-client-api:$terracottaApisVersion" compileOnly ("org.terracotta.management.dist:mnm-nms-agent:$terracottaPlatformVersion") { + // This is to avoid stats lib being directly used. exclude group:'org.terracotta', module:'statistics' } diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java index 6e819bf5f1..8343daf225 100644 --- a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java +++ b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java @@ -24,7 +24,6 @@ import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.InternalCacheManager; import org.ehcache.core.spi.time.TimeSourceService; -import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.management.ManagementRegistryService; import org.ehcache.management.ManagementRegistryServiceConfiguration; import org.ehcache.management.cluster.Clustering; @@ -56,6 +55,7 @@ public class DefaultManagementRegistryService extends DefaultManagementRegistry private volatile InternalCacheManager cacheManager; private volatile ClusteringManagementService clusteringManagementService; private volatile boolean clusteringManagementServiceAutoStarted; + private volatile StatisticsService statisticsService; public DefaultManagementRegistryService() { this(new DefaultManagementRegistryConfiguration()); @@ -70,7 +70,7 @@ public DefaultManagementRegistryService(ManagementRegistryServiceConfiguration c public void start(final ServiceProvider serviceProvider) { this.cacheManager = serviceProvider.getService(CacheManagerProviderService.class).getCacheManager(); - StatisticsService statisticsService = serviceProvider.getService(StatisticsService.class); + this.statisticsService = serviceProvider.getService(StatisticsService.class); TimeSourceService timeSourceService = serviceProvider.getService(TimeSourceService.class); // initialize management capabilities (stats, action calls, etc) @@ -105,7 +105,7 @@ public void stop() { @Override public void cacheAdded(String alias, Cache cache) { - DefaultStatisticsService.registerWithParent(cache, cacheManager); + statisticsService.registerWithParent(cache, cacheManager); register(new CacheBinding(alias, cache)); } @@ -114,7 +114,7 @@ public void cacheAdded(String alias, Cache cache) { public void cacheRemoved(String alias, Cache cache) { unregister(new CacheBinding(alias, cache)); - DefaultStatisticsService.deRegisterFromParent(cache, cacheManager); + statisticsService.deRegisterFromParent(cache, cacheManager); } @Override diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java index 93c55d4f8b..f6d86c3ce3 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java @@ -21,8 +21,8 @@ import org.ehcache.core.CacheConfigurationChangeListener; import org.ehcache.config.EvictionAdvisor; import org.ehcache.core.spi.service.DiskResourceService; +import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.WrapperStore; -import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.core.store.StoreSupport; import org.ehcache.impl.store.BaseStore; @@ -104,8 +104,8 @@ public class XAStore extends BaseStore implements WrapperStore private final StoreEventSourceWrapper eventSourceWrapper; public XAStore(Class keyType, Class valueType, Store> underlyingStore, TransactionManagerWrapper transactionManagerWrapper, - TimeSource timeSource, Journal journal, String uniqueXAResourceId) { - super(keyType, valueType, true); + TimeSource timeSource, Journal journal, String uniqueXAResourceId, StatisticsService statisticsService) { + super(keyType, valueType, true, statisticsService); this.underlyingStore = underlyingStore; this.transactionManagerWrapper = transactionManagerWrapper; this.timeSource = timeSource; @@ -115,7 +115,6 @@ public XAStore(Class keyType, Class valueType, Store> under this.recoveryXaResource = new EhcacheXAResource<>(underlyingStore, journal, transactionContextFactory); this.eventSourceWrapper = new StoreEventSourceWrapper<>(underlyingStore.getStoreEventSource()); - DefaultStatisticsService.registerWithParent(underlyingStore, this); } private static boolean isInDoubt(SoftLock softLock) { @@ -939,7 +938,9 @@ public Duration getExpiryForUpdate(K key, Supplier> oldSof // create the XA store TransactionManagerWrapper transactionManagerWrapper = transactionManagerProvider.getTransactionManagerWrapper(); Store store = new XAStore<>(storeConfig.getKeyType(), storeConfig.getValueType(), underlyingStore, - transactionManagerWrapper, timeSource, journal, uniqueXAResourceId); + transactionManagerWrapper, timeSource, journal, uniqueXAResourceId, serviceProvider.getService(StatisticsService.class)); + + serviceProvider.getService(StatisticsService.class).registerWithParent(underlyingStore, store); // create the softLockSerializer lifecycle helper SoftLockValueCombinedSerializerLifecycleHelper helper = diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreProviderTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreProviderTest.java index fb3085a48a..aabb0494f0 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreProviderTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreProviderTest.java @@ -18,8 +18,10 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.time.TimeSourceService; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.impl.internal.DefaultTimeSourceService; import org.ehcache.impl.internal.store.offheap.OffHeapStore; import org.ehcache.spi.persistence.StateRepository; @@ -60,6 +62,7 @@ public void testXAStoreProviderStatefulSerializer() { when(serviceProvider.getService(JournalProvider.class)).thenReturn(journalProvider); when(serviceProvider.getService(TimeSourceService.class)).thenReturn(new DefaultTimeSourceService(null)); when(serviceProvider.getService(TransactionManagerProvider.class)).thenReturn(transactionManagerProvider); + when(serviceProvider.getService(StatisticsService.class)).thenReturn(new DefaultStatisticsService()); when(serviceProvider.getServicesOfType(Store.Provider.class)).thenReturn(Collections.singleton(underlyingStoreProvider)); Store.Configuration configuration = mock(Store.Configuration.class); diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java index 9bd50e7fed..30b0bd2230 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java @@ -24,8 +24,10 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.core.spi.ServiceLocator; +import org.ehcache.core.spi.service.CacheManagerProviderService; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.config.copy.DefaultCopyProviderConfiguration; @@ -57,6 +59,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; +import org.mockito.Answers; import java.time.Duration; import java.util.Arrays; @@ -140,7 +143,7 @@ public void setUp() { 0, keySerializer, valueSerializer); testTimeSource = new TestTimeSource(); eventDispatcher = NullStoreEventDispatcher.nullStoreEventDispatcher(); - onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher); + onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher, new DefaultStatisticsService()); journal = new TransientJournal<>(); } @@ -690,7 +693,7 @@ public void testGetAndCompute() throws Exception { .build(), 0, keySerializer, valueSerializer); OffHeapStore> offHeapStore = new OffHeapStore<>(offHeapConfig, testTimeSource, eventDispatcher, MemorySizeParser - .parse("10M")); + .parse("10M"), new DefaultStatisticsService()); OffHeapStoreLifecycleHelper.init(offHeapStore); TieredStore> tieredStore = new TieredStore<>(onHeapStore, offHeapStore); @@ -880,7 +883,7 @@ public void testCompute() throws Exception { .build(), 0, keySerializer, valueSerializer); OffHeapStore> offHeapStore = new OffHeapStore<>(offHeapConfig, testTimeSource, eventDispatcher, MemorySizeParser - .parse("10M")); + .parse("10M"), new DefaultStatisticsService()); OffHeapStoreLifecycleHelper.init(offHeapStore); TieredStore> tieredStore = new TieredStore<>(onHeapStore, offHeapStore); @@ -1056,7 +1059,7 @@ public void testComputeIfAbsent() throws Exception { .build(), 0, keySerializer, valueSerializer); OffHeapStore> offHeapStore = new OffHeapStore<>(offHeapConfig, testTimeSource, eventDispatcher, MemorySizeParser - .parse("10M")); + .parse("10M"), new DefaultStatisticsService()); OffHeapStoreLifecycleHelper.init(offHeapStore); TieredStore> tieredStore = new TieredStore<>(onHeapStore, offHeapStore); @@ -1107,12 +1110,12 @@ public void testExpiry() throws Exception { Store.Configuration> onHeapConfig = new StoreConfigurationImpl<>(Long.class, valueClass, null, classLoader, expiry, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).build(), 0, keySerializer, valueSerializer); - onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher); + onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher, new DefaultStatisticsService()); Store.Configuration> offHeapConfig = new StoreConfigurationImpl<>(Long.class, valueClass, null, classLoader, expiry, ResourcePoolsBuilder.newResourcePoolsBuilder().offheap(10, MemoryUnit.MB).build(), 0, keySerializer, valueSerializer); OffHeapStore> offHeapStore = new OffHeapStore<>(offHeapConfig, testTimeSource, eventDispatcher, MemorySizeParser - .parse("10M")); + .parse("10M"), new DefaultStatisticsService()); OffHeapStoreLifecycleHelper.init(offHeapStore); TieredStore> tieredStore = new TieredStore<>(onHeapStore, offHeapStore); @@ -1155,12 +1158,12 @@ public Duration getExpiryForUpdate(Object key, Supplier oldValue, Object newV Store.Configuration> onHeapConfig = new StoreConfigurationImpl<>(Long.class, valueClass, null, classLoader, expiry, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).build(), 0, keySerializer, valueSerializer); - OnHeapStore> onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher); + OnHeapStore> onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher, new DefaultStatisticsService()); Store.Configuration> offHeapConfig = new StoreConfigurationImpl<>(Long.class, valueClass, null, classLoader, expiry, ResourcePoolsBuilder.newResourcePoolsBuilder().offheap(10, MemoryUnit.MB).build(), 0, keySerializer, valueSerializer); OffHeapStore> offHeapStore = new OffHeapStore<>(offHeapConfig, testTimeSource, eventDispatcher, MemorySizeParser - .parse("10M")); + .parse("10M"), new DefaultStatisticsService()); OffHeapStoreLifecycleHelper.init(offHeapStore); TieredStore> tieredStore = new TieredStore<>(onHeapStore, offHeapStore); @@ -1198,12 +1201,12 @@ public Duration getExpiryForUpdate(Object key, Supplier oldValue, Object newV Store.Configuration> onHeapConfig = new StoreConfigurationImpl<>(Long.class, valueClass, null, classLoader, expiry, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).build(), 0, keySerializer, valueSerializer); - OnHeapStore> onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher); + OnHeapStore> onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher, new DefaultStatisticsService()); Store.Configuration> offHeapConfig = new StoreConfigurationImpl<>(Long.class, valueClass, null, classLoader, expiry, ResourcePoolsBuilder.newResourcePoolsBuilder().offheap(10, MemoryUnit.MB).build(), 0, keySerializer, valueSerializer); OffHeapStore> offHeapStore = new OffHeapStore<>(offHeapConfig, testTimeSource, eventDispatcher, MemorySizeParser - .parse("10M")); + .parse("10M"), new DefaultStatisticsService()); OffHeapStoreLifecycleHelper.init(offHeapStore); TieredStore> tieredStore = new TieredStore<>(onHeapStore, offHeapStore); @@ -1248,12 +1251,12 @@ public Duration getExpiryForUpdate(Object key, Supplier oldValue, Object newV Store.Configuration> onHeapConfig = new StoreConfigurationImpl<>(Long.class, valueClass, null, classLoader, expiry, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).build(), 0, keySerializer, valueSerializer); - OnHeapStore> onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher); + OnHeapStore> onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher, new DefaultStatisticsService()); Store.Configuration> offHeapConfig = new StoreConfigurationImpl<>(Long.class, valueClass, null, classLoader, expiry, ResourcePoolsBuilder.newResourcePoolsBuilder().offheap(10, MemoryUnit.MB).build(), 0, keySerializer, valueSerializer); OffHeapStore> offHeapStore = new OffHeapStore<>(offHeapConfig, testTimeSource, eventDispatcher, MemorySizeParser - .parse("10M")); + .parse("10M"), new DefaultStatisticsService()); OffHeapStoreLifecycleHelper.init(offHeapStore); TieredStore> tieredStore = new TieredStore<>(onHeapStore, offHeapStore); @@ -1277,12 +1280,12 @@ public void testBulkCompute() throws Exception { Store.Configuration> onHeapConfig = new StoreConfigurationImpl<>(Long.class, valueClass, null, classLoader, expiry, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).build(), 0, keySerializer, valueSerializer); - OnHeapStore> onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher); + OnHeapStore> onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher, new DefaultStatisticsService()); Store.Configuration> offHeapConfig = new StoreConfigurationImpl<>(Long.class, valueClass, null, classLoader, expiry, ResourcePoolsBuilder.newResourcePoolsBuilder().offheap(10, MemoryUnit.MB).build(), 0, keySerializer, valueSerializer); OffHeapStore> offHeapStore = new OffHeapStore<>(offHeapConfig, testTimeSource, eventDispatcher, MemorySizeParser - .parse("10M")); + .parse("10M"), new DefaultStatisticsService()); OffHeapStoreLifecycleHelper.init(offHeapStore); TieredStore> tieredStore = new TieredStore<>(onHeapStore, offHeapStore); @@ -1352,12 +1355,12 @@ public void testBulkComputeIfAbsent() throws Exception { Store.Configuration> onHeapConfig = new StoreConfigurationImpl<>(Long.class, valueClass, null, classLoader, expiry, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).build(), 0, keySerializer, valueSerializer); - OnHeapStore> onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher); + OnHeapStore> onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher, new DefaultStatisticsService()); Store.Configuration> offHeapConfig = new StoreConfigurationImpl<>(Long.class, valueClass, null, classLoader, expiry, ResourcePoolsBuilder.newResourcePoolsBuilder().offheap(10, MemoryUnit.MB).build(), 0, keySerializer, valueSerializer); OffHeapStore> offHeapStore = new OffHeapStore<>(offHeapConfig, testTimeSource, eventDispatcher, MemorySizeParser - .parse("10M")); + .parse("10M"), new DefaultStatisticsService()); OffHeapStoreLifecycleHelper.init(offHeapStore); TieredStore> tieredStore = new TieredStore<>(onHeapStore, offHeapStore); @@ -1423,7 +1426,7 @@ public void testCustomEvictionAdvisor() throws Exception { .heap(10, EntryUnit.ENTRIES) .build(), 0, keySerializer, valueSerializer); - OnHeapStore> onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher); + OnHeapStore> onHeapStore = new OnHeapStore<>(onHeapConfig, testTimeSource, keyCopier, valueCopier, new NoopSizeOfEngine(), eventDispatcher, new DefaultStatisticsService()); final XAStore xaStore = getXAStore(onHeapStore); @@ -1450,6 +1453,7 @@ public void testRank() throws Exception { .with(provider) .with(Store.Provider.class) .with(mock(DiskResourceService.class)) + .with(mock(CacheManagerProviderService.class, Answers.RETURNS_DEEP_STUBS)) .with(mock(TransactionManagerProvider.class)).build(); serviceLocator.startAllServices(); @@ -1494,7 +1498,7 @@ private void assertSize(XAStore xaStore, int expectedSize) throws } private XAStore getXAStore(Store> store) { - return new XAStore<>(Long.class, String.class, store, transactionManagerWrapper, testTimeSource, journal, testName.getMethodName()); + return new XAStore<>(Long.class, String.class, store, transactionManagerWrapper, testTimeSource, journal, testName.getMethodName(), new DefaultStatisticsService()); } static class TestTransactionManager implements TransactionManager { From b113c04100e411b5f2de50736625fbbcc54cfa70 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Fri, 28 Jun 2019 09:31:31 -0700 Subject: [PATCH 148/372] bump tc-core version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index f9063c57fa..ad2ce49b36 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ jaxbVersion = 2.3.1 # Terracotta clustered terracottaPlatformVersion = 5.7.3-pre7 terracottaApisVersion = 1.6.1 -terracottaCoreVersion = 5.6.4-pre9 +terracottaCoreVersion = 5.6.4-pre10 terracottaPassthroughTestingVersion = 1.6.1 # Test lib versions From b9d729368365006dbdd9682c2695962add09193b Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Tue, 2 Jul 2019 07:51:11 -0700 Subject: [PATCH 149/372] Bump tc-core and tc-platform versions --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index ad2ce49b36..271282d492 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.3-pre7 +terracottaPlatformVersion = 5.7.3-pre9 terracottaApisVersion = 1.6.1 -terracottaCoreVersion = 5.6.4-pre10 +terracottaCoreVersion = 5.6.4-pre11 terracottaPassthroughTestingVersion = 1.6.1 # Test lib versions From 0ad4aaaec78575a26d890df56cf216a43e1b0c55 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Wed, 3 Jul 2019 14:34:30 -0700 Subject: [PATCH 150/372] bump tc-platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 271282d492..48acd2c42d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.3-pre9 +terracottaPlatformVersion = 5.7.3-pre10 terracottaApisVersion = 1.6.1 terracottaCoreVersion = 5.6.4-pre11 terracottaPassthroughTestingVersion = 1.6.1 From f43625184980b5948e287a36bdd4d624d7e6fe6e Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Mon, 15 Jul 2019 10:29:38 -0700 Subject: [PATCH 151/372] bump core version --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 48acd2c42d..b5a1b3dab7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.3-pre10 +terracottaPlatformVersion = 5.7.3-pre11 terracottaApisVersion = 1.6.1 -terracottaCoreVersion = 5.6.4-pre11 +terracottaCoreVersion = 5.6.4-pre12 terracottaPassthroughTestingVersion = 1.6.1 # Test lib versions From 23493e9fc1112e41a94880b807405a60290f7ba6 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 19 Jul 2019 13:00:40 -0400 Subject: [PATCH 152/372] Move to final versions in preparation for release --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index b5a1b3dab7..9c5a66f935 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.3-pre11 +terracottaPlatformVersion = 5.7.3 terracottaApisVersion = 1.6.1 -terracottaCoreVersion = 5.6.4-pre12 +terracottaCoreVersion = 5.6.4 terracottaPassthroughTestingVersion = 1.6.1 # Test lib versions From 9ab1327af4b02f76eb14f64a7ce8fa7b561acf28 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 19 Jul 2019 14:02:32 -0400 Subject: [PATCH 153/372] Advance documentation to account for 3.8 version release --- deploy.sh | 2 +- docs/src/docs/asciidoc/user/107.adoc | 24 +++++++-------- .../asciidoc/user/cache-event-listeners.adoc | 10 +++---- .../docs/asciidoc/user/caching-concepts.adoc | 4 +-- .../docs/asciidoc/user/caching-patterns.adoc | 4 +-- .../src/docs/asciidoc/user/caching-terms.adoc | 4 +-- .../src/docs/asciidoc/user/class-loading.adoc | 4 +-- .../docs/asciidoc/user/clustered-cache.adoc | 22 +++++++------- docs/src/docs/asciidoc/user/common.adoc | 8 ++--- .../src/docs/asciidoc/user/config-derive.adoc | 24 +++++++-------- .../docs/asciidoc/user/eviction-advisor.adoc | 6 ++-- docs/src/docs/asciidoc/user/examples.adoc | 6 ++-- docs/src/docs/asciidoc/user/expiry.adoc | 14 ++++----- .../docs/asciidoc/user/getting-started.adoc | 16 +++++----- docs/src/docs/asciidoc/user/index.adoc | 4 +-- docs/src/docs/asciidoc/user/management.adoc | 12 ++++---- .../docs/asciidoc/user/migration-guide.adoc | 6 ++-- docs/src/docs/asciidoc/user/osgi.adoc | 4 +-- docs/src/docs/asciidoc/user/performance.adoc | 6 ++-- docs/src/docs/asciidoc/user/resilience.adoc | 6 ++-- .../asciidoc/user/serializers-copiers.adoc | 8 ++--- docs/src/docs/asciidoc/user/thread-pools.adoc | 12 ++++---- docs/src/docs/asciidoc/user/tiering.adoc | 28 ++++++++--------- docs/src/docs/asciidoc/user/usermanaged.adoc | 14 ++++----- docs/src/docs/asciidoc/user/writers.adoc | 8 ++--- docs/src/docs/asciidoc/user/xa.adoc | 18 +++++------ docs/src/docs/asciidoc/user/xml.adoc | 30 +++++++++---------- docs/src/docs/asciidoc/user/xsds.adoc | 12 ++++---- 28 files changed, 158 insertions(+), 158 deletions(-) diff --git a/deploy.sh b/deploy.sh index 3921828d43..89d52e1347 100755 --- a/deploy.sh +++ b/deploy.sh @@ -208,7 +208,7 @@ if [ $is_major ]; then echo " layout: \"docs35_page\"" >> _config.yml echo " ehc_version: \"${major_version}\"" >> _config.yml echo " ehc_javadoc_version: \"${version}\"" >> _config.yml - echo " ehc_checkout_dir_var: \"sourcedir37\"" >> _config.yml + echo " ehc_checkout_dir_var: \"sourcedir38\"" >> _config.yml sed -i '' "s/#needle\_for\_sourcedir/ - sourcedir${short_major_version}=\/_eh${short_major_version}\\ #needle_for_sourcedir/" _config.yml diff --git a/docs/src/docs/asciidoc/user/107.adoc b/docs/src/docs/asciidoc/user/107.adoc index d398beef2e..9f6763c42f 100644 --- a/docs/src/docs/asciidoc/user/107.adoc +++ b/docs/src/docs/asciidoc/user/107.adoc @@ -1,9 +1,9 @@ --- --- = The Ehcache 3.x JSR-107 Provider -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -59,7 +59,7 @@ Here is a code sample that demonstrates the usage of the basic JCache configurat [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=basicConfigurationExample] +include::{sourcedir38}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=basicConfigurationExample] ---- <1> Retrieves the default CachingProvider implementation from the application's classpath. @@ -91,7 +91,7 @@ you can still get to the underlying Ehcache `CacheRuntimeConfiguration`: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=mutableConfigurationExample] +include::{sourcedir38}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=mutableConfigurationExample] ---- <1> Create a JCache cache using the `MutableConfiguration` interface from the JCache specification. @@ -109,7 +109,7 @@ The way you do this is as follows: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheCacheManagerConfigurationExample] +include::{sourcedir38}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheCacheManagerConfigurationExample] ---- <1> Cast the `CachingProvider` into the Ehcache specific implementation `org.ehcache.jsr107.EhcacheCachingProvider`, <2> Create a configuration using the specific Ehcache `DefaultConfiguration` and pass it some `CacheManager` level configurations, @@ -122,7 +122,7 @@ When using this mechanism, no JCache `CompleteConfiguration` is used and so you [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheBasedConfigurationExample] +include::{sourcedir38}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheBasedConfigurationExample] ---- <1> Create an Ehcache `CacheConfiguration`. @@ -142,14 +142,14 @@ The following is an example of an XML configuration: [source%nowrap,xml,indent=0] ---- -include::{sourcedir37}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml[] +include::{sourcedir38}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml[] ---- Here is an example of how to access the XML configuration using JCache: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107UsingXMLConfigExample] +include::{sourcedir38}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107UsingXMLConfigExample] ---- <1> Invoke `javax.cache.spi.CachingProvider.getCacheManager(java.net.URI, java.lang.ClassLoader)` @@ -179,7 +179,7 @@ You can do this at two different levels: [source%nowrap,xml,indent=0] ---- -include::{sourcedir37}/107/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml[lines=17..-1] +include::{sourcedir38}/107/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml[lines=17..-1] ---- <1> Using the JCache service extension, you can enable MBeans by default. @@ -201,7 +201,7 @@ To do this, add a `jsr107` service in your XML configuration file: [source%nowrap,xml,indent=0] ---- -include::{sourcedir37}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml[] +include::{sourcedir38}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml[] ---- <1> First, declare a namespace for the JCache extension, e.g. `jsr107`. @@ -218,7 +218,7 @@ Using the above configuration, you can not only supplement but also override the [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107SupplementWithTemplatesExample] +include::{sourcedir38}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107SupplementWithTemplatesExample] ---- <1> Assume existing JCache configuration code, which is store-by-value by default @@ -283,5 +283,5 @@ If you need _Ehcache through JCache_ behaviour, the following shows the relevant [source%nowrap,xml,indent=0] ---- -include::{sourcedir37}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml[tag=cacheThroughCAS] +include::{sourcedir38}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml[tag=cacheThroughCAS] ---- diff --git a/docs/src/docs/asciidoc/user/cache-event-listeners.adoc b/docs/src/docs/asciidoc/user/cache-event-listeners.adoc index d446fd3a38..e73a6b0166 100644 --- a/docs/src/docs/asciidoc/user/cache-event-listeners.adoc +++ b/docs/src/docs/asciidoc/user/cache-event-listeners.adoc @@ -1,9 +1,9 @@ --- --- = Cache Event Listeners -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -18,7 +18,7 @@ Listeners are registered at the cache level - and therefore only receive events [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEventListener] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEventListener] ---- <1> Create a `CacheEventListenerConfiguration` using the builder indicating the listener and the events to receive (in this case create and update events) @@ -57,7 +57,7 @@ Cache event listeners may also be added and removed while the cache is being use [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=registerListenerAtRuntime] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=registerListenerAtRuntime] ---- <1> Create a `CacheEventListener` implementation instance. @@ -73,7 +73,7 @@ Advanced users may want to tune the level of concurrency which may be used for d [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=configuringEventProcessingQueues] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=configuringEventProcessingQueues] ---- <1> Indicate the level of concurrency desired diff --git a/docs/src/docs/asciidoc/user/caching-concepts.adoc b/docs/src/docs/asciidoc/user/caching-concepts.adoc index 4984cf88f9..fd5a59e689 100644 --- a/docs/src/docs/asciidoc/user/caching-concepts.adoc +++ b/docs/src/docs/asciidoc/user/caching-concepts.adoc @@ -1,9 +1,9 @@ --- --- = Concepts Related to Caching -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/caching-patterns.adoc b/docs/src/docs/asciidoc/user/caching-patterns.adoc index 9331c3d04e..2708c74a5f 100644 --- a/docs/src/docs/asciidoc/user/caching-patterns.adoc +++ b/docs/src/docs/asciidoc/user/caching-patterns.adoc @@ -1,9 +1,9 @@ --- --- = Cache Usage Patterns -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/caching-terms.adoc b/docs/src/docs/asciidoc/user/caching-terms.adoc index 51b856a2a8..e61a9f250c 100644 --- a/docs/src/docs/asciidoc/user/caching-terms.adoc +++ b/docs/src/docs/asciidoc/user/caching-terms.adoc @@ -1,9 +1,9 @@ --- --- = Terms Related to Caching -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/class-loading.adoc b/docs/src/docs/asciidoc/user/class-loading.adoc index 119ec0a151..32152ef674 100644 --- a/docs/src/docs/asciidoc/user/class-loading.adoc +++ b/docs/src/docs/asciidoc/user/class-loading.adoc @@ -1,9 +1,9 @@ --- --- = Class loading -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/clustered-cache.adoc b/docs/src/docs/asciidoc/user/clustered-cache.adoc index df5f02c8f7..f079302b9d 100644 --- a/docs/src/docs/asciidoc/user/clustered-cache.adoc +++ b/docs/src/docs/asciidoc/user/clustered-cache.adoc @@ -1,9 +1,9 @@ --- --- = Clustered Cache -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -134,7 +134,7 @@ It contains the bare minimum configuration required for the samples in the rest [source,xml,indent=0] ---- -include::{sourcedir37}/clustered/client/src/test/resources/configs/docs/tc-config.xml[] +include::{sourcedir38}/clustered/client/src/test/resources/configs/docs/tc-config.xml[] ---- The above configuration defines two named server off-heap resources: @@ -175,7 +175,7 @@ Here is a code sample that shows how to configure a cache manager with clusterin [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] +include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] ---- <1> Returns the `org.ehcache.config.builders.CacheManagerBuilder` instance. @@ -192,7 +192,7 @@ This code sample demonstrates the usage of the concepts explained in the previou [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerWithServerSideConfigExample] +include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerWithServerSideConfigExample] ---- <1> `defaultServerResource(String)` on `ClusteringServiceConfigurationBuilder` instance sets the default server off-heap resource for the cache manager. @@ -219,7 +219,7 @@ When configuring a cache manager to connect to a cluster tier manager there are [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerLifecycle] +include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerLifecycle] ---- <1> In auto-create mode if no cluster tier manager exists then one is created with the supplied configuration. @@ -237,7 +237,7 @@ If it does not exist then the cache manager will fail to initialize. [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheTieredExample] +include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheTieredExample] ---- <1> Configuring the heap tier for cache. @@ -247,7 +247,7 @@ The equivalent XML configuration is as follows: [source%nowrap,xml,indent=0] ---- -include::{sourcedir37}/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=tieringSample] +include::{sourcedir38}/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=tieringSample] ---- <1> Specify the heap tier for cache. @@ -270,7 +270,7 @@ This comes with a latency penalty on the write operation required to give this g [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheConsistency] +include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheConsistency] ---- <1> Specify the consistency level through the use of additional service configuration, using _strong_ consistency here. @@ -280,7 +280,7 @@ The equivalent XML configuration is as follows: [source%nowrap,xml,indent=0] ---- -include::{sourcedir37}/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=consistencySample] +include::{sourcedir38}/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=consistencySample] ---- <1> Specify the consistency level through a custom service configuration from the `clustered` namespace. @@ -310,7 +310,7 @@ The example code below shows how this can be implemented. [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=unspecifiedClusteredCacheExample] +include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=unspecifiedClusteredCacheExample] ---- <1> Configure the first cache manager with auto create diff --git a/docs/src/docs/asciidoc/user/common.adoc b/docs/src/docs/asciidoc/user/common.adoc index 0a1860612e..8872d3424f 100644 --- a/docs/src/docs/asciidoc/user/common.adoc +++ b/docs/src/docs/asciidoc/user/common.adoc @@ -1,7 +1,7 @@ --- --- -ifndef::sourcedir37[] -:version: 3.7 +ifndef::sourcedir38[] +:version: 3.8 :notBuildingForSite: true ifdef::basebackend-html[:outfilesuffix: .html] :source-highlighter: coderay @@ -11,9 +11,9 @@ ifdef::basebackend-html[:outfilesuffix: .html] :icons: font :iconfont-remote!: :iconfont-name: font-awesome.min -:sourcedir37: ../../../../../ +:sourcedir38: ../../../../../ :imagesdir: images :sectanchors: :idprefix: :idseparator: - -endif::sourcedir37[] +endif::sourcedir38[] diff --git a/docs/src/docs/asciidoc/user/config-derive.adoc b/docs/src/docs/asciidoc/user/config-derive.adoc index bf860630fa..9ad0a5d7ce 100644 --- a/docs/src/docs/asciidoc/user/config-derive.adoc +++ b/docs/src/docs/asciidoc/user/config-derive.adoc @@ -1,9 +1,9 @@ --- --- = Configuration Derivation -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -22,7 +22,7 @@ with the configurations values [source,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=deriveContract] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=deriveContract] ---- <1> Creates a builder seeded with the configuration's state. <2> Configurations built using the builder are then functionally identical to the original configuration. @@ -34,13 +34,13 @@ The configuration builder returned by the derive method provide direct methods f .setting a custom classloader: [source,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=customClassLoader] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=customClassLoader] ---- .adding a cache: [source,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withCache] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withCache] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -65,7 +65,7 @@ include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivati .removing a cache: [source,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withoutCache] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withoutCache] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -93,7 +93,7 @@ builder seeded using the existing cache configuration. .updating a cache, by adding a resource: [source,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=updateCache] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=updateCache] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -131,7 +131,7 @@ creation configurations and service configurations: .adding a service creation configuration (constraining the default thread pool) [source,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withServiceCreation] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withServiceCreation] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -155,7 +155,7 @@ include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivati .updating a service creation configuration (changing the persistence path) [source,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=updateServiceCreation] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=updateServiceCreation] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -177,7 +177,7 @@ include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivati .adding a service configuration (setting a resilience strategy) [source,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withService] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withService] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -210,7 +210,7 @@ include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivati .updating a service configuration (changing a clustered cache's consistency) [source,java,indent=0] ---- -include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java[tag=updateService] +include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java[tag=updateService] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -258,7 +258,7 @@ instance its configuration are usually strongly coupled: .removing a service (making a cache manager non-clustered) [source,java,indent=0] ---- -include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java[tag=removeService] +include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java[tag=removeService] ---- <1> From all cache configurations... <2> remove any existing `ClusteredStoreConfiguration` instances. diff --git a/docs/src/docs/asciidoc/user/eviction-advisor.adoc b/docs/src/docs/asciidoc/user/eviction-advisor.adoc index 56a33d88cc..35e152e0cc 100644 --- a/docs/src/docs/asciidoc/user/eviction-advisor.adoc +++ b/docs/src/docs/asciidoc/user/eviction-advisor.adoc @@ -1,9 +1,9 @@ --- --- = Eviction Advisor -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -29,7 +29,7 @@ If the eviction is advised against, Ehcache will try to honor the preference of [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEvictionAdvisor] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEvictionAdvisor] ---- <1> Configure a constrained heap, as the eviction advisor is only relevant when mappings get evicted from the cache. diff --git a/docs/src/docs/asciidoc/user/examples.adoc b/docs/src/docs/asciidoc/user/examples.adoc index c8260b4dcc..ac1ec06d7a 100644 --- a/docs/src/docs/asciidoc/user/examples.adoc +++ b/docs/src/docs/asciidoc/user/examples.adoc @@ -1,9 +1,9 @@ --- --- = Examples -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -102,5 +102,5 @@ Note the presence of the +Filling cache with peeps+, +Clearing peeps cache+, and [source,xml,indent=0] ---- -include::{sourcedir37}/107/src/test/resources/ehcache-example.xml[] +include::{sourcedir38}/107/src/test/resources/ehcache-example.xml[] ---- diff --git a/docs/src/docs/asciidoc/user/expiry.adoc b/docs/src/docs/asciidoc/user/expiry.adoc index d154e14d3c..74f19f907d 100644 --- a/docs/src/docs/asciidoc/user/expiry.adoc +++ b/docs/src/docs/asciidoc/user/expiry.adoc @@ -1,9 +1,9 @@ --- --- = Expiry -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -20,7 +20,7 @@ Expiry is configured at the cache level, in Java or in XML: [source,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] ---- <1> Expiry policy is configured at the cache level, so start by defining a cache configuration, @@ -28,7 +28,7 @@ include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[t [source,xml,indent=0] ---- -include::{sourcedir37}/xml/src/test/resources/configs/docs/expiry.xml[tags=expiry] +include::{sourcedir38}/xml/src/test/resources/configs/docs/expiry.xml[tags=expiry] ---- <1> At the cache level, using the predefined _time-to-live_ again. @@ -50,7 +50,7 @@ Supporting your own expiration scheme simply means implementing the `ExpiryPolic [source,java,indent=0] ---- -include::{sourcedir37}/api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java[lines=21..-1] +include::{sourcedir38}/api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java[lines=21..-1] ---- The main points to remember on the return value from these methods: @@ -71,7 +71,7 @@ In Java: [source,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=customExpiry] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=customExpiry] ---- <1> Simply pass your custom expiry instance into the cache builder. @@ -80,7 +80,7 @@ In XML: [source,xml,indent=0] ---- -include::{sourcedir37}/xml/src/test/resources/configs/docs/expiry.xml[tags=customExpiry] +include::{sourcedir38}/xml/src/test/resources/configs/docs/expiry.xml[tags=customExpiry] ---- <1> Simply pass the fully qualified class name of your custom expiry. diff --git a/docs/src/docs/asciidoc/user/getting-started.adoc b/docs/src/docs/asciidoc/user/getting-started.adoc index f52d06de15..2123645127 100644 --- a/docs/src/docs/asciidoc/user/getting-started.adoc +++ b/docs/src/docs/asciidoc/user/getting-started.adoc @@ -1,7 +1,7 @@ = Ehcache {version} Documentation -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] We feel that the Ehcache 3.x API is a great improvement over the Ehcache 2.x API that has been used by millions of developers. We hope you enjoy this new generation of Ehcache! ifdef::notBuildingForSite[] @@ -25,7 +25,7 @@ As with the previous versions of Ehcache, the canonical way of dealing with `Cac [source,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cachemanagerExample] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cachemanagerExample] ---- <1> The static method `org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder` returns a new `org.ehcache.config.builders.CacheManagerBuilder` instance. @@ -60,7 +60,7 @@ Here is a shorter version featuring 3 important things: [source,java,indent=0] ---- -include::{sourcedir37}/integration-test/src/test/java/org/ehcache/docs/GettingStartedWithStaticImports.java[tag=java7Example] +include::{sourcedir38}/integration-test/src/test/java/org/ehcache/docs/GettingStartedWithStaticImports.java[tag=java7Example] ---- <1> A `CacheManager` implements `Closeable` so can be closed automatically by a try-with-resources. A `CacheManager` must be closed cleanly. In a `finally` block, with a `try-with-resources` or (more frequent for normal applications) in some shutdown hook. @@ -74,7 +74,7 @@ You can create an XML file to configure a `CacheManager`. [source,xml,indent=0] ---- -include::{sourcedir37}/xml/src/test/resources/configs/docs/getting-started.xml[tags=gettingStarted] +include::{sourcedir38}/xml/src/test/resources/configs/docs/getting-started.xml[tags=gettingStarted] ---- <1> Declares a `Cache` aliased to `foo`. @@ -108,7 +108,7 @@ In addition, for creating the cache manager with clustering support, you will ne [source,java,indent=0] ---- -include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] +include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] ---- <1> Returns the `org.ehcache.config.builders.CacheManagerBuilder` instance; @@ -137,7 +137,7 @@ A classical example would be using 3 tiers with a persistent disk storage. [source,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=threeTiersCacheManager] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=threeTiersCacheManager] ---- <1> If you wish to use disk storage (like for persistent `Cache` instances), you'll have to provide a @@ -156,7 +156,7 @@ The following illustrates how to configure a _time-to-live_ expiry. [source,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] ---- <1> Expiry is configured at the cache level, so start by defining a cache configuration, diff --git a/docs/src/docs/asciidoc/user/index.adoc b/docs/src/docs/asciidoc/user/index.adoc index 46900240ce..752db09394 100644 --- a/docs/src/docs/asciidoc/user/index.adoc +++ b/docs/src/docs/asciidoc/user/index.adoc @@ -1,7 +1,7 @@ = Ehcache {version} Documentation Overview -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/management.adoc b/docs/src/docs/asciidoc/user/management.adoc index 7859e685f5..e2e5ef80ab 100644 --- a/docs/src/docs/asciidoc/user/management.adoc +++ b/docs/src/docs/asciidoc/user/management.adoc @@ -1,9 +1,9 @@ --- --- = Management and Monitoring -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -30,7 +30,7 @@ cache manager builder as a service: [source,java,indent=0] ---- -include::{sourcedir37}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=usingManagementRegistry] +include::{sourcedir38}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=usingManagementRegistry] ---- <1> Optional: give a name to your cache manager by using a custom configuration <2> Create an instance of `org.ehcache.management.registry.DefaultManagementRegistryService`. This is only required because the service is used below. @@ -50,7 +50,7 @@ and a cache name to uniquely identify the cache on which you want to query stats [source,java,indent=0] ---- -include::{sourcedir37}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=capabilitiesAndContexts] +include::{sourcedir38}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=capabilitiesAndContexts] ---- <1> Query the `ManagementRegistry` for the registered managed objects' capabilities. <2> Each capability has a unique name you will need to refer to it. @@ -74,7 +74,7 @@ a managed object. Examples of actions could be: clear caches, get their configur [source,java,indent=0] ---- -include::{sourcedir37}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=actionCall] +include::{sourcedir38}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=actionCall] ---- <1> Put something in a cache. <2> Call the 'clear' action on the managed cache. Refer to the descriptors of the provider to get the exact list of @@ -92,7 +92,7 @@ manager by default, but sometimes you may want one `ManagementRegistry` to manag [source,java,indent=0] ---- -include::{sourcedir37}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=managingMultipleCacheManagers] +include::{sourcedir38}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=managingMultipleCacheManagers] ---- <1> Create an instance of `org.ehcache.management.SharedManagementService` <2> Pass it as a service to the first cache manager diff --git a/docs/src/docs/asciidoc/user/migration-guide.adoc b/docs/src/docs/asciidoc/user/migration-guide.adoc index 6eb67107fd..7f732fd2d2 100644 --- a/docs/src/docs/asciidoc/user/migration-guide.adoc +++ b/docs/src/docs/asciidoc/user/migration-guide.adoc @@ -1,9 +1,9 @@ --- --- = Migration Guide -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -65,7 +65,7 @@ having dedicated logic in the methods called during the lifecycle of added and u [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Ehcache3.java[tag=CustomExpiryEhcache3] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Ehcache3.java[tag=CustomExpiryEhcache3] ---- <1> Defining custom expiry to be called during the lifecycle of added mappings. diff --git a/docs/src/docs/asciidoc/user/osgi.adoc b/docs/src/docs/asciidoc/user/osgi.adoc index 261bdeb0e9..9c73c089f3 100644 --- a/docs/src/docs/asciidoc/user/osgi.adoc +++ b/docs/src/docs/asciidoc/user/osgi.adoc @@ -1,9 +1,9 @@ --- --- = OSGi Deployment -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/performance.adoc b/docs/src/docs/asciidoc/user/performance.adoc index 14c784055c..278475aa1c 100644 --- a/docs/src/docs/asciidoc/user/performance.adoc +++ b/docs/src/docs/asciidoc/user/performance.adoc @@ -1,9 +1,9 @@ --- --- = Performance Tuning -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -115,7 +115,7 @@ For instance, let's say you define an expiry policy like this. [source,java,indent=0] ---- -include::{sourcedir37}/integration-test/src/test/java/org/ehcache/docs/Performance.java[tag=expiryAllocation] +include::{sourcedir38}/integration-test/src/test/java/org/ehcache/docs/Performance.java[tag=expiryAllocation] ---- <1> Will instantiate a `Duration` every time an entry is accessed diff --git a/docs/src/docs/asciidoc/user/resilience.adoc b/docs/src/docs/asciidoc/user/resilience.adoc index cd141f8568..2a93cbebc2 100644 --- a/docs/src/docs/asciidoc/user/resilience.adoc +++ b/docs/src/docs/asciidoc/user/resilience.adoc @@ -1,9 +1,9 @@ --- --- = Resilience -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -64,7 +64,7 @@ Timeouts can be configured using a dedicated builder or in XML. [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java[tag=timeoutsExample] +include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java[tag=timeoutsExample] ---- <1> Start setting timeouts using the build diff --git a/docs/src/docs/asciidoc/user/serializers-copiers.adoc b/docs/src/docs/asciidoc/user/serializers-copiers.adoc index f96d1b087c..9148096cb3 100644 --- a/docs/src/docs/asciidoc/user/serializers-copiers.adoc +++ b/docs/src/docs/asciidoc/user/serializers-copiers.adoc @@ -1,9 +1,9 @@ --- --- = Serializers and Copiers -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -119,7 +119,7 @@ Implement the following interface, from package `org.ehcache.spi.serialization`: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/api/src/main/java/org/ehcache/spi/serialization/Serializer.java[lines=20..-1] +include::{sourcedir38}/api/src/main/java/org/ehcache/spi/serialization/Serializer.java[lines=20..-1] ---- As the Javadoc states, there are some constructor rules, see the section <> for that. @@ -256,7 +256,7 @@ Implement the following interface: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/api/src/main/java/org/ehcache/spi/copy/Copier.java[lines=19..-1] +include::{sourcedir38}/api/src/main/java/org/ehcache/spi/copy/Copier.java[lines=19..-1] ---- * `T copyForRead(T obj)` is invoked when a copy must be made upon a read operation (like a cache `get()`), diff --git a/docs/src/docs/asciidoc/user/thread-pools.adoc b/docs/src/docs/asciidoc/user/thread-pools.adoc index ed9bcfd48e..44991cbb4e 100644 --- a/docs/src/docs/asciidoc/user/thread-pools.adoc +++ b/docs/src/docs/asciidoc/user/thread-pools.adoc @@ -1,9 +1,9 @@ --- --- = Thread Pools -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -88,7 +88,7 @@ Following are examples of describing how to configure the thread pools the diffe [source%nowrap,java] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=diskStore] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=diskStore] ---- <1> Configure the thread pools. Note that the default one (`dflt`) is required for the events even when no event listener is configured. @@ -99,7 +99,7 @@ include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag= [source%nowrap,java] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=writeBehind] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=writeBehind] ---- <1> Configure the thread pools. Note that the default one (`dflt`) is required for the events even when no event listener is configured. @@ -110,7 +110,7 @@ include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag= [source%nowrap,java] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=events] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=events] ---- <1> Configure the thread pools. Note that there is no default one so all thread-using services must be configured with explicit defaults. @@ -124,7 +124,7 @@ Following is an example describing how to configure the thread pools the differe [source%nowrap,xml] ---- -include::{sourcedir37}/xml/src/test/resources/configs/docs/thread-pools.xml[tags=threadPools] +include::{sourcedir38}/xml/src/test/resources/configs/docs/thread-pools.xml[tags=threadPools] ---- <1> Configure the thread pools. Note that there is no default one. diff --git a/docs/src/docs/asciidoc/user/tiering.adoc b/docs/src/docs/asciidoc/user/tiering.adoc index 9decf0c2d9..2eb26c5453 100644 --- a/docs/src/docs/asciidoc/user/tiering.adoc +++ b/docs/src/docs/asciidoc/user/tiering.adoc @@ -1,9 +1,9 @@ --- --- = Ehcache Tiering Options -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -48,7 +48,7 @@ For this, simply define the single resource in the cache configuration: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheapOnly] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheapOnly] ---- <1> Start with defining the key and value type in the configuration builder. @@ -65,7 +65,7 @@ A heap tier can be sized by entries or by size. [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=heap] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=heap] ---- <1> Only 10 entries allowed on heap. Eviction will occur when full. @@ -83,7 +83,7 @@ NOTE: Byte sizing has a runtime performance impact that depends on the size and [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=byteSizedTieredCache] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=byteSizedTieredCache] ---- <1> This will limit the amount of memory used by the heap tier for storing key-value pairs. @@ -103,7 +103,7 @@ If you wish to use off-heap, you'll have to define a resource pool, giving the m [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheap] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheap] ---- <1> Only 10 MB allowed off-heap. @@ -126,7 +126,7 @@ The faster and more dedicated the disk is, the faster accessing the data will be [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=persistentCacheManager] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=persistentCacheManager] ---- <1> To obtain a `PersistentCacheManager` which is a normal `CacheManager` but with the ability to @@ -166,7 +166,7 @@ In some cases, you might want to reduce the concurrency and save resources by re [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=diskSegments] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=diskSegments] ---- <1> Define an `OffHeapDiskStoreConfiguration` instance specifying the required number of segments. @@ -234,7 +234,7 @@ Here is an example using heap, offheap and clustered. [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java[tag=threeTiersCacheManager] +include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java[tag=threeTiersCacheManager] ---- <1> Clustered specific information telling how to connect to the Terracotta cluster @@ -253,7 +253,7 @@ Let's revisit an example used earlier: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=threeTiersCacheManager] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=threeTiersCacheManager] ---- This is a cache using 3 tiers (heap, offheap, disk). @@ -267,7 +267,7 @@ Consider for instance this code: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=notShared] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=notShared] ---- You will end up with two caches that can contain 10 entries each. @@ -284,7 +284,7 @@ Thus you can't change the sizing of off-heap or disk tiers. [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=updateResourcesAtRuntime] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=updateResourcesAtRuntime] ---- <1> You will need to create a new `ResourcePools` object with resources of the required size, using `ResourcePoolsBuilder`. @@ -316,12 +316,12 @@ This method destroys a given cache. The cache shouldn't be in use by another cac .Multiple tiers using Put [plantuml] .... -include::{sourcedir37}/docs/src/docs/uml/put.puml[] +include::{sourcedir38}/docs/src/docs/uml/put.puml[] .... .Multiple tiers using Get [plantuml] .... -include::{sourcedir37}/docs/src/docs/uml/get.puml[] +include::{sourcedir38}/docs/src/docs/uml/get.puml[] .... -- In order to understand what happens for different cache operations when using multiple tiers, here are examples of _Put_ and _Get_ operations. diff --git a/docs/src/docs/asciidoc/user/usermanaged.adoc b/docs/src/docs/asciidoc/user/usermanaged.adoc index 0bbd39a845..10a83dd101 100644 --- a/docs/src/docs/asciidoc/user/usermanaged.adoc +++ b/docs/src/docs/asciidoc/user/usermanaged.adoc @@ -1,9 +1,9 @@ --- --- = User managed caches -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -44,7 +44,7 @@ The interface definition is shown in this code: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/api/src/main/java/org/ehcache/UserManagedCache.java[lines=17..-1] +include::{sourcedir38}/api/src/main/java/org/ehcache/UserManagedCache.java[lines=17..-1] ---- === User Managed Persistent Cache @@ -63,7 +63,7 @@ The interface definition is shown in this code: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/api/src/main/java/org/ehcache/PersistentUserManagedCache.java[lines=17..-1] +include::{sourcedir38}/api/src/main/java/org/ehcache/PersistentUserManagedCache.java[lines=17..-1] ---- [[code-examples]] @@ -75,7 +75,7 @@ Here is a simple example showing a basic lifecycle of a user managed cache: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=userManagedCacheExample] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=userManagedCacheExample] ---- <1> Create a `UserManagedCache` instance. You can either pass `true` to have the builder `init()` it for you, @@ -102,7 +102,7 @@ If you want to use disk persistent cache, you will need to create and lifecycle [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=persistentUserManagedCache] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=persistentUserManagedCache] ---- <1> Create the persistence service to be used by the cache for storing data on disk. @@ -125,7 +125,7 @@ For more information on cache event listeners, see the section < Provide the `ExecutorService` for ordered and unordered event delivery. diff --git a/docs/src/docs/asciidoc/user/writers.adoc b/docs/src/docs/asciidoc/user/writers.adoc index bbb04bcb59..0ef9d80de5 100644 --- a/docs/src/docs/asciidoc/user/writers.adoc +++ b/docs/src/docs/asciidoc/user/writers.adoc @@ -1,9 +1,9 @@ --- --- = Cache Loaders and Writers -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -74,7 +74,7 @@ After this time has elapsed, the batch is processed even if incomplete. [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeThroughCache] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeThroughCache] ---- <1> We register a sample `CacheLoaderWriter` that knows about the mapping ("41L" maps to "zero"). @@ -86,7 +86,7 @@ The returned mapping will populate the cache and be returned to the caller. [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeBehindCache] +include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeBehindCache] ---- <1> For write-behind you need a configured `CacheLoaderWriter`. diff --git a/docs/src/docs/asciidoc/user/xa.adoc b/docs/src/docs/asciidoc/user/xa.adoc index a3325b9935..e7c7f02432 100644 --- a/docs/src/docs/asciidoc/user/xa.adoc +++ b/docs/src/docs/asciidoc/user/xa.adoc @@ -1,9 +1,9 @@ --- --- = XA transactional caches -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -65,7 +65,7 @@ Here is an example: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testSimpleXACache] +include::{sourcedir38}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testSimpleXACache] ---- <1> First start the Bitronix transaction manager. By default, Ehcache will auto-detect it but will throw an exception during the cache manager initialization if BTM isn't started. @@ -96,7 +96,7 @@ Nothing special needs to be configured for this to happen, just ensure that the [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithWriteThrough] +include::{sourcedir38}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithWriteThrough] ---- <1> First start the Bitronix transaction manager. @@ -122,7 +122,7 @@ Any attempt to access one outside of such context will result in `XACacheExcepti [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testNonTransactionalAccess] +include::{sourcedir38}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testNonTransactionalAccess] ---- <1> First start the Bitronix transaction manager. @@ -151,7 +151,7 @@ Here is an example: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithThreeTiers] +include::{sourcedir38}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithThreeTiers] ---- <1> First start the Bitronix transaction manager. @@ -174,7 +174,7 @@ You can create a XML file to configure a `CacheManager`, lookup a specific trans [source%nowrap,xml,indent=0] ---- -include::{sourcedir37}/transactions/src/test/resources/docs/configs/xa-getting-started.xml[tags=gettingStarted] +include::{sourcedir38}/transactions/src/test/resources/docs/configs/xa-getting-started.xml[tags=gettingStarted] ---- <1> Declare a `TransactionManagerLookup` that will lookup your transaction manager. @@ -185,7 +185,7 @@ In order to parse an XML configuration, you can use the XmlConfiguration type: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithXMLConfig] +include::{sourcedir38}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithXMLConfig] ---- <1> The Bitronix transaction manager must be started before the cache manager is initialized. @@ -198,7 +198,7 @@ And here is what the BitronixTransactionManagerLookup implementation looks like: [source%nowrap,java,indent=0] ---- -include::{sourcedir37}/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixTransactionManagerLookup.java[tag=BitronixLookup] +include::{sourcedir38}/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixTransactionManagerLookup.java[tag=BitronixLookup] ---- <1> The `TransactionManagerLookup` interface must be implemented and the offer a `no-arg` constructor. diff --git a/docs/src/docs/asciidoc/user/xml.adoc b/docs/src/docs/asciidoc/user/xml.adoc index 3bf794c2bd..7e2dbcea46 100644 --- a/docs/src/docs/asciidoc/user/xml.adoc +++ b/docs/src/docs/asciidoc/user/xml.adoc @@ -1,9 +1,9 @@ --- --- = XML Configuration -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -108,7 +108,7 @@ NOTE: If you are obtaining your `CacheManager` through the JSR-107 API, what fol [source,java,indent=0] ---- -include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlConfig] +include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlConfig] ---- <1> Obtain a `URL` to your XML file's location <2> Instantiate an `XmlConfiguration` passing the XML file's URL to it @@ -121,14 +121,14 @@ to use a `` element from an XML file, e.g. the `/my-config.xml` [source,xml,indent=0] ---- -include::{sourcedir37}/xml/src/test/resources/configs/docs/template-sample.xml[tag=templateSample] +include::{sourcedir38}/xml/src/test/resources/configs/docs/template-sample.xml[tag=templateSample] ---- Creating a `CacheConfigurationBuilder` of that `example` `` element, would be done as follows: [source,java,indent=0] ---- -include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] +include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] ---- <1> Creates a builder, inheriting the capacity constraint of 200 entries <2> The inherent properties can be overridden by simply providing a different value prior to building the `CacheConfiguration` @@ -141,14 +141,14 @@ and the string representation of that object will give you the XML equivalent of [source,java,indent=0] ---- -include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] +include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] ---- <1> Creates a builder, inheriting the capacity constraint of 200 entries <2> The inherent properties can be overridden by simply providing a different value prior to building the `CacheConfiguration` [source,java,indent=0] ---- -include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTranslation] +include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTranslation] ---- <1> Instantiate an `XmlConfiguration` passing the cache manager `Configuration` <2> Retrieve the XML representation using the `toString` method. @@ -176,7 +176,7 @@ The simplest use of the multi-configuration features is to embed multiple cache file: [source,xml,indent=0] ---- -include::{sourcedir37}/xml/src/test/resources/configs/docs/multi/multiple-managers.xml[] +include::{sourcedir38}/xml/src/test/resources/configs/docs/multi/multiple-managers.xml[] ---- <1> A top-level `` container with namespace declarations for the `multi` and core schemas <2> Each Ehcache configuration is embedded inside a `configuration` tag with a required (unique) `identity` attribute @@ -184,7 +184,7 @@ include::{sourcedir37}/xml/src/test/resources/configs/docs/multi/multiple-manage These embedded configurations can then be retrieved via an `XmlMultiConfiguration` instance built from the XML document. [source,java,indent=0] ---- -include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleManagers] +include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleManagers] ---- <1> The `XmlMultiConfiguration` is assembled from the XML resource. <2> Once assembled the configuration is built. @@ -196,13 +196,13 @@ Multiple variant configurations for a given manager can be provided by including with a required `type` attribute: [source,xml,indent=0] ---- -include::{sourcedir37}/xml/src/test/resources/configs/docs/multi/multiple-variants.xml[tag=variants] +include::{sourcedir38}/xml/src/test/resources/configs/docs/multi/multiple-variants.xml[tag=variants] ---- A specific cache configuration can then be retrieved by choosing both a variant and an identity explicitly on retrieval. [source,java,indent=0] ---- -include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleVariants] +include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleVariants] ---- The samples above are just samples, variant types can be used to represent any kind of variation: development vs production, clustered vs unclustered, red vs blue, etc. @@ -218,7 +218,7 @@ Multiple cache managers can be retrieved from an `XmlMultiConfiguration` by iter `identities()`: [source,java,indent=0] ---- -include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleRetrieval] +include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleRetrieval] ---- <1> From a stream over the set of identities in a mult-configuration. <2> Map each identity to it's unique (non-varianted) configuration. @@ -232,7 +232,7 @@ of parsing XML multi-configuration documents are all just simple invocations of Configurations can be built from scratch as show below: [source,java,indent=0] ---- -include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=building] +include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=building] ---- <1> Starting with an initially empty set of configurations. <2> Add a configuration without variants. @@ -242,7 +242,7 @@ include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.ja They can also be built from existing configurations: [source,java,indent=0] ---- -include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=modifying] +include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=modifying] ---- <1> Starting with an existing `XmlMultiConfiguration`. <2> Remove the configuration with identity `"foo"`. @@ -250,7 +250,7 @@ include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.ja Once built a multi-configuration can be retrieved in XML form: [source,java,indent=0] ---- -include::{sourcedir37}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=rendering] +include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=rendering] ---- <1> Retrieving the XML as a rendered string. <2> Retrieving the XML as a DOM (`org.w3c.Document`). diff --git a/docs/src/docs/asciidoc/user/xsds.adoc b/docs/src/docs/asciidoc/user/xsds.adoc index 76ff465751..18f8482429 100644 --- a/docs/src/docs/asciidoc/user/xsds.adoc +++ b/docs/src/docs/asciidoc/user/xsds.adoc @@ -1,9 +1,9 @@ --- --- = Ehcache XSDs -ifndef::sourcedir37[] +ifndef::sourcedir38[] include::common.adoc[] -endif::sourcedir37[] +endif::sourcedir38[] ifdef::notBuildingForSite[] include::menu.adoc[] @@ -51,7 +51,7 @@ endif::notBuildingForSite[] [source,xml,indent=0] ---- -include::{sourcedir37}/107/src/test/resources/org/ehcache/docs/public-xsds-location.xml[tag=xsdLocations] +include::{sourcedir38}/107/src/test/resources/org/ehcache/docs/public-xsds-location.xml[tag=xsdLocations] ---- [[core]] @@ -59,7 +59,7 @@ include::{sourcedir37}/107/src/test/resources/org/ehcache/docs/public-xsds-locat [source,xsd,indent=0] ---- -include::{sourcedir37}/xml/src/main/resources/ehcache-core.xsd[lines=18..-1] +include::{sourcedir38}/xml/src/main/resources/ehcache-core.xsd[lines=18..-1] ---- [[jsr-107-extension]] @@ -67,12 +67,12 @@ include::{sourcedir37}/xml/src/main/resources/ehcache-core.xsd[lines=18..-1] [source,xsd,indent=0] ---- -include::{sourcedir37}/107/src/main/resources/ehcache-107-ext.xsd[lines=18..-1] +include::{sourcedir38}/107/src/main/resources/ehcache-107-ext.xsd[lines=18..-1] ---- == XA transactions extension [source,xsd,indent=0] ---- -include::{sourcedir37}/transactions/src/main/resources/ehcache-tx-ext.xsd[lines=18..-1] +include::{sourcedir38}/transactions/src/main/resources/ehcache-tx-ext.xsd[lines=18..-1] ---- From a2dfdb9f077bee486877431aeb2362385eed1896 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 19 Jul 2019 16:17:26 -0400 Subject: [PATCH 154/372] Update README.adoc for 3.8.0 release --- README.adoc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.adoc b/README.adoc index 14bf9f4f29..db1cd2aea4 100644 --- a/README.adoc +++ b/README.adoc @@ -12,12 +12,11 @@ For samples, documentation, and usage information, please see http://ehcache.org == Current release -We released 3.7.0 on February 25th 2019. +We released 3.8.0 on July 19th 2019. -The https://github.com/ehcache/ehcache3/releases/tag/v3.7.0[release notes] contain the links to the artifacts and the documentation to help you get started. +The https://github.com/ehcache/ehcache3/releases/tag/v3.8.0[release notes] contain the links to the artifacts and the documentation to help you get started. -You should consider upgrading to 3.7.x as it does all previous 3.x do and more with a fully compatible API. -The only thing to note compared to 3.0.x is that transactional support has been moved to a separate jar. +You should consider upgrading to 3.8.x as it does all previous 3.x do and more with a fully compatible API. == Current development & next release From ef9c1e06b9e8a40332b4ce76e2e272268cd1bb64 Mon Sep 17 00:00:00 2001 From: mobasherul Date: Mon, 15 Jul 2019 21:43:01 +0530 Subject: [PATCH 155/372] Running tests with java11 --- clustered/integration-test/build.gradle | 5 ---- clustered/osgi-test/build.gradle | 16 ++++------- .../org/ehcache/osgi/ClusteredOsgiTest.java | 5 ++-- .../java/org/ehcache/osgi/OsgiTestUtils.java | 27 ++++++++++++++----- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index e1e224a8e8..8bfc680750 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -64,14 +64,9 @@ task copyServerLibs(type: Copy) { test { dependsOn copyServerLibs environment 'JAVA_HOME', testJava.javaHome - if (testJava.javaVersion.isJava9Compatible()) { - environment 'JAVA_OPTS', '--add-modules java.xml.bind' - } //If this directory does not exist, tests will fail with a cryptic assert failure systemProperty 'kitInstallationPath', "$unzipKit.destinationDir/${project(':clustered:clustered-dist').archivesBaseName}-$project.version-kit" // Uncomment to include client logging in console output // testLogging.showStandardStreams = true -}.doFirst { - if (testJava.javaVersion.isJava11Compatible()) throw new StopExecutionException("Clustered Tests Not Working in Java 11") } diff --git a/clustered/osgi-test/build.gradle b/clustered/osgi-test/build.gradle index d05ea6ff6f..b41a2cf5ad 100644 --- a/clustered/osgi-test/build.gradle +++ b/clustered/osgi-test/build.gradle @@ -30,12 +30,14 @@ dependencies { osgiModule "javax.cache:cache-api:$parent.jcacheVersion" osgiModule "org.slf4j:slf4j-simple:$parent.slf4jVersion" osgiModule 'org.apache.felix:org.apache.felix.scr:2.1.6' + osgiModule 'com.sun.activation:javax.activation:1.2.0' + osgiModule 'org.glassfish.hk2:osgi-resource-locator:1.0.2' //IDEs cannot handle the :dist or :clustered:clustered-dist dependencies testCompileOnly project(':clustered:client') testCompileOnly project(':clustered:common') - testImplementation 'org.apache.felix:org.apache.felix.framework:6.0.1' + testImplementation 'org.apache.felix:org.apache.felix.framework:6.0.3' testImplementation ('org.ops4j.pax.exam:pax-exam-junit4:4.12.0') { exclude group:'org.slf4j', module:'slf4j-api' } @@ -46,7 +48,7 @@ dependencies { testRuntimeOnly ('org.ops4j.pax.exam:pax-exam-link-mvn:4.12.0') { exclude group:'org.slf4j', module:'slf4j-api' } - testRuntimeOnly ("org.ops4j.pax.url:pax-url-wrap:2.4.5") { + testRuntimeOnly ("org.ops4j.pax.url:pax-url-wrap:2.6.1") { exclude group:'org.slf4j', module:'slf4j-api' } @@ -57,6 +59,7 @@ configurations.all { force 'org.ops4j.base:ops4j-base-lang:1.5.0' force 'org.ops4j.base:ops4j-base-net:1.5.0' force 'org.ops4j.base:ops4j-base-util-property:1.5.0' + force 'org.ops4j.pax.url:pax-url-commons:2.6.1' } } @@ -80,17 +83,8 @@ task unzipKit(type: Copy) { test { dependsOn unzipKit - - if (testJava.javaVersion.isJava9Compatible()) { - //Deploying the jaxb-runtime as an OSGi module is currently impossible - don't ask... sigh. - jvmArgs += ['--add-modules', 'java.xml.bind'] - //Servers need JAXB too. - jvmArgs += ['-Dtc-server-opts=--add-modules java.xml.bind'] - } systemProperty 'kitInstallationPath', "$unzipKit.destinationDir/${project(':clustered:clustered-dist').archivesBaseName}-$project.version-kit" }.doFirst { - if (testJava.javaVersion.isJava11Compatible()) throw new StopExecutionException("OSGi Tests Not Working in Java 11") - configurations.osgiModule.resolvedConfiguration.resolvedArtifacts.forEach({ systemProperty "$it.moduleVersion.id.module:osgi-path", it.file }) diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java index 177015e2dd..b4b46aedcb 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java @@ -61,6 +61,7 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; +import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; import static org.ehcache.osgi.OsgiTestUtils.startServer; import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.hamcrest.core.Is.is; @@ -81,7 +82,7 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:api"), gradleBundle("org.ehcache.modules:core"), gradleBundle("org.ehcache.modules:impl"), - gradleBundle("org.ehcache.modules:xml"), + gradleBundle("org.ehcache.modules:xml"), jaxbConfiguration(), gradleBundle("org.ehcache:clustered-dist"), gradleBundle("org.terracotta.management:management-model"), @@ -98,7 +99,7 @@ public Option[] individualModules() { @Configuration public Option[] uberJar() { return options( - gradleBundle("org.ehcache:dist"), + gradleBundle("org.ehcache:dist"), jaxbConfiguration(), gradleBundle("org.ehcache:clustered-dist"), baseConfiguration("ClusteredOsgiTest", "uberJar") diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java index bb347f3af1..fc9b3bb4d5 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -33,7 +33,9 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Stream; +import static java.lang.Integer.parseInt; import static java.lang.String.join; +import static java.lang.System.getProperty; import static java.nio.file.Files.find; import static java.nio.file.Files.isRegularFile; import static java.util.Arrays.asList; @@ -56,17 +58,30 @@ public static Option baseConfiguration(String ... path) { gradleBundle("org.slf4j:slf4j-simple").noStart(), gradleBundle("org.apache.felix:org.apache.felix.scr"), systemProperty("pax.exam.osgi.unresolved.fail").value("true"), - systemPackages( - "javax.xml.bind;version=2.3.0", - "javax.xml.bind.annotation;version=2.3.0", - "javax.xml.bind.annotation.adapters;version=2.3.0" - ), cleanCaches(true), workingDirectory(join(File.separator, "build", "osgi-container", join(File.separator, path))), junitBundles() ); } + public static Option jaxbConfiguration() { + if (parseInt(getProperty("java.version").split("[^\\d]+")[0]) >= 9) { + return composite( + gradleBundle("org.glassfish.hk2:osgi-resource-locator"), + gradleBundle("javax.xml.bind:jaxb-api"), + gradleBundle("com.sun.activation:javax.activation"), + wrappedGradleBundle("org.glassfish.jaxb:jaxb-runtime"), + gradleBundle("com.sun.istack:istack-commons-runtime") + ); + } else { + return systemPackages( + "javax.xml.bind;version=2.3.0", + "javax.xml.bind.annotation;version=2.3.0", + "javax.xml.bind.annotation.adapters;version=2.3.0" + ); + } + } + public static UrlProvisionOption gradleBundle(String module) { return bundle(artifact(module).toUri().toString()); } @@ -76,7 +91,7 @@ public static WrappedUrlProvisionOption wrappedGradleBundle(String module) { } private static Path artifact(String module) { - Path path = Paths.get(requireNonNull(System.getProperty(module + ":osgi-path"), module + " not available")); + Path path = Paths.get(requireNonNull(getProperty(module + ":osgi-path"), module + " not available")); if (isRegularFile(path)) { return path; } else { From a90f24ae2f5b11825014965fd66cee72731a4570 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 23 Jul 2019 09:24:14 -0400 Subject: [PATCH 156/372] Fixes #2679 : Delegate the iterator() call to the underlying clustered store --- .../internal/loaderwriter/DelegatingLoaderWriterStore.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java index acd556f8eb..a5d9ee64ac 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java @@ -91,7 +91,7 @@ public StoreEventSource getStoreEventSource() { @Override public Iterator>> iterator() { - throw new UnsupportedOperationException("Implement me"); + return delegate.iterator(); } @Override From 1e2431ae1eec1ca6aa1e85941cf57cda195995c1 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 22 Jul 2019 11:04:17 -0400 Subject: [PATCH 157/372] Upgrade to Gradle 5.5.1 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1b2b07cfb0..430dfabc5c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From e436457f61fa73d3e24e17702f3680c42382e2e1 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 22 Jul 2019 09:23:34 -0400 Subject: [PATCH 158/372] Upgrade to dependency-check 5.2.0 --- build.gradle | 5 +++-- config/owasp-supressions.xml | 12 ++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 config/owasp-supressions.xml diff --git a/build.gradle b/build.gradle index 438a5a32da..ee7433f77e 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ plugins { // Declare osgi-ds at the top id 'org.jayware.osgi-ds' version '0.5.6' apply false //OWASP Security Vulnerability Detection - id 'org.owasp.dependencycheck' version '4.0.2' apply false + id 'org.owasp.dependencycheck' version '5.2.0' apply false // Declare bnd at the top id 'biz.aQute.bnd.builder' version '4.1.0' apply false } @@ -206,7 +206,8 @@ subprojects { dependencyCheck { failBuildOnCVSS = 0 - skipConfigurations += ['checkstyle'] + skipConfigurations += ['checkstyle', 'spotbugs'] + suppressionFile = 'config/owasp-supressions.xml' } check.dependsOn(dependencyCheckAnalyze) diff --git a/config/owasp-supressions.xml b/config/owasp-supressions.xml new file mode 100644 index 0000000000..5764563b32 --- /dev/null +++ b/config/owasp-supressions.xml @@ -0,0 +1,12 @@ + + + + + + ^pkg:maven/org\.ehcache.*@.*$ + CVE-2019-11065 + + From 7e28e057b1d42b5aa9dd16087e745c364b87f113 Mon Sep 17 00:00:00 2001 From: Ludovic Orban Date: Thu, 25 Jul 2019 11:54:09 +0200 Subject: [PATCH 159/372] add missing 3.7 and 3.8 xsd links --- docs/src/docs/asciidoc/user/xsds.adoc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/src/docs/asciidoc/user/xsds.adoc b/docs/src/docs/asciidoc/user/xsds.adoc index 18f8482429..3f15432bf8 100644 --- a/docs/src/docs/asciidoc/user/xsds.adoc +++ b/docs/src/docs/asciidoc/user/xsds.adoc @@ -19,6 +19,8 @@ endif::notBuildingForSite[] ** Location for 3.4: `http://www.ehcache.org/schema/ehcache-core-3.4.xsd` ** Location for 3.5: `http://www.ehcache.org/schema/ehcache-core-3.5.xsd` ** Location for 3.6: `http://www.ehcache.org/schema/ehcache-core-3.6.xsd` +** Location for 3.7: `http://www.ehcache.org/schema/ehcache-core-3.7.xsd` +** Location for 3.8: `http://www.ehcache.org/schema/ehcache-core-3.8.xsd` // needle_for_core_xsd * JSR-107 namespace: `http://www.ehcache.org/v3/jsr107` ** Location for 3.0: `http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd` @@ -28,6 +30,8 @@ endif::notBuildingForSite[] ** Location for 3.4: `http://www.ehcache.org/schema/ehcache-107-ext-3.4.xsd` ** Location for 3.5: `http://www.ehcache.org/schema/ehcache-107-ext-3.5.xsd` ** Location for 3.6: `http://www.ehcache.org/schema/ehcache-107-ext-3.6.xsd` +** Location for 3.7: `http://www.ehcache.org/schema/ehcache-107-ext-3.7.xsd` +** Location for 3.8: `http://www.ehcache.org/schema/ehcache-107-ext-3.8.xsd` // needle_for_107_xsd * Transactions namespace: `http://www.ehcache.org/v3/tx` ** Location for 3.0: `http://www.ehcache.org/schema/ehcache-tx-ext-3.0.xsd` @@ -37,6 +41,8 @@ endif::notBuildingForSite[] ** Location for 3.4: `http://www.ehcache.org/schema/ehcache-tx-ext-3.4.xsd` ** Location for 3.5: `http://www.ehcache.org/schema/ehcache-tx-ext-3.5.xsd` ** Location for 3.6: `http://www.ehcache.org/schema/ehcache-tx-ext-3.6.xsd` +** Location for 3.7: `http://www.ehcache.org/schema/ehcache-tx-ext-3.7.xsd` +** Location for 3.8: `http://www.ehcache.org/schema/ehcache-tx-ext-3.8.xsd` // needle_for_transactions_xsd * Clustering namespace: `http://www.ehcache.org/v3/clustered` ** Location for 3.1: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.1.xsd` @@ -45,6 +51,8 @@ endif::notBuildingForSite[] ** Location for 3.4: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.4.xsd` ** Location for 3.5: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.5.xsd` ** Location for 3.6: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.6.xsd` +** Location for 3.7: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.7.xsd` +** Location for 3.8: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.8.xsd` // needle_for_clustered_xsd === Usage example From b33bb77d00646e73883c528e968f88bb8498d7bc Mon Sep 17 00:00:00 2001 From: Ludovic Orban Date: Thu, 25 Jul 2019 12:11:54 +0200 Subject: [PATCH 160/372] clarifications and typo fixes --- docs/src/docs/asciidoc/user/performance.adoc | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/docs/src/docs/asciidoc/user/performance.adoc b/docs/src/docs/asciidoc/user/performance.adoc index 278475aa1c..54dc58f1f3 100644 --- a/docs/src/docs/asciidoc/user/performance.adoc +++ b/docs/src/docs/asciidoc/user/performance.adoc @@ -30,7 +30,7 @@ However, always do your own benchmark. == Stores -We probably know that the faster store is on-heap. +We probably know that the fastest store is on-heap. Until you overwhelm the garbage collector. Your next best bet is off-heap. @@ -44,11 +44,12 @@ The next question would be: "Should I use a single tier?" Is using a single-tier The answer depends on what you do with it. Having two tiers is a bit slower on writing. It is also a bit slower on reading when the data is not found in the caching tier (on-heap). -However, it will be faster for an entry that is indeed found there. +However, it will be faster for an entry that is indeed found in a higher tier. So again, it depends. The more you follow the caching hypothesis that the same data is always reused (and so in the caching -tier), the more interesting having two tiers will be. +tier), the more interesting having two or more tiers will be. As a general rule of thumb, a tier that has a +hit ratio of 50% or less is going to slow down the cache. Either enlarge such tier or completely get rid of it. == Byte Sizing @@ -63,15 +64,19 @@ Make sure of what is used to confirm you can't use a faster way on your platform == Serialization Off-heap, disk and clustering need to serialize keys and values before storing them. -By default, the Java serialization is used. +By default, custom super-fast serializers are used for `Long`, `Integer`, `Character`, `Double`, `Float`, `byte[]` and +`String` objects. +A slightly faster, customized Java serialization is used for other object types. It is well-known for not being the fastest thing around. Ehcache uses it because it is supported out of the box. -However, you can increase performances by provoding your own serializers. +However, you can increase performance by providing your own serializers. == Copier By default, on-heap storage stores the entries by reference. You might want to use a copier to store entries by value for whatever reason. +Out of the box, Ehcache bundles a copier that makes use of its serialization mechanism: +`org.ehcache.impl.copy.SerializingCopier`. This can be much slower so watch out. == Loader-Writer @@ -93,7 +98,7 @@ If you need to set an expiration time, TTL will be the faster one. This is because the expiration time of an entry is calculated and updated ony when the entry is inserted or updated in the cache. But it still requires an expiration check at access time. -So you can expect a 2% drop in performance when using TTL. Not bad. +So you can expect a 2% drop in performance when using TTL. === Time to Idle @@ -108,7 +113,7 @@ When using a custom policy, you are on your own. == Allocation rate -Ehcache won't allocate any object during a simple `get()`. +Ehcache won't allocate any object during a simple on-heap `get()`. However, keep in mind that your configuration might do so. For instance, let's say you define an expiry policy like this. From 9e80b4dbddbea58f0bedb4a11329987ac970696b Mon Sep 17 00:00:00 2001 From: Ludovic Orban Date: Thu, 25 Jul 2019 12:23:39 +0200 Subject: [PATCH 161/372] add missing but common caching terms --- .../src/docs/asciidoc/user/caching-terms.adoc | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/docs/src/docs/asciidoc/user/caching-terms.adoc b/docs/src/docs/asciidoc/user/caching-terms.adoc index e61a9f250c..17ee9b0ae8 100644 --- a/docs/src/docs/asciidoc/user/caching-terms.adoc +++ b/docs/src/docs/asciidoc/user/caching-terms.adoc @@ -18,7 +18,8 @@ computation. Data that is already in the cache can be repeatedly accessed with m resources. === Cache Entry -A cache entry consists of a key and its mapped data value within the cache. +A cache entry consists of a key and its mapped data value within the cache. This is also sometimes referred to as a +_cache mapping_. === Cache Hit When a data entry is requested from cache and the entry exists for the given key, it is referred to as a cache hit @@ -28,6 +29,18 @@ When a data entry is requested from cache and the entry exists for the given key When a data entry is requested from cache and the entry does not exist for the given key, it is referred to as a cache miss (or simply, a _miss_). +=== Cache Access +Any time a data entry is requested from cache, the cache is _accessed_ no matter if the outcome was a _hit_ or a _miss_. + +=== Hit Ratio +It is the ratio of cache hits over cache accesses, or _hits_ / _accesses_. For instance, a cache accessed 100 times +that hit 90 times has a hit ratio of: _90_ / _100_ or _0.9_ or _90%_. + +=== Miss Ratio +It is the ratio of cache misses over cache accesses, or _misses_ / _accesses_. For instance, a cache accessed 100 times +that missed 30 times has a miss ratio of: _30_ / _100_ or _0.3_ or _30%_. It is the corollary of _hit ratio_ as +_hit ratio_ + _miss ratio_ is always _1.0_ or _100%_. + === System-of-Record (SoR) The authoritative source of truth for the data. The cache acts as a local copy of data retrieved from or stored to the system-of-record (SOR). The SOR is often a traditional database, although it might be a specialized file system or some @@ -41,7 +54,22 @@ data storage capacity). The removal of entries from the cache after some amount of time has passed, typically as a strategy to avoid stale data in the cache. +=== Off-Heap +When large caches put too much pressure on the GC, a common resort is to store the caches' contents _off-heap_, i.e: +still in the memory of the JVM process but out of reach of the garbage collector. The off-heap implementation Ehcache +uses is https://github.com/Terracotta-OSS/offheap-store/[Terracotta's port] of +http://gee.cs.oswego.edu/dl/html/malloc.html[dlmalloc] to Java backed by NIO direct ``ByteBuffer``s. + === Hot Data Data that has recently been used by an application is very likely to be accessed again soon. Such data is considered _hot_. A cache may attempt to keep the _hottest_ data most quickly available, while attemping to choose the -_least hot_ data for eviction. +_least hot_ data for eviction. Following the Pareto Distribution, you ideally want all your hot data to fit into your +caches. + +=== Pareto Distribution +According to https://www.statisticshowto.datasciencecentral.com/pareto-distribution/[Data Science Central], _the Pareto +distribution is a skewed distribution with heavy, or “slowly decaying” tails (i.e. much of the data is in the tails)_. +This is more commonly known as the 80% / 20% rule. +The entire concept of caching is based on the Pareto Distribution, as caches are only effective when their hit ratio +reaches a certain level, i.e.: as a general rule of thumb 80% of your transactions should be served with cached data and +the remaining 20% by data coming from other, more expensive means. From 97bb216a897f44d9c5f3978f0e3f439d50582072 Mon Sep 17 00:00:00 2001 From: Anthony Dahanne Date: Thu, 25 Jul 2019 08:46:48 -0400 Subject: [PATCH 162/372] fix the doc --- docs/src/docs/asciidoc/user/getting-started.adoc | 2 +- docs/src/docs/asciidoc/user/index.adoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/docs/asciidoc/user/getting-started.adoc b/docs/src/docs/asciidoc/user/getting-started.adoc index 2123645127..e663252e79 100644 --- a/docs/src/docs/asciidoc/user/getting-started.adoc +++ b/docs/src/docs/asciidoc/user/getting-started.adoc @@ -1,4 +1,4 @@ -= Ehcache {version} Documentation += Ehcache 3.8 Documentation ifndef::sourcedir38[] include::common.adoc[] endif::sourcedir38[] diff --git a/docs/src/docs/asciidoc/user/index.adoc b/docs/src/docs/asciidoc/user/index.adoc index 752db09394..1fda737829 100644 --- a/docs/src/docs/asciidoc/user/index.adoc +++ b/docs/src/docs/asciidoc/user/index.adoc @@ -9,7 +9,7 @@ endif::notBuildingForSite[] == Table of Contents -The Table of Contents provides an overview of the Ehcache {version} documentation on this site. +The Table of Contents provides an overview of the Ehcache 3.8 documentation on this site. Each topic below corresponds to a menu item at the left. === Basic Topics From f007da4cde4ca65ad5faf28e6d3a4d9e2218c228 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 24 Jul 2019 23:20:42 -0400 Subject: [PATCH 163/372] Fixes #2681 : Fix for last-batch boundary condition iteration bugs --- .../client/internal/store/ClusteredStore.java | 65 ++++---- .../store/CommonServerStoreProxy.java | 2 +- .../clustered/ClusteredIterationTest.java | 154 ++++++++++++++++++ .../server/offheap/OffHeapChainMap.java | 52 +++++- .../server/offheap/ChainMapExtensionTest.java | 3 +- .../server/offheap/ChainMapTest.java | 4 +- gradle.properties | 2 +- 7 files changed, 235 insertions(+), 47 deletions(-) create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index eb09daf760..336dfa240a 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -457,43 +457,40 @@ public Cache.Entry> next() { } private java.util.Iterator>> nextChain() { - try { - while (true) { - Map> chainContents = resolver.resolveChain(chainIterator.next(), timeSource.getTimeMillis()); - if (!chainContents.isEmpty()) { - return chainContents.entrySet().stream().map(entry -> { - K key = entry.getKey(); - - PutOperation operation = entry.getValue(); - ValueHolder valueHolder; - if (operation.isExpiryAvailable()) { - valueHolder = new ClusteredValueHolder<>(operation.getValue(), operation.expirationTime()); - } else { - valueHolder = new ClusteredValueHolder<>(operation.getValue()); + while (chainIterator.hasNext()) { + Map> chainContents = resolver.resolveChain(chainIterator.next(), timeSource.getTimeMillis()); + if (!chainContents.isEmpty()) { + return chainContents.entrySet().stream().map(entry -> { + K key = entry.getKey(); + + PutOperation operation = entry.getValue(); + ValueHolder valueHolder; + if (operation.isExpiryAvailable()) { + valueHolder = new ClusteredValueHolder<>(operation.getValue(), operation.expirationTime()); + } else { + valueHolder = new ClusteredValueHolder<>(operation.getValue()); + } + return new Cache.Entry>() { + + @Override + public K getKey() { + return key; } - return new Cache.Entry>() { - - @Override - public K getKey() { - return key; - } - - @Override - public ValueHolder getValue() { - return valueHolder; - } - - @Override - public String toString() { - return getKey() + "=" + getValue(); - } - }; - }).iterator(); - } + + @Override + public ValueHolder getValue() { + return valueHolder; + } + + @Override + public String toString() { + return getKey() + "=" + getValue(); + } + }; + }).iterator(); } - } catch (NoSuchElementException e) { - return emptyIterator(); } + return emptyIterator(); } }; } catch (Exception e) { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java index 2dcce719c3..5ac185a32f 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java @@ -204,7 +204,7 @@ public boolean hasNext() { @Override public Chain next() { - if (batch.hasNext()) { + if (lastBatch || batch.hasNext()) { return batch.next(); } else { try { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java new file mode 100644 index 0000000000..53c7c5a1c3 --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java @@ -0,0 +1,154 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered; + +import org.ehcache.Cache; +import org.ehcache.CacheManager; +import org.ehcache.config.units.MemoryUnit; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.terracotta.testing.rules.Cluster; + +import java.io.File; +import java.util.HashSet; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; + +import static java.util.stream.LongStream.range; +import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; +import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; +import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; +import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; +import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.collection.IsIn.isIn; +import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsInstanceOf.any; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + +public class ClusteredIterationTest extends ClusteredTests { + + private static final String RESOURCE_CONFIG = + "" + + "" + + "64" + + "" + + "\n"; + + @ClassRule + public static Cluster CLUSTER = + newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + + @Rule + public final TestName testName = new TestName(); + + @Test + public void testIterationTerminatedWithException() { + try (CacheManager cacheManager = createTestCacheManager()) { + Cache cache = cacheManager.getCache(testName.getMethodName(), Long.class, byte[].class); + + byte[] data = new byte[101 * 1024]; + cache.put(1L, data); + cache.put(2L, data); + + Iterator> iterator = cache.iterator(); + + assertThat(iterator.next(), notNullValue()); + assertThat(iterator.next(), notNullValue()); + + try { + iterator.next(); + fail("Expected NoSuchElementException"); + } catch (NoSuchElementException e) { + //expected + } + } + } + + @Test @SuppressWarnings("unchecked") + public void testIterationWithSingleLastBatchIsBroken() { + try (CacheManager cacheManager = createTestCacheManager()) { + Cache cache = cacheManager.getCache(testName.getMethodName(), Long.class, byte[].class); + + byte[] data = new byte[101 * 1024]; + cache.put(1L, data); + cache.put(2L, data); + + assertThat(cache, containsInAnyOrder( + isEntry(is(1L), any(byte[].class)), + isEntry(is(2L), any(byte[].class)) + )); + } + } + + @Test + public void testIterationWithConcurrentClearedCacheException() { + try (CacheManager cacheManager = createTestCacheManager()) { + Cache cache = cacheManager.getCache(testName.getMethodName(), Long.class, byte[].class); + + byte[] data = new byte[10 * 1024]; + Set initialKeySet = new HashSet<>(); + range(0, 20).forEach(k -> { + cache.put(k, data); + initialKeySet.add(k); + }); + + Iterator> iterator = cache.iterator(); + + cache.clear(); + + HashSet foundKeys = new HashSet<>(); + try { + while (true) { + assertThat(foundKeys.add(iterator.next().getKey()), is(true)); + } + } catch (NoSuchElementException e) { + //expected + } + foundKeys.forEach(k -> assertThat(k, isIn(initialKeySet))); + } + } + + private CacheManager createTestCacheManager() { + return newCacheManagerBuilder().with(cluster(CLUSTER.getConnectionURI().resolve("/iteration-cm")) + .autoCreate().defaultServerResource("primary-server-resource")) + .withCache(testName.getMethodName(), newCacheConfigurationBuilder(Long.class, byte[].class, newResourcePoolsBuilder() + .with(clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB)))).build(true); + } + + private static Matcher> isEntry(Matcher keyMatcher, Matcher valueMatcher) { + return new TypeSafeMatcher>() { + @Override + public void describeTo(Description description) { + description.appendText(" a cache entry { key ").appendDescriptionOf(keyMatcher).appendText(": value ").appendDescriptionOf(valueMatcher).appendText(" }"); + } + + @Override + protected boolean matchesSafely(Cache.Entry item) { + return keyMatcher.matches(item.getKey()) && valueMatcher.matches(item.getValue()); + } + }; + } +} diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java index ec792c55cf..8dc31d2ba7 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java @@ -16,6 +16,7 @@ package org.ehcache.clustered.server.offheap; import java.nio.ByteBuffer; +import java.nio.IntBuffer; import java.util.Collections; import java.util.Iterator; import java.util.Map; @@ -25,7 +26,6 @@ import org.ehcache.clustered.common.internal.store.Chain; import org.terracotta.offheapstore.MapInternals; -import org.terracotta.offheapstore.ReadWriteLockedOffHeapClockCache; import org.terracotta.offheapstore.eviction.EvictionListener; import org.terracotta.offheapstore.eviction.EvictionListeningReadWriteLockedOffHeapClockCache; import org.terracotta.offheapstore.exceptions.OversizeMappingException; @@ -41,7 +41,7 @@ interface ChainMapEvictionListener { void onEviction(K key); } - protected final ReadWriteLockedOffHeapClockCache heads; + protected final HeadMap heads; private final ChainStorageEngine chainStorage; private volatile ChainMapEvictionListener evictionListener; @@ -62,9 +62,7 @@ private OffHeapChainMap(PageSource source, ChainStorageEngine storageEngine) } }; - //TODO: EvictionListeningReadWriteLockedOffHeapClockCache lacks ctor that takes shareByThieving - // this.heads = new ReadWriteLockedOffHeapClockCache(source, shareByThieving, chainStorage); - this.heads = new EvictionListeningReadWriteLockedOffHeapClockCache<>(listener, source, chainStorage); + this.heads = new HeadMap<>(listener, source, chainStorage); } public OffHeapChainMap(PageSource source, Factory> storageEngineFactory) { @@ -76,7 +74,7 @@ public OffHeapChainMap(PageSource source, Portability keyPortability, } //For tests - OffHeapChainMap(ReadWriteLockedOffHeapClockCache heads, OffHeapChainStorageEngine chainStorage) { + OffHeapChainMap(HeadMap heads, OffHeapChainStorageEngine chainStorage) { this.chainStorage = chainStorage; this.heads = heads; } @@ -242,7 +240,7 @@ public Set keySet() { @Override public Iterator iterator() { - Iterator> headsIterator = heads.entrySet().iterator(); + Iterator> headsIterator = heads.detachedEntryIterator(); return new Iterator() { @Override @@ -354,4 +352,44 @@ public Lock writeLock() { protected void storageEngineFailure(Object failure) { } + static class HeadMap extends EvictionListeningReadWriteLockedOffHeapClockCache { + + public HeadMap(EvictionListener listener, PageSource source, ChainStorageEngine chainStorage) { + super(listener, source, chainStorage); + } + + public Iterator> detachedEntryIterator() { + return new LockedEntryIterator() { + @Override + protected Entry create(IntBuffer entry) { + Entry attachedEntry = super.create(entry); + + try (InternalChain chain = attachedEntry.getValue()) { + Chain detachedChain = chain.detach(); + return new SimpleImmutableEntry<>(attachedEntry.getKey(), new InternalChain() { + @Override + public Chain detach() { + return detachedChain; + } + + @Override + public boolean append(ByteBuffer element) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean replace(Chain expected, Chain replacement) { + throw new UnsupportedOperationException(); + } + + @Override + public void close() { + // + } + }); + } + } + }; + } + } } diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java index 3d1ab352f7..5d4f169f52 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java @@ -131,8 +131,7 @@ private OffHeapChainMap getNewMap(ExtendedOffHeapChainStorageEngine> factory = OffHeapChainStorageEngine.createFactory(chainSource, StringPortability.INSTANCE, 4096, 4096, false, false); OffHeapChainStorageEngine storageEngine = (OffHeapChainStorageEngine) factory.newInstance(); - ReadWriteLockedOffHeapClockCache newMap = - new ReadWriteLockedOffHeapClockCache<>(chainSource, storageEngine); + OffHeapChainMap.HeadMap newMap = new OffHeapChainMap.HeadMap<>(e -> {}, chainSource, storageEngine); ese.replayIntoMap(newMap); return new OffHeapChainMap<>(newMap, storageEngine); } diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java index d42a4a2a3c..d298e91e24 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java @@ -354,7 +354,7 @@ public void testActiveChainsThreadSafety() throws ExecutionException, Interrupte UnlimitedPageSource source = new UnlimitedPageSource(new OffHeapBufferSource()); OffHeapChainStorageEngine chainStorage = new OffHeapChainStorageEngine<>(source, StringPortability.INSTANCE, minPageSize, maxPageSize, steal, steal); - ReadWriteLockedOffHeapClockCache heads = new EvictionListeningReadWriteLockedOffHeapClockCache<>(callable -> {}, source, chainStorage); + OffHeapChainMap.HeadMap heads = new OffHeapChainMap.HeadMap<>(callable -> {}, source, chainStorage); OffHeapChainMap map = new OffHeapChainMap<>(heads, chainStorage); @@ -382,7 +382,7 @@ public void testPutDoesNotLeakWhenMappingIsNotNull() { UnlimitedPageSource source = new UnlimitedPageSource(new OffHeapBufferSource()); OffHeapChainStorageEngine chainStorage = new OffHeapChainStorageEngine<>(source, StringPortability.INSTANCE, minPageSize, maxPageSize, steal, steal); - ReadWriteLockedOffHeapClockCache heads = new EvictionListeningReadWriteLockedOffHeapClockCache<>(callable -> {}, source, chainStorage); + OffHeapChainMap.HeadMap heads = new OffHeapChainMap.HeadMap<>(callable -> {}, source, chainStorage); OffHeapChainMap map = new OffHeapChainMap<>(heads, chainStorage); diff --git a/gradle.properties b/gradle.properties index 307fae0bac..59aad6f84e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ ehcacheVersion = 3.7-SNAPSHOT # Terracotta third parties -offheapVersion = 2.4.0 +offheapVersion = 2.4.2 statisticVersion = 2.1 jcacheVersion = 1.1.0 slf4jVersion = 1.7.25 From 14d72363f1ec83f6ad1896b2a75df4f05a61494a Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Sat, 6 Apr 2019 11:22:55 -0400 Subject: [PATCH 164/372] Upgrade to Asciidoctor Gradle Plugin 2.3.0 --- buildSrc/src/main/groovy/EhDocs.groovy | 4 +- docs/build.gradle | 59 ++++++++++--------- .../asciidoc/developer/design.tiering.adoc | 6 +- .../asciidoc/developer/module.clustering.adoc | 2 +- .../src/docs/asciidoc/user/.asciidoctorconfig | 3 + docs/src/docs/asciidoc/user/107.adoc | 4 +- .../asciidoc/user/cache-event-listeners.adoc | 4 +- .../docs/asciidoc/user/caching-concepts.adoc | 4 +- .../docs/asciidoc/user/caching-patterns.adoc | 4 +- .../src/docs/asciidoc/user/caching-terms.adoc | 4 +- .../src/docs/asciidoc/user/class-loading.adoc | 4 +- .../docs/asciidoc/user/clustered-cache.adoc | 4 +- docs/src/docs/asciidoc/user/common.adoc | 2 +- .../src/docs/asciidoc/user/config-derive.adoc | 4 +- .../docs/asciidoc/user/eviction-advisor.adoc | 4 +- docs/src/docs/asciidoc/user/examples.adoc | 4 +- docs/src/docs/asciidoc/user/expiry.adoc | 4 +- .../docs/asciidoc/user/getting-started.adoc | 4 +- docs/src/docs/asciidoc/user/index.adoc | 4 +- docs/src/docs/asciidoc/user/management.adoc | 4 +- .../docs/asciidoc/user/migration-guide.adoc | 4 +- docs/src/docs/asciidoc/user/osgi.adoc | 4 +- docs/src/docs/asciidoc/user/performance.adoc | 4 +- docs/src/docs/asciidoc/user/resilience.adoc | 4 +- .../asciidoc/user/serializers-copiers.adoc | 4 +- docs/src/docs/asciidoc/user/thread-pools.adoc | 4 +- docs/src/docs/asciidoc/user/tiering.adoc | 5 +- docs/src/docs/asciidoc/user/usermanaged.adoc | 4 +- docs/src/docs/asciidoc/user/writers.adoc | 4 +- docs/src/docs/asciidoc/user/xa.adoc | 4 +- docs/src/docs/asciidoc/user/xml.adoc | 4 +- docs/src/docs/asciidoc/user/xsds.adoc | 4 +- 32 files changed, 95 insertions(+), 86 deletions(-) create mode 100644 docs/src/docs/asciidoc/user/.asciidoctorconfig diff --git a/buildSrc/src/main/groovy/EhDocs.groovy b/buildSrc/src/main/groovy/EhDocs.groovy index 0a900fb480..8e950b8bb7 100644 --- a/buildSrc/src/main/groovy/EhDocs.groovy +++ b/buildSrc/src/main/groovy/EhDocs.groovy @@ -60,9 +60,9 @@ class EhDocs implements Plugin { } - project.task('asciidocZip', type: Zip, dependsOn: ':docs:asciidoctor') { + project.task('asciidocZip', type: Zip, dependsOn: ':docs:userDoc') { classifier = 'docs' - from project.tasks.getByPath(':docs:asciidoctor').outputDir + from project.tasks.getByPath(':docs:userDoc').outputDir } project.artifacts { diff --git a/docs/build.gradle b/docs/build.gradle index bd7880b24b..960c11aa21 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -14,50 +14,55 @@ * limitations under the License. */ +import org.asciidoctor.gradle.jvm.AsciidoctorJBasePlugin +import org.asciidoctor.gradle.jvm.AsciidoctorTask + plugins { - id 'org.asciidoctor.convert' version '1.6.0' + id 'org.asciidoctor.jvm.base' version '2.3.0' id 'org.kordamp.gradle.livereload' version '0.2.1' - id 'com.github.jruby-gradle.base' version '1.6.0' -} - -dependencies { - gems 'rubygems:asciidoctor-diagram:1.5.15' } -configurations.asciidoctor { - resolutionStrategy { - force 'com.github.jnr:jnr-enxio:0.19' - force 'com.github.jnr:jnr-posix:3.0.49' - force 'com.github.jnr:jnr-constants:0.9.12' +asciidoctorj { + safeMode 'UNSAFE' + attributes 'skip-front-matter': 'true' + fatalWarnings ~/.*/ + modules { + diagram.version '1.5.18' } } -task copyCSS(type: Copy) { - from ('css') { - include '**' +def createCopyCssTask(def asciidocTask) { + return tasks.register("copy${asciidocTask.name}CSS", Copy) { + from ('css') { + include '**' + } into("${asciidocTask.outputDir}/css") } - into("${buildDir}/asciidoc/user/css") } -asciidoctor.dependsOn copyCSS - -asciidoctor { - dependsOn jrubyPrepare - gemPath = jrubyPrepare.outputDir - requires = ['asciidoctor-diagram'] - separateOutputDirs = false - attributes 'skip-front-matter': 'true' - +tasks.withType(AsciidoctorTask) { + group = AsciidoctorJBasePlugin.TASK_GROUP resources { from('fonts') { include '*' - into('./user/fonts') - } + } into('./fonts') } + dependsOn createCopyCssTask(it) +} + +tasks.register('userDoc', AsciidoctorTask) { + description = 'Generate the user documentation' + sourceDir file('src/docs/asciidoc/user') + outputDir file("$buildDir/asciidoc/user") +} + +tasks.register('developerDoc', AsciidoctorTask) { + description = 'Generate the developer documentation' + sourceDir file('src/docs/asciidoc/developer') + outputDir file("$buildDir/asciidoc/developer") } liveReload { - docRoot asciidoctor.outputDir.canonicalPath + docRoot userDoc.outputDir.canonicalPath } dependencyCheck { diff --git a/docs/src/docs/asciidoc/developer/design.tiering.adoc b/docs/src/docs/asciidoc/developer/design.tiering.adoc index 4210177572..b6c66f975f 100644 --- a/docs/src/docs/asciidoc/developer/design.tiering.adoc +++ b/docs/src/docs/asciidoc/developer/design.tiering.adoc @@ -2,7 +2,7 @@ :toc: -The `Store` in Ehcache is designed to hold data in a tiered model. +The `Store` in Ehcache is designed to hold data in a tiered model. A cache will always have at least one tier, possible multiple. As soon as there are multiple tiers, they are immediately divided between a single `AuthoritativeTier` and one or more `CachingTier`. It is the `TieredStore` that wires the authority and caching tiers and provides a unified view of the `Store` for the Cache. @@ -49,7 +49,7 @@ authority. [plantuml] .... -include::../../uml/put.puml[] +include::{includedir}/../../uml/put.puml[] .... * All writes directly go to the Authoritative tier.This tier has all the data such that caching tier always has a subset of authority * On return, the mapping in the caching tier is invalidated. @@ -57,7 +57,7 @@ include::../../uml/put.puml[] [plantuml] .... -include::../../uml/get.puml[] +include::{includedir}/../../uml/get.puml[] .... * Any reading thread tries to get data from the caching tier and returns * If the key is not found in caching tier, it is faulted from authority diff --git a/docs/src/docs/asciidoc/developer/module.clustering.adoc b/docs/src/docs/asciidoc/developer/module.clustering.adoc index 4632aa2cb2..00102bff0a 100644 --- a/docs/src/docs/asciidoc/developer/module.clustering.adoc +++ b/docs/src/docs/asciidoc/developer/module.clustering.adoc @@ -68,5 +68,5 @@ _HA_? [plantuml] .... -include::../../uml/putIfAbsentUml.puml[] +include::{includedir}/../../uml/putIfAbsentUml.puml[] .... diff --git a/docs/src/docs/asciidoc/user/.asciidoctorconfig b/docs/src/docs/asciidoc/user/.asciidoctorconfig new file mode 100644 index 0000000000..8bfbdba299 --- /dev/null +++ b/docs/src/docs/asciidoc/user/.asciidoctorconfig @@ -0,0 +1,3 @@ + +:includedir: . +:gradle-rootdir: ../../../../.. diff --git a/docs/src/docs/asciidoc/user/107.adoc b/docs/src/docs/asciidoc/user/107.adoc index 9f6763c42f..037c931643 100644 --- a/docs/src/docs/asciidoc/user/107.adoc +++ b/docs/src/docs/asciidoc/user/107.adoc @@ -2,11 +2,11 @@ --- = The Ehcache 3.x JSR-107 Provider ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] [[overview]] diff --git a/docs/src/docs/asciidoc/user/cache-event-listeners.adoc b/docs/src/docs/asciidoc/user/cache-event-listeners.adoc index e73a6b0166..f23e76d6d4 100644 --- a/docs/src/docs/asciidoc/user/cache-event-listeners.adoc +++ b/docs/src/docs/asciidoc/user/cache-event-listeners.adoc @@ -2,11 +2,11 @@ --- = Cache Event Listeners ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] [[introduction]] diff --git a/docs/src/docs/asciidoc/user/caching-concepts.adoc b/docs/src/docs/asciidoc/user/caching-concepts.adoc index fd5a59e689..1ea1c185ae 100644 --- a/docs/src/docs/asciidoc/user/caching-concepts.adoc +++ b/docs/src/docs/asciidoc/user/caching-concepts.adoc @@ -2,11 +2,11 @@ --- = Concepts Related to Caching ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] [[data-freshness-and-expiration]] diff --git a/docs/src/docs/asciidoc/user/caching-patterns.adoc b/docs/src/docs/asciidoc/user/caching-patterns.adoc index 2708c74a5f..26f2505e1c 100644 --- a/docs/src/docs/asciidoc/user/caching-patterns.adoc +++ b/docs/src/docs/asciidoc/user/caching-patterns.adoc @@ -2,11 +2,11 @@ --- = Cache Usage Patterns ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] There are several common access patterns when using a cache. diff --git a/docs/src/docs/asciidoc/user/caching-terms.adoc b/docs/src/docs/asciidoc/user/caching-terms.adoc index 17ee9b0ae8..f53ed79af7 100644 --- a/docs/src/docs/asciidoc/user/caching-terms.adoc +++ b/docs/src/docs/asciidoc/user/caching-terms.adoc @@ -2,11 +2,11 @@ --- = Terms Related to Caching ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] == Basic Terms diff --git a/docs/src/docs/asciidoc/user/class-loading.adoc b/docs/src/docs/asciidoc/user/class-loading.adoc index 32152ef674..b3b8f6f6f0 100644 --- a/docs/src/docs/asciidoc/user/class-loading.adoc +++ b/docs/src/docs/asciidoc/user/class-loading.adoc @@ -2,11 +2,11 @@ --- = Class loading ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] [[about]] diff --git a/docs/src/docs/asciidoc/user/clustered-cache.adoc b/docs/src/docs/asciidoc/user/clustered-cache.adoc index f079302b9d..7de7ca7ac0 100644 --- a/docs/src/docs/asciidoc/user/clustered-cache.adoc +++ b/docs/src/docs/asciidoc/user/clustered-cache.adoc @@ -2,11 +2,11 @@ --- = Clustered Cache ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] == Introduction diff --git a/docs/src/docs/asciidoc/user/common.adoc b/docs/src/docs/asciidoc/user/common.adoc index 8872d3424f..3735b716df 100644 --- a/docs/src/docs/asciidoc/user/common.adoc +++ b/docs/src/docs/asciidoc/user/common.adoc @@ -11,7 +11,7 @@ ifdef::basebackend-html[:outfilesuffix: .html] :icons: font :iconfont-remote!: :iconfont-name: font-awesome.min -:sourcedir38: ../../../../../ +:sourcedir38: {gradle-rootdir} :imagesdir: images :sectanchors: :idprefix: diff --git a/docs/src/docs/asciidoc/user/config-derive.adoc b/docs/src/docs/asciidoc/user/config-derive.adoc index 9ad0a5d7ce..07ea68dd36 100644 --- a/docs/src/docs/asciidoc/user/config-derive.adoc +++ b/docs/src/docs/asciidoc/user/config-derive.adoc @@ -2,11 +2,11 @@ --- = Configuration Derivation ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] == Principles diff --git a/docs/src/docs/asciidoc/user/eviction-advisor.adoc b/docs/src/docs/asciidoc/user/eviction-advisor.adoc index 35e152e0cc..5c9941ee3a 100644 --- a/docs/src/docs/asciidoc/user/eviction-advisor.adoc +++ b/docs/src/docs/asciidoc/user/eviction-advisor.adoc @@ -2,11 +2,11 @@ --- = Eviction Advisor ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] == Introduction diff --git a/docs/src/docs/asciidoc/user/examples.adoc b/docs/src/docs/asciidoc/user/examples.adoc index ac1ec06d7a..fdb6ace920 100644 --- a/docs/src/docs/asciidoc/user/examples.adoc +++ b/docs/src/docs/asciidoc/user/examples.adoc @@ -2,11 +2,11 @@ --- = Examples ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] == Peeper - a simple message board diff --git a/docs/src/docs/asciidoc/user/expiry.adoc b/docs/src/docs/asciidoc/user/expiry.adoc index 74f19f907d..8a3a6706e4 100644 --- a/docs/src/docs/asciidoc/user/expiry.adoc +++ b/docs/src/docs/asciidoc/user/expiry.adoc @@ -2,11 +2,11 @@ --- = Expiry ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] == Introduction diff --git a/docs/src/docs/asciidoc/user/getting-started.adoc b/docs/src/docs/asciidoc/user/getting-started.adoc index e663252e79..af9774bb9c 100644 --- a/docs/src/docs/asciidoc/user/getting-started.adoc +++ b/docs/src/docs/asciidoc/user/getting-started.adoc @@ -1,11 +1,11 @@ = Ehcache 3.8 Documentation ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] We feel that the Ehcache 3.x API is a great improvement over the Ehcache 2.x API that has been used by millions of developers. We hope you enjoy this new generation of Ehcache! ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] == Configuring Ehcache diff --git a/docs/src/docs/asciidoc/user/index.adoc b/docs/src/docs/asciidoc/user/index.adoc index 1fda737829..ea45700041 100644 --- a/docs/src/docs/asciidoc/user/index.adoc +++ b/docs/src/docs/asciidoc/user/index.adoc @@ -1,10 +1,10 @@ = Ehcache {version} Documentation Overview ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] == Table of Contents diff --git a/docs/src/docs/asciidoc/user/management.adoc b/docs/src/docs/asciidoc/user/management.adoc index e2e5ef80ab..3850c4662a 100644 --- a/docs/src/docs/asciidoc/user/management.adoc +++ b/docs/src/docs/asciidoc/user/management.adoc @@ -2,11 +2,11 @@ --- = Management and Monitoring ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] == Intro diff --git a/docs/src/docs/asciidoc/user/migration-guide.adoc b/docs/src/docs/asciidoc/user/migration-guide.adoc index 7f732fd2d2..601b7d727c 100644 --- a/docs/src/docs/asciidoc/user/migration-guide.adoc +++ b/docs/src/docs/asciidoc/user/migration-guide.adoc @@ -2,11 +2,11 @@ --- = Migration Guide ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] == Introduction diff --git a/docs/src/docs/asciidoc/user/osgi.adoc b/docs/src/docs/asciidoc/user/osgi.adoc index 9c73c089f3..65f7785a38 100644 --- a/docs/src/docs/asciidoc/user/osgi.adoc +++ b/docs/src/docs/asciidoc/user/osgi.adoc @@ -2,11 +2,11 @@ --- = OSGi Deployment ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] == OSGi Compatible Bundles diff --git a/docs/src/docs/asciidoc/user/performance.adoc b/docs/src/docs/asciidoc/user/performance.adoc index 54dc58f1f3..240747e906 100644 --- a/docs/src/docs/asciidoc/user/performance.adoc +++ b/docs/src/docs/asciidoc/user/performance.adoc @@ -2,11 +2,11 @@ --- = Performance Tuning ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] == Introduction diff --git a/docs/src/docs/asciidoc/user/resilience.adoc b/docs/src/docs/asciidoc/user/resilience.adoc index 2a93cbebc2..131398f03e 100644 --- a/docs/src/docs/asciidoc/user/resilience.adoc +++ b/docs/src/docs/asciidoc/user/resilience.adoc @@ -2,11 +2,11 @@ --- = Resilience ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] == Introduction diff --git a/docs/src/docs/asciidoc/user/serializers-copiers.adoc b/docs/src/docs/asciidoc/user/serializers-copiers.adoc index 9148096cb3..959488c4b2 100644 --- a/docs/src/docs/asciidoc/user/serializers-copiers.adoc +++ b/docs/src/docs/asciidoc/user/serializers-copiers.adoc @@ -2,11 +2,11 @@ --- = Serializers and Copiers ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] [[overview]] diff --git a/docs/src/docs/asciidoc/user/thread-pools.adoc b/docs/src/docs/asciidoc/user/thread-pools.adoc index 44991cbb4e..8ad9ecfc9b 100644 --- a/docs/src/docs/asciidoc/user/thread-pools.adoc +++ b/docs/src/docs/asciidoc/user/thread-pools.adoc @@ -2,11 +2,11 @@ --- = Thread Pools ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] [[introduction]] diff --git a/docs/src/docs/asciidoc/user/tiering.adoc b/docs/src/docs/asciidoc/user/tiering.adoc index 2eb26c5453..720e2c1f1d 100644 --- a/docs/src/docs/asciidoc/user/tiering.adoc +++ b/docs/src/docs/asciidoc/user/tiering.adoc @@ -2,11 +2,12 @@ --- = Ehcache Tiering Options ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] +>>>>>>> Upgrade to Asciidoctor Gradle Plugin 2.0.0 ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] == Introduction diff --git a/docs/src/docs/asciidoc/user/usermanaged.adoc b/docs/src/docs/asciidoc/user/usermanaged.adoc index 10a83dd101..c16dcea2d1 100644 --- a/docs/src/docs/asciidoc/user/usermanaged.adoc +++ b/docs/src/docs/asciidoc/user/usermanaged.adoc @@ -2,11 +2,11 @@ --- = User managed caches ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] [[overview]] diff --git a/docs/src/docs/asciidoc/user/writers.adoc b/docs/src/docs/asciidoc/user/writers.adoc index 0ef9d80de5..a4e2d2217f 100644 --- a/docs/src/docs/asciidoc/user/writers.adoc +++ b/docs/src/docs/asciidoc/user/writers.adoc @@ -2,11 +2,11 @@ --- = Cache Loaders and Writers ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] [[introduction]] diff --git a/docs/src/docs/asciidoc/user/xa.adoc b/docs/src/docs/asciidoc/user/xa.adoc index e7c7f02432..606b84b518 100644 --- a/docs/src/docs/asciidoc/user/xa.adoc +++ b/docs/src/docs/asciidoc/user/xa.adoc @@ -2,11 +2,11 @@ --- = XA transactional caches ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] == Introduction diff --git a/docs/src/docs/asciidoc/user/xml.adoc b/docs/src/docs/asciidoc/user/xml.adoc index 7e2dbcea46..e49480c28c 100644 --- a/docs/src/docs/asciidoc/user/xml.adoc +++ b/docs/src/docs/asciidoc/user/xml.adoc @@ -2,11 +2,11 @@ --- = XML Configuration ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] == Introduction diff --git a/docs/src/docs/asciidoc/user/xsds.adoc b/docs/src/docs/asciidoc/user/xsds.adoc index 3f15432bf8..335a4c0fbb 100644 --- a/docs/src/docs/asciidoc/user/xsds.adoc +++ b/docs/src/docs/asciidoc/user/xsds.adoc @@ -2,11 +2,11 @@ --- = Ehcache XSDs ifndef::sourcedir38[] -include::common.adoc[] +include::{includedir}/common.adoc[] endif::sourcedir38[] ifdef::notBuildingForSite[] -include::menu.adoc[] +include::{includedir}/menu.adoc[] endif::notBuildingForSite[] == XSD namespaces and locations From 7a8ada1a1db6a3dfd1b6e12a25ad543a43214e67 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 4 Apr 2019 14:04:41 -0400 Subject: [PATCH 165/372] Fixes #2627 : Better XML error messages when service implementations are absent --- .../org/ehcache/xml/ConfigurationParser.java | 18 ++++++++-- .../org/ehcache/xml/XmlConfigurationTest.java | 33 +++++++++++++++++++ .../resources/configs/unknown-resource.xml | 12 +++++++ .../configs/unknown-service-creation.xml | 10 ++++++ .../resources/configs/unknown-service.xml | 9 +++++ 5 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 xml/src/test/resources/configs/unknown-resource.xml create mode 100644 xml/src/test/resources/configs/unknown-service-creation.xml create mode 100644 xml/src/test/resources/configs/unknown-service.xml diff --git a/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java index 3f9b462af3..e2c73890fb 100644 --- a/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java @@ -85,13 +85,16 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; +import static java.lang.String.format; import static java.security.AccessController.doPrivileged; import static java.util.Arrays.asList; import static java.util.Spliterators.spliterator; import static java.util.function.Function.identity; +import static java.util.regex.Pattern.quote; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toMap; +import static java.util.stream.Stream.of; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ConfigurationBuilder.newConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; @@ -366,19 +369,28 @@ public Document configToDocument(Configuration configuration) throws JAXBExcepti public static class FatalErrorHandler implements ErrorHandler { + private static final Pattern ABSTRACT_TYPE_FAILURES = of("service-creation-configuration", "service-configuration", "resource") + .map(element -> quote(format("\"http://www.ehcache.org/v3\":%s", element))) + .collect(collectingAndThen(joining("|", "^\\Qcvc-complex-type.2.4.a\\E.*'\\{.*(?:", ").*\\}'.*$"), Pattern::compile)); + @Override public void warning(SAXParseException exception) throws SAXException { - throw exception; + fatalError(exception); } @Override public void error(SAXParseException exception) throws SAXException { - throw exception; + fatalError(exception); } @Override public void fatalError(SAXParseException exception) throws SAXException { - throw exception; + if (ABSTRACT_TYPE_FAILURES.matcher(exception.getMessage()).matches()) { + throw new XmlConfigurationException( + "Cannot confirm XML sub-type correctness. You might be missing client side libraries.", exception); + } else { + throw exception; + } } } diff --git a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java index e445b8cdf1..e1a1ff31bb 100644 --- a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java @@ -850,6 +850,39 @@ public void testInnerClassNameArrayConversion() throws ClassNotFoundException { assertThat(getClassForName("java.util.Map.Entry[]", getDefaultClassLoader()), IsEqual.equalTo(Map.Entry[].class)); } + @Test + public void testUnknownServiceCreation() throws Exception { + URL resource = XmlConfigurationTest.class.getResource("/configs/unknown-service-creation.xml"); + try { + new XmlConfiguration(resource); + } catch (XmlConfigurationException e) { + assertThat(e.getMessage(), is("Cannot confirm XML sub-type correctness. You might be missing client side libraries.")); + assertThat(e.getCause(), instanceOf(SAXParseException.class)); + } + } + + @Test + public void testUnknownService() throws Exception { + URL resource = XmlConfigurationTest.class.getResource("/configs/unknown-service.xml"); + try { + new XmlConfiguration(resource); + } catch (XmlConfigurationException e) { + assertThat(e.getMessage(), is("Cannot confirm XML sub-type correctness. You might be missing client side libraries.")); + assertThat(e.getCause(), instanceOf(SAXParseException.class)); + } + } + + @Test + public void testUnknownResource() throws Exception { + URL resource = XmlConfigurationTest.class.getResource("/configs/unknown-resource.xml"); + try { + new XmlConfiguration(resource); + } catch (XmlConfigurationException e) { + assertThat(e.getMessage(), is("Cannot confirm XML sub-type correctness. You might be missing client side libraries.")); + assertThat(e.getCause(), instanceOf(SAXParseException.class)); + } + } + private void checkListenerConfigurationExists(Collection configuration) { int count = 0; for (Object o : configuration) { diff --git a/xml/src/test/resources/configs/unknown-resource.xml b/xml/src/test/resources/configs/unknown-resource.xml new file mode 100644 index 0000000000..0ee99b09ef --- /dev/null +++ b/xml/src/test/resources/configs/unknown-resource.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/xml/src/test/resources/configs/unknown-service-creation.xml b/xml/src/test/resources/configs/unknown-service-creation.xml new file mode 100644 index 0000000000..2f983b475c --- /dev/null +++ b/xml/src/test/resources/configs/unknown-service-creation.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/xml/src/test/resources/configs/unknown-service.xml b/xml/src/test/resources/configs/unknown-service.xml new file mode 100644 index 0000000000..e54fb4085d --- /dev/null +++ b/xml/src/test/resources/configs/unknown-service.xml @@ -0,0 +1,9 @@ + + + + + + + From c8acadb683539f215a676b9da01c7f4273504136 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 29 Jul 2019 17:15:53 -0400 Subject: [PATCH 166/372] Remove deprecated Gradle API usage --- build.gradle | 4 ++-- buildSrc/src/main/groovy/EhDocs.groovy | 4 ++-- clustered/clustered-dist/build.gradle | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index ee7433f77e..d795e73fe8 100644 --- a/build.gradle +++ b/build.gradle @@ -155,7 +155,7 @@ subprojects { task sourceJar(type: Jar, dependsOn: classes) { from sourceSets.main.allJava - classifier = 'sources' + archiveClassifier = 'sources' } javadoc { @@ -165,7 +165,7 @@ subprojects { task javadocJar(type: Jar, dependsOn: javadoc) { from javadoc.destinationDir - classifier = 'javadoc' + archiveClassifier = 'javadoc' } artifacts { diff --git a/buildSrc/src/main/groovy/EhDocs.groovy b/buildSrc/src/main/groovy/EhDocs.groovy index 8e950b8bb7..c1897f3863 100644 --- a/buildSrc/src/main/groovy/EhDocs.groovy +++ b/buildSrc/src/main/groovy/EhDocs.groovy @@ -54,14 +54,14 @@ class EhDocs implements Plugin { } project.task('spiJavadocJar', type: Jar, dependsOn: 'spiJavadoc') { - classifier = 'spi-javadoc' + archiveClassifier = 'spi-javadoc' from project.tasks.getByPath('spiJavadoc').destinationDir } } project.task('asciidocZip', type: Zip, dependsOn: ':docs:userDoc') { - classifier = 'docs' + archiveClassifier = 'docs' from project.tasks.getByPath(':docs:userDoc').outputDir } diff --git a/clustered/clustered-dist/build.gradle b/clustered/clustered-dist/build.gradle index c88112a666..72d21bbfb5 100644 --- a/clustered/clustered-dist/build.gradle +++ b/clustered/clustered-dist/build.gradle @@ -127,12 +127,12 @@ distributions { } distTar { - classifier = 'kit' + archiveClassifier = 'kit' compression = Compression.GZIP } distZip { - classifier = 'kit' + archiveClassifier = 'kit' } [distTar, distZip, installDist]*.dependsOn copyDocs, javadocJar, project(':dist').jar, project(':dist').javadocJar From 2f3e5741f4ceb8931e06a89d6ad5ee0d9e85d0a3 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 29 Jul 2019 17:25:05 -0400 Subject: [PATCH 167/372] Remove unecessary plugins --- build.gradle | 4 ---- docs/build.gradle | 5 ----- xml/build.gradle | 2 -- 3 files changed, 11 deletions(-) diff --git a/build.gradle b/build.gradle index d795e73fe8..3279df1edd 100644 --- a/build.gradle +++ b/build.gradle @@ -20,9 +20,6 @@ plugins { // This adds tasks to auto close or release nexus staging repos // see https://github.com/Codearte/gradle-nexus-staging-plugin/ id 'io.codearte.nexus-staging' version '0.12.0' - // This adds the ability to print a taskTree - // ./gradlew ... taskTree - id "com.dorongold.task-tree" version "1.3.1" // Declare spotbugs at the top id 'com.github.spotbugs' version '1.6.9' apply false // Declare osgi-ds at the top @@ -89,7 +86,6 @@ if (hasProperty('testVM')) { subprojects { apply plugin: 'java-library' - apply plugin: 'eclipse' apply plugin: 'checkstyle' apply plugin: 'com.github.spotbugs' apply plugin: 'jacoco' diff --git a/docs/build.gradle b/docs/build.gradle index 960c11aa21..40dc996565 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -19,7 +19,6 @@ import org.asciidoctor.gradle.jvm.AsciidoctorTask plugins { id 'org.asciidoctor.jvm.base' version '2.3.0' - id 'org.kordamp.gradle.livereload' version '0.2.1' } asciidoctorj { @@ -61,10 +60,6 @@ tasks.register('developerDoc', AsciidoctorTask) { outputDir file("$buildDir/asciidoc/developer") } -liveReload { - docRoot userDoc.outputDir.canonicalPath -} - dependencyCheck { skip = true } diff --git a/xml/build.gradle b/xml/build.gradle index abdda0b208..b97fa11712 100644 --- a/xml/build.gradle +++ b/xml/build.gradle @@ -16,12 +16,10 @@ plugins { id 'org.unbroken-dome.xjc' version '1.4.1' - id 'com.github.hauner.jarTest' version '1.0.1' } apply plugin: EhDeploy apply plugin: 'biz.aQute.bnd.builder' -apply plugin: 'com.github.hauner.jarTest' dependencies { api project(':api') From 25a033a9c3f0321cff0ec8f41dac17afbf4322c2 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 30 Jul 2019 10:41:38 -0400 Subject: [PATCH 168/372] Upgrade Gradle plugins --- build.gradle | 4 ++-- buildSrc/build.gradle | 2 +- demos/build.gradle | 2 +- xml/build.gradle | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 3279df1edd..bb39b3f9fd 100644 --- a/build.gradle +++ b/build.gradle @@ -19,9 +19,9 @@ import org.gradle.internal.jvm.Jvm plugins { // This adds tasks to auto close or release nexus staging repos // see https://github.com/Codearte/gradle-nexus-staging-plugin/ - id 'io.codearte.nexus-staging' version '0.12.0' + id 'io.codearte.nexus-staging' version '0.21.0' // Declare spotbugs at the top - id 'com.github.spotbugs' version '1.6.9' apply false + id 'com.github.spotbugs' version '2.0.0' apply false // Declare osgi-ds at the top id 'org.jayware.osgi-ds' version '0.5.6' apply false //OWASP Security Vulnerability Detection diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index b9fee4365a..02d773ee04 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -20,5 +20,5 @@ repositories { jcenter() } dependencies { compile gradleApi() compile localGroovy() - compile 'com.github.jengelman.gradle.plugins:shadow:5.0.0' + compile 'com.github.jengelman.gradle.plugins:shadow:5.1.0' } diff --git a/demos/build.gradle b/demos/build.gradle index 0fcee799ff..6b498aec82 100644 --- a/demos/build.gradle +++ b/demos/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'org.gretty' version '2.2.0' apply false + id 'org.gretty' version '2.3.1' apply false } subprojects { diff --git a/xml/build.gradle b/xml/build.gradle index b97fa11712..ad10e11b16 100644 --- a/xml/build.gradle +++ b/xml/build.gradle @@ -15,7 +15,7 @@ */ plugins { - id 'org.unbroken-dome.xjc' version '1.4.1' + id 'org.unbroken-dome.xjc' version '1.4.3' } apply plugin: EhDeploy From d5ff4a498f21055bef8aa9a31642a163ceea07a4 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 2 Aug 2019 13:47:14 -0400 Subject: [PATCH 169/372] Execute tests in parallel --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index bb39b3f9fd..4d02cf4ad9 100644 --- a/build.gradle +++ b/build.gradle @@ -214,6 +214,7 @@ subprojects { } tasks.withType(Test) { executable = testJava.javaExecutable + maxParallelForks 64 } tasks.withType(Javadoc) { options.addStringOption('Xdoclint:none', '-quiet') From 3ef2826c542d032db9009270ec0389b09b39acf9 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 5 Aug 2019 09:21:41 -0400 Subject: [PATCH 170/372] Eliminate tempus-fugit as a dependency --- clustered/integration-test/build.gradle | 4 ---- .../org/ehcache/clustered/sync/PassiveSyncTest.java | 11 +++++------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index 8bfc680750..c0e86fdaf5 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -38,10 +38,6 @@ dependencies { testRuntimeOnly project(':clustered:clustered-dist') testImplementation (group:'org.terracotta.internal', name:'galvan-support', version: terracottaCoreVersion) - testImplementation (group:'com.google.code.tempus-fugit', name:'tempus-fugit', version:'1.1') { - exclude group:'junit', module:'junit' - exclude group:'org.hamcrest', module:'hamcrest-core' - } testImplementation group: 'javax.cache', name: 'cache-api', version: jcacheVersion serverLibs ("org.terracotta.management.dist:mnm-server:$terracottaPlatformVersion") { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java index 2d357063bb..8de289a448 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java @@ -34,11 +34,9 @@ import java.io.File; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import static com.google.code.tempusfugit.temporal.Duration.seconds; -import static com.google.code.tempusfugit.temporal.Timeout.timeout; -import static com.google.code.tempusfugit.temporal.WaitFor.waitOrTimeout; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; @@ -89,10 +87,11 @@ public void testSync() throws Exception { CLUSTER.getClusterControl().terminateActive(); CLUSTER.getClusterControl().waitForActive(); - // Sometimes the new passive believes there is a second connection and we have to wait for the full reconnect window before getting a result - waitOrTimeout(() -> "value-5".equals(cache.get(-5L)), timeout(seconds(130))); + for (long end = System.nanoTime() + TimeUnit.SECONDS.toNanos(130); cache.get(0L) == null && System.nanoTime() < end; ) { + Thread.sleep(100); + } - for (long i = -4; i < 5; i++) { + for (long i = -5; i < 5; i++) { assertThat(cache.get(i), equalTo("value" + i)); } } finally { From f40e59397049786bd558d08ec3cfd45eac93b576 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 2 Aug 2019 20:19:20 -0400 Subject: [PATCH 171/372] Execute failover tests in parallel --- .../clustered/EventsFailureBehaviorTest.java | 17 +- .../clustered/TerminatedServerTest.java | 166 ++++----------- ...onReadWriteLockPassiveIntegrationTest.java | 21 +- .../AfterFailoverManagementServiceTest.java | 1 + .../ClusteredStatisticsCountTest.java | 1 + ...dCacheOpsReplicationMultiThreadedTest.java | 66 +++--- ...BasicClusteredCacheOpsReplicationTest.java | 60 +++--- ...OpsReplicationWithMultipleClientsTest.java | 67 +++--- .../BasicLifeCyclePassiveReplicationTest.java | 12 +- .../clustered/util/ParallelTestCluster.java | 198 ++++++++++++++++++ .../util/runners/ExecutorScheduler.java | 48 +++++ .../clustered/util/runners/Parallel.java | 29 +++ .../util/runners/ParallelParameterized.java | 34 +++ ...icClusteredWriteBehindMultiClientTest.java | 4 +- .../BasicClusteredWriteBehindTest.java | 2 +- ...WriteBehindWithPassiveMultiClientTest.java | 4 +- ...icClusteredWriteBehindWithPassiveTest.java | 16 +- .../writebehind/WriteBehindTestBase.java | 8 +- 18 files changed, 508 insertions(+), 246 deletions(-) create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/util/ParallelTestCluster.java create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ExecutorScheduler.java create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/Parallel.java create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ParallelParameterized.java diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index d69af161f8..379cf1bca9 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -21,6 +21,8 @@ import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.reconnect.ThrowingResiliencyStrategy; +import org.ehcache.clustered.util.ParallelTestCluster; +import org.ehcache.clustered.util.runners.Parallel; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheEventListenerConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; @@ -33,8 +35,12 @@ import org.ehcache.expiry.ExpiryPolicy; import org.junit.After; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; import org.terracotta.testing.rules.Cluster; import java.io.File; @@ -53,6 +59,7 @@ import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +@RunWith(Parallel.class) public class EventsFailureBehaviorTest extends ClusteredTests { private static final int KEYS = 500; @@ -65,9 +72,11 @@ public class EventsFailureBehaviorTest extends ClusteredTests { + "" + "\n"; + @ClassRule @Rule + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build()); @Rule - public Cluster CLUSTER = - newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + public final TestName testName = new TestName(); + private PersistentCacheManager cacheManager1; private PersistentCacheManager cacheManager2; @@ -77,11 +86,11 @@ public void waitForActive() throws Exception { CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); cacheManager1 = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/event-cm")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve(testName.getMethodName())) .autoCreate(s -> s.defaultServerResource("primary-server-resource"))).build(true); cacheManager2 = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/event-cm")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve(testName.getMethodName())) .autoCreate(s -> s.defaultServerResource("primary-server-resource"))).build(true); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java index 52c46d8b83..9733522d6b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java @@ -16,8 +16,6 @@ package org.ehcache.clustered; -import com.google.code.tempusfugit.concurrency.ConcurrentTestRunner; - import org.assertj.core.api.ThrowableAssertAlternative; import org.ehcache.Cache; import org.ehcache.CacheManager; @@ -28,6 +26,8 @@ import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; +import org.ehcache.clustered.util.ParallelTestCluster; +import org.ehcache.clustered.util.runners.Parallel; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; @@ -42,7 +42,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExternalResource; -import org.junit.rules.RuleChain; import org.junit.rules.TestName; import org.junit.rules.TestRule; import org.junit.runner.Description; @@ -63,7 +62,6 @@ import java.util.Map; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; -import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -84,40 +82,11 @@ // and stopping a server for each test. Each test and the environment supporting it must have // no side effects which can affect another test. // ============================================================================================= -@RunWith(ConcurrentTestRunner.class) +@RunWith(Parallel.class) public class TerminatedServerTest extends ClusteredTests { private static final int CLIENT_MAX_PENDING_REQUESTS = 5; - /** - * Determines the level of test concurrency. The number of allowed concurrent tests - * is set in {@link #setConcurrency()}. - */ - private static final Semaphore TEST_PERMITS = new Semaphore(0); - - @ClassRule - public static final TestCounter TEST_COUNTER = new TestCounter(); - - @BeforeClass - public static void setConcurrency() { - int availableProcessors = Runtime.getRuntime().availableProcessors(); - int testCount = TEST_COUNTER.getTestCount(); - /* - * Some build environments can't reliably handle running tests in this class concurrently. - * If the 'disable.concurrent.tests' system property is 'true', restrict the tests to - * single operation using a single test permit. - */ - boolean disableConcurrentTests = Boolean.getBoolean("disable.concurrent.tests"); - if (disableConcurrentTests) { - TEST_PERMITS.release(1); - } else { - TEST_PERMITS.release(Math.min(Math.max(1, testCount / 2), availableProcessors)); - } - System.out.format("TerminatedServerTest:" + - " disableConcurrentTests=%b, testCount=%d, availableProcessors=%d, TEST_PERMITS.availablePermits()=%d%n", - disableConcurrentTests, testCount, availableProcessors, TEST_PERMITS.availablePermits()); - } - private static final String RESOURCE_CONFIG = "" + "" @@ -169,34 +138,15 @@ private ThrowableAssertAlternative assertExceptionOccur .isThrownBy(() -> task.run()); } - private static Cluster createCluster() { - try { - return newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); - } catch (IllegalArgumentException e) { - assumeNoException(e); - return null; - } - } - + @ClassRule @Rule + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build()); @Rule public final TestName testName = new TestName(); - // Included in 'ruleChain' below. - private final Cluster cluster = createCluster(); - - - // The TestRule.apply method is called on the inner-most Rule first with the result being passed to each - // successively outer rule until the outer-most rule is reached. For ExternalResource rules, the before - // method of each rule is called from outer-most rule to inner-most rule; the after method is called from - // inner-most to outer-most. - @Rule - public final RuleChain ruleChain = RuleChain - .outerRule(new TestConcurrencyLimiter()) - .around(cluster); - @Before public void waitForActive() throws Exception { - cluster.getClusterControl().waitForActive(); + CLUSTER.getClusterControl().startAllServers(); + CLUSTER.getClusterControl().waitForActive(); } /** @@ -206,12 +156,12 @@ public void waitForActive() throws Exception { public void testTerminationBeforeCacheManagerClose() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); - cluster.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().terminateAllServers(); new TimeLimitedTask(10, TimeUnit.SECONDS) { @Override @@ -228,7 +178,7 @@ Void runTask() throws Exception { public void testTerminationBeforeCacheManagerCloseWithCaches() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, @@ -237,7 +187,7 @@ public void testTerminationBeforeCacheManagerCloseWithCaches() throws Exception PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); - cluster.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().terminateAllServers(); cacheManager.close(); @@ -246,12 +196,12 @@ public void testTerminationBeforeCacheManagerCloseWithCaches() throws Exception @Test public void testTerminationBeforeCacheManagerRetrieve() throws Exception { // Close all servers - cluster.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().terminateAllServers(); // Try to retrieve an entity (that doesn't exist but I don't care... the server is not running anyway CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().connection(Duration.ofSeconds(1))) // Need a connection timeout shorter than the TimeLimitedTask timeout .expecting(server -> server.defaultServerResource("primary-server-resource"))); PersistentCacheManager cacheManagerExisting = clusteredCacheManagerBuilder.build(false); @@ -275,7 +225,7 @@ Void runTask() { public void testTerminationBeforeCacheManagerDestroyCache() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, @@ -291,7 +241,7 @@ public void testTerminationBeforeCacheManagerDestroyCache() throws Exception { cacheManager.removeCache("simple-cache"); - cluster.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().terminateAllServers(); assertExceptionOccurred(CachePersistenceException.class, new TimeLimitedTask(10, TimeUnit.SECONDS) { @@ -308,12 +258,12 @@ Void runTask() throws Exception { public void testTerminationBeforeCacheCreate() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); - cluster.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().terminateAllServers(); assertExceptionOccurred(IllegalStateException.class, new TimeLimitedTask>(10, TimeUnit.SECONDS) { @@ -332,7 +282,7 @@ Cache runTask() throws Exception { public void testTerminationBeforeCacheRemove() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, @@ -341,7 +291,7 @@ public void testTerminationBeforeCacheRemove() throws Exception { PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); - cluster.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().terminateAllServers(); cacheManager.removeCache("simple-cache"); } @@ -350,7 +300,7 @@ public void testTerminationBeforeCacheRemove() throws Exception { public void testTerminationThenGet() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().read(Duration.of(1, ChronoUnit.SECONDS)).build()) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", @@ -367,7 +317,7 @@ public void testTerminationThenGet() throws Exception { assertThat(cache.get(2L)).isNotNull(); - cluster.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().terminateAllServers(); String value = new TimeLimitedTask(5, TimeUnit.SECONDS) { @Override @@ -383,7 +333,7 @@ String runTask() throws Exception { public void testTerminationThenContainsKey() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().read(Duration.of(1, ChronoUnit.SECONDS)).build()) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", @@ -400,7 +350,7 @@ public void testTerminationThenContainsKey() throws Exception { assertThat(cache.containsKey(2L)).isTrue(); - cluster.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().terminateAllServers(); boolean value = new TimeLimitedTask(5, TimeUnit.SECONDS) { @Override @@ -417,7 +367,7 @@ Boolean runTask() throws Exception { public void testTerminationThenIterator() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().read(Duration.of(1, ChronoUnit.SECONDS)).build()) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", @@ -432,7 +382,7 @@ public void testTerminationThenIterator() throws Exception { cache.put(2L, "deux"); cache.put(3L, "trois"); - cluster.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().terminateAllServers(); Iterator> value = new TimeLimitedTask>>(5, TimeUnit.SECONDS) { @Override @@ -448,7 +398,7 @@ Iterator> runTask() throws Exception { public void testTerminationThenPut() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().write(Duration.of(1, ChronoUnit.SECONDS)).build()) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", @@ -463,7 +413,7 @@ public void testTerminationThenPut() throws Exception { cache.put(2L, "deux"); cache.put(3L, "trois"); - cluster.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().terminateAllServers(); // The resilience strategy will pick it up and not exception is thrown new TimeLimitedTask(10, TimeUnit.SECONDS) { @@ -479,7 +429,7 @@ Void runTask() throws Exception { public void testTerminationThenPutIfAbsent() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().write(Duration.of(1, ChronoUnit.SECONDS)).build()) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", @@ -494,7 +444,7 @@ public void testTerminationThenPutIfAbsent() throws Exception { cache.put(2L, "deux"); cache.put(3L, "trois"); - cluster.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().terminateAllServers(); // The resilience strategy will pick it up and not exception is thrown new TimeLimitedTask(10, TimeUnit.SECONDS) { @@ -509,7 +459,7 @@ String runTask() throws Exception { public void testTerminationThenRemove() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().write(Duration.of(1, ChronoUnit.SECONDS)).build()) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", @@ -524,7 +474,7 @@ public void testTerminationThenRemove() throws Exception { cache.put(2L, "deux"); cache.put(3L, "trois"); - cluster.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().terminateAllServers(); new TimeLimitedTask(10, TimeUnit.SECONDS) { @Override @@ -541,7 +491,7 @@ public void testTerminationThenClear() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .using(statisticsService) - .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().write(Duration.of(1, ChronoUnit.SECONDS)).build()) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", @@ -556,7 +506,7 @@ public void testTerminationThenClear() throws Exception { cache.put(2L, "deux"); cache.put(3L, "trois"); - cluster.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().terminateAllServers(); // The resilience strategy will pick it up and not exception is thrown new TimeLimitedTask(10, TimeUnit.SECONDS) { @@ -580,7 +530,7 @@ public void testTerminationFreezesTheClient() throws Exception { try(PersistentCacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(cluster.getConnectionURI().resolve("/MyCacheManagerName")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts() .read(readOperationTimeout)) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) @@ -593,7 +543,7 @@ public void testTerminationFreezesTheClient() throws Exception { Cache cache = cacheManager.getCache("simple-cache", Long.class, String.class); cache.put(1L, "un"); - cluster.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().terminateAllServers(); // Fill the inflight queue and check that we wait no longer than the read timeout for (int i = 0; i < CLIENT_MAX_PENDING_REQUESTS; i++) { @@ -620,52 +570,6 @@ private static void overrideProperty(Map oldProperties, String p tcProperties.setProperty(propertyName, propertyValue); } - /** - * Used as a {@link Rule @Rule} to limit the number of concurrently executing tests. - */ - private final class TestConcurrencyLimiter extends ExternalResource { - - @Override - protected void before() throws Throwable { - try { - TEST_PERMITS.acquire(); - } catch (InterruptedException e) { - throw new AssertionError(e); - } - } - - @Override - protected void after() { - TEST_PERMITS.release(); - } - } - - /** - * Used as a {@link org.junit.ClassRule @ClassRule} to determine the number of tests to - * be run from the class. - */ - private static final class TestCounter implements TestRule { - - private int testCount; - - @Override - public Statement apply(Statement base, Description description) { - int testCount = 0; - for (Description child : description.getChildren()) { - if (child.isTest()) { - testCount++; - } - } - this.testCount = testCount; - - return base; - } - - private int getTestCount() { - return testCount; - } - } - /** * Runs a method under control of a timeout. * diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java index 619bfcf010..970417433d 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java @@ -24,9 +24,15 @@ import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock.Hold; +import org.ehcache.clustered.util.ParallelTestCluster; +import org.ehcache.clustered.util.runners.Parallel; import org.junit.Before; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; import org.terracotta.connection.Connection; import org.terracotta.testing.rules.Cluster; @@ -34,10 +40,13 @@ import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +@RunWith(Parallel.class) public class VoltronReadWriteLockPassiveIntegrationTest extends ClusteredTests { - @ClassRule - public static Cluster CLUSTER = newCluster(2).in(new File("build/cluster")).build(); + @ClassRule @Rule + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(new File("build/cluster")).build()); + @Rule + public final TestName testName = new TestName(); @Before public void waitForActive() throws Exception { @@ -48,7 +57,7 @@ public void waitForActive() throws Exception { @Test public void testSingleThreadSingleClientInteraction() throws Throwable { try (Connection client = CLUSTER.newConnection()) { - VoltronReadWriteLock lock = new VoltronReadWriteLock(client, "test"); + VoltronReadWriteLock lock = new VoltronReadWriteLock(client, testName.getMethodName()); Hold hold = lock.writeLock(); @@ -62,7 +71,7 @@ public void testSingleThreadSingleClientInteraction() throws Throwable { @Test public void testMultipleThreadsSingleConnection() throws Throwable { try (Connection client = CLUSTER.newConnection()) { - final VoltronReadWriteLock lock = new VoltronReadWriteLock(client, "test"); + final VoltronReadWriteLock lock = new VoltronReadWriteLock(client, testName.getMethodName()); Hold hold = lock.writeLock(); @@ -98,12 +107,12 @@ public void testMultipleThreadsSingleConnection() throws Throwable { public void testMultipleClients() throws Throwable { try (Connection clientA = CLUSTER.newConnection(); Connection clientB = CLUSTER.newConnection()) { - VoltronReadWriteLock lockA = new VoltronReadWriteLock(clientA, "test"); + VoltronReadWriteLock lockA = new VoltronReadWriteLock(clientA, testName.getMethodName()); Hold hold = lockA.writeLock(); Future waiter = async(() -> { - new VoltronReadWriteLock(clientB, "test").writeLock().unlock(); + new VoltronReadWriteLock(clientB, testName.getMethodName()).writeLock().unlock(); return null; }); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AfterFailoverManagementServiceTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AfterFailoverManagementServiceTest.java index 159eaace68..9ee18c315b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AfterFailoverManagementServiceTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AfterFailoverManagementServiceTest.java @@ -17,6 +17,7 @@ import org.ehcache.clustered.util.BeforeAll; import org.junit.FixMethodOrder; +import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java index daeb48aa5c..2f3d354cee 100755 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java @@ -79,6 +79,7 @@ public void countTest() throws Exception { (cacheHitCount != CACHE_HIT_COUNT) && (clusteredHitCount != CLUSTERED_HIT_COUNT) && (cacheMissCount != CACHE_MISS_COUNT) && (clusteredMissCount != CLUSTERED_MISS_COUNT)); + Assert.assertThat(cacheHitCount,is(CACHE_HIT_COUNT)); Assert.assertThat(clusteredHitCount,is(CLUSTERED_HIT_COUNT)); Assert.assertThat(cacheMissCount,is(CACHE_MISS_COUNT)); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index 77d9689f8d..bd630d6ed1 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -25,6 +25,8 @@ import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.common.Consistency; +import org.ehcache.clustered.util.runners.ParallelParameterized; +import org.ehcache.clustered.util.ParallelTestCluster; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; @@ -35,9 +37,11 @@ import org.junit.Before; import org.junit.ClassRule; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; import org.slf4j.Logger; @@ -75,7 +79,7 @@ * Note that fail-over is happening while client threads are still writing * Finally the same key set correctness is asserted. */ -@RunWith(Parameterized.class) +@RunWith(ParallelParameterized.class) public class BasicClusteredCacheOpsReplicationMultiThreadedTest extends ClusteredTests { private static final int NUM_OF_THREADS = 10; @@ -87,10 +91,10 @@ public class BasicClusteredCacheOpsReplicationMultiThreadedTest extends Clustere + "" + "\n"; - private static PersistentCacheManager CACHE_MANAGER1; - private static PersistentCacheManager CACHE_MANAGER2; - private static Cache CACHE1; - private static Cache CACHE2; + private PersistentCacheManager cacheManager1; + private PersistentCacheManager cacheManager2; + private Cache cache1; + private Cache cache2; @Parameters(name = "consistency={0}") public static Consistency[] data() { @@ -100,9 +104,10 @@ public static Consistency[] data() { @Parameter public Consistency cacheConsistency; - @ClassRule - public static Cluster CLUSTER = - newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + @ClassRule @Rule + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build()); + @Rule + public final TestName testName = new TestName(); private final Logger log = LoggerFactory.getLogger(getClass()); @@ -124,8 +129,8 @@ public void startServers() throws Exception { .read(Duration.ofMinutes(1)) .write(Duration.ofMinutes(1))) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); - CACHE_MANAGER1 = clusteredCacheManagerBuilder.build(true); - CACHE_MANAGER2 = clusteredCacheManagerBuilder.build(true); + cacheManager1 = clusteredCacheManagerBuilder.build(true); + cacheManager2 = clusteredCacheManagerBuilder.build(true); CacheConfiguration config = CacheConfigurationBuilder .newCacheConfigurationBuilder(Long.class, BlobValue.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(500, EntryUnit.ENTRIES) @@ -133,10 +138,10 @@ public void startServers() throws Exception { .withService(ClusteredStoreConfigurationBuilder.withConsistency(cacheConsistency)) .build(); - CACHE1 = CACHE_MANAGER1.createCache("clustered-cache", config); - CACHE2 = CACHE_MANAGER2.createCache("clustered-cache", config); + cache1 = cacheManager1.createCache(testName.getMethodName(), config); + cache2 = cacheManager2.createCache(testName.getMethodName(), config); - caches = Arrays.asList(CACHE1, CACHE2); + caches = Arrays.asList(cache1, cache2); } @After @@ -148,12 +153,11 @@ public void tearDown() throws Exception { if(!unprocessed.isEmpty()) { log.warn("Tearing down with {} unprocess task", unprocessed); } - if(CACHE_MANAGER1 != null && CACHE_MANAGER1.getStatus() != Status.UNINITIALIZED) { - CACHE_MANAGER1.close(); + if(cacheManager1 != null && cacheManager1.getStatus() != Status.UNINITIALIZED) { + cacheManager1.close(); } - if(CACHE_MANAGER2 != null && CACHE_MANAGER2.getStatus() != Status.UNINITIALIZED) { - CACHE_MANAGER2.close(); - CACHE_MANAGER2.destroy(); + if(cacheManager2 != null && cacheManager2.getStatus() != Status.UNINITIALIZED) { + cacheManager2.close(); } } @@ -173,8 +177,8 @@ public void testCRUD() throws Exception { //This step is to add values in local tier randomly to test invalidations happen correctly futures.add(executorService.submit(() -> universalSet.forEach(x -> { - CACHE1.get(x); - CACHE2.get(x); + cache1.get(x); + cache2.get(x); }))); CLUSTER.getClusterControl().terminateActive(); @@ -184,10 +188,10 @@ public void testCRUD() throws Exception { Set readKeysByCache1AfterFailOver = new HashSet<>(); Set readKeysByCache2AfterFailOver = new HashSet<>(); universalSet.forEach(x -> { - if (CACHE1.get(x) != null) { + if (cache1.get(x) != null) { readKeysByCache1AfterFailOver.add(x); } - if (CACHE2.get(x) != null) { + if (cache2.get(x) != null) { readKeysByCache2AfterFailOver.add(x); } }); @@ -216,8 +220,8 @@ public void testBulkOps() throws Exception { //This step is to add values in local tier randomly to test invalidations happen correctly futures.add(executorService.submit(() -> { universalSet.forEach(x -> { - CACHE1.get(x); - CACHE2.get(x); + cache1.get(x); + cache2.get(x); }); })); @@ -228,10 +232,10 @@ public void testBulkOps() throws Exception { Set readKeysByCache1AfterFailOver = new HashSet<>(); Set readKeysByCache2AfterFailOver = new HashSet<>(); universalSet.forEach(x -> { - if (CACHE1.get(x) != null) { + if (cache1.get(x) != null) { readKeysByCache1AfterFailOver.add(x); } - if (CACHE2.get(x) != null) { + if (cache2.get(x) != null) { readKeysByCache2AfterFailOver.add(x); } }); @@ -263,17 +267,17 @@ public void testClear() throws Exception { drainTasks(futures); universalSet.forEach(x -> { - CACHE1.get(x); - CACHE2.get(x); + cache1.get(x); + cache2.get(x); }); - Future clearFuture = executorService.submit(() -> CACHE1.clear()); + Future clearFuture = executorService.submit(() -> cache1.clear()); CLUSTER.getClusterControl().terminateActive(); clearFuture.get(); - universalSet.forEach(x -> assertThat(CACHE2.get(x), nullValue())); + universalSet.forEach(x -> assertThat(cache2.get(x), nullValue())); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java index 93aae3fad2..f1bf186b91 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java @@ -24,6 +24,8 @@ import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.common.Consistency; +import org.ehcache.clustered.util.runners.ParallelParameterized; +import org.ehcache.clustered.util.ParallelTestCluster; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; @@ -33,7 +35,10 @@ import org.junit.After; import org.junit.Before; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; @@ -54,19 +59,19 @@ import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -@RunWith(Parameterized.class) +@RunWith(ParallelParameterized.class) public class BasicClusteredCacheOpsReplicationTest extends ClusteredTests { private static final String RESOURCE_CONFIG = "" + "" - + "16" + + "32" + "" + "\n"; - private static PersistentCacheManager CACHE_MANAGER; - private static Cache CACHE1; - private static Cache CACHE2; + private PersistentCacheManager cacheManager; + private Cache cacheOne; + private Cache cacheTwo; @Parameters(name = "consistency={0}") public static Consistency[] data() { @@ -76,9 +81,11 @@ public static Consistency[] data() { @Parameter public Consistency cacheConsistency; - @ClassRule - public static Cluster CLUSTER = - newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + @ClassRule @Rule + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build()); + + @Rule + public final TestName testName = new TestName(); @Before public void startServers() throws Exception { @@ -92,28 +99,27 @@ public void startServers() throws Exception { .read(Duration.ofMinutes(1)) .write(Duration.ofMinutes(1))) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); - CACHE_MANAGER = clusteredCacheManagerBuilder.build(true); + cacheManager = clusteredCacheManagerBuilder.build(true); CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(100, EntryUnit.ENTRIES) - .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 4, MemoryUnit.MB))) + .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB))) .withService(ClusteredStoreConfigurationBuilder.withConsistency(cacheConsistency)) .build(); - CACHE1 = CACHE_MANAGER.createCache("clustered-cache", config); - CACHE2 = CACHE_MANAGER.createCache("another-cache", config); + cacheOne = cacheManager.createCache(testName.getMethodName() + "-1", config); + cacheTwo = cacheManager.createCache(testName.getMethodName() + "-2", config); } @After - public void tearDown() throws Exception { - CACHE_MANAGER.close(); - CACHE_MANAGER.destroy(); + public void tearDown() { + cacheManager.close(); } @Test public void testCRUD() throws Exception { List> caches = new ArrayList<>(); - caches.add(CACHE1); - caches.add(CACHE2); + caches.add(cacheOne); + caches.add(cacheTwo); caches.forEach(x -> { x.put(1L, "The one"); x.put(2L, "The two"); @@ -139,8 +145,8 @@ public void testCRUD() throws Exception { @Test public void testBulkOps() throws Exception { List> caches = new ArrayList<>(); - caches.add(CACHE1); - caches.add(CACHE2); + caches.add(cacheOne); + caches.add(cacheTwo); Map entriesMap = new HashMap<>(); entriesMap.put(1L, "one"); @@ -169,8 +175,8 @@ public void testBulkOps() throws Exception { @Test public void testCAS() throws Exception { List> caches = new ArrayList<>(); - caches.add(CACHE1); - caches.add(CACHE2); + caches.add(cacheOne); + caches.add(cacheTwo); caches.forEach(cache -> { assertThat(cache.putIfAbsent(1L, "one"), nullValue()); assertThat(cache.putIfAbsent(2L, "two"), nullValue()); @@ -192,8 +198,8 @@ public void testCAS() throws Exception { public void testClear() throws Exception { List> caches = new ArrayList<>(); - caches.add(CACHE1); - caches.add(CACHE2); + caches.add(cacheOne); + caches.add(cacheTwo); Map entriesMap = new HashMap<>(); entriesMap.put(1L, "one"); @@ -215,13 +221,13 @@ public void testClear() throws Exception { assertThat(all.get(6L), is("six")); }); - CACHE1.clear(); - CACHE2.clear(); + cacheOne.clear(); + cacheTwo.clear(); CLUSTER.getClusterControl().terminateActive(); - keySet.forEach(x -> assertThat(CACHE1.get(x), nullValue())); - keySet.forEach(x -> assertThat(CACHE2.get(x), nullValue())); + keySet.forEach(x -> assertThat(cacheOne.get(x), nullValue())); + keySet.forEach(x -> assertThat(cacheTwo.get(x), nullValue())); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java index 5fcc7cf13a..7508454da2 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java @@ -24,6 +24,8 @@ import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.common.Consistency; +import org.ehcache.clustered.util.runners.ParallelParameterized; +import org.ehcache.clustered.util.ParallelTestCluster; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; @@ -34,9 +36,11 @@ import org.junit.Before; import org.junit.ClassRule; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; import org.terracotta.testing.rules.Cluster; @@ -62,7 +66,7 @@ /** * The point of this test is to assert proper data read after fail-over handling. */ -@RunWith(Parameterized.class) +@RunWith(ParallelParameterized.class) public class BasicClusteredCacheOpsReplicationWithMultipleClientsTest extends ClusteredTests { private static final String RESOURCE_CONFIG = @@ -72,10 +76,10 @@ public class BasicClusteredCacheOpsReplicationWithMultipleClientsTest extends Cl + "" + "\n"; - private static PersistentCacheManager CACHE_MANAGER1; - private static PersistentCacheManager CACHE_MANAGER2; - private static Cache CACHE1; - private static Cache CACHE2; + private PersistentCacheManager cacheManager1; + private PersistentCacheManager cacheManager2; + private Cache cache1; + private Cache cache2; @Parameters(name = "consistency={0}") public static Consistency[] data() { @@ -85,9 +89,11 @@ public static Consistency[] data() { @Parameter public Consistency cacheConsistency; - @ClassRule - public static Cluster CLUSTER = - newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + @ClassRule @Rule + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build()); + + @Rule + public final TestName testName = new TestName(); @Before public void startServers() throws Exception { @@ -99,23 +105,22 @@ public void startServers() throws Exception { .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/crud-cm-replication")) .timeouts(TimeoutsBuilder.timeouts().read(Duration.ofSeconds(20)).write(Duration.ofSeconds(20))) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); - CACHE_MANAGER1 = clusteredCacheManagerBuilder.build(true); - CACHE_MANAGER2 = clusteredCacheManagerBuilder.build(true); + cacheManager1 = clusteredCacheManagerBuilder.build(true); + cacheManager2 = clusteredCacheManagerBuilder.build(true); CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, BlobValue.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(500, EntryUnit.ENTRIES) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 4, MemoryUnit.MB))) .withService(ClusteredStoreConfigurationBuilder.withConsistency(cacheConsistency)) .build(); - CACHE1 = CACHE_MANAGER1.createCache("clustered-cache", config); - CACHE2 = CACHE_MANAGER2.createCache("clustered-cache", config); + cache1 = cacheManager1.createCache(testName.getMethodName(), config); + cache2 = cacheManager2.createCache(testName.getMethodName(), config); } @After public void tearDown() throws Exception { - CACHE_MANAGER1.close(); - CACHE_MANAGER2.close(); - CACHE_MANAGER2.destroy(); + cacheManager1.close(); + cacheManager2.close(); } @Test(timeout=180000) @@ -124,13 +129,13 @@ public void testCRUD() throws Exception { LongStream longStream = random.longs(1000); Set added = new HashSet<>(); longStream.forEach(x -> { - CACHE1.put(x, new BlobValue()); + cache1.put(x, new BlobValue()); added.add(x); }); Set readKeysByCache2BeforeFailOver = new HashSet<>(); added.forEach(x -> { - if (CACHE2.get(x) != null) { + if (cache2.get(x) != null) { readKeysByCache2BeforeFailOver.add(x); } }); @@ -139,14 +144,14 @@ public void testCRUD() throws Exception { Set readKeysByCache1AfterFailOver = new HashSet<>(); added.forEach(x -> { - if (CACHE1.get(x) != null) { + if (cache1.get(x) != null) { readKeysByCache1AfterFailOver.add(x); } }); assertThat(readKeysByCache2BeforeFailOver.size(), greaterThanOrEqualTo(readKeysByCache1AfterFailOver.size())); - readKeysByCache1AfterFailOver.stream().filter(readKeysByCache2BeforeFailOver::contains).forEach(y -> assertThat(CACHE2.get(y), notNullValue())); + readKeysByCache1AfterFailOver.stream().filter(readKeysByCache2BeforeFailOver::contains).forEach(y -> assertThat(cache2.get(y), notNullValue())); } @@ -154,8 +159,8 @@ public void testCRUD() throws Exception { @Ignore //TODO: FIXME: FIX THIS RANDOMLY FAILING TEST public void testBulkOps() throws Exception { List> caches = new ArrayList<>(); - caches.add(CACHE1); - caches.add(CACHE2); + caches.add(cache1); + caches.add(cache2); Map entriesMap = new HashMap<>(); @@ -169,7 +174,7 @@ public void testBulkOps() throws Exception { Set readKeysByCache2BeforeFailOver = new HashSet<>(); keySet.forEach(x -> { - if (CACHE2.get(x) != null) { + if (cache2.get(x) != null) { readKeysByCache2BeforeFailOver.add(x); } }); @@ -178,22 +183,22 @@ public void testBulkOps() throws Exception { Set readKeysByCache1AfterFailOver = new HashSet<>(); keySet.forEach(x -> { - if (CACHE1.get(x) != null) { + if (cache1.get(x) != null) { readKeysByCache1AfterFailOver.add(x); } }); assertThat(readKeysByCache2BeforeFailOver.size(), greaterThanOrEqualTo(readKeysByCache1AfterFailOver.size())); - readKeysByCache1AfterFailOver.stream().filter(readKeysByCache2BeforeFailOver::contains).forEach(y -> assertThat(CACHE2.get(y), notNullValue())); + readKeysByCache1AfterFailOver.stream().filter(readKeysByCache2BeforeFailOver::contains).forEach(y -> assertThat(cache2.get(y), notNullValue())); } @Test(timeout=180000) public void testClear() throws Exception { List> caches = new ArrayList<>(); - caches.add(CACHE1); - caches.add(CACHE2); + caches.add(cache1); + caches.add(cache2); Map entriesMap = new HashMap<>(); @@ -207,19 +212,19 @@ public void testClear() throws Exception { Set readKeysByCache2BeforeFailOver = new HashSet<>(); keySet.forEach(x -> { - if (CACHE2.get(x) != null) { + if (cache2.get(x) != null) { readKeysByCache2BeforeFailOver.add(x); } }); - CACHE1.clear(); + cache1.clear(); CLUSTER.getClusterControl().terminateActive(); if (cacheConsistency == Consistency.STRONG) { - readKeysByCache2BeforeFailOver.forEach(x -> assertThat(CACHE2.get(x), nullValue())); + readKeysByCache2BeforeFailOver.forEach(x -> assertThat(cache2.get(x), nullValue())); } else { - readKeysByCache2BeforeFailOver.forEach(x -> assertThat(CACHE1.get(x), nullValue())); + readKeysByCache2BeforeFailOver.forEach(x -> assertThat(cache1.get(x), nullValue())); } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java index 911bf4a025..cb957c739e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java @@ -19,12 +19,16 @@ import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock; +import org.ehcache.clustered.util.ParallelTestCluster; +import org.ehcache.clustered.util.runners.Parallel; import org.ehcache.config.builders.CacheManagerBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; -import org.terracotta.testing.rules.Cluster; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; import java.io.File; @@ -39,6 +43,7 @@ import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +@RunWith(Parallel.class) public class BasicLifeCyclePassiveReplicationTest extends ClusteredTests { private static final String RESOURCE_CONFIG = @@ -48,9 +53,8 @@ public class BasicLifeCyclePassiveReplicationTest extends ClusteredTests { + "" + "\n"; - @ClassRule - public static Cluster CLUSTER = - newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + @ClassRule @Rule + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build()); @Before public void startServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/ParallelTestCluster.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/ParallelTestCluster.java new file mode 100644 index 0000000000..7b85ef2009 --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/ParallelTestCluster.java @@ -0,0 +1,198 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered.util; + +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; +import org.terracotta.connection.Connection; +import org.terracotta.connection.ConnectionException; +import org.terracotta.passthrough.IClusterControl; +import org.terracotta.testing.rules.Cluster; + +import java.net.URI; +import java.util.concurrent.Phaser; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +public class ParallelTestCluster extends Cluster { + + private final Cluster cluster; + private final IClusterControl control; + private final AtomicReference nextTask = new AtomicReference<>(); + + private final Phaser membership = new Phaser() { + @Override + protected boolean onAdvance(int phase, int registeredParties) { + activeCycle.bulkRegister(registeredParties); + return false; + } + }; + private final Phaser activeCycle = new Phaser() { + @Override + protected boolean onAdvance(int phase, int registeredParties) { + return false; + } + }; + + public ParallelTestCluster(Cluster cluster) { + this.cluster = cluster; + + IClusterControl underlyingControl = cluster.getClusterControl(); + this.control = new IClusterControl() { + @Override + public void waitForActive() throws Exception { + underlyingControl.waitForActive(); + } + + @Override + public void waitForRunningPassivesInStandby() throws Exception { + underlyingControl.waitForRunningPassivesInStandby(); + } + + @Override + public void startOneServer() { + request(ClusterTask.START_ONE_SERVER); + } + + @Override + public void startOneServerWithConsistency() { + request(ClusterTask.START_ONE_SERVER_WITH_CONSISTENCY); + } + + @Override + public void startAllServers() { + request(ClusterTask.START_ALL_SERVERS); + } + + @Override + public void startAllServersWithConsistency() { + request(ClusterTask.START_ALL_SERVERS_WITH_CONSISTENCY); + } + + @Override + public void terminateActive() { + request(ClusterTask.TERMINATE_ACTIVE); + } + + @Override + public void terminateOnePassive() { + request(ClusterTask.TERMINATE_ONE_PASSIVE); + } + + @Override + public void terminateAllServers() { + request(ClusterTask.TERMINATE_ALL_SERVERS); + } + + private void request(ClusterTask task) { + try { + if (nextTask.compareAndSet(null, task)) { + activeCycle.awaitAdvanceInterruptibly(activeCycle.arrive()); + nextTask.getAndSet(null).accept(underlyingControl); + activeCycle.awaitAdvanceInterruptibly(activeCycle.arrive()); + } else { + ClusterTask requestedTask = nextTask.get(); + if (requestedTask.equals(task)) { + activeCycle.awaitAdvanceInterruptibly(activeCycle.arrive()); + activeCycle.awaitAdvanceInterruptibly(activeCycle.arrive()); + } else { + throw new AssertionError("Existing requested task is " + requestedTask); + } + } + } catch (InterruptedException e) { + throw new AssertionError(e); + } + } + }; + } + + @Override + public URI getConnectionURI() { + return cluster.getConnectionURI(); + } + + @Override + public String[] getClusterHostPorts() { + return cluster.getClusterHostPorts(); + } + + @Override + public Connection newConnection() throws ConnectionException { + return cluster.newConnection(); + } + + @Override + public IClusterControl getClusterControl() { + return control; + } + + @Override + public Statement apply(Statement base, Description description) { + if (description.isSuite()) { + return cluster.apply(base, description); + } else if (description.isTest()) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + membership.register(); + Thread.sleep(100); + membership.awaitAdvanceInterruptibly(membership.arrive()); + try { + activeCycle.awaitAdvanceInterruptibly(activeCycle.arrive()); + try { + base.evaluate(); + } finally { + activeCycle.arriveAndDeregister(); + } + } finally { + membership.arriveAndDeregister(); + } + } + }; + } else { + return base; + } + } + + enum ClusterTask implements Consumer { + START_ONE_SERVER(IClusterControl::startOneServer), + START_ONE_SERVER_WITH_CONSISTENCY(IClusterControl::startOneServerWithConsistency), + START_ALL_SERVERS(IClusterControl::startAllServers), + START_ALL_SERVERS_WITH_CONSISTENCY(IClusterControl::startAllServersWithConsistency), + TERMINATE_ACTIVE(IClusterControl::terminateActive), + TERMINATE_ONE_PASSIVE(IClusterControl::terminateOnePassive), + TERMINATE_ALL_SERVERS(IClusterControl::terminateAllServers); + + private final Task task; + + ClusterTask(Task task) { + this.task = task; + } + public void accept(IClusterControl control) { + try { + task.run(control); + } catch (Exception e) { + throw new AssertionError(e); + } + } + + interface Task { + void run(IClusterControl control) throws Exception; + } + } +} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ExecutorScheduler.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ExecutorScheduler.java new file mode 100644 index 0000000000..fc60a33b9a --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ExecutorScheduler.java @@ -0,0 +1,48 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered.util.runners; + +import org.junit.runners.model.RunnerScheduler; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class ExecutorScheduler implements RunnerScheduler { + + public final ExecutorService executor; + + public ExecutorScheduler(ExecutorService executor) { + this.executor = executor; + } + + @Override + public void schedule(Runnable childStatement) { + executor.execute(childStatement); + } + + @Override + public void finished() { + executor.shutdown(); + try { + if (!executor.awaitTermination(1, TimeUnit.DAYS)) { + throw new AssertionError(new TimeoutException()); + } + } catch (InterruptedException e) { + throw new AssertionError(e); + } + } +} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/Parallel.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/Parallel.java new file mode 100644 index 0000000000..60dd8797dd --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/Parallel.java @@ -0,0 +1,29 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered.util.runners; + +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.InitializationError; + +import static java.util.concurrent.Executors.newCachedThreadPool; + +public class Parallel extends BlockJUnit4ClassRunner { + + public Parallel(Class klass) throws InitializationError { + super(klass); + setScheduler(new ExecutorScheduler(newCachedThreadPool(r -> new Thread(r, "TestRunner-Thread-" + klass)))); + } +} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ParallelParameterized.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ParallelParameterized.java new file mode 100644 index 0000000000..32364286f7 --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ParallelParameterized.java @@ -0,0 +1,34 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered.util.runners; + +import org.junit.runners.Parameterized; +import org.junit.runners.ParentRunner; + +import static java.util.concurrent.Executors.newCachedThreadPool; + +public class ParallelParameterized extends Parameterized { + + public ParallelParameterized(Class klass) throws Throwable { + super(klass); + setScheduler(new ExecutorScheduler(newCachedThreadPool(r -> new Thread(r, "TestRunner-Thread-" + klass)))); + getChildren().forEach(child -> { + if (child instanceof ParentRunner) { + ((ParentRunner) child).setScheduler(new ExecutorScheduler(newCachedThreadPool(r -> new Thread(r, "TestRunner-Thread-" + r.toString())))); + } + }); + } +} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java index bb638b5e2f..bbc33a5327 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java @@ -50,8 +50,8 @@ public void setUp() throws Exception { cacheManager1 = createCacheManager(CLUSTER.getConnectionURI()); cacheManager2 = createCacheManager(CLUSTER.getConnectionURI()); - client1 = cacheManager1.getCache(CACHE_NAME, Long.class, String.class); - client2 = cacheManager2.getCache(CACHE_NAME, Long.class, String.class); + client1 = cacheManager1.getCache(testName.getMethodName(), Long.class, String.class); + client2 = cacheManager2.getCache(testName.getMethodName(), Long.class, String.class); } @After diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java index d89351e168..3d2d032fd7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java @@ -59,7 +59,7 @@ public void setUp() throws Exception { CLUSTER.getClusterControl().waitForActive(); cacheManager = createCacheManager(CLUSTER.getConnectionURI()); - cache = cacheManager.getCache(CACHE_NAME, Long.class, String.class); + cache = cacheManager.getCache(testName.getMethodName(), Long.class, String.class); } @After diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java index 73e2de1cf1..1897e70b7e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java @@ -51,8 +51,8 @@ public void setUp() throws Exception { cacheManager1 = createCacheManager(CLUSTER.getConnectionURI()); cacheManager2 = createCacheManager(CLUSTER.getConnectionURI()); - client1 = cacheManager1.getCache(CACHE_NAME, Long.class, String.class); - client2 = cacheManager2.getCache(CACHE_NAME, Long.class, String.class); + client1 = cacheManager1.getCache(testName.getMethodName(), Long.class, String.class); + client2 = cacheManager2.getCache(testName.getMethodName(), Long.class, String.class); } @After diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java index bc57ff166b..3a75e2d410 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java @@ -18,21 +18,28 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; +import org.ehcache.clustered.util.ParallelTestCluster; +import org.ehcache.clustered.util.runners.Parallel; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; import org.terracotta.testing.rules.Cluster; import java.io.File; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +@RunWith(Parallel.class) public class BasicClusteredWriteBehindWithPassiveTest extends WriteBehindTestBase { - @ClassRule - public static Cluster CLUSTER = - newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + @ClassRule @Rule + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster( + newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build() + ); private PersistentCacheManager cacheManager; private Cache cache; @@ -46,14 +53,13 @@ public void setUp() throws Exception { CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); cacheManager = createCacheManager(CLUSTER.getConnectionURI()); - cache = cacheManager.getCache(CACHE_NAME, Long.class, String.class); + cache = cacheManager.getCache(testName.getMethodName(), Long.class, String.class); } @After public void tearDown() throws Exception { if (cacheManager != null) { cacheManager.close(); - cacheManager.destroy(); } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java index 6d3dac4313..69739db8ef 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java @@ -31,6 +31,8 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.TestName; import java.net.URI; import java.time.Duration; @@ -51,11 +53,13 @@ public class WriteBehindTestBase extends ClusteredTests { + "" + "\n"; - static final String CACHE_NAME = "cache-1"; static final long KEY = 1L; private static final String FLUSH_QUEUE_MARKER = "FLUSH_QUEUE"; + @Rule + public final TestName testName = new TestName(); + private RecordingLoaderWriter loaderWriter; @Before @@ -110,7 +114,7 @@ PersistentCacheManager createCacheManager(URI clusterUri) { return CacheManagerBuilder .newCacheManagerBuilder() .with(cluster(clusterUri.resolve("/cm-wb")).timeouts(TimeoutsBuilder.timeouts().read(Duration.ofMinutes(1)).write(Duration.ofMinutes(1))).autoCreate(c -> c)) - .withCache(CACHE_NAME, cacheConfiguration) + .withCache(testName.getMethodName(), cacheConfiguration) .build(true); } } From bd26ffeb83d88eee759ca4dc6a914ff77362d7fa Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 5 Aug 2019 16:29:19 -0400 Subject: [PATCH 172/372] Analyze dependencies in aggregate to reduce redundant lookups --- build.gradle | 20 ++++++++++++-------- buildSrc/src/main/groovy/EhPomMangle.groovy | 4 ---- demos/build.gradle | 4 ---- docs/build.gradle | 5 ----- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/build.gradle b/build.gradle index 4d02cf4ad9..36e4b3a690 100644 --- a/build.gradle +++ b/build.gradle @@ -84,12 +84,23 @@ if (hasProperty('testVM')) { println "Using Test JVM $testJava [Version: $testJava.javaVersion.majorVersion]" } +apply plugin: 'org.owasp.dependencycheck' + +dependencyCheck { + failBuildOnCVSS = 0 + suppressionFile = 'config/owasp-supressions.xml' + skipConfigurations += ['checkstyle', 'spotbugs'] + skipProjects += [':docs', ':demos:00-NoCache', ':demos:01-CacheAside'] +} +tasks.register('check') { + dependsOn dependencyCheckAggregate +} + subprojects { apply plugin: 'java-library' apply plugin: 'checkstyle' apply plugin: 'com.github.spotbugs' apply plugin: 'jacoco' - apply plugin: 'org.owasp.dependencycheck' group = 'org.ehcache.modules' version = baseVersion @@ -200,13 +211,6 @@ subprojects { } } - dependencyCheck { - failBuildOnCVSS = 0 - skipConfigurations += ['checkstyle', 'spotbugs'] - suppressionFile = 'config/owasp-supressions.xml' - } - check.dependsOn(dependencyCheckAnalyze) - tasks.withType(AbstractCompile) { options.with { fork = true diff --git a/buildSrc/src/main/groovy/EhPomMangle.groovy b/buildSrc/src/main/groovy/EhPomMangle.groovy index 959b5e2b98..2bc761fdb9 100644 --- a/buildSrc/src/main/groovy/EhPomMangle.groovy +++ b/buildSrc/src/main/groovy/EhPomMangle.groovy @@ -55,10 +55,6 @@ class EhPomMangle implements Plugin { pomOnlyProvided } - project.dependencyCheck { - skipConfigurations += ['pomOnlyCompile', 'pomOnlyProvided'] - } - def artifactFiltering = { project.configurations.forEach { pom.scopeMappings.mappings.remove(it) diff --git a/demos/build.gradle b/demos/build.gradle index 6b498aec82..bbda989716 100644 --- a/demos/build.gradle +++ b/demos/build.gradle @@ -22,8 +22,4 @@ subprojects { runtimeOnly 'ch.qos.logback:logback-classic:1.2.3' runtimeOnly 'com.h2database:h2:1.4.196' } - - dependencyCheck { - skipConfigurations += configurations.matching{it.name.startsWith 'gretty'}.names - } } diff --git a/docs/build.gradle b/docs/build.gradle index 40dc996565..75616b5f46 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -59,8 +59,3 @@ tasks.register('developerDoc', AsciidoctorTask) { sourceDir file('src/docs/asciidoc/developer') outputDir file("$buildDir/asciidoc/developer") } - -dependencyCheck { - skip = true -} - From c607ba14d9a6be0f953ccebec2560ab826726edf Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 6 Aug 2019 11:23:21 -0400 Subject: [PATCH 173/372] Don't break iteration until all counts are ready --- .../clustered/management/ClusteredStatisticsCountTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java index b36616a8df..d51a15fff3 100755 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java @@ -86,8 +86,8 @@ public void countTest() throws Exception { } } } - } while( (cacheHitCount != CACHE_HIT_COUNT) && (clusteredHitCount != CLUSTERED_HIT_COUNT) && - (cacheMissCount != CACHE_MISS_COUNT) && (clusteredMissCount != CLUSTERED_MISS_COUNT)); + } while( (cacheHitCount != CACHE_HIT_COUNT) || (clusteredHitCount != CLUSTERED_HIT_COUNT) || + (cacheMissCount != CACHE_MISS_COUNT) || (clusteredMissCount != CLUSTERED_MISS_COUNT)); Assert.assertThat(cacheHitCount,is(CACHE_HIT_COUNT)); Assert.assertThat(clusteredHitCount,is(CLUSTERED_HIT_COUNT)); From 2bc5618da75c9407343d3927e2e373ee1dd02709 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 4 Sep 2019 17:51:08 -0400 Subject: [PATCH 174/372] CVE-2019-10086 : Substitute the vulnerable commons-beanutils 1.9.3 for the fixed 1.9.4 --- xml/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xml/build.gradle b/xml/build.gradle index 2c677e00ed..e2d3039d62 100644 --- a/xml/build.gradle +++ b/xml/build.gradle @@ -29,6 +29,10 @@ dependencies { xjcClasspath 'org.jvnet.jaxb2_commons:jaxb2-basics-annotate:1.1.0' } +configurations.xjcClasspath.resolutionStrategy.dependencySubstitution { + substitute module('commons-beanutils:commons-beanutils:1.9.3') with module('commons-beanutils:commons-beanutils:1.9.4') +} + test { if (testJava.javaVersion.isJava9Compatible()) { jvmArgs += ['--add-modules', 'java.xml.bind'] From ccf4b03196403fbe32e4d57e2b530459077c3305 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 4 Sep 2019 18:01:34 -0400 Subject: [PATCH 175/372] CVE-2019-15052 : Suppress (false positive) Gradle vulnerabilities --- config/owasp-supressions.xml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/config/owasp-supressions.xml b/config/owasp-supressions.xml index 5764563b32..66b53a94cd 100644 --- a/config/owasp-supressions.xml +++ b/config/owasp-supressions.xml @@ -1,12 +1,17 @@ + - ^pkg:maven/org\.ehcache.*@.*$ CVE-2019-11065 + + + ^pkg:maven/org\.ehcache.*@.*$ + CVE-2019-15052 + From f79a27d9343d372d35ef9a0afccaa45ced74e267 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Wed, 4 Sep 2019 16:54:39 -0700 Subject: [PATCH 176/372] bump tc-core version to latest --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 9c5a66f935..421ac06783 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ jaxbVersion = 2.3.1 # Terracotta clustered terracottaPlatformVersion = 5.7.3 terracottaApisVersion = 1.6.1 -terracottaCoreVersion = 5.6.4 +terracottaCoreVersion = 5.6.5 terracottaPassthroughTestingVersion = 1.6.1 # Test lib versions From f930f2663e010756ed45dbc6d306261b0c2fec7e Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 5 Sep 2019 08:59:25 -0400 Subject: [PATCH 177/372] Update readme for 3.8.1 release --- README.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index db1cd2aea4..2780a27eaf 100644 --- a/README.adoc +++ b/README.adoc @@ -12,9 +12,9 @@ For samples, documentation, and usage information, please see http://ehcache.org == Current release -We released 3.8.0 on July 19th 2019. +We released 3.8.1 on September 4th 2019. -The https://github.com/ehcache/ehcache3/releases/tag/v3.8.0[release notes] contain the links to the artifacts and the documentation to help you get started. +The https://github.com/ehcache/ehcache3/releases/tag/v3.8.1[release notes] contain the links to the artifacts and the documentation to help you get started. You should consider upgrading to 3.8.x as it does all previous 3.x do and more with a fully compatible API. From 8c5c7cd1eab971b0ad23c05d5390f581826f54b1 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 5 Sep 2019 15:02:20 -0400 Subject: [PATCH 178/372] Fixes #2694 : On reconnect failure switch out for a failing store proxy --- #azure-pipelines.yml# | 30 ++++ .../PerpetualCachePersistenceException.java | 49 +++++++ ...ClusterTierManagerClientEntityFactory.java | 3 +- .../service/DefaultClusteringService.java | 28 ++-- .../client/internal/store/ClusteredStore.java | 131 +++++++++--------- .../store/FailedReconnectStoreProxy.java | 66 +++++++++ .../store/ReconnectingServerStoreProxy.java | 2 +- .../store/SimpleClusterTierClientEntity.java | 2 +- .../ResourcePoolAllocationFailureTest.java | 3 +- .../reconnect/CacheManagerReconnectTest.java | 121 ++++++++++++++++ .../DefaultDiskResourceService.java | 5 +- .../ehcache/impl/persistence/FileUtils.java | 3 +- 12 files changed, 362 insertions(+), 81 deletions(-) create mode 100644 #azure-pipelines.yml# create mode 100644 api/src/main/java/org/ehcache/PerpetualCachePersistenceException.java create mode 100644 clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/FailedReconnectStoreProxy.java create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerReconnectTest.java diff --git a/#azure-pipelines.yml# b/#azure-pipelines.yml# new file mode 100644 index 0000000000..d482b40b9c --- /dev/null +++ b/#azure-pipelines.yml# @@ -0,0 +1,30 @@ +# +# Copyright Terracotta, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# See shared code location for steps and parameters: +# https://dev.azure.com/TerracottaCI/_git/terracotta + +resources: + repositories: + - repository: templates + type: git + name: terracotta/terracotta + +jobs: +- template: build-templates/gradle-common.yml@templates +- template: build-templates/gradle-common.yml@templates + parameters: + gradleOptions: -PtestVM= diff --git a/api/src/main/java/org/ehcache/PerpetualCachePersistenceException.java b/api/src/main/java/org/ehcache/PerpetualCachePersistenceException.java new file mode 100644 index 0000000000..a1ad043dfc --- /dev/null +++ b/api/src/main/java/org/ehcache/PerpetualCachePersistenceException.java @@ -0,0 +1,49 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache; + +/** + * Thrown to indicate a perpetual (non-transient) failure in a persistent cache manager. + *

+ * Receiving this exception indicates that future interactions with the throwing entity will continue to fail without + * corrective action. + * + * @see CachePersistenceException + */ +public class PerpetualCachePersistenceException extends CachePersistenceException { + + private static final long serialVersionUID = -5858875151420107041L; + + /** + * Creates a {@code PerpetualCachePersistenceException} with the provided message. + * + * @param message information about the exception + */ + public PerpetualCachePersistenceException(String message) { + super(message); + } + + /** + * Creates a {@code PerpetualCachePersistenceException} with the provided message and cause. + * + * @param message information about the exception + * @param cause the cause of this exception + */ + public PerpetualCachePersistenceException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java index 5e4ebcacb5..f4f2334914 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java @@ -17,6 +17,7 @@ package org.ehcache.clustered.client.internal; import org.ehcache.CachePersistenceException; +import org.ehcache.PerpetualCachePersistenceException; import org.ehcache.clustered.client.config.Timeouts; import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock; @@ -262,7 +263,7 @@ public ClusterTierClientEntity fetchOrCreateClusteredStoreEntity(String clusterT } catch (EntityAlreadyExistsException e) { // Ignore - entity exists } catch (EntityConfigurationException e) { - throw new CachePersistenceException("Unable to create cluster tier", e); + throw new PerpetualCachePersistenceException("Unable to create cluster tier", e); } catch (EntityException e) { throw new AssertionError(e); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java index 799e0b6f12..920b6a47f7 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java @@ -17,6 +17,7 @@ package org.ehcache.clustered.client.internal.service; import org.ehcache.CachePersistenceException; +import org.ehcache.PerpetualCachePersistenceException; import org.ehcache.clustered.client.config.ClusteredResourcePool; import org.ehcache.clustered.client.config.ClusteredResourceType; import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; @@ -283,7 +284,7 @@ public PersistenceSpaceIdentifier getPersistenceSpaceIdentifier(String name, Cac public void releasePersistenceSpaceIdentifier(PersistenceSpaceIdentifier identifier) throws CachePersistenceException { ClusteredCacheIdentifier clusterCacheIdentifier = (ClusteredCacheIdentifier) identifier; if (knownPersistenceSpaces.remove(clusterCacheIdentifier.getId()) == null) { - throw new CachePersistenceException("Unknown identifier: " + clusterCacheIdentifier); + throw new PerpetualCachePersistenceException("Unknown identifier: " + clusterCacheIdentifier); } } @@ -292,7 +293,7 @@ public StateRepository getStateRepositoryWithin(PersistenceSpaceIdentifier id ClusteredCacheIdentifier clusterCacheIdentifier = (ClusteredCacheIdentifier) identifier; ClusteredSpace clusteredSpace = knownPersistenceSpaces.get(clusterCacheIdentifier.getId()); if (clusteredSpace == null) { - throw new CachePersistenceException("Clustered space not found for identifier: " + clusterCacheIdentifier); + throw new PerpetualCachePersistenceException("Clustered space not found for identifier: " + clusterCacheIdentifier); } ConcurrentMap stateRepositories = clusteredSpace.stateRepositories; ClusterStateRepository currentRepo = stateRepositories.get(name); @@ -416,15 +417,24 @@ public ServerStoreProxy getServerStoreProxy(final ClusteredCacheIdentifie } try { - storeClientEntity.validate(clientStoreConfiguration); - } catch (ClusterTierException e) { - serverStoreProxy.close(); - throw new CachePersistenceException("Unable to create cluster tier proxy '" + cacheIdentifier.getId() + "' for entity '" + entityIdentifier + "'", e); - } catch (TimeoutException e) { - serverStoreProxy.close(); - throw new CachePersistenceException("Unable to create cluster tier proxy '" + try { + storeClientEntity.validate(clientStoreConfiguration); + } catch (ClusterTierValidationException e) { + throw new PerpetualCachePersistenceException("Unable to create cluster tier proxy '" + cacheIdentifier.getId() + "' for entity '" + entityIdentifier + "'", e); + } catch (ClusterTierException e) { + throw new CachePersistenceException("Unable to create cluster tier proxy '" + cacheIdentifier.getId() + "' for entity '" + entityIdentifier + "'", e); + } catch (TimeoutException e) { + throw new CachePersistenceException("Unable to create cluster tier proxy '" + cacheIdentifier.getId() + "' for entity '" + entityIdentifier + "'; validate operation timed out", e); + } + } catch (Throwable t) { + try { + serverStoreProxy.close(); + } catch (Throwable u) { + t.addSuppressed(u); + } + throw t; } return serverStoreProxy; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index e290f42f2b..7cb12342c4 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -18,6 +18,7 @@ import org.ehcache.Cache; import org.ehcache.CachePersistenceException; +import org.ehcache.PerpetualCachePersistenceException; import org.ehcache.clustered.client.config.ClusteredResourceType; import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; import org.ehcache.clustered.client.internal.store.ServerStoreProxy.ServerCallback; @@ -646,6 +647,14 @@ public void releaseStore(final Store resource) { @Override public void initStore(final Store resource) { + try { + initStoreInternal(resource); + } catch (CachePersistenceException e) { + throw new RuntimeException(e); + } + } + + private void initStoreInternal(Store resource) throws CachePersistenceException { reconnectLock.lock(); try { StoreConfig storeConfig = createdStores.get(resource); @@ -654,87 +663,79 @@ public void initStore(final Store resource) { } final ClusteredStore clusteredStore = (ClusteredStore) resource; ClusteredCacheIdentifier cacheIdentifier = storeConfig.getCacheIdentifier(); - try { - ServerStoreProxy storeProxy = clusteringService.getServerStoreProxy(cacheIdentifier, storeConfig.getStoreConfig(), storeConfig.getConsistency(), - new ServerCallback() { - @Override - public void onInvalidateHash(long hash) { - EvictionOutcome result = EvictionOutcome.SUCCESS; - clusteredStore.evictionObserver.begin(); - if (clusteredStore.invalidationValve != null) { - try { - LOGGER.debug("CLIENT: calling invalidation valve for hash {}", hash); - clusteredStore.invalidationValve.invalidateAllWithHash(hash); - } catch (StoreAccessException sae) { - //TODO: what should be done here? delegate to resilience strategy? - LOGGER.error("Error invalidating hash {}", hash, sae); - result = EvictionOutcome.FAILURE; - } - } - clusteredStore.evictionObserver.end(result); - } - - @Override - public void onInvalidateAll() { - if (clusteredStore.invalidationValve != null) { - try { - LOGGER.debug("CLIENT: calling invalidation valve for all"); - clusteredStore.invalidationValve.invalidateAll(); - } catch (StoreAccessException sae) { - //TODO: what should be done here? delegate to resilience strategy? - LOGGER.error("Error invalidating all", sae); - } - } - } - - @Override - public Chain compact(Chain chain) { - return clusteredStore.resolver.applyOperation(chain, clusteredStore.timeSource.getTimeMillis()); - } - }); - ReconnectingServerStoreProxy reconnectingServerStoreProxy = new ReconnectingServerStoreProxy(storeProxy, () -> { - Runnable reconnectTask = () -> { - reconnectLock.lock(); + ServerStoreProxy storeProxy = clusteringService.getServerStoreProxy(cacheIdentifier, storeConfig.getStoreConfig(), storeConfig.getConsistency(), + new ServerCallback() { + @Override + public void onInvalidateHash(long hash) { + EvictionOutcome result = EvictionOutcome.SUCCESS; + clusteredStore.evictionObserver.begin(); + if (clusteredStore.invalidationValve != null) { + try { + LOGGER.debug("CLIENT: calling invalidation valve for hash {}", hash); + clusteredStore.invalidationValve.invalidateAllWithHash(hash); + } catch (StoreAccessException sae) { + //TODO: what should be done here? delegate to resilience strategy? + LOGGER.error("Error invalidating hash {}", hash, sae); + result = EvictionOutcome.FAILURE; + } + } + clusteredStore.evictionObserver.end(result); + } + + @Override + public void onInvalidateAll() { + if (clusteredStore.invalidationValve != null) { + try { + LOGGER.debug("CLIENT: calling invalidation valve for all"); + clusteredStore.invalidationValve.invalidateAll(); + } catch (StoreAccessException sae) { + //TODO: what should be done here? delegate to resilience strategy? + LOGGER.error("Error invalidating all", sae); + } + } + } + + @Override + public Chain compact(Chain chain) { + return clusteredStore.resolver.applyOperation(chain, clusteredStore.timeSource.getTimeMillis()); + } + }); + ReconnectingServerStoreProxy reconnectingServerStoreProxy = new ReconnectingServerStoreProxy(storeProxy, () -> { + Runnable reconnectTask = () -> { + String cacheId = cacheIdentifier.getId(); + reconnectLock.lock(); + try { try { //TODO: handle race between disconnect event and connection closed exception being thrown // this guy should wait till disconnect event processing is complete. - String cacheId = clusteredStore.storeProxy.getCacheId(); LOGGER.info("Cache {} got disconnected from cluster, reconnecting", cacheId); clusteringService.releaseServerStoreProxy(clusteredStore.storeProxy, true); - initStore(clusteredStore); + initStoreInternal(clusteredStore); LOGGER.info("Cache {} got reconnected to cluster", cacheId); - } finally { - reconnectLock.unlock(); + } catch (PerpetualCachePersistenceException t) { + LOGGER.error("Cache {} failed reconnecting to cluster (failure is perpetual)", cacheId, t); + clusteredStore.storeProxy = new FailedReconnectStoreProxy(cacheId, t); } - }; - CompletableFuture.runAsync(reconnectTask); - }); - clusteredStore.storeProxy = reconnectingServerStoreProxy; - } catch (CachePersistenceException e) { - throw new RuntimeException("Unable to create cluster tier proxy - " + cacheIdentifier, e); - } + } catch (CachePersistenceException e) { + throw new RuntimeException(e); + } finally { + reconnectLock.unlock(); + } + }; + CompletableFuture.runAsync(reconnectTask); + }); + clusteredStore.storeProxy = reconnectingServerStoreProxy; Serializer keySerializer = clusteredStore.codec.getKeySerializer(); if (keySerializer instanceof StatefulSerializer) { - StateRepository stateRepository; - try { - stateRepository = clusteringService.getStateRepositoryWithin(cacheIdentifier, cacheIdentifier.getId() + "-Key"); - } catch (CachePersistenceException e) { - throw new RuntimeException(e); - } + StateRepository stateRepository = clusteringService.getStateRepositoryWithin(cacheIdentifier, cacheIdentifier.getId() + "-Key"); ((StatefulSerializer) keySerializer).init(stateRepository); } Serializer valueSerializer = clusteredStore.codec.getValueSerializer(); if (valueSerializer instanceof StatefulSerializer) { - StateRepository stateRepository; - try { - stateRepository = clusteringService.getStateRepositoryWithin(cacheIdentifier, cacheIdentifier.getId() + "-Value"); - } catch (CachePersistenceException e) { - throw new RuntimeException(e); - } + StateRepository stateRepository = clusteringService.getStateRepositoryWithin(cacheIdentifier, cacheIdentifier.getId() + "-Value"); ((StatefulSerializer) valueSerializer).init(stateRepository); } - } finally { reconnectLock.unlock(); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/FailedReconnectStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/FailedReconnectStoreProxy.java new file mode 100644 index 0000000000..599679597f --- /dev/null +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/FailedReconnectStoreProxy.java @@ -0,0 +1,66 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered.client.internal.store; + +import org.ehcache.clustered.common.internal.store.Chain; + +import java.nio.ByteBuffer; + +public class FailedReconnectStoreProxy implements ServerStoreProxy { + private final Throwable failure; + private final String cacheId; + + public FailedReconnectStoreProxy(String cacheId, Throwable failure) { + this.cacheId = cacheId; + this.failure = failure; + } + + @Override + public Chain get(long key) { + throw new RuntimeException("Cache " + getCacheId() + " failed reconnecting to cluster", failure); + } + + @Override + public void append(long key, ByteBuffer payLoad) { + throw new RuntimeException("Cache " + getCacheId() + " failed reconnecting to cluster", failure); + } + + @Override + public Chain getAndAppend(long key, ByteBuffer payLoad) { + throw new RuntimeException("Cache " + getCacheId() + " failed reconnecting to cluster", failure); + } + + @Override + public void replaceAtHead(long key, Chain expect, Chain update) { + throw new RuntimeException("Cache " + getCacheId() + " failed reconnecting to cluster", failure); + } + + @Override + public void clear() { + throw new RuntimeException("Cache " + getCacheId() + " failed reconnecting to cluster", failure); + } + + @Override + public String getCacheId() { + return cacheId; + } + + @Override + public void close() { + //ignore + } +} diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java index 3028398a1f..f228224027 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java @@ -31,7 +31,7 @@ public class ReconnectingServerStoreProxy implements ServerStoreProxy { public ReconnectingServerStoreProxy(ServerStoreProxy serverStoreProxy, Runnable onReconnect) { this.delegate = serverStoreProxy; - this.delegateRef = new AtomicReference(serverStoreProxy); + this.delegateRef = new AtomicReference<>(serverStoreProxy); this.onReconnect = onReconnect; } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java index 860e7d60bc..871feab498 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java @@ -168,7 +168,7 @@ public void addResponseListener(Class respo } @Override - public void validate(ServerStoreConfiguration clientStoreConfiguration) throws ClusterTierException, TimeoutException { + public void validate(ServerStoreConfiguration clientStoreConfiguration) throws ClusterTierValidationException, TimeoutException { try { invokeInternalAndWait(endpoint.beginInvoke(), timeouts.getConnectionTimeout(), messageFactory.validateServerStore(storeIdentifier , clientStoreConfiguration), false); } catch (ClusterException e) { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java index d067541f17..52e96e49c2 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java @@ -17,6 +17,7 @@ package org.ehcache.clustered; import org.ehcache.CachePersistenceException; +import org.ehcache.PerpetualCachePersistenceException; import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; import org.ehcache.clustered.client.config.DedicatedClusteredResourcePool; @@ -69,7 +70,7 @@ public void testTooLowResourceException() throws InterruptedException { cacheManagerBuilder.build(true); fail("InvalidServerStoreConfigurationException expected"); } catch (Exception e) { - Throwable cause = getCause(e, CachePersistenceException.class); + Throwable cause = getCause(e, PerpetualCachePersistenceException.class); assertThat(cause, notNullValue()); assertThat(cause.getMessage(), startsWith("Unable to create")); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerReconnectTest.java new file mode 100644 index 0000000000..48c0acf963 --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerReconnectTest.java @@ -0,0 +1,121 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered.reconnect; + +import org.ehcache.Cache; +import org.ehcache.PersistentCacheManager; +import org.ehcache.clustered.ClusteredTests; +import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.internal.resilience.RobustResilienceStrategy; +import org.ehcache.spi.resilience.RecoveryStore; +import org.ehcache.spi.resilience.ResilienceStrategy; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.junit.ClassRule; +import org.junit.Test; +import org.terracotta.testing.rules.Cluster; + +import java.io.File; +import java.net.URI; + +import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; +import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; +import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; +import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; +import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsInstanceOf.instanceOf; +import static org.hamcrest.core.IsNull.nullValue; +import static org.junit.Assert.assertThat; +import static org.junit.internal.matchers.ThrowableMessageMatcher.hasMessage; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.hamcrest.MockitoHamcrest.argThat; +import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + +public class CacheManagerReconnectTest extends ClusteredTests { + public static final String RESOURCE_CONFIG = + "" + + "" + + "64" + + "" + + "\n" + + + "" + + "" + + "30" + + "" + + ""; + + @ClassRule + public static Cluster CLUSTER = newCluster(1) + .in(new File("build/cluster")) + .withServiceFragment(RESOURCE_CONFIG) + .build(); + + @Test + public void cacheManagerCanReconnect() throws Exception { + URI connectionURI = CLUSTER.getConnectionURI(); + + try (PersistentCacheManager cacheManager = newCacheManagerBuilder() + .with(cluster(connectionURI.resolve("/crud-cm")) + .autoCreate().defaultServerResource("primary-server-resource")) + .build(true)) { + + @SuppressWarnings("unchecked") + ResilienceStrategy resilienceStrategy = spy(new RobustResilienceStrategy<>(mock(RecoveryStore.class))); + + Cache cache = cacheManager.createCache("clustered-cache", + newCacheConfigurationBuilder(Long.class, String.class, newResourcePoolsBuilder() + .with(clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB))) + .withResilienceStrategy(resilienceStrategy) + .build()); + + cache.put(1L, "one"); + + CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.getClusterControl().startAllServers(); + + for (int i = 0; i < 400; i++) { + try { + assertThat(cache.get(1L), nullValue()); + verify(resilienceStrategy).getFailure(eq(1L), argThat(cause(hasMessage(is("Cache clustered-cache failed reconnecting to cluster"))))); + return; + } catch (AssertionError e) { + Thread.sleep(100); + } + } + throw new AssertionError(); + } + } + + private static Matcher cause(Matcher matches) { + return new TypeSafeMatcher() { + @Override + protected boolean matchesSafely(Throwable item) { + return matches.matches(item.getCause()); + } + + @Override + public void describeTo(Description description) { + description.appendText("a throwable whose cause is ").appendDescriptionOf(matches); + } + }; + } +} diff --git a/impl/src/main/java/org/ehcache/impl/persistence/DefaultDiskResourceService.java b/impl/src/main/java/org/ehcache/impl/persistence/DefaultDiskResourceService.java index 2d3e273a19..6729104851 100644 --- a/impl/src/main/java/org/ehcache/impl/persistence/DefaultDiskResourceService.java +++ b/impl/src/main/java/org/ehcache/impl/persistence/DefaultDiskResourceService.java @@ -17,6 +17,7 @@ package org.ehcache.impl.persistence; import org.ehcache.CachePersistenceException; +import org.ehcache.PerpetualCachePersistenceException; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.ResourceType; import org.ehcache.core.spi.service.DiskResourceService; @@ -218,8 +219,8 @@ public StateRepository getStateRepositoryWithin(PersistenceSpaceIdentifier id return stateRepository; } - private CachePersistenceException newCachePersistenceException(PersistenceSpaceIdentifier identifier) { - return new CachePersistenceException("Unknown space: " + identifier); + private PerpetualCachePersistenceException newCachePersistenceException(PersistenceSpaceIdentifier identifier) { + return new PerpetualCachePersistenceException("Unknown space: " + identifier); } private PersistenceSpace getPersistenceSpace(PersistenceSpaceIdentifier identifier) { diff --git a/impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java b/impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java index 33ce48bbb7..390a583bda 100644 --- a/impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java +++ b/impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java @@ -19,6 +19,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.ehcache.CachePersistenceException; +import org.ehcache.PerpetualCachePersistenceException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -95,7 +96,7 @@ static void create(File directory) throws CachePersistenceException { // if create directory fails, check once more if it is due to concurrent creation. LOGGER.debug("Reusing {}", directory.getAbsolutePath()); } else { - throw new CachePersistenceException("Unable to create or reuse directory: " + directory.getAbsolutePath()); + throw new PerpetualCachePersistenceException("Unable to create or reuse directory: " + directory.getAbsolutePath()); } } From 550798b243420def360a274b6ea088fabf1767e2 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 6 Sep 2019 13:47:01 -0400 Subject: [PATCH 179/372] Issue #2694 : Move PerpetualCachePersistenceException to being private to avoid needing to bump the minor version --- .../internal/ClusterTierManagerClientEntityFactory.java | 1 - .../client/internal}/PerpetualCachePersistenceException.java | 4 +++- .../client/internal/service/DefaultClusteringService.java | 2 +- .../clustered/client/internal/store/ClusteredStore.java | 2 +- .../ehcache/clustered/ResourcePoolAllocationFailureTest.java | 3 +-- .../ehcache/impl/persistence/DefaultDiskResourceService.java | 5 ++--- .../main/java/org/ehcache/impl/persistence/FileUtils.java | 3 +-- 7 files changed, 9 insertions(+), 11 deletions(-) rename {api/src/main/java/org/ehcache => clustered/client/src/main/java/org/ehcache/clustered/client/internal}/PerpetualCachePersistenceException.java (94%) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java index f4f2334914..9db3fcae26 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java @@ -17,7 +17,6 @@ package org.ehcache.clustered.client.internal; import org.ehcache.CachePersistenceException; -import org.ehcache.PerpetualCachePersistenceException; import org.ehcache.clustered.client.config.Timeouts; import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock; diff --git a/api/src/main/java/org/ehcache/PerpetualCachePersistenceException.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/PerpetualCachePersistenceException.java similarity index 94% rename from api/src/main/java/org/ehcache/PerpetualCachePersistenceException.java rename to clustered/client/src/main/java/org/ehcache/clustered/client/internal/PerpetualCachePersistenceException.java index a1ad043dfc..fbf83a626c 100644 --- a/api/src/main/java/org/ehcache/PerpetualCachePersistenceException.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/PerpetualCachePersistenceException.java @@ -14,7 +14,9 @@ * limitations under the License. */ -package org.ehcache; +package org.ehcache.clustered.client.internal; + +import org.ehcache.CachePersistenceException; /** * Thrown to indicate a perpetual (non-transient) failure in a persistent cache manager. diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java index 920b6a47f7..41eb8bfa7b 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java @@ -17,7 +17,7 @@ package org.ehcache.clustered.client.internal.service; import org.ehcache.CachePersistenceException; -import org.ehcache.PerpetualCachePersistenceException; +import org.ehcache.clustered.client.internal.PerpetualCachePersistenceException; import org.ehcache.clustered.client.config.ClusteredResourcePool; import org.ehcache.clustered.client.config.ClusteredResourceType; import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index 7cb12342c4..0b46e3214a 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -18,7 +18,7 @@ import org.ehcache.Cache; import org.ehcache.CachePersistenceException; -import org.ehcache.PerpetualCachePersistenceException; +import org.ehcache.clustered.client.internal.PerpetualCachePersistenceException; import org.ehcache.clustered.client.config.ClusteredResourceType; import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; import org.ehcache.clustered.client.internal.store.ServerStoreProxy.ServerCallback; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java index 52e96e49c2..c1f0c5967b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java @@ -16,8 +16,7 @@ package org.ehcache.clustered; -import org.ehcache.CachePersistenceException; -import org.ehcache.PerpetualCachePersistenceException; +import org.ehcache.clustered.client.internal.PerpetualCachePersistenceException; import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; import org.ehcache.clustered.client.config.DedicatedClusteredResourcePool; diff --git a/impl/src/main/java/org/ehcache/impl/persistence/DefaultDiskResourceService.java b/impl/src/main/java/org/ehcache/impl/persistence/DefaultDiskResourceService.java index 6729104851..2d3e273a19 100644 --- a/impl/src/main/java/org/ehcache/impl/persistence/DefaultDiskResourceService.java +++ b/impl/src/main/java/org/ehcache/impl/persistence/DefaultDiskResourceService.java @@ -17,7 +17,6 @@ package org.ehcache.impl.persistence; import org.ehcache.CachePersistenceException; -import org.ehcache.PerpetualCachePersistenceException; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.ResourceType; import org.ehcache.core.spi.service.DiskResourceService; @@ -219,8 +218,8 @@ public StateRepository getStateRepositoryWithin(PersistenceSpaceIdentifier id return stateRepository; } - private PerpetualCachePersistenceException newCachePersistenceException(PersistenceSpaceIdentifier identifier) { - return new PerpetualCachePersistenceException("Unknown space: " + identifier); + private CachePersistenceException newCachePersistenceException(PersistenceSpaceIdentifier identifier) { + return new CachePersistenceException("Unknown space: " + identifier); } private PersistenceSpace getPersistenceSpace(PersistenceSpaceIdentifier identifier) { diff --git a/impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java b/impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java index 390a583bda..33ce48bbb7 100644 --- a/impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java +++ b/impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java @@ -19,7 +19,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.ehcache.CachePersistenceException; -import org.ehcache.PerpetualCachePersistenceException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -96,7 +95,7 @@ static void create(File directory) throws CachePersistenceException { // if create directory fails, check once more if it is due to concurrent creation. LOGGER.debug("Reusing {}", directory.getAbsolutePath()); } else { - throw new PerpetualCachePersistenceException("Unable to create or reuse directory: " + directory.getAbsolutePath()); + throw new CachePersistenceException("Unable to create or reuse directory: " + directory.getAbsolutePath()); } } From f99367bebfbab0ca10f8480b633a11d4fdd0e310 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 13 Sep 2019 17:08:46 -0400 Subject: [PATCH 180/372] Fixes #2702 : Do not consult the loader on containsKey(K) --- .../ClusteredLoaderWriterStore.java | 9 +++++++ .../ClusteredLoaderWriterStoreTest.java | 27 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java index 1d1bee76f6..525caefcfa 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java @@ -106,6 +106,15 @@ protected ValueHolder getInternal(K key) throws StoreAccessException, Timeout return holder; } + @Override + public boolean containsKey(K key) throws StoreAccessException { + try { + return super.getInternal(key) != null; + } catch (TimeoutException e) { + return false; + } + } + private void append(K key, V value) throws TimeoutException { PutOperation operation = new PutOperation<>(key, value, timeSource.getTimeMillis()); ByteBuffer payload = codec.encode(operation); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java index 2f5d9907df..952edc3dbd 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java @@ -42,6 +42,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; @@ -55,6 +56,32 @@ public class ClusteredLoaderWriterStoreTest { private EternalChainResolver resolver = new EternalChainResolver<>(codec); private TimeSource timeSource = mock(TimeSource.class); + @Test + public void testContainsKeyValueAbsentInCache() throws Exception { + ServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + @SuppressWarnings("unchecked") + CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); + when(storeProxy.get(eq(1L))).thenReturn(EMPTY_CHAIN); + ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, + timeSource, loaderWriter); + assertThat(store.containsKey(1L), is(false)); + verify(loaderWriter, never()).load(anyLong()); + } + + @Test + public void testContainsKeyValuePresentInCache() throws Exception { + ServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); + @SuppressWarnings("unchecked") + CacheLoaderWriter loaderWriter = mock(CacheLoaderWriter.class); + PutOperation operation = new PutOperation<>(1L, "one", System.currentTimeMillis()); + Chain toReturn = Util.getChain(false, codec.encode(operation)); + when(storeProxy.get(anyLong())).thenReturn(toReturn); + ClusteredLoaderWriterStore store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, + timeSource, loaderWriter); + assertThat(store.containsKey(1L), is(true)); + verify(loaderWriter, never()).load(anyLong()); + } + @Test public void testGetValueAbsentInSOR() throws Exception { ServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); From 96ba8a860ca9eef1d5105a1bc8acda81e944c72e Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 16 Sep 2019 10:38:55 -0400 Subject: [PATCH 181/372] Fixes #2703 : When cache manager is persistent - use it to destroy the cache --- .../main/java/org/ehcache/jsr107/Eh107Cache.java | 16 ---------------- .../org/ehcache/jsr107/Eh107CacheManager.java | 11 ++++++++++- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107Cache.java b/107/src/main/java/org/ehcache/jsr107/Eh107Cache.java index 9cb7440f66..71af2ccb49 100644 --- a/107/src/main/java/org/ehcache/jsr107/Eh107Cache.java +++ b/107/src/main/java/org/ehcache/jsr107/Eh107Cache.java @@ -440,27 +440,11 @@ public boolean isClosed() { } void closeInternal(MultiCacheException closeException) { - closeInternal(false, closeException); - } - - private void closeInternal(boolean destroy, MultiCacheException closeException) { if (closed.compareAndSet(false, true)) { - if (destroy) { - try { - clear(false); - } catch (Throwable t) { - closeException.addThrowable(t); - } - } - cacheResources.closeResources(closeException); } } - void destroy(MultiCacheException destroyException) { - closeInternal(true, destroyException); - } - @Override public T unwrap(Class clazz) { return Unwrap.unwrap(clazz, ehCache); diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107CacheManager.java b/107/src/main/java/org/ehcache/jsr107/Eh107CacheManager.java index 74f3824192..b765dbf3f4 100644 --- a/107/src/main/java/org/ehcache/jsr107/Eh107CacheManager.java +++ b/107/src/main/java/org/ehcache/jsr107/Eh107CacheManager.java @@ -36,6 +36,7 @@ import javax.management.InstanceNotFoundException; import javax.management.MBeanServer; +import org.ehcache.PersistentCacheManager; import org.ehcache.config.CacheConfigurationBuilder; import org.ehcache.internal.serialization.JavaSerializationProvider; import org.ehcache.internal.store.service.OnHeapStoreServiceConfig; @@ -293,13 +294,21 @@ public void destroyCache(String cacheName) { destroyException.addThrowable(t); } - cache.destroy(destroyException); + cache.closeInternal(destroyException); try { ehCacheManager.removeCache(cache.getName()); } catch (Throwable t) { destroyException.addThrowable(t); } + + if (ehCacheManager instanceof PersistentCacheManager) { + try { + ((PersistentCacheManager) ehCacheManager).destroyCache(cache.getName()); + } catch (Throwable t) { + destroyException.addThrowable(t); + } + } } destroyException.throwIfNotEmpty(); From 13eeea8fc389e893a7dae27e17ab32f8526c2e32 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 19 Sep 2019 11:43:03 -0400 Subject: [PATCH 182/372] CVE-2019-16370 : Suppress (false positive) Gradle vulnerabilities --- config/owasp-supressions.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/owasp-supressions.xml b/config/owasp-supressions.xml index 5764563b32..f8ff2d20b4 100644 --- a/config/owasp-supressions.xml +++ b/config/owasp-supressions.xml @@ -9,4 +9,9 @@ ^pkg:maven/org\.ehcache.*@.*$ CVE-2019-11065 + + + ^pkg:maven/org\.ehcache.*@.*$ + CVE-2019-16370 + From 33ac1f7d7b0a314fa8704ac66a87433d0ea755a8 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 16 Aug 2019 12:09:27 -0400 Subject: [PATCH 183/372] Upgrade to Gradle 5.6 --- gradle/wrapper/gradle-wrapper.jar | Bin 55190 -> 55616 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 18 +++++++++++++++++- gradlew.bat | 18 +++++++++++++++++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 87b738cbd051603d91cc39de6cb000dd98fe6b02..5c2d1cf016b3885f6930543d57b744ea8c220a1a 100644 GIT binary patch delta 3320 zcmai0c|2768`iN!wwN(!Oxeo5?`tVU3{m#%jC~noTx!q_nHtNnR`zAgWC@krB#b55 znJk4YA);()+(!K-w|npJuix)IpYu7-^SqzuJ>T~|?;j_-ma(;-@!<_I_B>B@4FVej z11CRtM@$8afpkN^v*te{ycR9yTldxXJbmio?@}x{9}zaw&=aQt(a^ZXN9S3i8a+Z% zGc@&(5}jplZjJKk2wNlTp(mbeKL5J9Gjo==yT{-eVKj?*rT1%bQ@%#Xce~~1f{19^ zoD75QEoSzDVh@!9qG4yl`;9=Ysp?rRX=(8$VDRz=R+oA3>jLxjW-H!-2biNSYuy)U z7-B-qC5l;>qjMTg!DbWPY}h7qxi6xp)_T)_O2+*&NDg?v;RyY@5XtWHx%(ImQ_3E% zA%$s3xrxE0Fk>DhG!pG)4}I!pWJl~QtV_3Jl2W4PuWWssMq^UpGatK+4CING9pB#5 z_NDc)aonVrZuXsr5!RcE#?aXFZQjt2VMd)-p00K$EheT?H!m_D2Mdqq;0moaO=C&y zgJnvzgUn!wkx^{r049pU#gsIMhl`%{MDNl;}JRbneC zSTB=5f;o9=2Rt24_lt&%%f~m{Ts)zu8H9j`INrgMp>l-|k%Kj%U`OXL1J2e+CJHJxreHLD_#o*ZeuXE4uGDQAJS_PpEGt7hmd7psmLEBL^h zD#JbHiklZEXkk9(6uF$ErsUu^jg7c~1oRS&CuTq*Xg_cOvGw~FZ&1#p(6|jz9lJnP zSIJ)sX_W2$PSksX&}*_ejz+t*X)xK|JcakaMRGd%c*R)cQcT|?sM^#{fdjh5_I$iK zBX_d;wz+cf>b}r!i3yo6eaua)d`|Mi_|Q3mAz5Qn?#~xgE9In<;TwYN^~mtaYy#WU z*ffWtxwlk&!e@UfqQ$bn23RDFV3o-H_WM}44yQpYw;JuRf$at#XX-qmuVnKqg-Bo# zJjZE39)!{i$qJh?oJzVzWFDlSW;{Wf`Z)33Y$Fh^+qasrsEJsfy9yhyTFe?Lej&3n zEAS(D8WCt(ew(SGD z-J#7@l?KI*ZbS)AVQ23qV&{c=$@zUp0@6=kZp+5by+gnAWdB||7e=!yJ|WTpG0OC7 zKlKWFv6#(>nrEq@d1i-#L9SVxTDNb1DaY%2$=@)`k&3s8wz$M*;THa&!2Isj%6CQS zY>A4HtmWY3@9e@F)mCHJQzBz~Lt(wcJE{!CAr=wxn4|5n(jslTy)~IF?tNK zD^2#hTM0d6MDg>`9;s5*(4W1V8y}F8OT6Xap{`=h1XVKO3zrBh=;JnIs*RB>@7t5T zwV=G^T)L=(9P7tS={6`tEBBBm^u~_!-#m75G*h}y_Jj7|STtiY_LDR5UUHI@awWmB zDn6q9{2M-EHaTm53ln%ENJ$HpLwRcL>7^hUrM=}&`qmWTgtr{Ul*Lqcd_9S0xZ1s>F2dVd(s)3&$`gxFAu6jXYIS ze#M~w@=X@lm)sFI4EEiqKh7JxN=_?+}D=iHCc&S2<^VPZ6 zYKXZgvi(Yne9}k6o=ezgquABVB77}x$nKXh`@LjH&lQPqm_;MTL>4RGO|E#_7AS4@43rz=ij?gcMZalnd-JK4ILhL)Ee(3G zN}g99HmhxoBjHR~y@b>-7{f+`p zIZ<^8%d;wCA#xfwSc6$DNVPjAX6FCkb|MQ|6hFyz9UhoLF0^xUd#*^2Ofn zOJgmwDyb1=Z8T)ArRy|VQOM+BrhZ>W_ELJ6u(d^JTu|j%*6g8JKZ-ewoj)sXJCdS= zHOo?HscL;Z`H18}%WnE1&o42KZ+=fg(*VN>t>kRkcd{mP9NF6;MnzH&m2WsD)sX~h zbhv|Ux$w2avQwoI`IKiGMLrL;Z>R}Y_0K*L=63V z)ut+5tM74Glzb?92kbu5@3M#1Hi7K3$c)?TL$}`aKf0hC3`r!>Xy3!f{ z`}Y#@$`|mG1JlKzVE!vD04aX}x#hV*+AC>bQ|%XJ1<&;=0?uX!RM?CIB=+!tgkB-w zu*HF--^U4#nG1mXz0v^0@|UCs1lt}!1zTaTwoe+k?sPym`pyB-F25ivXx)#1|1%|e zJ7Vpujkk#Lu%U{v6xiQ5LW2`~QXrR`ja@*L=b0ejT977v%C)0WAik0gV7U z6a-7##p#p>>>3a{^Z}e3Z~?A|foBFU12bqaEE*0vqdCCVLFq%{;F%$Dkb6i8;Qo!C z&;zkU(!i5zbSMd)zQzg8(kU^HPQ^flVIzR)<^jwbwget09YD?zV*rx+mx@0IN{#S< zsB|8Ve>>sJI7sHE!@=(((ttqL0ks%C4M^r5!0H?rJ;MV|jtT)1cMl{|9xo_Okp@Ka ze^CzbCPf?IDFWLlE`V1FDDpZ0C@7~VMZt%!6%SFtxz{!Tb1UfBDEg~49x!4|2#_L! zX=6UXeh28_?VY*suC^Sy!?XXp?9-G{ zEbF`ELqycMcTK-$-pw|Jox9S^<_NX$7{PI7aX1p5N>aOyj&D01H#;3?=q^!=_mq@k zUHheWO_|CDYA~8r<-%q8&Gm$uPSx4S`reKPnv?Nif4kS)^smTg&m@kLYT87txGxGxw+Qc zTAi=`vzavOlyLrgf2A~;1~Gx$jcb|fkhfctRt6CjRooL|#wr)(*8D4n;2cBe>p9_T zCeJf!IgCH0h1m)UPLk3hZz120oe5YH$oXjSMHcPv@#wX;OP5bBSJMavm2}5Q8(V&# zXGA!+dAwOiXuQ)|+XwF2HW1@_MPm3*v{M86V_~+xk1K7cI7mxBKU5#bofCjZqqjs$ z(sipv#Ul%KJ)h?ua}a3Dg(6yaxeJ(HD-&`AT9kZJVLJTz?WIfgao$bYwEhXh+&GA= zkpI03HVxtWc*H!~z~9%DC;;Qej=WppOD!i1$MO1`&8LW%IWd2sbnS7j+<0b`v1%qx!owUU+ZIHJFp1yH9BFvUYI^up=ZYX$K_YM|Bn2fCG3sq#(EpRB$|A9~9*^M%Sq)EAjr0&W`hHyz96Z9h*odHK|Ju$JQ0c zO9oayZQv;2b{pLJo`T)C%yS@sAKO*WC%22XDmrdRTd;uFr*sb_{GDl=*Y`l*;>lNWh=XCbn#V}C&jmw3>t zNH(fnG%j@AI$TSggf(e3DxrpHjnpeKExsb|hC`kxjD4HUSmu)&aJNt&DtCWh#51*} zS!qfplP(f0`hJ)VHrXFD_uB7ia4#%U)3S8lGY9^(T1)M8xQxP*3w4&QJr~O`$A&N5 z_taom$34zt+reJDV?oZ*qr5ERUH7#~xm7)D(u#q#m`~~-F+TZ6Q*L)s_#T3GZUuZM zhCH9!{qXnD)9jln$|GDeDPqo=+D6#vQkAjdHtT>{VxU#AQJW-je=UWN5*R>v5vWF6 zK_6z?#thq>&%@fu5epvO$rfx`v9GojdOLGFaQ2V8?Ri z(?L2JBK(;G)bIF7r5T6Ahzst5k4j#hvhl3a`@Ksfyj3^Cx}zGE)vm$ecB$?~2`S&e zE)Nx6TiDO*JO6UmWWc+zLDmnII+)ROEvW3_{*%Fjs8Q^k4+Z&cJ0lp=@p*N!fw0>L zPSWrxar=HPDCwZnmN%orA-K2142{bJ0el>N{KM(xoHJu_HWSQihq^y%SEmj>CsBjl zj6)jxqm7NwiVHh-xQ`ex^02-y_ZO`A`P(1UwLK5G_T8=uI8@e%Kh31Xay z>H$7OG8cQ%>c_RjXhRA|Yh=93MnM)V0JlD#yP-1YNx}5`sg}-vE%slfve&}e$*L>+ zSAq_CMc5SYx6N)5h%-)?JOAhiVM5`TWT7?<9 zKKxMMb9GXHpQ1ajAr?!hxcauobJLf{IpvJ=9ny}FwdGCYmwgj?0qhIG{5zbTTVc2b zo+3h|{F_Yg96k{?rVn`m`%d??#avI-eh^XnTH2r*o>5n>`UuIsuCIeN5Br62W!Yy#8)0uWcVG%-QnMHczpWoe zftoSf-WJq~x8`|ws<-9{Va9@s#SoH3uw`>4!~uyB-(lV)SD9f(TPNa!o7JLL%!a)@gUmedno%~}$ z#zZLYah$5mf@Z2}a(oDDM^$qq>*nb;?aVn?D`($Om=?j+T%S?eSgR1t=zzwGw|kvM zt~WiOO&UVW=7N=8ERxM<4?Wbj4bPIP4z3=hjp(uuT}ne*E9ct0)Lsk?bG=1nNo=oB z0JEoKzAw45q-lB!IbJKsY=Lpru48qY6ql!Z#J13ywC&7??l&AtxiowZ|Cg(k*UE#@ zrJm|m^EV_6jz}f($PrOb`S;imdEwtu`#cCu3aMXBgUUH4t2j_qu=KmOO645(v(_DL z^G5PF%RR0@X5D{(V%x5L{xD1Sa>^wR+$0j(DeVfwk;tp3<@i$~qOsvx^uUy!zV8G0~0`$f?VV=?vm zOwYnZB>UV_b#sh6ibtN`5I+l%mTE9T%*J!xaz}cWisUNLg@>nEiKv4hgmv`5C)GIDbBOgq{?5K-!=>z{CLJ$wIBkL-~yV{}~e*^#eZ1f%)RR;DgcM zfOqnA#42!t$D;@!QT3n50ve1d0$Zl^m}ABc){bz2HDhq#o&{ZLlQ=*lO9Alv7y_uW z`bTL2KkVsP<{%6$`1yeL}DmCZuxPZRJp*( z*Kk1M23@g@UjhQ6PEZ{58CL@Aqv>cB0|#ltT;SR`95{}ptMe0@zz&v<>j{GNDt-bE zn5EFw?u0e)Ee+J0^aq@C>E_j>A%MyU^@?Rcohe{^TCd{d<=ub5$bWAh Date: Fri, 23 Aug 2019 14:22:35 -0400 Subject: [PATCH 184/372] Switch to new pluginManagment block --- 107/build.gradle | 8 +++++--- api/build.gradle | 6 ++++-- build.gradle | 14 +++++--------- buildSrc/build.gradle | 23 ++++++++++++++++++++++- clustered/client/build.gradle | 6 ++++-- clustered/clustered-dist/build.gradle | 7 ++++--- clustered/common/build.gradle | 4 +++- clustered/server/build.gradle | 4 +++- core/build.gradle | 6 ++++-- demos/build.gradle | 2 +- dist/build.gradle | 6 ++++-- docs/build.gradle | 2 +- impl/build.gradle | 8 +++++--- management/build.gradle | 4 +++- settings.gradle | 13 +++++++++++++ transactions/build.gradle | 10 ++++++---- xml/build.gradle | 7 +++---- 17 files changed, 90 insertions(+), 40 deletions(-) diff --git a/107/build.gradle b/107/build.gradle index 93609d3c0e..b8831ae28c 100644 --- a/107/build.gradle +++ b/107/build.gradle @@ -14,9 +14,11 @@ * limitations under the License. */ -apply plugin: EhDeploy -apply plugin: 'biz.aQute.bnd.builder' -apply plugin: 'osgi-ds' +plugins { + id 'biz.aQute.bnd.builder' + id 'org.jayware.osgi-ds' + id 'org.ehcache.build.deploy' +} configurations { tckTestClasses diff --git a/api/build.gradle b/api/build.gradle index 002ef43993..0ea554e654 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -14,8 +14,10 @@ * limitations under the License. */ -apply plugin: EhDeploy -apply plugin: 'biz.aQute.bnd.builder' +plugins { + id 'org.ehcache.build.deploy' + id 'biz.aQute.bnd.builder' +} checkstyle { configFile = file("$projectDir/config/checkstyle.xml") diff --git a/build.gradle b/build.gradle index 36e4b3a690..37f2fb791a 100644 --- a/build.gradle +++ b/build.gradle @@ -19,15 +19,13 @@ import org.gradle.internal.jvm.Jvm plugins { // This adds tasks to auto close or release nexus staging repos // see https://github.com/Codearte/gradle-nexus-staging-plugin/ - id 'io.codearte.nexus-staging' version '0.21.0' - // Declare spotbugs at the top - id 'com.github.spotbugs' version '2.0.0' apply false - // Declare osgi-ds at the top - id 'org.jayware.osgi-ds' version '0.5.6' apply false + id 'io.codearte.nexus-staging' //OWASP Security Vulnerability Detection - id 'org.owasp.dependencycheck' version '5.2.0' apply false + id 'org.owasp.dependencycheck' + // Declare spotbugs at the top + id 'com.github.spotbugs' apply false // Declare bnd at the top - id 'biz.aQute.bnd.builder' version '4.1.0' apply false + id 'biz.aQute.bnd.builder' apply false } wrapper { @@ -84,8 +82,6 @@ if (hasProperty('testVM')) { println "Using Test JVM $testJava [Version: $testJava.javaVersion.majorVersion]" } -apply plugin: 'org.owasp.dependencycheck' - dependencyCheck { failBuildOnCVSS = 0 suppressionFile = 'config/owasp-supressions.xml' diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 02d773ee04..48971da90a 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -14,9 +14,30 @@ * limitations under the License. */ -apply plugin: 'groovy' +plugins { + id 'groovy' + id 'java-gradle-plugin' +} repositories { jcenter() } + +gradlePlugin { + plugins { + ehDeploy { + id = 'org.ehcache.build.deploy' + implementationClass = 'EhDeploy' + } + ehDistribute { + id = 'org.ehcache.build.distribute' + implementationClass = 'EhDistribute' + } + ehPomMangle { + id = 'org.ehcache.build.pom-mangle' + implementationClass = 'EhPomMangle' + } + } +} + dependencies { compile gradleApi() compile localGroovy() diff --git a/clustered/client/build.gradle b/clustered/client/build.gradle index f336936d60..87f26c0423 100644 --- a/clustered/client/build.gradle +++ b/clustered/client/build.gradle @@ -14,8 +14,10 @@ * limitations under the License. */ -apply plugin: EhDeploy -apply plugin: 'osgi-ds' +plugins { + id 'org.ehcache.build.deploy' + id 'org.jayware.osgi-ds' +} dependencies { compileOnly project(':impl') diff --git a/clustered/clustered-dist/build.gradle b/clustered/clustered-dist/build.gradle index 72d21bbfb5..8c1f4db93f 100644 --- a/clustered/clustered-dist/build.gradle +++ b/clustered/clustered-dist/build.gradle @@ -21,6 +21,10 @@ * https://discuss.gradle.org/t/dependency-substitution-wrong-with-more-than-one-sub-project-with-same-name/7253/6 */ +plugins { + id 'distribution' + id 'org.ehcache.build.distribute' +} group = 'org.ehcache' archivesBaseName = 'ehcache-clustered' @@ -37,9 +41,6 @@ dependencies { compileOnly "org.terracotta:runnel:$parent.terracottaPlatformVersion" } -apply plugin: 'distribution' -apply plugin: EhDistribute - configurations { kit serverLibs diff --git a/clustered/common/build.gradle b/clustered/common/build.gradle index dc4fe6a9d9..af5ff01306 100644 --- a/clustered/common/build.gradle +++ b/clustered/common/build.gradle @@ -14,7 +14,9 @@ * limitations under the License. */ -apply plugin: EhDeploy +plugins { + id 'org.ehcache.build.deploy' +} dependencies { providedImplementation project(':api') diff --git a/clustered/server/build.gradle b/clustered/server/build.gradle index 046ae67c00..68382f3ac7 100644 --- a/clustered/server/build.gradle +++ b/clustered/server/build.gradle @@ -14,7 +14,9 @@ * limitations under the License. */ -apply plugin: EhDeploy +plugins { + id 'org.ehcache.build.deploy' +} dependencies { api "org.terracotta:client-message-tracker:$terracottaPlatformVersion" diff --git a/core/build.gradle b/core/build.gradle index b08f7270f9..782444732a 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -14,8 +14,10 @@ * limitations under the License. */ -apply plugin: EhDeploy -apply plugin: 'biz.aQute.bnd.builder' +plugins { + id 'org.ehcache.build.deploy' + id 'biz.aQute.bnd.builder' +} dependencies { api project(':api') diff --git a/demos/build.gradle b/demos/build.gradle index bbda989716..17fa97b7dd 100644 --- a/demos/build.gradle +++ b/demos/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'org.gretty' version '2.3.1' apply false + id 'org.gretty' apply false } subprojects { diff --git a/dist/build.gradle b/dist/build.gradle index d33cec4345..9d7dcb397e 100644 --- a/dist/build.gradle +++ b/dist/build.gradle @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id 'org.ehcache.build.distribute' +} + group = 'org.ehcache' archivesBaseName = 'ehcache' @@ -25,8 +29,6 @@ dependencies { compileOnly project(':xml') } -apply plugin: EhDistribute - dependencies { shadowCompile "org.slf4j:slf4j-api:$parent.slf4jVersion" shadowCompile "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" diff --git a/docs/build.gradle b/docs/build.gradle index 75616b5f46..69b7943e39 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -18,7 +18,7 @@ import org.asciidoctor.gradle.jvm.AsciidoctorJBasePlugin import org.asciidoctor.gradle.jvm.AsciidoctorTask plugins { - id 'org.asciidoctor.jvm.base' version '2.3.0' + id 'org.asciidoctor.jvm.base' } asciidoctorj { diff --git a/impl/build.gradle b/impl/build.gradle index 048ae0d77e..4fa4c679ab 100644 --- a/impl/build.gradle +++ b/impl/build.gradle @@ -14,9 +14,11 @@ * limitations under the License. */ -apply plugin: EhDeploy -apply plugin: 'biz.aQute.bnd.builder' -apply plugin: 'osgi-ds' +plugins { + id 'org.ehcache.build.deploy' + id 'biz.aQute.bnd.builder' + id 'org.jayware.osgi-ds' +} sourceSets { unsafe { diff --git a/management/build.gradle b/management/build.gradle index 51076cbc5b..12e1251eda 100644 --- a/management/build.gradle +++ b/management/build.gradle @@ -14,7 +14,9 @@ * limitations under the License. */ -apply plugin: EhDeploy +plugins { + id 'org.ehcache.build.deploy' +} dependencies { // optional: if we want xml config diff --git a/settings.gradle b/settings.gradle index 279d39141c..a6bb800e62 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,6 +14,19 @@ * limitations under the License. */ +pluginManagement { + plugins { + id 'io.codearte.nexus-staging' version '0.21.0' + id 'com.github.spotbugs' version '2.0.0' + id 'org.jayware.osgi-ds' version '0.5.6' + id 'org.owasp.dependencycheck' version '5.2.0' + id 'biz.aQute.bnd.builder' version '4.1.0' + id 'org.gretty' version '2.3.1' + id 'org.asciidoctor.jvm.base' version '2.3.0' + id 'org.unbroken-dome.xjc' version '1.4.3' + } +} + include "api", "spi-tester", "core", "core-spi-test", "impl", "management", "transactions", "107", "xml", "clustered", "clustered:test-utils", "clustered:common", "clustered:client", "clustered:server", "clustered:integration-test", "clustered:clustered-dist", "clustered:ops-tool", "integration-test", "dist", "osgi-test", "clustered:osgi-test", "demos", "demos:00-NoCache", "demos:01-CacheAside", "docs" diff --git a/transactions/build.gradle b/transactions/build.gradle index e57de17458..f1d1616668 100644 --- a/transactions/build.gradle +++ b/transactions/build.gradle @@ -14,11 +14,13 @@ * limitations under the License. */ -group = 'org.ehcache' +plugins { + id 'biz.aQute.bnd.builder' + id 'org.jayware.osgi-ds' + id 'org.ehcache.build.pom-mangle' +} -apply plugin: 'biz.aQute.bnd.builder' -apply plugin: 'osgi-ds' -apply plugin: EhPomMangle +group = 'org.ehcache' dependencies { api group: 'javax.transaction', name: 'jta', version: '1.1' diff --git a/xml/build.gradle b/xml/build.gradle index d570fb9f44..cef41b55af 100644 --- a/xml/build.gradle +++ b/xml/build.gradle @@ -15,12 +15,11 @@ */ plugins { - id 'org.unbroken-dome.xjc' version '1.4.3' + id 'org.unbroken-dome.xjc' + id 'org.ehcache.build.deploy' + id 'biz.aQute.bnd.builder' } -apply plugin: EhDeploy -apply plugin: 'biz.aQute.bnd.builder' - dependencies { api project(':api') implementation project(':core') From 312344873536b91dd86be240f2c453291e55df68 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 23 Aug 2019 14:27:18 -0400 Subject: [PATCH 185/372] Update and/or normalize use of plugins --- api/config/checkstyle.xml | 14 ++++++-------- .../persistence/PersistableResourceService.java | 2 ++ .../spi/service/OptionalServiceDependencies.java | 2 ++ .../ehcache/spi/service/ServiceDependencies.java | 2 ++ build.gradle | 12 ++++++++---- config/checkstyle.xml | 16 ++++++---------- gradle.properties | 2 -- impl/build.gradle | 2 +- settings.gradle | 2 +- 9 files changed, 28 insertions(+), 26 deletions(-) diff --git a/api/config/checkstyle.xml b/api/config/checkstyle.xml index 58acf9aadf..796ef315bc 100644 --- a/api/config/checkstyle.xml +++ b/api/config/checkstyle.xml @@ -24,13 +24,6 @@ - - - - - - - @@ -41,7 +34,12 @@ - + + + + + + diff --git a/api/src/main/java/org/ehcache/spi/persistence/PersistableResourceService.java b/api/src/main/java/org/ehcache/spi/persistence/PersistableResourceService.java index 43453d3e36..b45f4c5516 100644 --- a/api/src/main/java/org/ehcache/spi/persistence/PersistableResourceService.java +++ b/api/src/main/java/org/ehcache/spi/persistence/PersistableResourceService.java @@ -104,6 +104,8 @@ public interface PersistableResourceService extends MaintainableService { /** * An identifier for an existing persistable resource. + * + * @param the associated persistence service type */ interface PersistenceSpaceIdentifier extends ServiceConfiguration {} } diff --git a/api/src/main/java/org/ehcache/spi/service/OptionalServiceDependencies.java b/api/src/main/java/org/ehcache/spi/service/OptionalServiceDependencies.java index 231f71de9d..bb73063c4d 100644 --- a/api/src/main/java/org/ehcache/spi/service/OptionalServiceDependencies.java +++ b/api/src/main/java/org/ehcache/spi/service/OptionalServiceDependencies.java @@ -30,6 +30,8 @@ /** * Array of {@link Service} dependency classes + * + * @return the dependency class names */ String[] value(); } diff --git a/api/src/main/java/org/ehcache/spi/service/ServiceDependencies.java b/api/src/main/java/org/ehcache/spi/service/ServiceDependencies.java index 770e6103ee..a09ba1e71a 100644 --- a/api/src/main/java/org/ehcache/spi/service/ServiceDependencies.java +++ b/api/src/main/java/org/ehcache/spi/service/ServiceDependencies.java @@ -30,6 +30,8 @@ /** * Array of {@link Service} dependency classes + * + * @return the dependency class names */ Class[] value(); } diff --git a/build.gradle b/build.gradle index 37f2fb791a..8482886838 100644 --- a/build.gradle +++ b/build.gradle @@ -125,8 +125,8 @@ subprojects { dependencies { implementation "org.slf4j:slf4j-api:$parent.slf4jVersion" - compileOnly "com.github.spotbugs:spotbugs-annotations:$parent.spotbugsVersion" - testCompileOnly "com.github.spotbugs:spotbugs-annotations:$parent.spotbugsVersion" + compileOnly "com.github.spotbugs:spotbugs-annotations:${project.spotbugs.toolVersion}" + testCompileOnly "com.github.spotbugs:spotbugs-annotations:${project.spotbugs.toolVersion}" testImplementation "junit:junit:$junitVersion" testImplementation "org.assertj:assertj-core:$assertjVersion" testImplementation "org.hamcrest:hamcrest-library:$hamcrestVersion" @@ -179,15 +179,19 @@ subprojects { checkstyle { configFile = file("$rootDir/config/checkstyle.xml") configProperties = ['projectDir':projectDir, 'rootDir':rootDir] - toolVersion = checkstyleVersion } spotbugs { ignoreFailures = false sourceSets = [sourceSets.main] - toolVersion = spotbugsVersion + } + // Spotbugs itself has a divergence in it's slf4j dependencies. + // This version is independent of the version we use. + configurations.spotbugs.resolutionStrategy { + force 'org.slf4j:slf4j-api:1.8.0-beta4' + } spotbugsMain { reports { // Switch from xml to html by changing these flags diff --git a/config/checkstyle.xml b/config/checkstyle.xml index 190ec79cba..326add3b8f 100644 --- a/config/checkstyle.xml +++ b/config/checkstyle.xml @@ -24,21 +24,17 @@ - - - - - - - - - - + + + + + + diff --git a/gradle.properties b/gradle.properties index 421ac06783..b664a18997 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,8 +24,6 @@ jacksonVersion = 2.7.5 jcacheTckVersion = 1.1.0 # Tools -spotbugsVersion = 3.1.3 -checkstyleVersion = 5.9 jacocoVersion = 0.8.3 sonatypeUser = OVERRIDE_ME diff --git a/impl/build.gradle b/impl/build.gradle index 4fa4c679ab..29ca869ec6 100644 --- a/impl/build.gradle +++ b/impl/build.gradle @@ -41,7 +41,7 @@ dependencies { testImplementation ("org.terracotta:statistics:$parent.statisticVersion") unsafeImplementation project(':api') - unsafeCompileOnly "com.github.spotbugs:spotbugs-annotations:$parent.spotbugsVersion" + unsafeCompileOnly "com.github.spotbugs:spotbugs-annotations:${project.spotbugs.toolVersion}" api files(sourceSets.unsafe.output.classesDirs) { builtBy compileUnsafeJava } diff --git a/settings.gradle b/settings.gradle index a6bb800e62..d60519cf7a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -19,7 +19,7 @@ pluginManagement { id 'io.codearte.nexus-staging' version '0.21.0' id 'com.github.spotbugs' version '2.0.0' id 'org.jayware.osgi-ds' version '0.5.6' - id 'org.owasp.dependencycheck' version '5.2.0' + id 'org.owasp.dependencycheck' version '5.2.1' id 'biz.aQute.bnd.builder' version '4.1.0' id 'org.gretty' version '2.3.1' id 'org.asciidoctor.jvm.base' version '2.3.0' From e1334515150ff0e750e4c4ada057f799d96ac4a0 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 22 Aug 2019 16:12:20 -0400 Subject: [PATCH 186/372] A minor JAXB/XSD Cleanup (stone polishing) --- .../xml/multi/XmlMultiConfiguration.java | 45 ++++++------------- xml/src/main/resources/ehcache-multi.xsd | 32 +++++++------ 2 files changed, 28 insertions(+), 49 deletions(-) diff --git a/xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java b/xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java index ec887ddbc7..8ca6ad1fd9 100644 --- a/xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java +++ b/xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java @@ -23,11 +23,9 @@ import org.ehcache.xml.multi.model.ObjectFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.w3c.dom.Node; import org.xml.sax.SAXException; import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; @@ -38,28 +36,14 @@ import javax.xml.validation.Schema; import java.io.IOException; import java.net.URL; -import java.util.AbstractMap.SimpleImmutableEntry; -import java.util.AbstractSet; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; import static java.util.Collections.emptyMap; import static java.util.Collections.emptySet; -import static java.util.Collections.singleton; import static java.util.Collections.unmodifiableSet; -import static java.util.function.Function.identity; -import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import static org.ehcache.xml.ConfigurationParser.discoverSchema; @@ -94,15 +78,13 @@ private XmlMultiConfiguration(URL url, BiFunction { - List configOrVariant = c.getConfigOrVariant(); - if (configOrVariant.size() == 1 && configOrVariant.get(0) instanceof Node) { + Element configuration = c.getConfig(); + if (configuration != null) { Document configDoc = domBuilder.newDocument(); - configDoc.appendChild(configDoc.importNode((Element) configOrVariant.get(0), true)); + configDoc.appendChild(configDoc.importNode(configuration, true)); return new SingleConfig(configParser.apply(c.getIdentity(), configDoc)); } else { - return new VariantConfig(configOrVariant.stream() - .map(e -> (JAXBElement) e) - .map(JAXBElement::getValue) + return new VariantConfig(c.getVariant().stream() .collect(toMap(Configurations.Configuration.Variant::getType, v -> { Document configDoc = domBuilder.newDocument(); configDoc.appendChild(configDoc.importNode(v.getConfig(), true)); @@ -123,8 +105,7 @@ private XmlMultiConfiguration(Map configurations) { ObjectFactory objectFactory = new ObjectFactory(); Configurations jaxb = objectFactory.createConfigurations().withConfiguration(configurations.entrySet().stream().map( - entry -> objectFactory.createConfigurationsConfiguration().withIdentity(entry.getKey()).withConfigOrVariant(entry.getValue().unparse(objectFactory)) - ).collect(toList())); + entry -> entry.getValue().unparse(objectFactory, objectFactory.createConfigurationsConfiguration().withIdentity(entry.getKey()))).collect(toList())); JAXBContext jaxbContext = JAXBContext.newInstance(Configurations.class); Marshaller marshaller = jaxbContext.createMarshaller(); @@ -243,7 +224,7 @@ private interface Config { Configuration configuration(String variant); - Collection unparse(ObjectFactory factory); + Configurations.Configuration unparse(ObjectFactory factory, Configurations.Configuration container); Set variants(); } @@ -267,8 +248,8 @@ public Configuration configuration(String variant) { } @Override - public Collection unparse(ObjectFactory factory) { - return singleton(unparseEhcacheConfiguration(config)); + public Configurations.Configuration unparse(ObjectFactory factory, Configurations.Configuration container) { + return container.withConfig(unparseEhcacheConfiguration(config)); } @Override @@ -308,12 +289,12 @@ public Configuration configuration(String variant) { } @Override - public Collection unparse(ObjectFactory factory) { - return configs.entrySet().stream() - .map(v -> factory.createConfigurationsConfigurationVariant().withType(v.getKey()) + public Configurations.Configuration unparse(ObjectFactory factory, Configurations.Configuration container) { + return container.withVariant(configs.entrySet().stream() + .map(v -> factory.createConfigurationsConfigurationVariant() + .withType(v.getKey()) .withConfig(unparseEhcacheConfiguration(v.getValue()))) - .map(factory::createConfigurationsConfigurationVariant) - .collect(toList()); + .collect(toList())); } @Override diff --git a/xml/src/main/resources/ehcache-multi.xsd b/xml/src/main/resources/ehcache-multi.xsd index 3bc758687d..a0980cf84f 100644 --- a/xml/src/main/resources/ehcache-multi.xsd +++ b/xml/src/main/resources/ehcache-multi.xsd @@ -38,7 +38,7 @@ - + @@ -46,22 +46,20 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + From 5ea5e526332e94480aa91f3a90502bec95383e63 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 18 Sep 2019 11:51:47 -0400 Subject: [PATCH 187/372] Fixes #2704 : Add getAndPut and getAndRemove to Store to support clustered implementation of 107 operations --- .../client/internal/store/ClusteredStore.java | 85 +++++++++++++------ .../main/java/org/ehcache/core/Ehcache.java | 4 +- .../org/ehcache/core/spi/store/Store.java | 34 ++++++++ .../internal/store/tiering/TieredStore.java | 18 ++++ 4 files changed, 114 insertions(+), 27 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index 3f8fb89de8..6b1a84fcda 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -219,27 +219,49 @@ public boolean containsKey(final K key) throws StoreAccessException { @Override public PutStatus put(final K key, final V value) throws StoreAccessException { putObserver.begin(); - PutStatus status = silentPut(key, value); - switch (status) { - case PUT: - putObserver.end(StoreOperationOutcomes.PutOutcome.PUT); - break; - case NOOP: - putObserver.end(StoreOperationOutcomes.PutOutcome.NOOP); - break; - default: - throw new AssertionError("Invalid put status: " + status); - } - return status; + silentPut(key, value); + putObserver.end(StoreOperationOutcomes.PutOutcome.PUT); + return PutStatus.PUT; } - private PutStatus silentPut(final K key, final V value) throws StoreAccessException { + private void silentPut(final K key, final V value) throws StoreAccessException { try { PutOperation operation = new PutOperation<>(key, value, timeSource.getTimeMillis()); ByteBuffer payload = codec.encode(operation); long extractedKey = extractLongKey(key); storeProxy.append(extractedKey, payload); - return PutStatus.PUT; + } catch (Exception re) { + throw handleException(re); + } + } + + @Override + public ValueHolder getAndPut(K key, V value) throws StoreAccessException { + putObserver.begin(); + ValueHolder oldValue = silentGetAndPut(key, value); + putObserver.end(StoreOperationOutcomes.PutOutcome.PUT); + return oldValue; + } + + private ValueHolder silentGetAndPut(final K key, final V value) throws StoreAccessException { + try { + PutOperation operation = new PutOperation<>(key, value, timeSource.getTimeMillis()); + ByteBuffer payload = codec.encode(operation); + long extractedKey = extractLongKey(key); + Chain chain = storeProxy.getAndAppend(extractedKey, payload); + ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); + + if (resolvedChain.getCompactionCount() > chainCompactionLimit) { + Chain compactedChain = resolvedChain.getCompactedChain(); + storeProxy.replaceAtHead(extractedKey, chain, compactedChain); + } + + Result result = resolvedChain.getResolvedResult(key); + if (result == null) { + return null; + } else { + return new ClusteredValueHolder<>(result.getValue()); + } } catch (Exception re) { throw handleException(re); } @@ -276,7 +298,7 @@ public ValueHolder putIfAbsent(final K key, final V value, Consumer @Override public boolean remove(final K key) throws StoreAccessException { removeObserver.begin(); - if(silentRemove(key)) { + if(silentRemove(key) != null) { removeObserver.end(StoreOperationOutcomes.RemoveOutcome.REMOVED); return true; } else { @@ -285,7 +307,18 @@ public boolean remove(final K key) throws StoreAccessException { } } - private boolean silentRemove(final K key) throws StoreAccessException { + public ValueHolder getAndRemove(K key) throws StoreAccessException { + removeObserver.begin(); + ValueHolder value = silentRemove(key); + if(value != null) { + removeObserver.end(StoreOperationOutcomes.RemoveOutcome.REMOVED); + } else { + removeObserver.end(StoreOperationOutcomes.RemoveOutcome.MISS); + } + return value; + } + + private ValueHolder silentRemove(final K key) throws StoreAccessException { try { RemoveOperation operation = new RemoveOperation<>(key, timeSource.getTimeMillis()); ByteBuffer payload = codec.encode(operation); @@ -293,11 +326,15 @@ private boolean silentRemove(final K key) throws StoreAccessException { Chain chain = storeProxy.getAndAppend(extractedKey, payload); ResolvedChain resolvedChain = resolver.resolve(chain, key, timeSource.getTimeMillis()); - if(resolvedChain.getResolvedResult(key) != null) { + Result result = resolvedChain.getResolvedResult(key); + if(result != null) { storeProxy.replaceAtHead(extractedKey, chain, resolvedChain.getCompactedChain()); - return true; + } + + if (result == null) { + return null; } else { - return false; + return new ClusteredValueHolder<>(result.getValue()); } } catch (Exception re) { throw handleException(re); @@ -446,16 +483,14 @@ public Map> bulkCompute(final Set keys, final Fun Ehcache.PutAllFunction putAllFunction = (Ehcache.PutAllFunction)remappingFunction; Map entriesToRemap = putAllFunction.getEntriesToRemap(); for(Map.Entry entry: entriesToRemap.entrySet()) { - PutStatus putStatus = silentPut(entry.getKey(), entry.getValue()); - if(putStatus == PutStatus.PUT) { - putAllFunction.getActualPutCount().incrementAndGet(); - valueHolderMap.put(entry.getKey(), new ClusteredValueHolder<>(entry.getValue())); - } + silentPut(entry.getKey(), entry.getValue()); + putAllFunction.getActualPutCount().incrementAndGet(); + valueHolderMap.put(entry.getKey(), new ClusteredValueHolder<>(entry.getValue())); } } else if(remappingFunction instanceof Ehcache.RemoveAllFunction) { Ehcache.RemoveAllFunction removeAllFunction = (Ehcache.RemoveAllFunction)remappingFunction; for (K key : keys) { - boolean removed = silentRemove(key); + boolean removed = silentRemove(key) != null; if(removed) { removeAllFunction.getActualRemoveCount().incrementAndGet(); } diff --git a/core/src/main/java/org/ehcache/core/Ehcache.java b/core/src/main/java/org/ehcache/core/Ehcache.java index cf6dcd2bf7..ce6733f597 100644 --- a/core/src/main/java/org/ehcache/core/Ehcache.java +++ b/core/src/main/java/org/ehcache/core/Ehcache.java @@ -215,7 +215,7 @@ public V getAndRemove(K key) { ValueHolder existingValue; try { - existingValue = store.getAndCompute(key, (mappedKey, mappedValue) -> null); + existingValue = store.getAndRemove(key); } catch (StoreAccessException e) { getObserver.end(org.ehcache.core.statistics.CacheOperationOutcomes.GetOutcome.FAILURE); removeObserver.end(RemoveOutcome.FAILURE); @@ -239,7 +239,7 @@ public V getAndPut(K key, final V value) { ValueHolder existingValue; try { - existingValue = store.getAndCompute(key, (mappedKey, mappedValue) -> value); + existingValue = store.getAndPut(key, value); } catch (StoreAccessException e) { getObserver.end(org.ehcache.core.statistics.CacheOperationOutcomes.GetOutcome.FAILURE); putObserver.end(PutOutcome.FAILURE); diff --git a/core/src/main/java/org/ehcache/core/spi/store/Store.java b/core/src/main/java/org/ehcache/core/spi/store/Store.java index 2f49c6acc5..a4ed87c191 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/Store.java +++ b/core/src/main/java/org/ehcache/core/spi/store/Store.java @@ -112,6 +112,22 @@ public interface Store extends ConfigurationChangeSupport { */ PutStatus put(K key, V value) throws StoreAccessException; + /** + * Maps the specified key to the specified value in this store. + * Neither the key nor the value can be {@code null}. + * + * @param key key with which the specified value is to be associated + * @param value value to be associated with the specified key + * @return the previously associated value + * + * @throws NullPointerException if any of the arguments is {@code null} + * @throws ClassCastException if the specified key or value are not of the correct types ({@code K} or {@code V}) + * @throws StoreAccessException if the mapping can't be installed + */ + default ValueHolder getAndPut(K key, V value) throws StoreAccessException { + return getAndCompute(key, (k, v) -> value); + } + /** * Maps the specified key to the specified value in this store, unless a non-expired mapping * already exists. @@ -160,6 +176,24 @@ public interface Store extends ConfigurationChangeSupport { */ boolean remove(K key) throws StoreAccessException; + + /** + * Removes the key (and its corresponding value) from this store. + * This method does nothing if the key is not mapped. + *

+ * The key cannot be {@code null}. + * + * @param key the key that needs to be removed + * @return the previously associated value + * + * @throws NullPointerException if the specified key is null + * @throws NullPointerException if the argument is {@code null} + * @throws StoreAccessException if the mapping can't be removed + */ + default ValueHolder getAndRemove(K key) throws StoreAccessException { + return getAndCompute(key, (k, v) -> null); + } + /** * Removes the entry for a key only if currently mapped to the given value * and the entry is not expired. diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java index 29d4e0bc6b..c33feb434e 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java @@ -111,6 +111,15 @@ public PutStatus put(final K key, final V value) throws StoreAccessException { } } + @Override + public ValueHolder getAndPut(K key, V value) throws StoreAccessException { + try { + return authoritativeTier.getAndPut(key, value); + } finally { + cachingTier().invalidate(key); + } + } + @Override public ValueHolder putIfAbsent(K key, V value, Consumer put) throws StoreAccessException { try { @@ -129,6 +138,15 @@ public boolean remove(K key) throws StoreAccessException { } } + @Override + public ValueHolder getAndRemove(K key) throws StoreAccessException { + try { + return authoritativeTier.getAndRemove(key); + } finally { + cachingTier().invalidate(key); + } + } + @Override public RemoveStatus remove(K key, V value) throws StoreAccessException { try { From 0d1113b0e7cad5156622472bb495b588355ab900 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 13 Sep 2019 17:07:37 -0400 Subject: [PATCH 188/372] Run TCK against clustered caches --- clustered/integration-test/build.gradle | 6 + .../clustered/JCacheClusteredTest.java | 40 ++-- .../org/ehcache/testing/ExternalTests.java | 190 ++++++++++++++++++ .../src/test/resources/ExcludeList | 119 +++++++++++ .../resources/configs/jcache-clustered.xml | 25 ++- 5 files changed, 355 insertions(+), 25 deletions(-) create mode 100644 clustered/integration-test/src/test/java/org/ehcache/testing/ExternalTests.java create mode 100644 clustered/integration-test/src/test/resources/ExcludeList diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index c0e86fdaf5..87ffd20f03 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -27,6 +27,12 @@ dependencies { testCompile "org.terracotta.internal:client-runtime:$terracottaCoreVersion" testCompile "org.terracotta:runnel:$terracottaPlatformVersion" testCompile "org.terracotta:lease-api:$terracottaPlatformVersion" + testCompile("javax.cache:cache-tests:$jcacheTckVersion") { + exclude group:'junit', module:'junit' + } + testCompile("javax.cache:cache-tests:$jcacheTckVersion:tests") { + exclude group:'junit', module:'junit' + } testImplementation project(':management') testImplementation "org.terracotta.management.dist:mnm-nms:$terracottaPlatformVersion" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java index 0d8474405f..bc27dac2ad 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java @@ -16,29 +16,43 @@ package org.ehcache.clustered; +import org.ehcache.testing.ExternalTests; +import org.jsr107.tck.spi.CachingProviderTest; +import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.ClassRule; -import org.junit.Test; +import org.junit.runner.RunWith; import org.terracotta.testing.rules.Cluster; import java.io.File; import java.net.URL; - -import javax.cache.Caching; -import javax.cache.spi.CachingProvider; +import java.util.Properties; import static org.ehcache.clustered.CacheManagerLifecycleEhcacheIntegrationTest.substitute; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; /** - * JCacheClusteredTest + * JCacheClusteredTest - runs the TCK test suite using clustered caches */ +@RunWith(ExternalTests.class) +@ExternalTests.From(javax.cache.CachingTest.class) +@ExternalTests.Ignore(value=CachingProviderTest.class, method="getCacheManagerUsingDefaultURI") public class JCacheClusteredTest extends ClusteredTests { + private static final Properties TCK_PROPERTIES = new Properties(); + static { + TCK_PROPERTIES.setProperty("java.net.preferIPv4Stack", "true"); + TCK_PROPERTIES.setProperty("javax.management.builder.initial", "org.ehcache.jsr107.internal.tck.Eh107MBeanServerBuilder"); + TCK_PROPERTIES.setProperty("org.jsr107.tck.management.agentId", "Eh107MBeanServer"); + TCK_PROPERTIES.setProperty("javax.cache.CacheManager", "org.ehcache.CacheManager"); + TCK_PROPERTIES.setProperty("javax.cache.Cache", "org.ehcache.Cache"); + TCK_PROPERTIES.setProperty("javax.cache.Cache.Entry", "org.ehcache.Cache$Entry"); + TCK_PROPERTIES.setProperty("javax.cache.annotation.CacheInvocationContext", "javax.cache.annotation.impl.cdi.CdiCacheKeyInvocationContextImpl"); + } private static final String RESOURCE_CONFIG = "" + "" - + "64" + + "256" + "" + "\n"; @@ -47,14 +61,16 @@ public class JCacheClusteredTest extends ClusteredTests { @BeforeClass public static void waitForActive() throws Exception { + URL xml = CacheManagerLifecycleEhcacheIntegrationTest.class.getResource("/configs/jcache-clustered.xml"); + URL substitutedXml = substitute(xml, "cluster-uri", CLUSTER.getConnectionURI().toString()); + System.setProperty("ehcache.jsr107.config.default", substitutedXml.toURI().toString()); + TCK_PROPERTIES.forEach((k, v) -> System.setProperty(k.toString(), v.toString())); CLUSTER.getClusterControl().waitForActive(); } - @Test - public void testJCacheClustered() throws Exception { - URL xml = CacheManagerLifecycleEhcacheIntegrationTest.class.getResource("/configs/jcache-clustered.xml"); - URL substitutedXml = substitute(xml, "cluster-uri", CLUSTER.getConnectionURI().toString()); - CachingProvider cachingProvider = Caching.getCachingProvider(); - cachingProvider.getCacheManager(substitutedXml.toURI(), getClass().getClassLoader()); + @AfterClass + public static void cleanup() { + System.clearProperty("ehcache.jsr107.config.default"); + TCK_PROPERTIES.forEach((k, v) -> System.clearProperty(k.toString())); } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/testing/ExternalTests.java b/clustered/integration-test/src/test/java/org/ehcache/testing/ExternalTests.java new file mode 100644 index 0000000000..9317468f4e --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/testing/ExternalTests.java @@ -0,0 +1,190 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.testing; + +import org.junit.runner.Description; +import org.junit.runner.Request; +import org.junit.runner.manipulation.Filter; +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.ParentRunner; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.TestClass; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import java.util.stream.Collectors; + +import static java.util.Arrays.asList; + +public class ExternalTests extends ParentRunner { + + private final List children; + + public ExternalTests(Class testClass) throws InitializationError, IOException, ClassNotFoundException { + super(testClass); + this.children = parseChildren(getTestClass(), parseFilter(getTestClass())); + } + + @Override + protected List getChildren() { + return children; + } + + @Override + protected Description describeChild(Request child) { + return child.getRunner().getDescription(); + } + + @Override + protected void runChild(Request child, RunNotifier notifier) { + child.getRunner().run(notifier); + } + + private static Filter parseFilter(TestClass testClass) { + return groupAnnotations(testClass, Ignore.class, Ignores.class).stream().map(IgnoreFilter::ignore).reduce(Filter.ALL, Filter::intersect); + } + + private static class IgnoreFilter extends Filter { + + private Ignore ignore; + + public static Filter ignore(Ignore ignore) { + return new IgnoreFilter(ignore); + } + + private IgnoreFilter(Ignore ignore) { + this.ignore = ignore; + } + + @Override + public boolean shouldRun(Description description) { + if (ignore.value().equals(description.getTestClass())) { + if (ignore.method().isEmpty()) { + return false; + } else { + return !ignore.method().equals(description.getMethodName()); + } + } else { + return true; + } + } + + @Override + public String describe() { + if (ignore.method().isEmpty()) { + return "Ignore " + ignore.value(); + } else { + return "Ignore " + ignore.value() + "#" + ignore.method(); + } + } + } + + private static List parseChildren(TestClass testClass, Filter filter) throws IOException, ClassNotFoundException { + List froms = groupAnnotations(testClass, From.class, Froms.class); + List tests = groupAnnotations(testClass, Test.class, Tests.class); + + List> classes = new ArrayList<>(); + + for (From from : froms) { + URL location = from.value().getProtectionDomain().getCodeSource().getLocation(); + try (InputStream is = location.openStream(); JarInputStream jis = new JarInputStream(is)) { + while (true) { + JarEntry entry = jis.getNextJarEntry(); + if (entry == null) { + break; + } else if (entry.getName().endsWith("Test.class")) { + classes.add(Class.forName(entry.getName().replace(".class", "").replace('/', '.'))); + } + } + } + } + for (Test test : tests) { + classes.add(test.value()); + } + + return classes.stream() + .filter(c -> Modifier.isPublic(c.getModifiers()) && !Modifier.isAbstract(c.getModifiers())) + .filter(c -> !c.getSimpleName().startsWith("Abstract")) + .map(Request::aClass).map(r -> r.filterWith(filter)).collect(Collectors.toList()); + + } + + @SuppressWarnings("unchecked") + private static List groupAnnotations(TestClass testClass, Class annoType, Class wrapperType) { + try { + List annotations = new ArrayList<>(); + + WT testsAnn = testClass.getAnnotation(wrapperType); + if (testsAnn != null) { + annotations.addAll(asList((T[]) wrapperType.getMethod("value").invoke(testsAnn))); + } + + T singularAnn = testClass.getAnnotation(annoType); + if (singularAnn != null) { + annotations.add(singularAnn); + } + return annotations; + } catch (ReflectiveOperationException e) { + throw new IllegalArgumentException(e); + } + } + + + @Retention(RetentionPolicy.RUNTIME) + @Repeatable(Tests.class) + public @interface Test { + + Class value(); + } + @Retention(RetentionPolicy.RUNTIME) + public @interface Tests { + Test[] value(); + } + + @Retention(RetentionPolicy.RUNTIME) + @Repeatable(Froms.class) + public @interface From { + + Class value(); + } + @Retention(RetentionPolicy.RUNTIME) + public @interface Froms { + From[] value(); + } + + @Retention(RetentionPolicy.RUNTIME) + @Repeatable(Ignores.class) + public @interface Ignore { + Class value(); + + String method() default ""; + } + + @Retention(RetentionPolicy.RUNTIME) + public @interface Ignores { + Ignore[] value(); + } +} diff --git a/clustered/integration-test/src/test/resources/ExcludeList b/clustered/integration-test/src/test/resources/ExcludeList new file mode 100644 index 0000000000..40f1074143 --- /dev/null +++ b/clustered/integration-test/src/test/resources/ExcludeList @@ -0,0 +1,119 @@ +# This is a dummy test that fails if not in the exclude list. +org.jsr107.tck.CachingTest#dummyTest + +# Hard assertions on the default URI +org.jsr107.tck.CachingTest#getCacheManager_defaultURI +org.jsr107.tck.CachingTest#getCacheManager_nullUriParameter +org.jsr107.tck.CachingTest#getCacheManager_URI +org.jsr107.tck.spi.CachingProviderClassLoaderTest#getCacheManagerSameURI +org.jsr107.tck.spi.CachingProviderClassLoaderTest#getCacheManagerDefaultURI +org.jsr107.tck.spi.CachingProviderTest#getCacheManagerUsingDefaultURI + +# Assumes store-by-reference semantics +org.jsr107.tck.StoreByReferenceTest#get_Existing +org.jsr107.tck.StoreByReferenceTest#get_Existing_NotSameKey +org.jsr107.tck.StoreByReferenceTest#put_Existing_NotSameKey +org.jsr107.tck.StoreByReferenceTest#getAndPut_NotThere +org.jsr107.tck.StoreByReferenceTest#getAndPut_Existing +org.jsr107.tck.StoreByReferenceTest#getAndPut_Existing_NotSameKey +org.jsr107.tck.StoreByReferenceTest#putAll +org.jsr107.tck.StoreByReferenceTest#putIfAbsent_Missing +org.jsr107.tck.StoreByReferenceTest#putIfAbsent_There +org.jsr107.tck.StoreByReferenceTest#replace_3arg +org.jsr107.tck.StoreByReferenceTest#getAndReplace +org.jsr107.tck.TypesTest#simpleAPINoGenericsAndNoTypeEnforcementStoreByReference + +# Assumes inline expiry policy calls +org.jsr107.tck.management.CacheMBStatisticsBeanTest#testExpiryOnCreation +org.jsr107.tck.expiry.CacheExpiryTest#putShouldCallGetExpiry +org.jsr107.tck.expiry.CacheExpiryTest#getAndReplaceShouldCallGetExpiryForModifiedEntry +org.jsr107.tck.expiry.CacheExpiryTest#containsKeyShouldNotCallExpiryPolicyMethods +org.jsr107.tck.expiry.CacheExpiryTest#removeEntryShouldNotCallExpiryPolicyMethods +org.jsr107.tck.expiry.CacheExpiryTest#putIfAbsentShouldCallGetExpiry +org.jsr107.tck.expiry.CacheExpiryTest#replaceSpecificShouldCallGetExpiry +org.jsr107.tck.expiry.CacheExpiryTest#getAllShouldCallGetExpiryForAccessedEntry +org.jsr107.tck.expiry.CacheExpiryTest#removeSpecifiedEntryShouldNotCallExpiryPolicyMethods +org.jsr107.tck.expiry.CacheExpiryTest#replaceShouldCallGetExpiryForModifiedEntry +org.jsr107.tck.expiry.CacheExpiryTest#putAllShouldCallGetExpiry +org.jsr107.tck.expiry.CacheExpiryTest#invokeAllSetValueShouldCallGetExpiry +org.jsr107.tck.expiry.CacheExpiryTest#iteratorNextShouldCallGetExpiryForAccessedEntry +org.jsr107.tck.expiry.CacheExpiryTest#getShouldCallGetExpiryForAccessedEntry +org.jsr107.tck.expiry.CacheExpiryTest#invokeAllReadThroughEnabledGetOnNonExistentEntry +org.jsr107.tck.expiry.CacheExpiryTest#expire_whenCreated_ModifiedExpiryPolicy +org.jsr107.tck.expiry.CacheExpiryTest#expire_whenCreated_ParameterizedExpiryPolicy +org.jsr107.tck.expiry.CacheExpiryTest#expire_whenCreated_TouchedExpiryPolicy +org.jsr107.tck.expiry.CacheExpiryTest#expire_whenCreated_CreatedExpiryPolicy +org.jsr107.tck.expiry.CacheExpiryTest#expire_whenCreated_AccessedExpiryPolicy +org.jsr107.tck.expiry.CacheExpiryTest#getAndRemoveShouldNotCallExpiryPolicyMethods +org.jsr107.tck.expiry.CacheExpiryTest#getAndPutShouldCallEitherCreatedOrModifiedExpiryPolicy + +# Clustered cache TTI is busted(-ish) +org.jsr107.tck.integration.CacheLoaderWithExpiryTest#shouldLoadWhenMissCausedByExpiry +org.jsr107.tck.expiry.CacheExpiryTest#expire_whenAccessed + +# Implement org.ehcache.clustered.client.internal.store.ClusteredStore.computeAndGet +org.jsr107.tck.event.CacheListenerTest#testBrokenCacheEntryListener +org.jsr107.tck.event.CacheListenerTest#testCacheEntryListener +org.jsr107.tck.management.CacheMBStatisticsBeanTest#testCacheStatisticsInvokeEntryProcessorRemove +org.jsr107.tck.management.CacheMBStatisticsBeanTest#testCacheStatisticsInvokeEntryProcessorUpdate +org.jsr107.tck.management.CacheMBStatisticsBeanTest#testCacheStatisticsInvokeEntryProcessorGet +org.jsr107.tck.management.CacheMBStatisticsBeanTest#testCacheStatisticsInvokeEntryProcessorNoOp +org.jsr107.tck.processor.CacheInvokeTest#removeMissing +org.jsr107.tck.processor.CacheInvokeTest#noValueException +org.jsr107.tck.processor.CacheInvokeTest#testProcessorEmptyExceptionIsWrapped +org.jsr107.tck.processor.CacheInvokeTest#varArgumentsPassedIn +org.jsr107.tck.processor.CacheInvokeTest#removeException +org.jsr107.tck.processor.CacheInvokeTest#noValueSetValue +org.jsr107.tck.processor.CacheInvokeTest#noValueNoMutation +org.jsr107.tck.processor.CacheInvokeTest#testProcessorExceptionIsWrapped +org.jsr107.tck.processor.CacheInvokeTest#setValueToNull +org.jsr107.tck.processor.CacheInvokeTest#removeExisting +org.jsr107.tck.processor.CacheInvokeTest#existingException +org.jsr107.tck.processor.CacheInvokeTest#invokeAllgetResultFromMap +org.jsr107.tck.processor.CacheInvokeTest#existingReplace +org.jsr107.tck.processor.CacheInvokeTest#nullGetValue +org.jsr107.tck.expiry.CacheExpiryTest#invokeSetValueShouldCallGetExpiry +org.jsr107.tck.expiry.CacheExpiryTest#invokeGetValueShouldCallGetExpiry +org.jsr107.tck.expiry.CacheExpiryTest#invokeMultiSetValueShouldCallGetExpiry +org.jsr107.tck.expiry.CacheExpiryTest#invokeGetValueWithReadThroughForNonExistentEntryShouldCallGetExpiryForCreatedEntry +org.jsr107.tck.integration.CacheWriterTest#shouldWriteThroughUsingInvoke_setValue_CreateEntryThenRemove +org.jsr107.tck.integration.CacheWriterTest#shouldWriteThroughUsingInvoke_remove +org.jsr107.tck.integration.CacheWriterTest#shouldWriteThroughUsingInvoke_setValue_CreateEntryGetValue +org.jsr107.tck.integration.CacheWriterTest#shouldWriteThroughUsingInvoke_setValue_UpdateEntry +org.jsr107.tck.integration.CacheWriterTest#shouldWriteThroughUsingInvoke_remove_createEntry +org.jsr107.tck.integration.CacheWriterTest#shouldWriteThroughUsingInvoke_setValue_CreateEntry +org.jsr107.tck.integration.CacheWriterTest#shouldWriteThroughUsingInvoke_remove_nonExistingEntry +org.jsr107.tck.integration.CacheLoaderWithoutReadThroughTest#shouldLoadWhenAccessingWithEntryProcessor +org.jsr107.tck.integration.CacheLoaderTest#shouldLoadWhenAccessingWithEntryProcessor +org.jsr107.tck.integration.CacheLoaderWriterTest#shouldLoadWhenAccessingWithEntryProcessor +org.jsr107.tck.processor.CacheInvokeTest#invokeAllEntryProcessorReturnsNullResult +org.jsr107.tck.integration.CacheWriterTest#shouldWriteThroughUsingInvokeAll_setValue_UpdateEntry +org.jsr107.tck.integration.CacheWriterTest#shouldWriteThroughUsingInvokeAll_setValue_CreateEntry +org.jsr107.tck.integration.CacheWriterTest#shouldWriteThroughUsingInvokeAll_setValue_RemoveEntry + +# Implement org.ehcache.clustered.client.internal.store.ClusteredStore.bulkComputeIfAbsent +org.jsr107.tck.integration.CacheLoaderTest#shouldNotLoadMultipleNullEntriesUsingLoadAll +org.jsr107.tck.integration.CacheLoaderTest#shouldNotLoadMultipleNullValuesUsingLoadAll +org.jsr107.tck.integration.CacheLoaderWithoutReadThroughTest#shouldLoadMultipleNonExistingEntryUsingLoadAll +org.jsr107.tck.integration.CacheLoaderWithoutReadThroughTest#shouldNotLoadMultipleNullEntriesUsingLoadAll +org.jsr107.tck.integration.CacheLoaderWithoutReadThroughTest#shouldNotLoadMultipleNullValuesUsingLoadAll +org.jsr107.tck.integration.CacheLoaderWithoutReadThroughTest#shouldLoadSingleMissingEntryUsingLoadAll +org.jsr107.tck.integration.CacheLoaderTest#shouldLoadMultipleNonExistingEntryUsingLoadAll +org.jsr107.tck.integration.CacheLoaderTest#shouldLoadSingleMissingEntryUsingLoadAll +org.jsr107.tck.integration.CacheLoaderWriterTest#shouldLoadSingleMissingEntryUsingLoadAll +org.jsr107.tck.integration.CacheLoaderWriterTest#shouldLoadMultipleNonExistingEntryUsingLoadAll +org.jsr107.tck.expiry.CacheExpiryTest#loadAllWithReadThroughEnabledShouldCallGetExpiryForCreatedEntry + +# Implement org.ehcache.clustered.client.internal.store.ClusteredStore.bulkCompute +org.jsr107.tck.integration.CacheLoaderWithoutReadThroughTest#shouldLoadSingleExistingEntryUsingLoadAll +org.jsr107.tck.integration.CacheLoaderWithoutReadThroughTest#shouldLoadMultipleExistingEntryUsingLoadAll +org.jsr107.tck.integration.CacheLoaderTest#shouldLoadSingleExistingEntryUsingLoadAll +org.jsr107.tck.integration.CacheLoaderWriterTest#shouldNotWriteThroughUsingLoadAll +org.jsr107.tck.integration.CacheLoaderTest#shouldLoadMultipleExistingEntryUsingLoadAll +org.jsr107.tck.integration.CacheLoaderWriterTest#shouldLoadMultipleExistingEntryUsingLoadAll +org.jsr107.tck.integration.CacheLoaderWriterTest#shouldLoadSingleExistingEntryUsingLoadAll + +# Clustered removeAll/putAll incorrectly terminates early when hitting an exception on a key +org.jsr107.tck.integration.CacheWriterTest#shouldWriteThroughRemoveAllSpecific_partialSuccess +org.jsr107.tck.integration.CacheWriterTest#shouldWriteThroughRemoveAll_partialSuccess +org.jsr107.tck.integration.CacheWriterTest#shouldWriteThoughUsingPutAll_partialSuccess diff --git a/clustered/integration-test/src/test/resources/configs/jcache-clustered.xml b/clustered/integration-test/src/test/resources/configs/jcache-clustered.xml index 11061512bc..2d34c7c579 100644 --- a/clustered/integration-test/src/test/resources/configs/jcache-clustered.xml +++ b/clustered/integration-test/src/test/resources/configs/jcache-clustered.xml @@ -15,27 +15,26 @@ ~ limitations under the License. --> - -] -> + xmlns:tc="http://www.ehcache.org/v3/clustered" + xmlns:jsr107="http://www.ehcache.org/v3/jsr107"> - + - + + + + + - 10 - 10 + 1000 + 4 - - - \ No newline at end of file + + From 7c4851a59327401195bd01f6801c3183c2839c15 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 16 Sep 2019 15:28:24 -0400 Subject: [PATCH 189/372] Issue #2694 : Support optional entity auto-creation on reconnect --- .../ClusteringServiceConfiguration.java | 100 ++++++++++-- ...ClusteringServiceConfigurationBuilder.java | 51 +++--- ...ClusterTierManagerClientEntityFactory.java | 17 +- ...acheManagerServiceConfigurationParser.java | 105 ++++++++----- .../internal/service/ConnectionState.java | 27 ++-- .../main/resources/ehcache-clustered-ext.xsd | 26 +++- .../ClusteringServiceConfigurationTest.java | 1 + .../clustered/client/docs/GettingStarted.java | 25 ++- ...ManagerServiceConfigurationParserTest.java | 103 ++++++++++--- .../DefaultClusteringServiceDestroyTest.java | 26 ++-- .../service/DefaultClusteringServiceTest.java | 145 ++++++++++-------- .../store/AbstractServerStoreProxyTest.java | 3 +- .../store/ClusteredStoreEventsTest.java | 3 +- .../internal/store/ClusteredStoreTest.java | 3 +- .../src/test/resources/configs/cluster-ha.xml | 2 +- .../resources/configs/clustered-cache.xml | 2 +- .../test/resources/configs/simple-cluster.xml | 2 +- ...nknown-cluster-cache-invalid-attribute.xml | 2 +- .../unknown-cluster-cache-invalid-element.xml | 2 +- .../configs/unknown-cluster-cache.xml | 2 +- ...st.java => AutoCreateOnReconnectTest.java} | 58 +------ .../test/resources/clusteredConfiguration.txt | 2 +- .../src/test/resources/configs/clustered.xml | 4 +- .../resources/configs/jcache-clustered.xml | 2 +- .../ehcache/osgi/ehcache-clustered-osgi.xml | 2 +- .../docs/asciidoc/user/clustered-cache.adoc | 15 +- 26 files changed, 454 insertions(+), 276 deletions(-) rename clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/{CacheManagerReconnectTest.java => AutoCreateOnReconnectTest.java} (56%) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java b/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java index 22c81869bb..d8082c55b6 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java @@ -34,6 +34,7 @@ import org.ehcache.clustered.common.ServerSideConfiguration; +import static java.util.Objects.requireNonNull; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.seededFrom; /** @@ -44,9 +45,34 @@ public class ClusteringServiceConfiguration CacheManagerConfiguration, HumanReadable { - public static final boolean DEFAULT_AUTOCREATE = false; + /** + * An enumeration of configurable client to server connection behaviors. + */ + public enum ClientMode { + /** + * Connect to the cluster with no expectations regarding the cluster state. + */ + CONNECT, + /** + * Connect to the cluster and validate the cluster state is compatible with {@link #getServerConfiguration()}. + */ + EXPECTING, + /** + * Connect to the cluster and create or validate the cluster state is compatible with {@link #getServerConfiguration()}. + */ + AUTO_CREATE, + /** + * Auto creates the necessary state on reconnecting to a cluster as well as on initial connection like {@link #AUTO_CREATE}. + */ + AUTO_CREATE_ON_RECONNECT + } + + public static final ClientMode DEFAULT_CLIENT_MODE = ClientMode.CONNECT; + @Deprecated + public static final boolean DEFAULT_AUTOCREATE = DEFAULT_CLIENT_MODE.equals(ClientMode.AUTO_CREATE); + private final ConnectionSource connectionSource; - private final boolean autoCreate; + private final ClientMode clientMode; private final ServerSideConfiguration serverConfiguration; private final Timeouts timeouts; private final Properties properties; @@ -58,7 +84,9 @@ public class ClusteringServiceConfiguration * * @throws NullPointerException if {@code clusterUri} is {@code null} * @throws IllegalArgumentException if {@code clusterUri} is not URI valid for cluster operations + * @deprecated In favor of {@link ClusteringServiceConfigurationBuilder#cluster(URI)} */ + @Deprecated public ClusteringServiceConfiguration(URI clusterUri) { this(clusterUri, Timeouts.DEFAULT); } @@ -70,7 +98,9 @@ public ClusteringServiceConfiguration(URI clusterUri) { * @param clusterTierManager the non-{@code null} cluster tier manager identifier * * @throws NullPointerException if {@code servers} is {@code null} + * @deprecated In favor of {@link ClusteringServiceConfigurationBuilder#cluster(Iterable, String)} */ + @Deprecated public ClusteringServiceConfiguration(Iterable servers, String clusterTierManager) { this(servers, clusterTierManager, Timeouts.DEFAULT); } @@ -83,7 +113,9 @@ public ClusteringServiceConfiguration(Iterable servers, Strin * * @throws NullPointerException if {@code clusterUri} is {@code null} * @throws IllegalArgumentException if {@code clusterUri} is not URI valid for cluster operations + * @deprecated In favor of {@link ClusteringServiceConfigurationBuilder#cluster(URI)} */ + @Deprecated public ClusteringServiceConfiguration(URI clusterUri, Timeouts timeouts) { this(clusterUri, timeouts, null); } @@ -96,7 +128,9 @@ public ClusteringServiceConfiguration(URI clusterUri, Timeouts timeouts) { * @param timeouts the {@link Timeouts} specifying the time limit for clustered cache operations * * @throws NullPointerException if {@code servers} is {@code null} + * @deprecated In favor of {@link ClusteringServiceConfigurationBuilder#cluster(Iterable, String)} */ + @Deprecated public ClusteringServiceConfiguration(Iterable servers, String clusterTierManager, Timeouts timeouts) { this(servers, clusterTierManager, timeouts, null); } @@ -109,7 +143,9 @@ public ClusteringServiceConfiguration(Iterable servers, Strin * * @throws NullPointerException if {@code clusterUri} is {@code null} * @throws IllegalArgumentException if {@code clusterUri} is not URI valid for cluster operations + * @deprecated In favor of {@link ClusteringServiceConfigurationBuilder#cluster(URI)} */ + @Deprecated public ClusteringServiceConfiguration(URI clusterUri, ServerSideConfiguration serverConfig) { this(clusterUri, Timeouts.DEFAULT, serverConfig); } @@ -123,7 +159,9 @@ public ClusteringServiceConfiguration(URI clusterUri, ServerSideConfiguration se * * @throws NullPointerException if {@code clusterUri} is {@code null} * @throws IllegalArgumentException if {@code clusterUri} is not URI valid for cluster operations + * @deprecated In favor of {@link ClusteringServiceConfigurationBuilder#cluster(URI)} */ + @Deprecated public ClusteringServiceConfiguration(URI clusterUri, Timeouts timeouts, ServerSideConfiguration serverConfig) { this(clusterUri, timeouts, DEFAULT_AUTOCREATE, serverConfig); } @@ -137,7 +175,9 @@ public ClusteringServiceConfiguration(URI clusterUri, Timeouts timeouts, ServerS * @param serverConfig the server side entity configuration required * * @throws NullPointerException if {@code servers} is {@code null} + * @deprecated In favor of {@link ClusteringServiceConfigurationBuilder#cluster(Iterable, String)} */ + @Deprecated public ClusteringServiceConfiguration(Iterable servers, String clusterTierManager, Timeouts timeouts, ServerSideConfiguration serverConfig) { this(servers, clusterTierManager, timeouts, DEFAULT_AUTOCREATE, serverConfig); @@ -152,7 +192,9 @@ public ClusteringServiceConfiguration(Iterable servers, Strin * * @throws NullPointerException if {@code clusterUri} is {@code null} * @throws IllegalArgumentException if {@code clusterUri} is not URI valid for cluster operations + * @deprecated In favor of {@link ClusteringServiceConfigurationBuilder#cluster(URI)} */ + @Deprecated public ClusteringServiceConfiguration(URI clusterUri, boolean autoCreate, ServerSideConfiguration serverConfig) { this(clusterUri, Timeouts.DEFAULT, autoCreate, serverConfig); } @@ -166,7 +208,9 @@ public ClusteringServiceConfiguration(URI clusterUri, boolean autoCreate, Server * @param serverConfig the server side entity configuration required * * @throws NullPointerException if {@code servers} is {@code null} + * @deprecated In favor of {@link ClusteringServiceConfigurationBuilder#cluster(Iterable, String)} */ + @Deprecated public ClusteringServiceConfiguration(Iterable servers, String clusterTierManager, boolean autoCreate, ServerSideConfiguration serverConfig) { this(servers, clusterTierManager, Timeouts.DEFAULT, autoCreate, serverConfig); @@ -182,7 +226,9 @@ public ClusteringServiceConfiguration(Iterable servers, Strin * * @throws NullPointerException if {@code clusterUri} is {@code null} * @throws IllegalArgumentException if {@code clusterUri} is not URI valid for cluster operations + * @deprecated In favor of {@link ClusteringServiceConfigurationBuilder#cluster(URI)} */ + @Deprecated public ClusteringServiceConfiguration(URI clusterUri, Timeouts timeouts, boolean autoCreate, ServerSideConfiguration serverConfig) { this(clusterUri, timeouts, autoCreate, serverConfig, new Properties()); } @@ -197,7 +243,9 @@ public ClusteringServiceConfiguration(URI clusterUri, Timeouts timeouts, boolean * @param serverConfig the server side entity configuration required * * @throws NullPointerException if {@code servers} is {@code null} + * @deprecated In favor of {@link ClusteringServiceConfigurationBuilder#cluster(Iterable, String)} */ + @Deprecated public ClusteringServiceConfiguration(Iterable servers, String clusterTierManager, Timeouts timeouts, boolean autoCreate, ServerSideConfiguration serverConfig) { this(servers, clusterTierManager, timeouts, autoCreate, serverConfig, new Properties()); @@ -214,7 +262,9 @@ public ClusteringServiceConfiguration(Iterable servers, Strin * * @throws NullPointerException if {@code clusterUri} is {@code null} * @throws IllegalArgumentException if {@code clusterUri} is not URI valid for cluster operations + * @deprecated In favor of {@link ClusteringServiceConfigurationBuilder#cluster(URI)} */ + @Deprecated public ClusteringServiceConfiguration(URI clusterUri, Timeouts timeouts, boolean autoCreate, ServerSideConfiguration serverConfig, Properties properties) { this(new ConnectionSource.ClusterUri(clusterUri), timeouts, autoCreate, serverConfig, properties); } @@ -230,7 +280,9 @@ public ClusteringServiceConfiguration(URI clusterUri, Timeouts timeouts, boolean * @param properties the non-{@code null} connection Properties * * @throws NullPointerException if {@code servers} is {@code null} + * @deprecated In favor of {@link ClusteringServiceConfigurationBuilder#cluster(Iterable, String)} */ + @Deprecated public ClusteringServiceConfiguration(Iterable servers, String clusterTierManager, Timeouts timeouts, boolean autoCreate, ServerSideConfiguration serverConfig, Properties properties) { this(new ConnectionSource.ServerList(servers, clusterTierManager), timeouts, autoCreate, serverConfig, properties); @@ -246,21 +298,39 @@ public ClusteringServiceConfiguration(Iterable servers, Strin * @param properties the non-{@code null} connection Properties * * @throws NullPointerException if {@code servers} is {@code null} + * @deprecated In favor of {@link #ClusteringServiceConfiguration(ConnectionSource, Timeouts, ClientMode, ServerSideConfiguration, Properties)} )} */ + @Deprecated public ClusteringServiceConfiguration(ConnectionSource connectionSource, Timeouts timeouts, boolean autoCreate, ServerSideConfiguration serverSideConfiguration, Properties properties) { - this.connectionSource = connectionSource; - this.autoCreate = autoCreate; + this(connectionSource, timeouts, + autoCreate ? ClientMode.AUTO_CREATE : (serverSideConfiguration == null ? ClientMode.CONNECT : ClientMode.EXPECTING), + serverSideConfiguration, properties); + } + + /** + * Creates a {@code ClusteringServiceConfiguration} from the properties provided. + * + * @param connectionSource the non-{@code null} {@code ConnectionSource} identifying the source of connection to servers in the cluster + * @param timeouts the {@link Timeouts} specifying the time limit for clustered cache operations + * @param clientMode behavioral mode when connecting to the cluster + * @param serverSideConfiguration the server side entity configuration required + * @param properties the non-{@code null} connection Properties + */ + public ClusteringServiceConfiguration(ConnectionSource connectionSource, Timeouts timeouts, ClientMode clientMode, + ServerSideConfiguration serverSideConfiguration, Properties properties) { + this.connectionSource = requireNonNull(connectionSource); + this.clientMode = requireNonNull(clientMode); this.serverConfiguration = serverSideConfiguration; - this.timeouts = Objects.requireNonNull(timeouts, "Operation timeouts cannot be null"); - this.properties = (Properties) Objects.requireNonNull(properties, "Properties cannot be null").clone(); + this.timeouts = requireNonNull(timeouts, "Operation timeouts cannot be null"); + this.properties = (Properties) requireNonNull(properties, "Properties cannot be null").clone(); } protected ClusteringServiceConfiguration(ClusteringServiceConfiguration baseConfig) { Objects.requireNonNull(baseConfig, "Base configuration cannot be null"); this.connectionSource = baseConfig.getConnectionSource(); this.timeouts = baseConfig.getTimeouts(); - this.autoCreate = baseConfig.isAutoCreate(); + this.clientMode = baseConfig.getClientMode(); this.serverConfiguration = baseConfig.getServerConfiguration(); this.properties = baseConfig.getProperties(); } @@ -288,9 +358,21 @@ public ConnectionSource getConnectionSource() { * Returns {@code true} is server side components should be automatically created. * * @return {@code true} is auto-create is enabled + * @deprecated Deprecated in favor of {@link #getClientMode()} */ + @Deprecated public boolean isAutoCreate() { - return autoCreate; + final ClientMode clientMode = getClientMode(); + return ClientMode.AUTO_CREATE.equals(clientMode) || ClientMode.AUTO_CREATE_ON_RECONNECT.equals(clientMode); + } + + /** + * Returns the client connection mode. + * + * @return the client mode + */ + public ClientMode getClientMode() { + return clientMode; } /** @@ -348,7 +430,7 @@ public String readableString() { return this.getClass().getName() + ":\n " + getConnectionSource() + "\n " + "timeouts: " + getTimeouts()+ "\n " + - "autoCreate: " + isAutoCreate() + "\n " + + "clientMode: " + getClientMode() + "\n " + "defaultServerResource: " + (serverConfiguration == null ? null : serverConfiguration.getDefaultServerResource()) + "\n " + readablePoolsString(); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteringServiceConfigurationBuilder.java b/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteringServiceConfigurationBuilder.java index 3c44b920a1..3c0e3722d1 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteringServiceConfigurationBuilder.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteringServiceConfigurationBuilder.java @@ -27,12 +27,13 @@ import java.util.concurrent.TimeUnit; import java.util.function.UnaryOperator; +import org.ehcache.clustered.client.config.ClusteringServiceConfiguration.ClientMode; import org.ehcache.clustered.client.config.Timeouts; import org.ehcache.clustered.client.internal.ConnectionSource; import org.ehcache.clustered.common.ServerSideConfiguration; import org.ehcache.config.Builder; -import static org.ehcache.clustered.client.config.ClusteringServiceConfiguration.DEFAULT_AUTOCREATE; +import static org.ehcache.clustered.client.config.ClusteringServiceConfiguration.DEFAULT_CLIENT_MODE; /** * A builder of ClusteringService configurations. @@ -41,7 +42,7 @@ public final class ClusteringServiceConfigurationBuilder implements Builder servers, String clusterTierManager) { - return new ClusteringServiceConfigurationBuilder(new ConnectionSource.ServerList(servers, clusterTierManager), TimeoutsBuilder.timeouts().build(), DEFAULT_AUTOCREATE, null, new Properties()); + return new ClusteringServiceConfigurationBuilder(new ConnectionSource.ServerList(servers, clusterTierManager), TimeoutsBuilder.timeouts().build(), DEFAULT_CLIENT_MODE, null, new Properties()); } /** @@ -79,17 +80,17 @@ public static ClusteringServiceConfigurationBuilder seededFrom(ClusteringService ServerSideConfiguration serverSideConfiguration = configuration.getServerConfiguration(); if (serverSideConfiguration == null) { return new ClusteringServiceConfigurationBuilder(configuration.getConnectionSource(), configuration.getTimeouts(), - configuration.isAutoCreate(), null, configuration.getProperties()); + configuration.getClientMode(), null, configuration.getProperties()); } else { return new ClusteringServiceConfigurationBuilder(configuration.getConnectionSource(), configuration.getTimeouts(), - configuration.isAutoCreate(), new ServerSideConfigurationBuilder(serverSideConfiguration), configuration.getProperties()); + configuration.getClientMode(), new ServerSideConfigurationBuilder(serverSideConfiguration), configuration.getProperties()); } } - private ClusteringServiceConfigurationBuilder(ConnectionSource connectionSource, Timeouts timeouts, boolean autoCreate, ServerSideConfigurationBuilder serverSideConfiguration, Properties properties) { + private ClusteringServiceConfigurationBuilder(ConnectionSource connectionSource, Timeouts timeouts, ClientMode clientMode, ServerSideConfigurationBuilder serverSideConfiguration, Properties properties) { this.connectionSource = connectionSource; this.timeouts = Objects.requireNonNull(timeouts, "Timeouts can't be null"); - this.autoCreate = autoCreate; + this.clientMode = clientMode; this.serverSideConfiguration = serverSideConfiguration; this.properties = properties; } @@ -100,7 +101,7 @@ private ClusteringServiceConfigurationBuilder(ConnectionSource connectionSource, * @return a clustering service configuration builder */ public ClusteringServiceConfigurationBuilder usingUri(URI clusterUri) { - return new ClusteringServiceConfigurationBuilder(new ConnectionSource.ClusterUri(clusterUri), timeouts, autoCreate, serverSideConfiguration, properties); + return new ClusteringServiceConfigurationBuilder(new ConnectionSource.ClusterUri(clusterUri), timeouts, clientMode, serverSideConfiguration, properties); } /** @@ -109,7 +110,7 @@ public ClusteringServiceConfigurationBuilder usingUri(URI clusterUri) { * @return a clustering service configuration builder */ public ClusteringServiceConfigurationBuilder usingServers(Iterable servers) { - return new ClusteringServiceConfigurationBuilder(new ConnectionSource.ServerList(servers, connectionSource.getClusterTierManager()), timeouts, autoCreate, serverSideConfiguration, properties); + return new ClusteringServiceConfigurationBuilder(new ConnectionSource.ServerList(servers, connectionSource.getClusterTierManager()), timeouts, clientMode, serverSideConfiguration, properties); } /** @@ -118,7 +119,7 @@ public ClusteringServiceConfigurationBuilder usingServers(Iterable servers, String clusterTierManager) { - return new ClusteringServiceConfigurationBuilder(new ConnectionSource.ServerList(servers, clusterTierManager), timeouts, autoCreate, serverSideConfiguration, properties); + return new ClusteringServiceConfigurationBuilder(new ConnectionSource.ServerList(servers, clusterTierManager), timeouts, clientMode, serverSideConfiguration, properties); } /** @@ -129,7 +130,7 @@ public ClusteringServiceConfigurationBuilder usingServers(Iterable serverSideConfig) { - return new ClusteringServiceConfigurationBuilder(this.connectionSource, this.timeouts, true, + return new ClusteringServiceConfigurationBuilder(this.connectionSource, this.timeouts, ClientMode.AUTO_CREATE, + serverSideConfig.apply(new ServerSideConfigurationBuilder()), properties); + } + + /** + * Support connection to an existing entity or create if the entity if absent on initial connection or any subsequent reconnect attempt. + *

+ * An empty server-side configuration can be created by performing no operations on the supplied builder: + * {@code builder.autoCreateOnReconnect(b -> b)} + * + * @return a clustering service configuration builder + */ + public ClusteringServiceConfigurationBuilder autoCreateOnReconnect(UnaryOperator serverSideConfig) { + return new ClusteringServiceConfigurationBuilder(this.connectionSource, this.timeouts, ClientMode.AUTO_CREATE_ON_RECONNECT, serverSideConfig.apply(new ServerSideConfigurationBuilder()), properties); } @@ -165,7 +179,7 @@ public ClusteringServiceConfigurationBuilder autoCreate(UnaryOperator serverSideConfig) { - return new ClusteringServiceConfigurationBuilder(this.connectionSource, this.timeouts, false, + return new ClusteringServiceConfigurationBuilder(this.connectionSource, this.timeouts, ClientMode.EXPECTING, serverSideConfig.apply(new ServerSideConfigurationBuilder()), properties); } @@ -182,7 +196,7 @@ public ClusteringServiceConfigurationBuilder expecting(UnaryOperator timeoutsBuilder) { - return new ClusteringServiceConfigurationBuilder(connectionSource, timeoutsBuilder.build(), autoCreate, serverSideConfiguration, properties); + return new ClusteringServiceConfigurationBuilder(connectionSource, timeoutsBuilder.build(), clientMode, serverSideConfiguration, properties); } /** @@ -240,7 +254,7 @@ public ClusteringServiceConfiguration build() { * {@code ClusteringServiceConfigurationBuilder} and the {@code serverSideConfiguration} provided */ ClusteringServiceConfiguration build(ServerSideConfiguration serverSideConfiguration) { - return new ClusteringServiceConfiguration(connectionSource, timeouts, autoCreate, serverSideConfiguration, properties); + return new ClusteringServiceConfiguration(connectionSource, timeouts, clientMode, serverSideConfiguration, properties); } private static ChronoUnit toChronoUnit(TimeUnit unit) { @@ -258,5 +272,4 @@ private static ChronoUnit toChronoUnit(TimeUnit unit) { default: throw new AssertionError("Unknown unit: " + unit); } } - } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java index 92969c9e29..938a9dab65 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java @@ -17,6 +17,8 @@ package org.ehcache.clustered.client.internal; import org.ehcache.CachePersistenceException; +import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; +import org.ehcache.clustered.client.config.ClusteringServiceConfiguration.ClientMode; import org.ehcache.clustered.client.config.Timeouts; import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock; @@ -272,7 +274,7 @@ private EntityRef entityRef; try { entityRef = connection.getEntityRef(InternalClusterTierClientEntity.class, ENTITY_VERSION, entityName(clusterTierManagerIdentifier, storeIdentifier)); @@ -280,7 +282,7 @@ public ClusterTierClientEntity fetchOrCreateClusteredStoreEntity(String clusterT throw new AssertionError(e); } - if (autoCreate) { + if ((ClientMode.AUTO_CREATE.equals(clientMode) && !isReconnect) || ClientMode.AUTO_CREATE_ON_RECONNECT.equals(clientMode)) { while (true) { try { entityRef.create(new ClusterTierEntityConfiguration(clusterTierManagerIdentifier, storeIdentifier, clientStoreConfiguration)); @@ -304,17 +306,6 @@ public ClusterTierClientEntity fetchOrCreateClusteredStoreEntity(String clusterT } } - public ClusterTierClientEntity getClusterTierClientEntity(String clusterTierManagerIdentifier, String storeIdentifier) throws EntityNotFoundException { - EntityRef entityRef; - try { - entityRef = connection.getEntityRef(InternalClusterTierClientEntity.class, ENTITY_VERSION, entityName(clusterTierManagerIdentifier, storeIdentifier)); - } catch (EntityNotProvidedException e) { - throw new AssertionError(e); - } - - return fetchClusterTierClientEntity(storeIdentifier, entityRef); - } - private ClusterTierClientEntity fetchClusterTierClientEntity(String storeIdentifier, EntityRef entityRef) throws EntityNotFoundException { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java index ca9ede0b42..73bc725f4d 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java @@ -16,6 +16,7 @@ package org.ehcache.clustered.client.internal.config.xml; import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; +import org.ehcache.clustered.client.config.ClusteringServiceConfiguration.ClientMode; import org.ehcache.clustered.client.config.Timeouts; import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.client.internal.ConnectionSource; @@ -46,6 +47,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Properties; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; @@ -82,6 +84,7 @@ public class ClusteringCacheManagerServiceConfigurationParser extends BaseConfig public static final String SHARED_POOL_ELEMENT_NAME = "shared-pool"; public static final String SERVER_SIDE_CONFIG = "server-side-config"; public static final String AUTO_CREATE_ATTRIBUTE_NAME = "auto-create"; + public static final String CLIENT_MODE_ATTRIBUTE_NAME = "client-mode"; public static final String UNIT_ATTRIBUTE_NAME = "unit"; public static final String NAME_ATTRIBUTE_NAME = "name"; public static final String FROM_ATTRIBUTE_NAME = "from"; @@ -184,7 +187,7 @@ public URI getNamespace() { /* * is an optional element */ - serverConfig = processServerSideConfig(item); + serverConfig = processServerSideConfig((Element) item); break; default: throw new XmlConfigurationException( @@ -195,26 +198,25 @@ public URI getNamespace() { } try { - Timeouts timeouts = getTimeouts(getTimeout, putTimeout, connectionTimeout); - if (serverConfig == null) { - if (connectionUri != null) { - return new ClusteringServiceConfiguration(connectionUri, timeouts); - } else { - return new ClusteringServiceConfiguration(serverAddresses, clusterTierManager, timeouts); - } - } - - ServerSideConfiguration serverSideConfiguration; - if (serverConfig.defaultServerResource == null) { - serverSideConfiguration = new ServerSideConfiguration(serverConfig.pools); + ConnectionSource connectionSource; + if (connectionUri != null) { + connectionSource = new ConnectionSource.ClusterUri(connectionUri); } else { - serverSideConfiguration = new ServerSideConfiguration(serverConfig.defaultServerResource, serverConfig.pools); + connectionSource = new ConnectionSource.ServerList(serverAddresses, clusterTierManager); } - if (connectionUri != null) { - return new ClusteringServiceConfiguration(connectionUri, timeouts, serverConfig.autoCreate, serverSideConfiguration); + Timeouts timeouts = getTimeouts(getTimeout, putTimeout, connectionTimeout); + + if (serverConfig == null) { + return new ClusteringServiceConfiguration(connectionSource, timeouts, ClientMode.CONNECT, null, new Properties()); } else { - return new ClusteringServiceConfiguration(serverAddresses, clusterTierManager, timeouts, serverConfig.autoCreate, serverSideConfiguration); + ServerSideConfiguration serverSideConfiguration; + if (serverConfig.defaultServerResource == null) { + serverSideConfiguration = new ServerSideConfiguration(serverConfig.pools); + } else { + serverSideConfiguration = new ServerSideConfiguration(serverConfig.defaultServerResource, serverConfig.pools); + } + return new ClusteringServiceConfiguration(connectionSource, timeouts, serverConfig.clientMode, serverSideConfiguration, new Properties()); } } catch (IllegalArgumentException e) { throw new XmlConfigurationException(e); @@ -293,7 +295,9 @@ protected Element createRootElement(Document doc, ClusteringServiceConfiguration processTimeUnits(doc, rootElement, clusteringServiceConfiguration); Element serverSideConfigurationElem = processServerSideElements(doc, clusteringServiceConfiguration); - rootElement.appendChild(serverSideConfigurationElem); + if (serverSideConfigurationElem != null) { + rootElement.appendChild(serverSideConfigurationElem); + } return rootElement; } @@ -328,32 +332,37 @@ private Element createTimeoutElement(Document doc, String timeoutName, Duration } protected Element processServerSideElements(Document doc, ClusteringServiceConfiguration clusteringServiceConfiguration) { - Element serverSideConfigurationElem = createServerSideConfigurationElement(doc, clusteringServiceConfiguration); - - if (clusteringServiceConfiguration.getServerConfiguration() != null) { - ServerSideConfiguration serverSideConfiguration = clusteringServiceConfiguration.getServerConfiguration(); - String defaultServerResource = serverSideConfiguration.getDefaultServerResource(); - if (!(defaultServerResource == null || defaultServerResource.trim().length() == 0)) { - Element defaultResourceElement = createDefaultServerResourceElement(doc, defaultServerResource); - serverSideConfigurationElem.appendChild(defaultResourceElement); - } - Map resourcePools = serverSideConfiguration.getResourcePools(); - if (resourcePools != null) { - resourcePools.forEach( - (key, value) -> { - Element poolElement = createSharedPoolElement(doc, key, value); - serverSideConfigurationElem.appendChild(poolElement); - } - ); - } + switch (clusteringServiceConfiguration.getClientMode()) { + case CONNECT: + return null; + case EXPECTING: + case AUTO_CREATE: + case AUTO_CREATE_ON_RECONNECT: + Element serverSideConfigurationElem = createServerSideConfigurationElement(doc, clusteringServiceConfiguration); + ServerSideConfiguration serverSideConfiguration = clusteringServiceConfiguration.getServerConfiguration(); + String defaultServerResource = serverSideConfiguration.getDefaultServerResource(); + if (!(defaultServerResource == null || defaultServerResource.trim().length() == 0)) { + Element defaultResourceElement = createDefaultServerResourceElement(doc, defaultServerResource); + serverSideConfigurationElem.appendChild(defaultResourceElement); + } + Map resourcePools = serverSideConfiguration.getResourcePools(); + if (resourcePools != null) { + resourcePools.forEach( + (key, value) -> { + Element poolElement = createSharedPoolElement(doc, key, value); + serverSideConfigurationElem.appendChild(poolElement); + } + ); + } + return serverSideConfigurationElem; } - return serverSideConfigurationElem; + throw new AssertionError(); } private Element createServerSideConfigurationElement(Document doc, ClusteringServiceConfiguration clusteringServiceConfiguration) { Element serverSideConfigurationElem = doc.createElement(TC_CLUSTERED_NAMESPACE_PREFIX + SERVER_SIDE_CONFIG); - serverSideConfigurationElem.setAttribute(AUTO_CREATE_ATTRIBUTE_NAME, Boolean.toString(clusteringServiceConfiguration - .isAutoCreate())); + serverSideConfigurationElem.setAttribute(CLIENT_MODE_ATTRIBUTE_NAME, clusteringServiceConfiguration.getClientMode() + .name().toLowerCase(Locale.ROOT).replace('_', '-')); return serverSideConfigurationElem; } @@ -380,9 +389,21 @@ private Element createDefaultServerResourceElement(Document doc, String defaultS return defaultResourceElement; } - private ClusteringCacheManagerServiceConfigurationParser.ServerSideConfig processServerSideConfig(Node serverSideConfigElement) { + private ClusteringCacheManagerServiceConfigurationParser.ServerSideConfig processServerSideConfig(Element serverSideConfigElement) { ClusteringCacheManagerServiceConfigurationParser.ServerSideConfig serverSideConfig = new ClusteringCacheManagerServiceConfigurationParser.ServerSideConfig(); - serverSideConfig.autoCreate = Boolean.parseBoolean(((Element)serverSideConfigElement).getAttribute("auto-create")); + + String autoCreateAttr = serverSideConfigElement.getAttribute(AUTO_CREATE_ATTRIBUTE_NAME); + String clientModeAttr = serverSideConfigElement.getAttribute(CLIENT_MODE_ATTRIBUTE_NAME); + if (clientModeAttr.isEmpty()) { + if (!autoCreateAttr.isEmpty()) { + serverSideConfig.clientMode = Boolean.parseBoolean(autoCreateAttr) ? ClientMode.AUTO_CREATE : ClientMode.EXPECTING; + } + } else if (autoCreateAttr.isEmpty()) { + serverSideConfig.clientMode = ClientMode.valueOf(clientModeAttr.toUpperCase(Locale.ROOT).replace('-', '_')); + } else { + throw new XmlConfigurationException("Cannot define both '" + AUTO_CREATE_ATTRIBUTE_NAME + "' and '" + CLIENT_MODE_ATTRIBUTE_NAME + "' attributes"); + } + final NodeList serverSideNodes = serverSideConfigElement.getChildNodes(); for (int i = 0; i < serverSideNodes.getLength(); i++) { final Node item = serverSideNodes.item(i); @@ -461,7 +482,7 @@ private Timeouts getTimeouts(Duration getTimeout, Duration putTimeout, Duration } private static final class ServerSideConfig { - private boolean autoCreate = false; + private ClientMode clientMode = ClientMode.CONNECT; private String defaultServerResource = null; private final Map pools = new HashMap<>(); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java index d7d2c60387..b0fa4a7cad 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java @@ -17,6 +17,7 @@ import org.ehcache.CachePersistenceException; import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; +import org.ehcache.clustered.client.config.ClusteringServiceConfiguration.ClientMode; import org.ehcache.clustered.client.config.Timeouts; import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntity; import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntityFactory; @@ -98,12 +99,8 @@ public ClusterTierClientEntity createClusterTierClientEntity(String cacheId, ClusterTierClientEntity storeClientEntity; while (true) { try { - if (isReconnect) { - storeClientEntity = entityFactory.getClusterTierClientEntity(entityIdentifier, cacheId); - } else { - storeClientEntity = entityFactory.fetchOrCreateClusteredStoreEntity(entityIdentifier, cacheId, - clientStoreConfiguration, serviceConfiguration.isAutoCreate()); - } + storeClientEntity = entityFactory.fetchOrCreateClusteredStoreEntity(entityIdentifier, cacheId, + clientStoreConfiguration, serviceConfiguration.getClientMode(), isReconnect); clusterTierEntities.put(cacheId, storeClientEntity); break; } catch (EntityNotFoundException e) { @@ -134,6 +131,9 @@ private void reconnect() { while (true) { try { connect(); + if (serviceConfiguration.getClientMode().equals(ClientMode.AUTO_CREATE_ON_RECONNECT)) { + autoCreateEntity(); + } LOGGER.info("New connection to server is established, reconnect count is {}", reconnectCounter.incrementAndGet()); break; } catch (ConnectionException e) { @@ -196,10 +196,17 @@ public void acquireLeadership() { public void initializeState() { try { - if (serviceConfiguration.isAutoCreate()) { - autoCreateEntity(); - } else { - retrieveEntity(); + switch (serviceConfiguration.getClientMode()) { + case CONNECT: + case EXPECTING: + retrieveEntity(); + break; + case AUTO_CREATE: + case AUTO_CREATE_ON_RECONNECT: + autoCreateEntity(); + break; + default: + throw new AssertionError(serviceConfiguration.getClientMode()); } } catch (RuntimeException e) { entityFactory = null; diff --git a/clustered/client/src/main/resources/ehcache-clustered-ext.xsd b/clustered/client/src/main/resources/ehcache-clustered-ext.xsd index 1a8aeae70a..f613874eb6 100644 --- a/clustered/client/src/main/resources/ehcache-clustered-ext.xsd +++ b/clustered/client/src/main/resources/ehcache-clustered-ext.xsd @@ -157,10 +157,24 @@ - + + - xml:lang="en"> + True if server side components should be automatically created if they are absent. + + This attribute is deprecated, and has been replaced by the 'client-mode' attribute. + Use of both at the same time (although legal per the schema) will fail at parse time in Ehcache. + + + + + + xml:lang="en"> + The client connection behavior, either: + * expecting - expect a matching server configuration (fail otherwise) + * auto-create - expect a matching server configuration or create one if none is present + * auto-create-on-reconnect - as 'auto-create' but also auto-create on reconnection @@ -186,6 +200,14 @@ + + + + + + + + diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java index 65256785d1..7e9b4803eb 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java @@ -36,6 +36,7 @@ import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; +@SuppressWarnings("deprecation") public class ClusteringServiceConfigurationTest { private static final URI DEFAULT_URI = URI.create("terracotta://localhost:9450"); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java index 00d335dfd7..2a7e7b73e3 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java @@ -61,7 +61,7 @@ public void clusteredCacheManagerExample() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() // <1> .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) // <2> - .autoCreate(c -> c)); // <3> + .autoCreateOnReconnect(c -> c)); // <3> PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); // <4> cacheManager.close(); // <5> @@ -73,7 +73,7 @@ public void clusteredCacheManagerWithServerSideConfigExample() throws Exception // tag::clusteredCacheManagerWithServerSideConfigExample[] CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")).autoCreate(server -> server + .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")).autoCreateOnReconnect(server -> server .defaultServerResource("primary-server-resource") // <1> .resourcePool("resource-pool-a", 8, MemoryUnit.MB, "secondary-server-resource") // <2> .resourcePool("resource-pool-b", 10, MemoryUnit.MB))) // <3> @@ -98,7 +98,7 @@ public void clusteredCacheManagerWithDynamicallyAddedCacheExample() throws Excep CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .autoCreate(server -> server.defaultServerResource("primary-server-resource") + .autoCreateOnReconnect(server -> server.defaultServerResource("primary-server-resource") .resourcePool("resource-pool-a", 8, MemoryUnit.MB))); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); @@ -121,7 +121,7 @@ public void explicitConsistencyConfiguration() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .autoCreate(server -> server.defaultServerResource("primary-server-resource") + .autoCreateOnReconnect(server -> server.defaultServerResource("primary-server-resource") .resourcePool("resource-pool-a", 8, MemoryUnit.MB))); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); @@ -148,7 +148,7 @@ public void clusteredCacheTieredExample() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .autoCreate(server -> server.defaultServerResource("primary-server-resource") + .autoCreateOnReconnect(server -> server.defaultServerResource("primary-server-resource") .resourcePool("resource-pool-a", 8, MemoryUnit.MB))); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); @@ -182,9 +182,17 @@ public void clusteredCacheManagerLifecycleExamples() throws Exception { ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredShared("resource-pool")))); + CacheManagerBuilder autoCreateOnReconnect = CacheManagerBuilder.newCacheManagerBuilder() + .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) + .autoCreateOnReconnect(server -> server // <2> + .resourcePool("resource-pool", 8, MemoryUnit.MB, "primary-server-resource"))) + .withCache("clustered-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, + ResourcePoolsBuilder.newResourcePoolsBuilder() + .with(ClusteredResourcePoolBuilder.clusteredShared("resource-pool")))); + CacheManagerBuilder expecting = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .expecting(server -> server // <2> + .expecting(server -> server // <3> .resourcePool("resource-pool", 8, MemoryUnit.MB, "primary-server-resource"))) .withCache("clustered-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -192,13 +200,14 @@ public void clusteredCacheManagerLifecycleExamples() throws Exception { CacheManagerBuilder configless = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application"))) - // <3> + // <4> .withCache("clustered-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredShared("resource-pool")))); // end::clusteredCacheManagerLifecycle[] autoCreate.build(true).close(); + autoCreateOnReconnect.build(true).close(); expecting.build(true).close(); configless.build(true).close(); } @@ -215,7 +224,7 @@ public void unknownClusteredCacheExample() CacheManagerBuilder cacheManagerBuilderAutoCreate = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .autoCreate(server -> server // <1> + .autoCreateOnReconnect(server -> server // <1> .resourcePool("resource-pool", 8, MemoryUnit.MB, "primary-server-resource"))); PersistentCacheManager cacheManager1 = cacheManagerBuilderAutoCreate.build(false); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java index bb45fdda78..fdbbde4aa7 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java @@ -48,6 +48,7 @@ import java.net.InetSocketAddress; import java.net.URI; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.time.Duration; import java.time.temporal.TemporalUnit; import java.util.Arrays; @@ -62,6 +63,7 @@ import static java.time.temporal.ChronoUnit.MINUTES; import static java.util.Spliterators.spliterator; import static java.util.stream.StreamSupport.stream; +import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; import static org.ehcache.xml.XmlModel.convertToJavaTimeUnit; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -141,7 +143,7 @@ public void testGetTimeout() throws Exception { assertThat(serviceCreationConfigurations, is(not(Matchers.empty()))); ClusteringServiceConfiguration clusteringServiceConfiguration = - ServiceUtils.findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); + findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); assertThat(clusteringServiceConfiguration, is(notNullValue())); Timeouts timeouts = clusteringServiceConfiguration.getTimeouts(); @@ -175,7 +177,7 @@ public void testGetTimeoutNone() throws Exception { assertThat(serviceCreationConfigurations, is(not(Matchers.empty()))); ClusteringServiceConfiguration clusteringServiceConfiguration = - ServiceUtils.findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); + findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); assertThat(clusteringServiceConfiguration, is(notNullValue())); assertThat(clusteringServiceConfiguration.getTimeouts(), is(TimeoutsBuilder.timeouts().build())); @@ -207,7 +209,7 @@ public void testGetTimeoutUnitDefault() throws Exception { assertThat(serviceCreationConfigurations, is(not(Matchers.empty()))); ClusteringServiceConfiguration clusteringServiceConfiguration = - ServiceUtils.findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); + findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); assertThat(clusteringServiceConfiguration, is(notNullValue())); TemporalUnit defaultUnit = convertToJavaTimeUnit(new TimeType().getUnit()); @@ -368,7 +370,7 @@ public void testServersWithClusterTierManager() throws Exception { final Configuration configuration = new XmlConfiguration(makeConfig(config)); Collection> serviceCreationConfigurations = configuration.getServiceCreationConfigurations(); ClusteringServiceConfiguration clusteringServiceConfiguration = - ServiceUtils.findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); + findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); ConnectionSource.ServerList connectionSource = (ConnectionSource.ServerList) clusteringServiceConfiguration.getConnectionSource(); Iterable servers = connectionSource.getServers(); @@ -405,7 +407,7 @@ public void testServersWithClusterTierManagerAndOptionalPorts() throws Exception final Configuration configuration = new XmlConfiguration(makeConfig(config)); Collection> serviceCreationConfigurations = configuration.getServiceCreationConfigurations(); ClusteringServiceConfiguration clusteringServiceConfiguration = - ServiceUtils.findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); + findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); ConnectionSource.ServerList connectionSource = (ConnectionSource.ServerList)clusteringServiceConfiguration.getConnectionSource(); Iterable servers = connectionSource.getServers(); @@ -419,6 +421,75 @@ public void testServersWithClusterTierManagerAndOptionalPorts() throws Exception assertThat(servers, is(expectedServers)); } + @Test @SuppressWarnings("deprecation") + public void testAutoCreateFalseMapsToExpecting() throws IOException { + final String[] config = new String[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + XmlConfiguration configuration = new XmlConfiguration(makeConfig(config)); + ClusteringServiceConfiguration clusterConfig = findSingletonAmongst(ClusteringServiceConfiguration.class, configuration.getServiceCreationConfigurations()); + + assertThat(clusterConfig.isAutoCreate(), is(false)); + assertThat(clusterConfig.getClientMode(), is(ClusteringServiceConfiguration.ClientMode.EXPECTING)); + } + + @Test @SuppressWarnings("deprecation") + public void testAutoCreateTrueMapsToAutoCreate() throws IOException { + final String[] config = new String[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + XmlConfiguration configuration = new XmlConfiguration(makeConfig(config)); + ClusteringServiceConfiguration clusterConfig = findSingletonAmongst(ClusteringServiceConfiguration.class, configuration.getServiceCreationConfigurations()); + + assertThat(clusterConfig.isAutoCreate(), is(true)); + assertThat(clusterConfig.getClientMode(), is(ClusteringServiceConfiguration.ClientMode.AUTO_CREATE)); + } + + @Test + public void testBothAutoCreateAndClientModeIsDisallowed() throws IOException { + final String[] config = new String[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + try { + new XmlConfiguration(makeConfig(config)); + } catch (XmlConfigurationException e) { + assertThat(e.getMessage(), is("Cannot define both 'auto-create' and 'client-mode' attributes")); + } + } + @Test public void testTranslateServiceCreationConfiguration() throws Exception { URI connectionUri = new URI("terracotta://localhost:9510/my-application"); @@ -438,7 +509,7 @@ public void testTranslateServiceCreationConfiguration() throws Exception { "5" + "5" + "150" + - "" + + "" + "" + "5368709120" + "10737418240" + @@ -464,7 +535,7 @@ public void testTranslateServiceCreationConfigurationWithNoResourcePoolAndAutoCr "5" + "5" + "150" + - "" + + "" + "" + ""; assertThat(returnElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() @@ -486,8 +557,7 @@ public void testTranslateServiceCreationConfigurationWithNoServerSideConfig() th "5" + "5" + "150" + - "" + - ""; + ""; assertThat(returnElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } @@ -518,7 +588,7 @@ public void testTranslateServiceCreationConfigurationWithInetSocketAddress() { "5" + "5" + "150" + - ""; + ""; assertThat(returnElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } @@ -530,24 +600,13 @@ public void testTranslateServiceCreationConfigurationWithInetSocketAddress() { * @return a {@code URL} pointing to the XML configuration file * @throws IOException if an error is raised while creating or writing the XML configuration file */ - @SuppressWarnings("ThrowFromFinallyBlock") private URL makeConfig(final String[] lines) throws IOException { final File configFile = folder.newFile(testName.getMethodName() + "_config.xml"); - OutputStreamWriter out = null; - try { - out = new OutputStreamWriter(new FileOutputStream(configFile), "UTF-8"); + try (FileOutputStream fout = new FileOutputStream(configFile); OutputStreamWriter out = new OutputStreamWriter(fout, StandardCharsets.UTF_8)) { for (final String line : lines) { out.write(line); } - } finally { - if (out != null) { - try { - out.close(); - } catch (IOException e) { - throw new AssertionError(e); - } - } } return configFile.toURI().toURL(); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java index e61074d825..2e3055d231 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java @@ -16,12 +16,10 @@ package org.ehcache.clustered.client.internal.service; -import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntity; import org.ehcache.clustered.client.internal.MockConnectionService; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLockClient; import org.ehcache.clustered.client.internal.store.InternalClusterTierClientEntity; -import org.ehcache.clustered.common.ServerSideConfiguration; import org.ehcache.clustered.common.internal.ClusterTierManagerConfiguration; import org.ehcache.clustered.common.internal.exceptions.DestroyInProgressException; import org.ehcache.clustered.common.internal.lock.LockMessaging; @@ -39,7 +37,7 @@ import java.util.HashSet; import java.util.Set; -import static java.util.Collections.emptyMap; +import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.clustered.common.EhcacheEntityVersion.ENTITY_VERSION; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertThat; @@ -91,8 +89,8 @@ public void testDestroyAllFullyMocked() throws Exception { when(tierEntityRef.destroy()).thenReturn(true); when(managerEntityRef.destroy()).thenReturn(true); - DefaultClusteringService service = new DefaultClusteringService(new ClusteringServiceConfiguration(URI - .create("mock://localhost/whatever"))); + DefaultClusteringService service = new DefaultClusteringService(cluster((URI + .create("mock://localhost/whatever"))).build()); service.startForMaintenance(null, MaintainableService.MaintenanceScope.CACHE_MANAGER); service.destroyAll(); @@ -103,8 +101,6 @@ public void testDestroyAllFullyMocked() throws Exception { @Test public void testAutoCreateOnPartialDestroyState() throws Exception { - ServerSideConfiguration serverConfig = new ServerSideConfiguration("default", emptyMap()); - mockLockForWriteLockSuccess(); when(getEntityRef(ClusterTierManagerClientEntity.class)).thenReturn(managerEntityRef); @@ -114,14 +110,14 @@ public void testAutoCreateOnPartialDestroyState() throws Exception { doThrow(new EntityAlreadyExistsException("className", "entityName")) // Next time simulate creation .doNothing() - .when(managerEntityRef).create(new ClusterTierManagerConfiguration("whatever", serverConfig)); + .when(managerEntityRef).create(new ClusterTierManagerConfiguration("whatever", any())); // And can be fetch when(managerEntityRef.fetchEntity(null)).thenReturn(managerEntity); // However validate indicates destroy in progress doThrow(new DestroyInProgressException("destroying")) // Next time validation succeeds .doNothing() - .when(managerEntity).validate(serverConfig); + .when(managerEntity).validate(any()); Set stores = new HashSet<>(); stores.add("store1"); @@ -133,8 +129,8 @@ public void testAutoCreateOnPartialDestroyState() throws Exception { when(tierEntityRef.destroy()).thenReturn(true); when(managerEntityRef.destroy()).thenReturn(true); - DefaultClusteringService service = new DefaultClusteringService(new ClusteringServiceConfiguration(URI - .create("mock://localhost/whatever"), true, serverConfig)); + DefaultClusteringService service = new DefaultClusteringService(cluster(URI + .create("mock://localhost/whatever")).autoCreate(s -> s).build()); service.start(null); verify(managerEntity).prepareForDestroy(); @@ -154,8 +150,8 @@ public void testFetchOnPartialDestroyState() throws Exception { // However validate indicates destroy in progress doThrow(new DestroyInProgressException("destroying")).when(managerEntity).validate(null); - DefaultClusteringService service = new DefaultClusteringService(new ClusteringServiceConfiguration(URI - .create("mock://localhost/whatever"))); + DefaultClusteringService service = new DefaultClusteringService(cluster(URI + .create("mock://localhost/whatever")).build()); try { service.start(null); fail("IllegalStateException expected"); @@ -183,8 +179,8 @@ public void testDestroyOnPartialDestroyState() throws Exception { when(tierEntityRef.destroy()).thenReturn(true); when(managerEntityRef.destroy()).thenReturn(true); - DefaultClusteringService service = new DefaultClusteringService(new ClusteringServiceConfiguration(URI - .create("mock://localhost/whatever"))); + DefaultClusteringService service = new DefaultClusteringService(cluster(URI + .create("mock://localhost/whatever")).build()); service.startForMaintenance(null, MaintainableService.MaintenanceScope.CACHE_MANAGER); service.destroyAll(); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java index b25e6a17d1..cb094b6559 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java @@ -20,6 +20,8 @@ import org.ehcache.clustered.client.config.ClusteredResourcePool; import org.ehcache.clustered.client.config.ClusteredResourceType; import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; +import org.ehcache.clustered.client.config.ClusteringServiceConfiguration.ClientMode; +import org.ehcache.clustered.client.config.Timeouts; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntityFactory; @@ -78,6 +80,7 @@ import static org.ehcache.clustered.client.config.ClusteredResourceType.Types.DEDICATED; import static org.ehcache.clustered.client.config.ClusteredResourceType.Types.SHARED; +import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.clustered.client.internal.service.TestServiceProvider.providerContaining; import static org.ehcache.config.ResourceType.Core.DISK; import static org.ehcache.config.ResourceType.Core.HEAP; @@ -135,7 +138,7 @@ public void removePassthroughServer() throws Exception { @Test public void testHandlesResourceType() throws Exception { ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(c -> c) .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); @@ -171,7 +174,7 @@ public int getTierHeight() { @Test public void testGetPersistenceSpaceIdentifier() throws Exception { ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(c -> c) .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); @@ -204,9 +207,9 @@ public void testCreate() throws Exception { public void testConnectionName() throws Exception { String entityIdentifier = "my-application"; ClusteringServiceConfiguration configuration = - new ClusteringServiceConfiguration( - URI.create(CLUSTER_URI_BASE + entityIdentifier), - true, new ServerSideConfiguration(Collections.emptyMap())); + ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + entityIdentifier)) + .autoCreate(s -> s) + .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); service.start(null); @@ -250,7 +253,7 @@ public void testStartStopAutoCreate() throws Exception { public void testStartStopNoAutoCreate() throws Exception { URI clusterUri = URI.create(CLUSTER_URI_BASE + "my-application"); ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(clusterUri) + cluster(clusterUri) .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); try { @@ -275,7 +278,7 @@ public void testStartStopNoAutoCreate() throws Exception { @Test public void testStartStopAutoCreateTwiceA() throws Exception { ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(c -> c) .build(); DefaultClusteringService firstService = new DefaultClusteringService(configuration); @@ -306,7 +309,7 @@ public void testStartStopAutoCreateTwiceA() throws Exception { @Test public void testStartStopAutoCreateTwiceB() throws Exception { ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(c -> c) .build(); DefaultClusteringService firstService = new DefaultClusteringService(configuration); @@ -335,7 +338,7 @@ public void testStartStopAutoCreateTwiceB() throws Exception { public void testStartForMaintenanceAutoStart() throws Exception { URI clusterUri = URI.create(CLUSTER_URI_BASE + "my-application"); ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(clusterUri) + cluster(clusterUri) .autoCreate(c -> c) .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); @@ -357,7 +360,7 @@ public void testStartForMaintenanceAutoStart() throws Exception { @Test public void testStartForMaintenanceOtherAutoCreate() throws Exception { ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(c -> c) .build(); DefaultClusteringService createService = new DefaultClusteringService(configuration); @@ -389,7 +392,7 @@ public void testStartForMaintenanceOtherAutoCreate() throws Exception { @Test public void testStartForMaintenanceOtherCreated() throws Exception { ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(c -> c) .build(); DefaultClusteringService createService = new DefaultClusteringService(configuration); @@ -422,7 +425,7 @@ public void testStartForMaintenanceOtherCreated() throws Exception { @Test public void testMultipleAutoCreateClientsRunConcurrently() throws InterruptedException, ExecutionException { final ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(c -> c) .build(); @@ -449,7 +452,7 @@ public void testMultipleAutoCreateClientsRunConcurrently() throws InterruptedExc @Test public void testStartForMaintenanceInterlock() throws Exception { ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(c -> c) .build(); DefaultClusteringService maintenanceService1 = new DefaultClusteringService(configuration); @@ -472,7 +475,7 @@ public void testStartForMaintenanceInterlock() throws Exception { @Test public void testStartForMaintenanceSequence() throws Exception { ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(c -> c) .build(); DefaultClusteringService maintenanceService1 = new DefaultClusteringService(configuration); @@ -493,7 +496,7 @@ public void testStartForMaintenanceSequence() throws Exception { @Test public void testBasicConfiguration() throws Exception { ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -529,7 +532,7 @@ public void testGetServerStoreProxySharedAutoCreate() throws Exception { String cacheAlias = "cacheAlias"; String targetPool = "sharedPrimary"; ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") @@ -578,7 +581,7 @@ public void testGetServerStoreProxySharedNoAutoCreateNonExistent() throws Except String cacheAlias = "cacheAlias"; String targetPool = "sharedPrimary"; ClusteringServiceConfiguration creationConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") @@ -590,7 +593,7 @@ public void testGetServerStoreProxySharedNoAutoCreateNonExistent() throws Except creationService.stop(); ClusteringServiceConfiguration accessConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .expecting(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") @@ -636,7 +639,7 @@ public void testGetServerStoreProxySharedNoAutoCreateExists() throws Exception { String cacheAlias = "cacheAlias"; String targetPool = "sharedPrimary"; ClusteringServiceConfiguration creationConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") @@ -673,7 +676,7 @@ public void testGetServerStoreProxySharedNoAutoCreateExists() throws Exception { ClusteringServiceConfiguration accessConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .expecting(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") @@ -717,7 +720,7 @@ public void testGetServerStoreProxySharedAutoCreateTwice() throws Exception { String cacheAlias = "cacheAlias"; String targetPool = "sharedPrimary"; ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") @@ -779,7 +782,7 @@ public void testReleaseServerStoreProxyShared() throws Exception { String cacheAlias = "cacheAlias"; String targetPool = "sharedPrimary"; ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") @@ -830,7 +833,7 @@ public void testGetServerStoreProxyDedicatedAutoCreate() throws Exception { String cacheAlias = "cacheAlias"; String targetResource = "serverResource2"; ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -881,7 +884,7 @@ public void testGetServerStoreProxyDedicatedNoAutoCreateNonExistent() throws Exc String cacheAlias = "cacheAlias"; String targetResource = "serverResource2"; ClusteringServiceConfiguration creationConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -893,7 +896,7 @@ public void testGetServerStoreProxyDedicatedNoAutoCreateNonExistent() throws Exc creationService.stop(); ClusteringServiceConfiguration accessConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .expecting(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -941,7 +944,7 @@ public void testGetServerStoreProxyDedicatedNoAutoCreateExists() throws Exceptio String cacheAlias = "cacheAlias"; String targetResource = "serverResource2"; ClusteringServiceConfiguration creationConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -978,7 +981,7 @@ public void testGetServerStoreProxyDedicatedNoAutoCreateExists() throws Exceptio assertThat(clusterTierActiveEntity.getConnectedClients(), empty()); ClusteringServiceConfiguration accessConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .expecting(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1024,7 +1027,7 @@ public void testGetServerStoreProxyDedicatedAutoCreateTwice() throws Exception { String cacheAlias = "cacheAlias"; String targetResource = "serverResource2"; ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1091,7 +1094,7 @@ public void testReleaseServerStoreProxyDedicated() throws Exception { String cacheAlias = "cacheAlias"; String targetResource = "serverResource2"; ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1143,7 +1146,7 @@ public void testGetServerStoreProxySharedDestroy() throws Exception { String cacheAlias = "cacheAlias"; String targetPool = "sharedPrimary"; ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool(targetPool, 2, MemoryUnit.MB, "serverResource1") @@ -1196,7 +1199,7 @@ public void testGetServerStoreProxyDedicatedDestroy() throws Exception { String cacheAlias = "cacheAlias"; String targetResource = "serverResource2"; ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1251,7 +1254,7 @@ public void testDestroyCantBeCalledIfStopped() throws Exception { String cacheAlias = "cacheAlias"; String targetResource = "serverResource2"; ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource")) .build(); @@ -1266,7 +1269,7 @@ public void testDestroyCantBeCalledIfStopped() throws Exception { @Test public void testDestroyAllNoStores() throws Exception { ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1310,7 +1313,7 @@ public void testDestroyAllNoStores() throws Exception { @Test public void testDestroyAllWithStores() throws Exception { ClusteringServiceConfiguration configuration = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1372,7 +1375,7 @@ public void testDestroyAllWithStores() throws Exception { @Test public void testStartNoAutoCreateThenAutoCreate() throws Exception { ClusteringServiceConfiguration creationConfigBad = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .expecting(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1392,7 +1395,7 @@ public void testStartNoAutoCreateThenAutoCreate() throws Exception { assertThat(activeEntitiesBad.size(), is(0)); ClusteringServiceConfiguration creationConfigGood = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1408,7 +1411,7 @@ public void testStartNoAutoCreateThenAutoCreate() throws Exception { public void testStoreValidation_autoCreateConfigGood_autoCreateConfigBad() throws Exception { String cacheAlias = "cacheAlias"; ClusteringServiceConfiguration config = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1470,7 +1473,7 @@ public void testStoreValidation_autoCreateConfigGood_autoCreateConfigBad() throw public void testStoreValidation_autoCreateConfigGood_autoCreateConfigGood() throws Exception { String cacheAlias = "cacheAlias"; ClusteringServiceConfiguration config = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1522,7 +1525,7 @@ public void testStoreValidation_autoCreateConfigGood_autoCreateConfigGood() thro public void testStoreValidation_autoCreateConfigBad() throws Exception { String cacheAlias = "cacheAlias"; ClusteringServiceConfiguration config = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1569,7 +1572,7 @@ public void testStoreValidation_autoCreateConfigBad() throws Exception { public void testStoreValidation_autoCreateConfigGood_noAutoCreateConfigBad() throws Exception { String cacheAlias = "cacheAlias"; ClusteringServiceConfiguration autoConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1588,7 +1591,7 @@ public void testStoreValidation_autoCreateConfigGood_noAutoCreateConfigBad() thr creationService.getServerStoreProxy(getClusteredCacheIdentifier(creationService, cacheAlias), creationStoreConfig, Consistency.EVENTUAL, mock(ServerCallback.class)); ClusteringServiceConfiguration noAutoConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .expecting(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1638,7 +1641,7 @@ public void testStoreValidation_autoCreateConfigGood_noAutoCreateConfigBad() thr public void testStoreValidation_autoCreateConfigGood_noAutoCreateConfigGood() throws Exception { String cacheAlias = "cacheAlias"; ClusteringServiceConfiguration autoConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1658,7 +1661,7 @@ public void testStoreValidation_autoCreateConfigGood_noAutoCreateConfigGood() th ClusteringServiceConfiguration noAutoConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .expecting(server -> server.defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") .resourcePool("sharedSecondary", 2, MemoryUnit.MB, "serverResource2") @@ -1699,7 +1702,7 @@ public void testStoreValidation_autoCreateConfigGood_noAutoCreateConfigGood() th public void testStoreValidation_MismatchedPoolTypes_ConfiguredDedicatedValidateShared() throws Exception { String cacheAlias = "cacheAlias"; ClusteringServiceConfiguration creationConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1720,7 +1723,7 @@ public void testStoreValidation_MismatchedPoolTypes_ConfiguredDedicatedValidateS creationService.stop(); ClusteringServiceConfiguration accessConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1767,7 +1770,7 @@ public void testStoreValidation_MismatchedPoolTypes_ConfiguredDedicatedValidateS public void testStoreValidation_MismatchedPoolTypes_ConfiguredSharedValidateDedicated() throws Exception { String cacheAlias = "cacheAlias"; ClusteringServiceConfiguration creationConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1788,7 +1791,7 @@ public void testStoreValidation_MismatchedPoolTypes_ConfiguredSharedValidateDedi creationService.stop(); ClusteringServiceConfiguration accessConfig = - ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + "my-application")) + cluster(URI.create(CLUSTER_URI_BASE + "my-application")) .autoCreate(server -> server .defaultServerResource("defaultResource") .resourcePool("sharedPrimary", 2, MemoryUnit.MB, "serverResource1") @@ -1872,9 +1875,9 @@ private ClusteredCacheIdentifier getClusteredCacheIdentifier( public void testGetServerStoreProxyReturnsEventualStore() throws Exception { String entityIdentifier = "my-application"; ClusteringServiceConfiguration configuration = - new ClusteringServiceConfiguration( - URI.create(CLUSTER_URI_BASE + entityIdentifier), - true, new ServerSideConfiguration(Collections.emptyMap())); + ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + entityIdentifier)) + .autoCreate(s -> s) + .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); service.start(null); @@ -1896,9 +1899,9 @@ public void testGetServerStoreProxyReturnsEventualStore() throws Exception { public void testGetServerStoreProxyReturnsStrongStore() throws Exception { String entityIdentifier = "my-application"; ClusteringServiceConfiguration configuration = - new ClusteringServiceConfiguration( - URI.create(CLUSTER_URI_BASE + entityIdentifier), - true, new ServerSideConfiguration(Collections.emptyMap())); + ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + entityIdentifier)) + .autoCreate(s -> s) + .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); service.start(null); @@ -1921,9 +1924,9 @@ public void testGetServerStoreProxyFailureClearsEntityListeners() throws Excepti // Initial setup begin String entityIdentifier = "my-application"; ClusteringServiceConfiguration configuration = - new ClusteringServiceConfiguration( - URI.create(CLUSTER_URI_BASE + entityIdentifier), - true, new ServerSideConfiguration(Collections.emptyMap())); + ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + entityIdentifier)) + .autoCreate(s -> s) + .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); service.start(null); @@ -1957,9 +1960,9 @@ public void testGetServerStoreProxyFailureDoesNotClearOtherStoreEntityListeners( // Initial setup begin String entityIdentifier = "my-application"; ClusteringServiceConfiguration configuration = - new ClusteringServiceConfiguration( - URI.create(CLUSTER_URI_BASE + entityIdentifier), - true, new ServerSideConfiguration(Collections.emptyMap())); + ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE + entityIdentifier)) + .autoCreate(s -> s) + .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); service.start(null); @@ -1994,7 +1997,9 @@ public void testGetServerStoreProxyFailureDoesNotClearOtherStoreEntityListeners( @Test public void testGetStateRepositoryWithinTwiceWithSameName() throws Exception { ClusteringServiceConfiguration configuration = - new ClusteringServiceConfiguration(URI.create(CLUSTER_URI_BASE), true, new ServerSideConfiguration(Collections.emptyMap())); + ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE)) + .autoCreate(s -> s) + .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); PersistableResourceService.PersistenceSpaceIdentifier cacheIdentifier = service.getPersistenceSpaceIdentifier("myCache", null); StateRepository repository1 = service.getStateRepositoryWithin(cacheIdentifier, "myRepo"); @@ -2005,7 +2010,9 @@ public void testGetStateRepositoryWithinTwiceWithSameName() throws Exception { @Test public void testGetStateRepositoryWithinTwiceWithSameNameDifferentPersistenceSpaceIdentifier() throws Exception { ClusteringServiceConfiguration configuration = - new ClusteringServiceConfiguration(URI.create(CLUSTER_URI_BASE), true, new ServerSideConfiguration(Collections.emptyMap())); + ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE)) + .autoCreate(s -> s) + .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); PersistableResourceService.PersistenceSpaceIdentifier cacheIdentifier1 = service.getPersistenceSpaceIdentifier("myCache1", null); PersistableResourceService.PersistenceSpaceIdentifier cacheIdentifier2 = service.getPersistenceSpaceIdentifier("myCache2", null); @@ -2019,7 +2026,9 @@ public void testGetStateRepositoryWithinWithNonExistentPersistenceSpaceIdentifie expectedException.expect(CachePersistenceException.class); expectedException.expectMessage("Clustered space not found for identifier"); ClusteringServiceConfiguration configuration = - new ClusteringServiceConfiguration(URI.create(CLUSTER_URI_BASE), true, new ServerSideConfiguration(Collections.emptyMap())); + ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE)) + .autoCreate(s -> s) + .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); ClusteredCacheIdentifier cacheIdentifier = mock(ClusteredCacheIdentifier.class); doReturn("foo").when(cacheIdentifier).getId(); @@ -2031,7 +2040,9 @@ public void testReleaseNonExistentPersistenceSpaceIdentifierTwice() throws Excep expectedException.expect(CachePersistenceException.class); expectedException.expectMessage("Unknown identifier"); ClusteringServiceConfiguration configuration = - new ClusteringServiceConfiguration(URI.create(CLUSTER_URI_BASE), true, new ServerSideConfiguration(Collections.emptyMap())); + ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE)) + .autoCreate(s -> s) + .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); ClusteredCacheIdentifier cacheIdentifier = mock(ClusteredCacheIdentifier.class); doReturn("foo").when(cacheIdentifier).getId(); @@ -2043,7 +2054,9 @@ public void testReleasePersistenceSpaceIdentifierTwice() throws Exception { expectedException.expect(CachePersistenceException.class); expectedException.expectMessage("Unknown identifier"); ClusteringServiceConfiguration configuration = - new ClusteringServiceConfiguration(URI.create(CLUSTER_URI_BASE), true, new ServerSideConfiguration(Collections.emptyMap())); + ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE)) + .autoCreate(s -> s) + .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); PersistableResourceService.PersistenceSpaceIdentifier cacheIdentifier = service.getPersistenceSpaceIdentifier("myCache", null); try { @@ -2057,7 +2070,9 @@ public void testReleasePersistenceSpaceIdentifierTwice() throws Exception { @Test public void releaseMaintenanceHoldsWhenConnectionClosedDuringDestruction() { ClusteringServiceConfiguration configuration = - new ClusteringServiceConfiguration(URI.create(CLUSTER_URI_BASE), true, new ServerSideConfiguration(Collections.emptyMap())); + ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE)) + .autoCreate(s -> s) + .build(); DefaultClusteringService service = new DefaultClusteringService(configuration); assertThat(service.isConnected(), is(false)); service.startForMaintenance(null, MaintainableService.MaintenanceScope.CACHE_MANAGER); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java index addbeabe78..10d2f18f0f 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java @@ -16,6 +16,7 @@ package org.ehcache.clustered.client.internal.store; import org.ehcache.clustered.client.config.ClusteredResourcePool; +import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntityFactory; @@ -85,7 +86,7 @@ protected static SimpleClusterTierClientEntity createClientEntity(String name, entityFactory.create(name, new ServerSideConfiguration("defaultResource", Collections.emptyMap())); } // Create or fetch the ClusterTierClientEntity - SimpleClusterTierClientEntity clientEntity = (SimpleClusterTierClientEntity) entityFactory.fetchOrCreateClusteredStoreEntity(name, name, configuration, create); + SimpleClusterTierClientEntity clientEntity = (SimpleClusterTierClientEntity) entityFactory.fetchOrCreateClusteredStoreEntity(name, name, configuration, create ? ClusteringServiceConfiguration.ClientMode.AUTO_CREATE : ClusteringServiceConfiguration.ClientMode.CONNECT, false); if (validate) { clientEntity.validate(configuration); } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java index 4cc3a11cdb..20d9ee67d1 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java @@ -19,6 +19,7 @@ import org.ehcache.clustered.ChainUtils; import org.ehcache.clustered.client.TestTimeSource; import org.ehcache.clustered.client.config.ClusteredResourcePool; +import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntityFactory; import org.ehcache.clustered.client.internal.UnitTestConnectionService; @@ -155,7 +156,7 @@ public void setup() throws Exception { ClusteredResourcePool resourcePool = ClusteredResourcePoolBuilder.clusteredDedicated(4, MemoryUnit.MB); ServerStoreConfiguration serverStoreConfiguration = new ServerStoreConfiguration(resourcePool.getPoolAllocation(), Long.class.getName(), String.class.getName(), LongSerializer.class.getName(), StringSerializer.class.getName(), null, false); - ClusterTierClientEntity clientEntity = entityFactory.fetchOrCreateClusteredStoreEntity("TestCacheManager", CACHE_IDENTIFIER, serverStoreConfiguration, true); + ClusterTierClientEntity clientEntity = entityFactory.fetchOrCreateClusteredStoreEntity("TestCacheManager", CACHE_IDENTIFIER, serverStoreConfiguration, ClusteringServiceConfiguration.ClientMode.AUTO_CREATE, false); clientEntity.validate(serverStoreConfiguration); ServerStoreProxy serverStoreProxy = new CommonServerStoreProxy(CACHE_IDENTIFIER, clientEntity, mock(ServerCallback.class)); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java index d828ecf52b..9aabc6c5eb 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java @@ -21,6 +21,7 @@ import org.ehcache.Cache; import org.ehcache.clustered.client.TestTimeSource; import org.ehcache.clustered.client.config.ClusteredResourcePool; +import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntityFactory; import org.ehcache.clustered.client.internal.UnitTestConnectionService; @@ -159,7 +160,7 @@ public void setup() throws Exception { ClusteredResourcePool resourcePool = ClusteredResourcePoolBuilder.clusteredDedicated(4, MemoryUnit.MB); ServerStoreConfiguration serverStoreConfiguration = new ServerStoreConfiguration(resourcePool.getPoolAllocation(), Long.class.getName(), String.class.getName(), LongSerializer.class.getName(), StringSerializer.class.getName(), null, false); - ClusterTierClientEntity clientEntity = entityFactory.fetchOrCreateClusteredStoreEntity("TestCacheManager", CACHE_IDENTIFIER, serverStoreConfiguration, true); + ClusterTierClientEntity clientEntity = entityFactory.fetchOrCreateClusteredStoreEntity("TestCacheManager", CACHE_IDENTIFIER, serverStoreConfiguration, ClusteringServiceConfiguration.ClientMode.AUTO_CREATE, false); clientEntity.validate(serverStoreConfiguration); ServerStoreProxy serverStoreProxy = new CommonServerStoreProxy(CACHE_IDENTIFIER, clientEntity, mock(ServerCallback.class)); diff --git a/clustered/client/src/test/resources/configs/cluster-ha.xml b/clustered/client/src/test/resources/configs/cluster-ha.xml index f3e8ba0fdb..1e5ef784b0 100644 --- a/clustered/client/src/test/resources/configs/cluster-ha.xml +++ b/clustered/client/src/test/resources/configs/cluster-ha.xml @@ -23,7 +23,7 @@ 5 - + 8 diff --git a/clustered/client/src/test/resources/configs/clustered-cache.xml b/clustered/client/src/test/resources/configs/clustered-cache.xml index 4b065bd150..33e84b2194 100644 --- a/clustered/client/src/test/resources/configs/clustered-cache.xml +++ b/clustered/client/src/test/resources/configs/clustered-cache.xml @@ -23,7 +23,7 @@ 5 5 150 - + 8388608 diff --git a/clustered/client/src/test/resources/configs/simple-cluster.xml b/clustered/client/src/test/resources/configs/simple-cluster.xml index 429e80b9fe..e8016a8f54 100644 --- a/clustered/client/src/test/resources/configs/simple-cluster.xml +++ b/clustered/client/src/test/resources/configs/simple-cluster.xml @@ -23,7 +23,7 @@ 5 - + 8 diff --git a/clustered/client/src/test/resources/configs/unknown-cluster-cache-invalid-attribute.xml b/clustered/client/src/test/resources/configs/unknown-cluster-cache-invalid-attribute.xml index 89295bc1bb..80392dddd8 100644 --- a/clustered/client/src/test/resources/configs/unknown-cluster-cache-invalid-attribute.xml +++ b/clustered/client/src/test/resources/configs/unknown-cluster-cache-invalid-attribute.xml @@ -23,7 +23,7 @@ - + diff --git a/clustered/client/src/test/resources/configs/unknown-cluster-cache-invalid-element.xml b/clustered/client/src/test/resources/configs/unknown-cluster-cache-invalid-element.xml index ed0af06f8b..f200afde6b 100644 --- a/clustered/client/src/test/resources/configs/unknown-cluster-cache-invalid-element.xml +++ b/clustered/client/src/test/resources/configs/unknown-cluster-cache-invalid-element.xml @@ -23,7 +23,7 @@ - + diff --git a/clustered/client/src/test/resources/configs/unknown-cluster-cache.xml b/clustered/client/src/test/resources/configs/unknown-cluster-cache.xml index 63f9c7a278..80f4f54963 100644 --- a/clustered/client/src/test/resources/configs/unknown-cluster-cache.xml +++ b/clustered/client/src/test/resources/configs/unknown-cluster-cache.xml @@ -23,7 +23,7 @@ - + diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java similarity index 56% rename from clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerReconnectTest.java rename to clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java index 8f197c66f7..094c1e311d 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java @@ -19,18 +19,13 @@ import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.ClusteredTests; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.impl.internal.resilience.RobustResilienceStrategy; -import org.ehcache.spi.resilience.RecoveryStore; -import org.ehcache.spi.resilience.ResilienceStrategy; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; import org.junit.ClassRule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; import java.io.File; import java.net.URI; +import java.util.concurrent.TimeUnit; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; @@ -38,30 +33,16 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.hamcrest.core.Is.is; -import static org.hamcrest.core.IsInstanceOf.instanceOf; -import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertThat; -import static org.junit.internal.matchers.ThrowableMessageMatcher.hasMessage; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.hamcrest.MockitoHamcrest.argThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class CacheManagerReconnectTest extends ClusteredTests { +public class AutoCreateOnReconnectTest extends ClusteredTests { public static final String RESOURCE_CONFIG = "" + "" + "64" + "" - + "\n" - - + "" - + "" - + "30" - + "" - + ""; + + "\n"; @ClassRule public static Cluster CLUSTER = newCluster(1) @@ -75,16 +56,12 @@ public void cacheManagerCanReconnect() throws Exception { try (PersistentCacheManager cacheManager = newCacheManagerBuilder() .with(cluster(connectionURI.resolve("/crud-cm")) - .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) + .autoCreateOnReconnect(server -> server.defaultServerResource("primary-server-resource"))) .build(true)) { - @SuppressWarnings("unchecked") - ResilienceStrategy resilienceStrategy = spy(new RobustResilienceStrategy<>(mock(RecoveryStore.class))); - Cache cache = cacheManager.createCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, newResourcePoolsBuilder() .with(clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB))) - .withResilienceStrategy(resilienceStrategy) .build()); cache.put(1L, "one"); @@ -92,30 +69,11 @@ public void cacheManagerCanReconnect() throws Exception { CLUSTER.getClusterControl().terminateAllServers(); CLUSTER.getClusterControl().startAllServers(); - for (int i = 0; i < 400; i++) { - try { - assertThat(cache.get(1L), nullValue()); - verify(resilienceStrategy).getFailure(eq(1L), argThat(cause(hasMessage(is("Cache clustered-cache failed reconnecting to cluster"))))); - return; - } catch (AssertionError e) { - Thread.sleep(100); - } + while (cache.get(1L) == null) { + Thread.sleep(100); + cache.put(1L, "two"); } - throw new AssertionError(); + assertThat(cache.get(1L), is("two")); } } - - private static Matcher cause(Matcher matches) { - return new TypeSafeMatcher() { - @Override - protected boolean matchesSafely(Throwable item) { - return matches.matches(item.getCause()); - } - - @Override - public void describeTo(Description description) { - description.appendText("a throwable whose cause is ").appendDescriptionOf(matches); - } - }; - } } diff --git a/clustered/integration-test/src/test/resources/clusteredConfiguration.txt b/clustered/integration-test/src/test/resources/clusteredConfiguration.txt index e1b6721eac..4e742d8a1c 100644 --- a/clustered/integration-test/src/test/resources/clusteredConfiguration.txt +++ b/clustered/integration-test/src/test/resources/clusteredConfiguration.txt @@ -34,7 +34,7 @@ services: - org.ehcache.clustered.client.config.ClusteringServiceConfiguration: clusterUri: terracotta://server-1/my-server-entity-2 timeouts: Timeouts{readOperation=PT5S,writeOperation=PT5S,connection=PT2M30S} - autoCreate: true + clientMode: AUTO_CREATE defaultServerResource: primary-server-resource resourcePools: resource-pool-a: [10485760 bytes from ''] diff --git a/clustered/integration-test/src/test/resources/configs/clustered.xml b/clustered/integration-test/src/test/resources/configs/clustered.xml index 007d0ac885..e1e0a2a12a 100644 --- a/clustered/integration-test/src/test/resources/configs/clustered.xml +++ b/clustered/integration-test/src/test/resources/configs/clustered.xml @@ -11,8 +11,8 @@ - + - \ No newline at end of file + diff --git a/clustered/integration-test/src/test/resources/configs/jcache-clustered.xml b/clustered/integration-test/src/test/resources/configs/jcache-clustered.xml index 2d34c7c579..8e47f844a6 100644 --- a/clustered/integration-test/src/test/resources/configs/jcache-clustered.xml +++ b/clustered/integration-test/src/test/resources/configs/jcache-clustered.xml @@ -23,7 +23,7 @@ - + diff --git a/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml b/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml index 053ae5fc5e..782cf9ea9a 100644 --- a/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml +++ b/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml @@ -24,7 +24,7 @@ - + diff --git a/docs/src/docs/asciidoc/user/clustered-cache.adoc b/docs/src/docs/asciidoc/user/clustered-cache.adoc index 7de7ca7ac0..c5225aa2c9 100644 --- a/docs/src/docs/asciidoc/user/clustered-cache.adoc +++ b/docs/src/docs/asciidoc/user/clustered-cache.adoc @@ -181,7 +181,7 @@ include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/clie <1> Returns the `org.ehcache.config.builders.CacheManagerBuilder` instance. <2> Use the `ClusteringServiceConfigurationBuilder` static method `.cluster(URI)` for connecting the cache manager to the clustered storage at the `URI` specified that returns the clustering service configuration builder instance. Sample `URI` provided in the example is pointing to the clustered storage instance named "my-application" on the Terracotta server (assuming the server is running on localhost and port 9410). -<3> Auto-create the clustered storage if it doesn't already exist. +<3> Auto-create the clustered storage if it doesn't already exist. We also allow auto-create on reconnection since the cluster is not persistent. <4> Returns a fully initialized cache manager that can be used to create clustered caches. <5> Close the cache manager. @@ -221,13 +221,14 @@ When configuring a cache manager to connect to a cluster tier manager there are ---- include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerLifecycle] ---- - -<1> In auto-create mode if no cluster tier manager exists then one is created with the supplied configuration. +<1> In auto create mode if no cluster tier manager exists then one is created with the supplied configuration. If it exists and its configuration matches the supplied configuration then a connection is established. If the supplied configuration does not match then the cache manager will fail to initialize. -<2> In expected mode if a cluster tier manager exists and its configuration matches the supplied configuration then a connection is established. +<2> In auto create on reconnect mode we additionally support auto creation of any necessary entities when reconnecting to a cluster. +This behavior is useful in an non-persistent cluster in case the cluster loses its state due to a restart (planned or accidental). +<3> In expected mode if a cluster tier manager exists and its configuration matches the supplied configuration then a connection is established. If the supplied configuration does not match or the cluster tier manager does not exist then the cache manager will fail to initialize. -<3> In config-less mode if a cluster tier manager exists then a connection is established without regard to its configuration. +<4> In config-less mode if a cluster tier manager exists then a connection is established without regard to its configuration. If it does not exist then the cache manager will fail to initialize. [[clustered-cache]] @@ -313,9 +314,9 @@ The example code below shows how this can be implemented. include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=unspecifiedClusteredCacheExample] ---- -<1> Configure the first cache manager with auto create +<1> Configure the first cache manager with auto create on reconnect <2> Build a cache configuration for a clustered `dedicated` resource pool <3> Create cache `my-dedicated-cache` using the cache configuration -<4> Configure the second cache manager as _expecting_ (auto create off) +<4> Configure the second cache manager as _expecting_ <5> Build a cache configuration for a clustered _unspecified_ resource pool, which will use the previously configured clustered _dedicated_ resource pool. <6> Create cache with the same name `my-dedicated-cache` and use the clustered _unspecified_ cache configuration From e799202729bfc9ca32ec034ea1b5e13afa66a3db Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Thu, 26 Sep 2019 15:15:33 -0700 Subject: [PATCH 190/372] bump dependencies --- .../management/AbstractClusteringManagementTest.java | 2 ++ .../management/ManagementClusterConnectionTest.java | 2 ++ gradle.properties | 8 ++++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 976dd9e7d6..6c9dc0cdc2 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -174,6 +174,8 @@ protected void initCM() throws InterruptedException { // test_notifs_sent_at_CM_init waitForAllNotifications( "CLIENT_CONNECTED", + "CLIENT_PROPERTY_ADDED", + "CLIENT_PROPERTY_ADDED", "CLIENT_REGISTRY_AVAILABLE", "CLIENT_TAGS_UPDATED", "EHCACHE_RESOURCE_POOLS_CONFIGURED", diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index c37923437c..4e262c97b9 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -121,6 +121,8 @@ public static void beforeClass() throws Exception { // test_notifs_sent_at_CM_init AbstractClusteringManagementTest.waitForAllNotifications( "CLIENT_CONNECTED", + "CLIENT_PROPERTY_ADDED", + "CLIENT_PROPERTY_ADDED", "CLIENT_REGISTRY_AVAILABLE", "CLIENT_TAGS_UPDATED", "EHCACHE_RESOURCE_POOLS_CONFIGURED", diff --git a/gradle.properties b/gradle.properties index b664a18997..357f4d4c3b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,10 +10,10 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.3 -terracottaApisVersion = 1.6.1 -terracottaCoreVersion = 5.6.5 -terracottaPassthroughTestingVersion = 1.6.1 +terracottaPlatformVersion = 5.7.4-pre1 +terracottaApisVersion = 1.7.0-pre1 +terracottaCoreVersion = 5.7.0-pre2 +terracottaPassthroughTestingVersion = 1.7.0-pre1 # Test lib versions junitVersion = 4.12 From f79793fc2c31b860d5487bb51bd16b95643c524b Mon Sep 17 00:00:00 2001 From: Saurabh Agarwal Date: Thu, 17 Oct 2019 13:36:05 +0530 Subject: [PATCH 191/372] Version bumps --- .../clustered/server/ClusterTierManagerActiveEntityTest.java | 5 +++++ .../server/ClusterTierManagerPassiveEntityTest.java | 5 +++++ .../clustered/server/store/ClusterTierActiveEntityTest.java | 5 +++++ .../clustered/server/store/ClusterTierPassiveEntityTest.java | 5 +++++ gradle.properties | 4 ++-- 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java index b299335a02..0b188d6023 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java @@ -606,6 +606,11 @@ public Set getAllIdentifiers() { public OffHeapResource getOffHeapResource(OffHeapResourceIdentifier identifier) { return pools.get(identifier); } + + @Override + public boolean addOffHeapResource(OffHeapResourceIdentifier identifier, long capacity) { + return false; + } }, config.getConfig().getConfiguration(), DEFAULT_MAPPER, service -> {}); } return (T) (this.storeManagerService); diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java index 4823b90f3d..2353242754 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java @@ -366,6 +366,11 @@ public Set getAllIdentifiers() { public OffHeapResource getOffHeapResource(OffHeapResourceIdentifier identifier) { return pools.get(identifier); } + + @Override + public boolean addOffHeapResource(OffHeapResourceIdentifier identifier, long capacity) { + return false; + } }, config.getConfig().getConfiguration(), DEFAULT_MAPPER, service -> {}); } return (T) (this.storeManagerService); diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index daf4faa108..0f6422ec36 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -1356,6 +1356,11 @@ public Set getAllIdentifiers() { public OffHeapResource getOffHeapResource(OffHeapResourceIdentifier identifier) { return pools.get(identifier); } + + @Override + public boolean addOffHeapResource(OffHeapResourceIdentifier identifier, long capacity) { + return false; + } }, new ServerSideConfiguration(sharedPools), DEFAULT_MAPPER, service -> {}); try { this.storeManagerService.configure(); diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java index f418e2855b..ed2b2916b5 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java @@ -341,6 +341,11 @@ public Set getAllIdentifiers() { public OffHeapResource getOffHeapResource(OffHeapResourceIdentifier identifier) { return pools.get(identifier); } + + @Override + public boolean addOffHeapResource(OffHeapResourceIdentifier identifier, long capacity) { + return false; + } }, new ServerSideConfiguration(sharedPools), DEFAULT_MAPPER, service -> {}); try { this.storeManagerService.configure(); diff --git a/gradle.properties b/gradle.properties index 357f4d4c3b..e33e04f991 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.4-pre1 +terracottaPlatformVersion = 5.7.4-pre4 terracottaApisVersion = 1.7.0-pre1 -terracottaCoreVersion = 5.7.0-pre2 +terracottaCoreVersion = 5.7.0-pre3 terracottaPassthroughTestingVersion = 1.7.0-pre1 # Test lib versions From 860e27905f55bc7e7fa7aabc01a3171c4eb94feb Mon Sep 17 00:00:00 2001 From: Venkata Sairam Madduri Date: Thu, 31 Oct 2019 22:05:25 +0530 Subject: [PATCH 192/372] terracotta-core version bump --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index e33e04f991..86e84291f6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.4-pre4 +terracottaPlatformVersion = 5.7.4-pre5 terracottaApisVersion = 1.7.0-pre1 -terracottaCoreVersion = 5.7.0-pre3 +terracottaCoreVersion = 5.7.0-pre4 terracottaPassthroughTestingVersion = 1.7.0-pre1 # Test lib versions From a86cc925b96dd6d171ad3ac969e67a51533d9c4b Mon Sep 17 00:00:00 2001 From: Tathagata Chakraborty Date: Thu, 7 Nov 2019 11:28:35 +0530 Subject: [PATCH 193/372] Version bump --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 86e84291f6..4672ef9c8e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.4-pre5 +terracottaPlatformVersion = 5.7.4-pre6 terracottaApisVersion = 1.7.0-pre1 terracottaCoreVersion = 5.7.0-pre4 terracottaPassthroughTestingVersion = 1.7.0-pre1 From cc7757772460f90904f762af49a651865efe3b61 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 19 Nov 2019 16:39:01 -0500 Subject: [PATCH 194/372] Add Java 11 testing in Azure --- azure-pipelines-windows.yml | 14 ++++++++++++-- azure-pipelines.yml | 13 +++++++++++-- build.gradle | 6 +++++- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/azure-pipelines-windows.yml b/azure-pipelines-windows.yml index 3b7e1d0210..0242a8775b 100644 --- a/azure-pipelines-windows.yml +++ b/azure-pipelines-windows.yml @@ -20,11 +20,21 @@ resources: repositories: - repository: templates - type: git + type: git name: terracotta/terracotta jobs: -- template: build-templates/gradle-common.yml@templates +- template: build-templates/gradle-common.yml@templates parameters: vmImage: 'vs2017-win2016' gradleTasks: 'test -x :clustered:integration-test:test' + jdkVersion: '1.8' + jobName: 'Java8' + +- template: build-templates/gradle-common.yml@templates + parameters: + vmImage: 'vs2017-win2016' + gradleTasks: 'test -x :clustered:integration-test:test' + jdkVersion: '1.8' + options: '-PtestVM=java11Home' + jobName: 'Java11' diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 807c859598..09e2981ac8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -20,8 +20,17 @@ resources: repositories: - repository: templates - type: git + type: git name: terracotta/terracotta jobs: -- template: build-templates/gradle-common.yml@templates +- template: build-templates/gradle-common.yml@templates + parameters: + jdkVersion: '1.8' + jobName: 'Java8' + +- template: build-templates/gradle-common.yml@templates + parameters: + jdkVersion: '1.8' + options: '-PtestVM=java11Home' + jobName: 'Java11' diff --git a/build.gradle b/build.gradle index 8482886838..3201919352 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,11 @@ ext { } if (hasProperty('testVM')) { - testJava = Utils.jvmForHome(new File(testVM)) + File jvmHome = new File(testVM) + if (!jvmHome.exists() && hasProperty(testVM)) { + jvmHome = new File(project.property(testVM).toString()) + } + testJava = Utils.jvmForHome(jvmHome) println "Using Test JVM $testJava [Version: $testJava.javaVersion.majorVersion]" } From 09fdce4c0298369ff032258284e1673b2070b2e5 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 19 Nov 2019 13:50:35 -0500 Subject: [PATCH 195/372] Upgrade to Gradle 6.0 (and pickup new plugins versions) --- 107/build.gradle | 2 +- buildSrc/build.gradle | 6 +++--- clustered/integration-test/build.gradle | 20 ++++++++++---------- clustered/test-utils/build.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 4 ++-- settings.gradle | 6 +++--- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/107/build.gradle b/107/build.gradle index b8831ae28c..207519abde 100644 --- a/107/build.gradle +++ b/107/build.gradle @@ -42,7 +42,7 @@ dependencies { compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' - tckTestRuntime "javax.cache:cache-tests:$jcacheTckVersion" + tckTestRuntimeOnly "javax.cache:cache-tests:$jcacheTckVersion" tckTestClasses("javax.cache:cache-tests:$jcacheTckVersion:tests") { transitive = false } diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 48971da90a..a7d6b18d2c 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -39,7 +39,7 @@ gradlePlugin { } dependencies { - compile gradleApi() - compile localGroovy() - compile 'com.github.jengelman.gradle.plugins:shadow:5.1.0' + api gradleApi() + implementation localGroovy() + api 'com.github.jengelman.gradle.plugins:shadow:5.2.0' } diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index 87ffd20f03..5a7cac3389 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -19,18 +19,18 @@ configurations { } dependencies { - testCompile project(':clustered:client') - testCompile project(':clustered:common') - testCompile project(':impl') - testCompile project(':xml') - testCompile project(':107') - testCompile "org.terracotta.internal:client-runtime:$terracottaCoreVersion" - testCompile "org.terracotta:runnel:$terracottaPlatformVersion" - testCompile "org.terracotta:lease-api:$terracottaPlatformVersion" - testCompile("javax.cache:cache-tests:$jcacheTckVersion") { + testImplementation project(':clustered:client') + testImplementation project(':clustered:common') + testImplementation project(':impl') + testImplementation project(':xml') + testImplementation project(':107') + testImplementation "org.terracotta.internal:client-runtime:$terracottaCoreVersion" + testImplementation "org.terracotta:runnel:$terracottaPlatformVersion" + testImplementation "org.terracotta:lease-api:$terracottaPlatformVersion" + testImplementation("javax.cache:cache-tests:$jcacheTckVersion") { exclude group:'junit', module:'junit' } - testCompile("javax.cache:cache-tests:$jcacheTckVersion:tests") { + testImplementation("javax.cache:cache-tests:$jcacheTckVersion:tests") { exclude group:'junit', module:'junit' } diff --git a/clustered/test-utils/build.gradle b/clustered/test-utils/build.gradle index b7bfb406d0..b4a17f93c7 100644 --- a/clustered/test-utils/build.gradle +++ b/clustered/test-utils/build.gradle @@ -1,4 +1,4 @@ dependencies { - compile project(':clustered:common') - compile "org.hamcrest:hamcrest-core:$hamcrestVersion" + api project(':clustered:common') + api "org.hamcrest:hamcrest-core:$hamcrestVersion" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8d58bda447..562e2c8841 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 8e25e6c19d..83f2acfdc3 100755 --- a/gradlew +++ b/gradlew @@ -125,8 +125,8 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` diff --git a/settings.gradle b/settings.gradle index d60519cf7a..7480d3c564 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,10 +16,10 @@ pluginManagement { plugins { - id 'io.codearte.nexus-staging' version '0.21.0' - id 'com.github.spotbugs' version '2.0.0' + id 'io.codearte.nexus-staging' version '0.21.1' + id 'com.github.spotbugs' version '2.0.1' id 'org.jayware.osgi-ds' version '0.5.6' - id 'org.owasp.dependencycheck' version '5.2.1' + id 'org.owasp.dependencycheck' version '5.2.4' id 'biz.aQute.bnd.builder' version '4.1.0' id 'org.gretty' version '2.3.1' id 'org.asciidoctor.jvm.base' version '2.3.0' From e8eee3ca88753eef3f41f456191b927ba3410d2a Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 21 Nov 2019 14:10:58 -0500 Subject: [PATCH 196/372] Upgrade to Gradle 6.0.1 --- gradle/wrapper/gradle-wrapper.jar | Bin 55616 -> 58702 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 29 ++++++++++------------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016b3885f6930543d57b744ea8c220a1a..cc4fdc293d0e50b0ad9b65c16e7ddd1db2f6025b 100644 GIT binary patch delta 16535 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 Date: Thu, 21 Nov 2019 17:37:56 -0500 Subject: [PATCH 197/372] Upgrade to Jacoco 0.8.5 to support Java 13 & 14 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4672ef9c8e..51fdca0d27 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,7 +24,7 @@ jacksonVersion = 2.7.5 jcacheTckVersion = 1.1.0 # Tools -jacocoVersion = 0.8.3 +jacocoVersion = 0.8.5 sonatypeUser = OVERRIDE_ME sonatypePwd = OVERRIDE_ME From d444b091c62560d3c0f6ce37689ae81a98904a0a Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Mon, 2 Dec 2019 14:24:27 -0800 Subject: [PATCH 198/372] bump upstream dependencies --- build.gradle | 3 +++ clustered/clustered-dist/build.gradle | 2 +- clustered/server/build.gradle | 1 + gradle.properties | 6 +++--- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 3201919352..a311421249 100644 --- a/build.gradle +++ b/build.gradle @@ -149,6 +149,9 @@ subprojects { if (parent.isCloudbees) { systemProperty 'disable.concurrent.tests', 'true' } + jacoco { + excludes += "org.terracotta.tripwire.*" + } } task slowTest(type: Test) { diff --git a/clustered/clustered-dist/build.gradle b/clustered/clustered-dist/build.gradle index 8c1f4db93f..e4b0fca250 100644 --- a/clustered/clustered-dist/build.gradle +++ b/clustered/clustered-dist/build.gradle @@ -79,7 +79,7 @@ jar { 'Bundle-SymbolicName': 'org.ehcache.clustered', 'Export-Package': '!com.tc.*, !com.terracotta.*, !org.terracotta.*, !org.ehcache.*.internal.*, !sun.misc, ' + 'org.ehcache.clustered.client.*, org.ehcache.clustered.common.*', - 'Import-Package': '!sun.misc.*, org.ehcache.xml.*;resolution:=optional, *' + 'Import-Package': '!sun.misc.*, org.ehcache.xml.*;resolution:=optional, jdk.jfr.*;resolution:=optional, *' ) } diff --git a/clustered/server/build.gradle b/clustered/server/build.gradle index 68382f3ac7..5ea9ae374f 100644 --- a/clustered/server/build.gradle +++ b/clustered/server/build.gradle @@ -35,4 +35,5 @@ dependencies { providedImplementation "org.terracotta:runnel:$terracottaPlatformVersion" testImplementation project(':clustered:test-utils') + testImplementation ("org.terracotta:passthrough-server:$terracottaPassthroughTestingVersion") } diff --git a/gradle.properties b/gradle.properties index 51fdca0d27..38b589ae50 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,10 +10,10 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.4-pre6 +terracottaPlatformVersion = 5.7.4-pre7 terracottaApisVersion = 1.7.0-pre1 -terracottaCoreVersion = 5.7.0-pre4 -terracottaPassthroughTestingVersion = 1.7.0-pre1 +terracottaCoreVersion = 5.7.0-pre9 +terracottaPassthroughTestingVersion = 1.7.0-pre4 # Test lib versions junitVersion = 4.12 From c3475171e1a528e21655627ae1fa6856784f03e6 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 13 Dec 2019 09:58:48 -0500 Subject: [PATCH 199/372] Ensure the tc-tripwire-plugin is not misidentified as Tripwire --- config/owasp-supressions.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/owasp-supressions.xml b/config/owasp-supressions.xml index 310de04fc0..bfb162d6c3 100644 --- a/config/owasp-supressions.xml +++ b/config/owasp-supressions.xml @@ -19,4 +19,9 @@ ^pkg:maven/org\.ehcache.*@.*$ CVE-2019-16370 + + + ^pkg:maven/org\.terracotta/tc\-tripwire\-plugin@.*$ + cpe:/a:tripwire:tripwire + From 9b51a8fa024e761fbb364cb7ad9a68d075e79c3c Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 12 Dec 2019 16:34:14 -0500 Subject: [PATCH 200/372] Fixes #2731 : Make sure we lock when constructing a locked iterator --- .../server/offheap/OffHeapChainMap.java | 66 ++++++++++--------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java index 8dc31d2ba7..f9e7cf90e3 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java @@ -359,37 +359,43 @@ public HeadMap(EvictionListener listener, PageSource source, C } public Iterator> detachedEntryIterator() { - return new LockedEntryIterator() { - @Override - protected Entry create(IntBuffer entry) { - Entry attachedEntry = super.create(entry); - - try (InternalChain chain = attachedEntry.getValue()) { - Chain detachedChain = chain.detach(); - return new SimpleImmutableEntry<>(attachedEntry.getKey(), new InternalChain() { - @Override - public Chain detach() { - return detachedChain; - } - - @Override - public boolean append(ByteBuffer element) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean replace(Chain expected, Chain replacement) { - throw new UnsupportedOperationException(); - } - - @Override - public void close() { - // - } - }); + Lock lock = readLock(); + lock.lock(); + try { + return new LockedEntryIterator() { + @Override + protected Entry create(IntBuffer entry) { + Entry attachedEntry = super.create(entry); + + try (InternalChain chain = attachedEntry.getValue()) { + Chain detachedChain = chain.detach(); + return new SimpleImmutableEntry<>(attachedEntry.getKey(), new InternalChain() { + @Override + public Chain detach() { + return detachedChain; + } + + @Override + public boolean append(ByteBuffer element) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean replace(Chain expected, Chain replacement) { + throw new UnsupportedOperationException(); + } + + @Override + public void close() { + // + } + }); + } } - } - }; + }; + } finally { + lock.unlock(); + } } } } From 3d0faed7d072623b0559837b1b930c683854f6d1 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 12 Dec 2019 16:33:43 -0500 Subject: [PATCH 201/372] Update to offheap-store 2.5.1 --- .../offheap/OffHeapChainStorageEngine.java | 25 ++++++++++++++++--- .../server/offheap/ChainMapExtensionTest.java | 6 +++-- gradle.properties | 2 +- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java index 8601790d64..2dd995e4ad 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java @@ -17,6 +17,7 @@ import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -36,6 +37,7 @@ import org.terracotta.offheapstore.storage.portability.WriteContext; import org.terracotta.offheapstore.util.Factory; +import static java.util.Collections.emptyList; import static java.util.Collections.unmodifiableList; public class OffHeapChainStorageEngine implements ChainStorageEngine, BinaryStorageEngine { @@ -800,16 +802,31 @@ private boolean isHead(long address) { class StorageOwner implements OffHeapStorageArea.Owner { @Override - public boolean evictAtAddress(long address, boolean shrink) { - long chain = findHead(address); + public Collection evictAtAddress(long address, boolean shrink) { + Collection elements = new ArrayList<>(); + long chain = -1L; + long element = address; + do { + elements.add(element); + if (isHead(element)) { + chain = element; + element += OffHeapChainStorageEngine.this.totalChainHeaderSize; + } + element = storage.readLong(element + ELEMENT_HEADER_NEXT_OFFSET); + } while (element != address); + for (AttachedInternalChain activeChain : activeChains) { if (activeChain.chain == chain) { - return false; + return emptyList(); } } int hash = storage.readInt(chain + CHAIN_HEADER_KEY_HASH_OFFSET); int slot = owner.getSlotForHashAndEncoding(hash, chain, ~0); - return owner.evict(slot, shrink); + if (owner.evict(slot, shrink)) { + return elements; + } else { + return emptyList(); + } } @Override diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java index ea0690a3a2..a2627cd3a6 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java @@ -32,11 +32,13 @@ import org.terracotta.offheapstore.util.Factory; import java.nio.ByteBuffer; +import java.util.Collection; import java.util.HashSet; import java.util.Set; import java.util.concurrent.locks.Lock; import static org.ehcache.clustered.server.offheap.OffHeapChainMap.chain; +import static java.util.Collections.emptyList; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.emptyIterable; @@ -338,8 +340,8 @@ private void localMove(long fromChainAddress, long toChainAddress) { private class ExtendedEngineOwner implements OffHeapStorageArea.Owner { @Override - public boolean evictAtAddress(long address, boolean shrink) { - return false; + public Collection evictAtAddress(long address, boolean shrink) { + return emptyList(); } @Override diff --git a/gradle.properties b/gradle.properties index 1a1611b49f..929055370e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Terracotta third parties -offheapVersion = 2.4.0 +offheapVersion = 2.5.1 statisticVersion = 2.0.5 jcacheVersion = 1.1.0 slf4jVersion = 1.7.25 From ff0ed485dcdb5cc12bee90b311a94ee0f4416103 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 20 Dec 2019 10:36:19 -0500 Subject: [PATCH 202/372] Fixes #2734 : Make sure to free the original suffix head element --- .../offheap/OffHeapChainStorageEngine.java | 48 ++++++++++++--- .../server/offheap/ChainMapTest.java | 61 ++++++++++++++++++- 2 files changed, 99 insertions(+), 10 deletions(-) diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java index 8601790d64..a92566c435 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java @@ -39,11 +39,34 @@ import static java.util.Collections.unmodifiableList; public class OffHeapChainStorageEngine implements ChainStorageEngine, BinaryStorageEngine { + + /* + * ELEMENT + * 0 7 + * 0 | sequence number | + * 8 | length | next | + * 16 | next | [[----- + * --- contents ---]] (length bytes) + * + * `next` is the address of the next element in the chain. + * `next` on the last element in the chain points to the chain head. + * (byte 0 in the heads chain structure, not byte 0 in the element) + */ private static final int ELEMENT_HEADER_SEQUENCE_OFFSET = 0; private static final int ELEMENT_HEADER_LENGTH_OFFSET = 8; private static final int ELEMENT_HEADER_NEXT_OFFSET = 12; private static final int ELEMENT_HEADER_SIZE = 20; + /* + * CHAIN + * 0 7 + * 0 |k-length| k-hash | + * 8 | tail | + * [[--- ELEMENT ---]] + * [[ key-contents ]] (k-length bytes) + * + * `tail` is the address of the last element in the chain + */ private static final int CHAIN_HEADER_KEY_LENGTH_OFFSET = 0; private static final int CHAIN_HEADER_KEY_HASH_OFFSET = 4; private static final int CHAIN_HEADER_TAIL_OFFSET = 8; @@ -532,20 +555,20 @@ public boolean replace(Chain expected, Chain replacement) { } } - public boolean removeHeader(Chain header) { + public boolean removeHeader(Chain expected) { long suffixHead = chain + OffHeapChainStorageEngine.this.totalChainHeaderSize; - long prefixTail; - Iterator iterator = header.iterator(); + Iterator expectedIt = expected.iterator(); do { - if (!compare(iterator.next(), suffixHead)) { + if (!compare(expectedIt.next(), suffixHead)) { return true; } - prefixTail = suffixHead; suffixHead = storage.readLong(suffixHead + ELEMENT_HEADER_NEXT_OFFSET); - } while (iterator.hasNext()); + } while (expectedIt.hasNext() && suffixHead != chain); - if (suffixHead == chain) { + if (expectedIt.hasNext()) { + return true; + } else if (suffixHead == chain) { //whole chain removed int slot = owner.getSlotForHashAndEncoding(readKeyHash(chain), chain, ~0); if (!owner.evict(slot, true)) { @@ -570,7 +593,10 @@ public boolean removeHeader(Chain header) { } if (owner.updateEncoding(hash, chain, newChainAddress, ~0)) { - storage.writeLong(prefixTail + ELEMENT_HEADER_NEXT_OFFSET, chain); + // NOTE: we leave the original suffix head attached to the prefix so that it gets freed along with the + // prefix since we took a copy of it for the new chain. + storage.writeLong(suffixHead + ELEMENT_HEADER_NEXT_OFFSET, chain); + storage.writeLong(chain + CHAIN_HEADER_TAIL_OFFSET, suffixHead); chainMoved(chain, newChainAddress); free(); return true; @@ -594,7 +620,11 @@ public boolean replaceHeader(Chain expected, Chain replacement) { } prefixTail = suffixHead; suffixHead = storage.readLong(suffixHead + ELEMENT_HEADER_NEXT_OFFSET); - } while (expectedIt.hasNext()); + } while (expectedIt.hasNext() && suffixHead != chain); + + if (expectedIt.hasNext()) { + return true; + } int hash = readKeyHash(chain); Long newChainAddress = createAttachedChain(readKeyBuffer(chain), hash, replacement.iterator()); diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java index 533ec3b007..63f239cef2 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java @@ -78,6 +78,8 @@ public void testInitiallyEmptyChain() { OffHeapChainMap map = new OffHeapChainMap<>(new UnlimitedPageSource(new OffHeapBufferSource()), StringPortability.INSTANCE, minPageSize, maxPageSize, steal); assertThat(map.get("foo"), emptyIterable()); + + emptyAndValidate(map); } @Test @@ -86,6 +88,8 @@ public void testAppendToEmptyChain() { map.append("foo", buffer(1)); assertThat(map.get("foo"), contains(element(1))); + + emptyAndValidate(map); } @Test @@ -94,6 +98,8 @@ public void testGetAndAppendToEmptyChain() { assertThat(map.getAndAppend("foo", buffer(1)), emptyIterable()); assertThat(map.get("foo"), contains(element(1))); + + emptyAndValidate(map); } @Test @@ -103,6 +109,8 @@ public void testAppendToSingletonChain() { map.append("foo", buffer(2)); assertThat(map.get("foo"), contains(element(1), element(2))); + + emptyAndValidate(map); } @Test @@ -112,6 +120,8 @@ public void testGetAndAppendToSingletonChain() { assertThat(map.getAndAppend("foo", buffer(2)), contains(element(1))); assertThat(map.get("foo"), contains(element(1), element(2))); + + emptyAndValidate(map); } @Test @@ -122,6 +132,8 @@ public void testAppendToDoubleChain() { map.append("foo", buffer(3)); assertThat(map.get("foo"), contains(element(1), element(2), element(3))); + + emptyAndValidate(map); } @Test @@ -132,6 +144,8 @@ public void testGetAndAppendToDoubleChain() { assertThat(map.getAndAppend("foo", buffer(3)), contains(element(1), element(2))); assertThat(map.get("foo"), contains(element(1), element(2), element(3))); + + emptyAndValidate(map); } @Test @@ -143,6 +157,8 @@ public void testAppendToTripleChain() { map.append("foo", buffer(4)); assertThat(map.get("foo"), contains(element(1), element(2), element(3), element(4))); + + emptyAndValidate(map); } @Test @@ -154,6 +170,8 @@ public void testGetAndAppendToTripleChain() { assertThat(map.getAndAppend("foo", buffer(4)), contains(element(1), element(2), element(3))); assertThat(map.get("foo"), contains(element(1), element(2), element(3), element(4))); + + emptyAndValidate(map); } @Test @@ -166,6 +184,8 @@ public void testReplaceEmptyChainAtHeadOnEmptyChainFails() { } catch (IllegalArgumentException e) { //expected } + + emptyAndValidate(map); } @Test @@ -179,6 +199,8 @@ public void testReplaceEmptyChainAtHeadOnNonEmptyChain() { } catch (IllegalArgumentException e) { //expected } + + emptyAndValidate(map); } @Test @@ -188,6 +210,8 @@ public void testMismatchingReplaceSingletonChainAtHeadOnSingletonChain() { map.replaceAtHead("foo", chain(buffer(2)), chain(buffer(42))); assertThat(map.get("foo"), contains(element(1))); + + emptyAndValidate(map); } @Test @@ -197,6 +221,8 @@ public void testReplaceSingletonChainAtHeadOnSingletonChain() { map.replaceAtHead("foo", chain(buffer(1)), chain(buffer(42))); assertThat(map.get("foo"), contains(element(42))); + + emptyAndValidate(map); } @Test @@ -207,6 +233,8 @@ public void testReplaceSingletonChainAtHeadOnDoubleChain() { map.replaceAtHead("foo", chain(buffer(1)), chain(buffer(42))); assertThat(map.get("foo"), contains(element(42), element(2))); + + emptyAndValidate(map); } @Test @@ -218,6 +246,8 @@ public void testReplaceSingletonChainAtHeadOnTripleChain() { map.replaceAtHead("foo", chain(buffer(1)), chain(buffer(42))); assertThat(map.get("foo"), contains(element(42), element(2), element(3))); + + emptyAndValidate(map); } @Test @@ -228,6 +258,8 @@ public void testMismatchingReplacePluralChainAtHead() { map.replaceAtHead("foo", chain(buffer(1), buffer(3)), chain(buffer(42))); assertThat(map.get("foo"), contains(element(1), element(2))); + + emptyAndValidate(map); } @Test @@ -238,6 +270,8 @@ public void testReplacePluralChainAtHeadOnDoubleChain() { map.replaceAtHead("foo", chain(buffer(1), buffer(2)), chain(buffer(42))); assertThat(map.get("foo"), contains(element(42))); + + emptyAndValidate(map); } @Test @@ -249,6 +283,8 @@ public void testReplacePluralChainAtHeadOnTripleChain() { map.replaceAtHead("foo", chain(buffer(1), buffer(2)), chain(buffer(42))); assertThat(map.get("foo"), contains(element(42), element(3))); + + emptyAndValidate(map); } @Test @@ -262,6 +298,8 @@ public void testReplacePluralChainAtHeadWithEmpty() { map.replaceAtHead("foo", chain(buffer(1), buffer(2)), chain()); assertThat(map.getDataOccupiedMemory(), lessThan(before)); assertThat(map.get("foo"), contains(element(3))); + + emptyAndValidate(map); } @Test @@ -273,6 +311,8 @@ public void testSequenceBasedChainComparison() { map.replaceAtHead("foo", map.get("foo"), chain()); assertThat(map.get("foo"), emptyIterable()); + + emptyAndValidate(map); } @Test @@ -286,6 +326,8 @@ public void testReplaceFullPluralChainAtHeadWithEmpty() { map.replaceAtHead("foo", chain(buffer(1), buffer(2), buffer(3)), chain()); assertThat(map.getDataOccupiedMemory(), is(0L)); assertThat(map.get("foo"), emptyIterable()); + + emptyAndValidate(map); } @Test @@ -311,6 +353,9 @@ public void testContinualAppendCausingEvictionIsStable() { break; } } + + emptyAndValidate(mapA); + emptyAndValidate(mapB); } else { OffHeapChainMap map = new OffHeapChainMap<>(pageSource, StringPortability.INSTANCE, minPageSize, maxPageSize, false); @@ -328,6 +373,8 @@ public void testContinualAppendCausingEvictionIsStable() { break; } } + + emptyAndValidate(map); } } @@ -338,6 +385,8 @@ public void testPutWhenKeyIsNotNull() { map.put("key", chain(buffer(1), buffer(2))); assertThat(map.get("key"), contains(element(1), element(2))); + + emptyAndValidate(map); } @Test @@ -346,6 +395,8 @@ public void testPutWhenKeyIsNull() { map.put("key", chain(buffer(1), buffer(2))); assertThat(map.get("key"), contains(element(1), element(2))); + + emptyAndValidate(map); } @Test @@ -374,6 +425,7 @@ public void testActiveChainsThreadSafety() throws ExecutionException, Interrupte assertThat(chainStorage.getActiveChains().size(), is(0)); + emptyAndValidate(map); } @Test @@ -390,6 +442,7 @@ public void testPutDoesNotLeakWhenMappingIsNotNull() { assertThat(chainStorage.getActiveChains().size(), is(0)); + emptyAndValidate(map); } private static ByteBuffer buffer(int i) { @@ -414,5 +467,11 @@ public void describeTo(Description description) { }; } - + private void emptyAndValidate(OffHeapChainMap map) { + for (String key : map.keySet()) { + map.replaceAtHead(key, map.get(key), chain()); + } + assertThat(map.getSize(), is(0L)); + assertThat(map.getDataOccupiedMemory(), is(0L)); + } } From cb12d3450c48d44a4b7965f4f5137a65c0499e2a Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 20 Dec 2019 13:45:37 -0500 Subject: [PATCH 203/372] Terracotta Core Upgrades --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 89d9995215..f2749136df 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,8 +12,8 @@ jaxbVersion = 2.3.1 # Terracotta clustered terracottaPlatformVersion = 5.7.4-pre7 terracottaApisVersion = 1.7.0-pre1 -terracottaCoreVersion = 5.7.0-pre9 -terracottaPassthroughTestingVersion = 1.7.0-pre4 +terracottaCoreVersion = 5.7.0-pre13 +terracottaPassthroughTestingVersion = 1.7.0-pre6 # Test lib versions junitVersion = 4.12 From ea626cd4afa0f7c94b20acf398021d985660ab32 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 13 Jan 2020 09:47:21 -0500 Subject: [PATCH 204/372] Bump minor version to become Ehcache 3.9 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 357f4d4c3b..13fdaf4e7a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # Ehcache version -ehcacheVersion = 3.8-SNAPSHOT +ehcacheVersion = 3.9-SNAPSHOT # Terracotta third parties offheapVersion = 2.4.3 From 504797ee259edeb03145540b43ecdf588d963960 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 28 Jan 2020 15:45:51 -0500 Subject: [PATCH 205/372] Issue #2739 : Move to PAX-URL 2.6.1 for standalone OSGi tests. --- osgi-test/build.gradle | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/osgi-test/build.gradle b/osgi-test/build.gradle index ec6e16d174..7ed674bc2f 100644 --- a/osgi-test/build.gradle +++ b/osgi-test/build.gradle @@ -37,6 +37,22 @@ dependencies { } +configurations.all { + resolutionStrategy { + dependencySubstitution { + substitute(module('org.ops4j.pax.url:pax-url-aether:2.0.0')) +// .because('https://ops4j1.jira.com/browse/PAXURL-341') + .with(module('org.ops4j.pax.url:pax-url-aether:2.6.1')) + substitute(module('org.ops4j.pax.url:pax-url-classpath:2.0.0')) +// .because('https://ops4j1.jira.com/browse/PAXURL-341') + .with(module('org.ops4j.pax.url:pax-url-classpath:2.6.1')) + substitute(module('org.ops4j.pax.url:pax-url-link:2.0.0')) +// .because('https://ops4j1.jira.com/browse/PAXURL-341') + .with(module('org.ops4j.pax.url:pax-url-link:2.6.1')) + } + } +} + sourceSets { test { // Needed for PaxExam which makes the dynamic bundle load content of a single dir From 56b90de2551d879b9e513afdfbfab82c6b247660 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 28 Jan 2020 16:19:38 -0500 Subject: [PATCH 206/372] Issue #2739 : Move to PAX-URL 2.6.1 for clustered OSGi tests. --- clustered/osgi-test/build.gradle | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/clustered/osgi-test/build.gradle b/clustered/osgi-test/build.gradle index f16d5fffa1..4a47485293 100644 --- a/clustered/osgi-test/build.gradle +++ b/clustered/osgi-test/build.gradle @@ -46,7 +46,7 @@ dependencies { testRuntimeOnly ('org.ops4j.pax.exam:pax-exam-link-mvn:4.12.0') { exclude group:'org.slf4j', module:'slf4j-api' } - testRuntimeOnly ("org.ops4j.pax.url:pax-url-wrap:2.4.5") { + testRuntimeOnly ("org.ops4j.pax.url:pax-url-wrap:2.6.1") { exclude group:'org.slf4j', module:'slf4j-api' } @@ -54,9 +54,17 @@ dependencies { configurations.all { resolutionStrategy { - force 'org.ops4j.base:ops4j-base-lang:1.5.0' - force 'org.ops4j.base:ops4j-base-net:1.5.0' - force 'org.ops4j.base:ops4j-base-util-property:1.5.0' + dependencySubstitution { + substitute(module('org.ops4j.pax.url:pax-url-aether:2.4.5')) + .because('https://ops4j1.jira.com/browse/PAXURL-341') + .with(module('org.ops4j.pax.url:pax-url-aether:2.6.1')) + substitute(module('org.ops4j.pax.url:pax-url-classpath:2.4.5')) + .because('https://ops4j1.jira.com/browse/PAXURL-341') + .with(module('org.ops4j.pax.url:pax-url-classpath:2.6.1')) + substitute(module('org.ops4j.pax.url:pax-url-link:2.4.5')) + .because('https://ops4j1.jira.com/browse/PAXURL-341') + .with(module('org.ops4j.pax.url:pax-url-link:2.6.1')) + } } } From 7f516237e75875cc0f02cbfbeb410ac3a7ba3454 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 28 Jan 2020 14:09:50 -0500 Subject: [PATCH 207/372] Upgrade to Platform 5.7.4-pre8 to pickup Windows MAC Address performance fix --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index eef8788f5e..c9b9e102d2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.4-pre7 +terracottaPlatformVersion = 5.7.4-pre8 terracottaApisVersion = 1.7.0-pre1 terracottaCoreVersion = 5.7.0-pre13 terracottaPassthroughTestingVersion = 1.7.0-pre6 From 0d59346f8747e0558f3cff60be3f5783df7eec0b Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 6 Mar 2020 17:52:15 -0500 Subject: [PATCH 208/372] Server side entity splitting --- buildSrc/build.gradle | 4 + buildSrc/src/main/groovy/EhVoltron.groovy | 48 ++++++ clustered/client/build.gradle | 4 +- clustered/clustered-dist/build.gradle | 37 +++-- clustered/common-api/build.gradle | 24 +++ .../config/checkstyle-suppressions.xml | 0 .../{server => common-api}/gradle.properties | 4 +- .../ehcache/clustered/common/Consistency.java | 0 .../clustered/common/PoolAllocation.java | 0 .../common/ServerSideConfiguration.java | 0 .../ClusterTierManagerConfiguration.java | 0 .../internal/ServerStoreConfiguration.java | 0 .../internal/exceptions/ClusterException.java | 0 .../DestroyInProgressException.java | 0 ...validServerSideConfigurationException.java | 0 .../exceptions/InvalidStoreException.java | 0 .../exceptions/LifecycleException.java | 0 .../messages/EhcacheEntityMessage.java | 0 .../messages/EhcacheEntityResponse.java | 0 .../internal/messages/EhcacheMessageType.java | 0 .../messages/EhcacheOperationMessage.java | 0 .../messages/EhcacheResponseType.java | 0 .../messages/StateRepositoryOpMessage.java | 0 .../common/internal/store/Chain.java | 0 .../common/internal/store/Element.java | 0 .../common/internal/store/ServerStore.java | 0 .../common/internal/store/ValueWrapper.java | 0 .../common/ServerSideConfigurationTest.java | 0 clustered/common/build.gradle | 2 + .../BasicCacheOpsMultiThreadedTest.java | 3 +- .../clustered/BasicClusteredCacheOpsTest.java | 3 +- .../clustered/BasicEntityInteractionTest.java | 3 +- ...anagerLifecycleEhcacheIntegrationTest.java | 2 +- ...gerClientEntityFactoryIntegrationTest.java | 3 +- .../clustered/ClusteredIterationTest.java | 3 +- .../clustered/ClusteredLoaderWriterTest.java | 3 +- .../org/ehcache/clustered/ClusteredTests.java | 4 + .../ehcache/clustered/DestroyLoopTest.java | 3 +- .../clustered/EventsFailureBehaviorTest.java | 5 +- .../IterationFailureBehaviorTest.java | 3 +- .../clustered/JCacheClusteredTest.java | 3 +- .../java/org/ehcache/clustered/LeaseTest.java | 3 +- .../clustered/OversizedCacheOpsTest.java | 3 +- .../clustered/ReconnectDuringDestroyTest.java | 3 +- .../ResourcePoolAllocationFailureTest.java | 4 +- .../clustered/TerminatedServerTest.java | 9 +- .../VoltronReadWriteLockIntegrationTest.java | 3 +- ...onReadWriteLockPassiveIntegrationTest.java | 6 +- .../AbstractClusteringManagementTest.java | 16 +- .../management/CMClosedEventSentTest.java | 7 +- .../EhcacheConfigWithManagementTest.java | 4 +- .../ManagementClusterConnectionTest.java | 6 +- .../reconnect/AutoCreateOnReconnectTest.java | 4 +- .../reconnect/BasicCacheReconnectTest.java | 3 +- .../CacheManagerDestroyReconnectTest.java | 3 +- .../reconnect/EventsReconnectTest.java | 3 +- ...dCacheOpsReplicationMultiThreadedTest.java | 5 +- ...BasicClusteredCacheOpsReplicationTest.java | 6 +- ...OpsReplicationWithMultipleClientsTest.java | 5 +- ...CacheOpsReplicationWithServersApiTest.java | 3 +- .../BasicLifeCyclePassiveReplicationTest.java | 5 +- .../clustered/replication/DuplicateTest.java | 3 +- .../OversizedCacheOpsPassiveTest.java | 3 +- .../clustered/sync/PassiveSyncTest.java | 3 +- .../clustered/util/ParallelTestCluster.java | 14 -- ...icClusteredWriteBehindMultiClientTest.java | 4 +- .../BasicClusteredWriteBehindTest.java | 3 +- ...WriteBehindWithPassiveMultiClientTest.java | 4 +- ...icClusteredWriteBehindWithPassiveTest.java | 6 +- .../java/org/ehcache/osgi/OsgiTestUtils.java | 2 +- clustered/server/build.gradle | 39 ----- clustered/server/entity/build.gradle | 32 ++++ .../entity/config/checkstyle-suppressions.xml | 9 ++ clustered/server/entity/gradle.properties | 18 +++ .../VoltronReadWriteLockActiveEntity.java | 0 .../VoltronReadWriteLockPassiveEntity.java | 0 ...ltronReadWriteLockServerEntityService.java | 0 .../server/messages/LockSyncMessaging.java | 0 .../ClusterTierManagerActiveEntity.java | 0 .../server/ClusterTierManagerDump.java | 0 .../ClusterTierManagerPassiveEntity.java | 0 ...ClusterTierManagerServerEntityService.java | 0 .../CommunicatorServiceConfiguration.java | 0 .../server/ConcurrencyStrategies.java | 0 .../server/EhcacheExecutionStrategy.java | 0 .../server/ServerStoreCompatibility.java | 0 .../messages/EhcacheDataSyncMessage.java | 3 - .../EhcacheMessageTrackerMessage.java | 2 - .../internal/messages/EhcacheServerCodec.java | 0 .../messages/EhcacheSyncMessageCodec.java | 0 .../messages/PassiveReplicationMessage.java | 0 .../PassiveReplicationMessageCodec.java | 0 .../management/ClusterTierManagement.java | 0 .../management/ClusterTierManagerBinding.java | 0 ...TierManagerSettingsManagementProvider.java | 0 .../server/management/Management.java | 0 .../server/management/Notification.java | 0 .../server/management/PoolBinding.java | 0 .../PoolSettingsManagementProvider.java | 0 .../PoolStatisticsManagementProvider.java | 0 .../server/management/ServerStoreBinding.java | 0 ...ServerStoreSettingsManagementProvider.java | 0 ...rverStoreStatisticsManagementProvider.java | 0 .../server/store/ClusterTierActiveEntity.java | 0 .../server/store/ClusterTierDump.java | 0 .../store/ClusterTierPassiveEntity.java | 0 .../store/ClusterTierServerEntityService.java | 0 .../server/store/LockManagerImpl.java | 0 .../MessageToTrackerSegmentFunction.java | 0 .../server/store/NoopLockManager.java | 0 .../server/store/ServerLockManager.java | 0 .../org.terracotta.entity.EntityServerService | 0 .../VoltronReadWriteLockActiveEntityTest.java | 0 .../ClusterTierManagerActiveEntityTest.java | 0 .../ClusterTierManagerPassiveEntityTest.java | 0 .../DefaultConcurrencyStrategyTest.java | 0 .../server/ServerStoreCompatibilityTest.java | 0 .../server/TestClientDescriptor.java | 0 .../clustered/server/TestClientSourceId.java | 0 .../clustered/server/TestInvokeContext.java | 0 .../EhcacheMessageTrackerMessageTest.java | 0 .../messages/EhcacheServerCodecTest.java | 0 .../messages/EhcacheSyncMessageCodecTest.java | 0 .../PassiveReplicationMessageCodecTest.java | 0 .../store/ClusterTierActiveEntityTest.java | 0 .../store/ClusterTierPassiveEntityTest.java | 0 .../server/store/InvalidMessage.java | 0 .../server/store/LockManagerImplTest.java | 0 clustered/server/service-api/build.gradle | 26 +++ .../config/checkstyle-suppressions.xml | 9 ++ .../server/service-api/gradle.properties | 18 +++ .../clustered/server/KeySegmentMapper.java | 3 - .../server/ServerSideServerStore.java | 3 - .../server/ServerStoreEventListener.java | 2 - .../messages/EhcacheStateRepoSyncMessage.java | 3 - .../internal/messages/EhcacheSyncMessage.java | 3 - .../internal/messages/SyncMessageType.java | 3 - .../server/offheap/InternalChain.java | 2 - .../server/repo/ServerStateRepository.java | 0 .../server/repo/StateRepositoryManager.java | 3 - .../server/state/EhcacheStateContext.java | 3 - .../server/state/EhcacheStateService.java | 3 - .../server/state/InvalidationTracker.java | 3 - .../server/state/ResourcePageSource.java | 2 - .../config/EhcacheStateServiceConfig.java | 3 - .../EhcacheStoreStateServiceConfig.java | 3 - .../repo/ServerStateRepositoryTest.java | 0 .../repo/StateRepositoryManagerTest.java | 0 clustered/server/service/build.gradle | 31 ++++ .../config/checkstyle-suppressions.xml | 9 ++ clustered/server/service/gradle.properties | 18 +++ .../server/EhcacheStateServiceImpl.java | 0 .../clustered/server/ServerStoreImpl.java | 3 - .../server/offheap/ChainStorageEngine.java | 0 .../server/offheap/LongPortability.java | 0 .../server/offheap/OffHeapChainMap.java | 0 .../offheap/OffHeapChainStorageEngine.java | 0 .../server/offheap/OffHeapServerStore.java | 0 .../offheap/PinningOffHeapChainMap.java | 0 .../server/state/EhcacheStateServiceDump.java | 0 .../state/EhcacheStateServiceProvider.java | 0 .../server/state/InvalidationTrackerImpl.java | 0 .../org.terracotta.entity.ServiceProvider | 0 .../main/resources/offheap-message.properties | 0 .../server/EhcacheStateServiceImplTest.java | 0 .../server/offheap/ChainMapExtensionTest.java | 0 .../server/offheap/ChainMapTest.java | 0 .../offheap/OffHeapServerStoreTest.java | 0 .../offheap/PinningOffHeapChainMapTest.java | 0 .../EhcacheStateServiceProviderTest.java | 0 .../state/InvalidationTrackerImplTest.java | 0 .../clustered/server/store/ChainBuilder.java | 0 .../server/store/ElementBuilder.java | 0 .../server/store/ServerStoreTest.java | 0 .../server/store/impl/HeapChainBuilder.java | 0 .../server/store/impl/HeapChainImpl.java | 0 .../server/store/impl/HeapElementBuilder.java | 0 .../server/store/impl/HeapElementImpl.java | 0 .../server/store/impl/ReferenceStoreImpl.java | 0 .../server/store/impl/ReferenceStoreTest.java | 0 .../server/state/MessageTracker.java | 149 ------------------ gradle.properties | 4 +- settings.gradle | 5 +- 183 files changed, 343 insertions(+), 375 deletions(-) create mode 100644 buildSrc/src/main/groovy/EhVoltron.groovy create mode 100644 clustered/common-api/build.gradle rename clustered/{server => common-api}/config/checkstyle-suppressions.xml (100%) rename clustered/{server => common-api}/gradle.properties (83%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/Consistency.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/PoolAllocation.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/ServerSideConfiguration.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/ClusterTierManagerConfiguration.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/ServerStoreConfiguration.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/exceptions/ClusterException.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/exceptions/DestroyInProgressException.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationException.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreException.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/exceptions/LifecycleException.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityMessage.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheOperationMessage.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpMessage.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/store/Chain.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/store/Element.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java (100%) rename clustered/{common => common-api}/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java (100%) rename clustered/{common => common-api}/src/test/java/org/ehcache/clustered/common/ServerSideConfigurationTest.java (100%) delete mode 100644 clustered/server/build.gradle create mode 100644 clustered/server/entity/build.gradle create mode 100644 clustered/server/entity/config/checkstyle-suppressions.xml create mode 100644 clustered/server/entity/gradle.properties rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntity.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockPassiveEntity.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockServerEntityService.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/lock/server/messages/LockSyncMessaging.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntity.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/ClusterTierManagerDump.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntity.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/ClusterTierManagerServerEntityService.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/CommunicatorServiceConfiguration.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/ConcurrencyStrategies.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/EhcacheExecutionStrategy.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/ServerStoreCompatibility.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheDataSyncMessage.java (95%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java (97%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessage.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagement.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerBinding.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerSettingsManagementProvider.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/management/Management.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/management/Notification.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/management/PoolBinding.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/management/PoolSettingsManagementProvider.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/management/PoolStatisticsManagementProvider.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/management/ServerStoreBinding.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/management/ServerStoreStatisticsManagementProvider.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/store/ClusterTierDump.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/store/LockManagerImpl.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/store/MessageToTrackerSegmentFunction.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/store/NoopLockManager.java (100%) rename clustered/server/{ => entity}/src/main/java/org/ehcache/clustered/server/store/ServerLockManager.java (100%) rename clustered/server/{ => entity}/src/main/resources/META-INF/services/org.terracotta.entity.EntityServerService (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/DefaultConcurrencyStrategyTest.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/TestClientSourceId.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/TestInvokeContext.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessageTest.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodecTest.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/store/InvalidMessage.java (100%) rename clustered/server/{ => entity}/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java (100%) create mode 100644 clustered/server/service-api/build.gradle create mode 100644 clustered/server/service-api/config/checkstyle-suppressions.xml create mode 100644 clustered/server/service-api/gradle.properties rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/KeySegmentMapper.java (93%) rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java (95%) rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java (96%) rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java (95%) rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessage.java (93%) rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java (95%) rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java (94%) rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/repo/ServerStateRepository.java (100%) rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/repo/StateRepositoryManager.java (97%) rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/state/EhcacheStateContext.java (93%) rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java (97%) rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/state/InvalidationTracker.java (93%) rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java (97%) rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStateServiceConfig.java (96%) rename clustered/server/{ => service-api}/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStoreStateServiceConfig.java (95%) rename clustered/server/{ => service-api}/src/test/java/org/ehcache/clustered/server/repo/ServerStateRepositoryTest.java (100%) rename clustered/server/{ => service-api}/src/test/java/org/ehcache/clustered/server/repo/StateRepositoryManagerTest.java (100%) create mode 100644 clustered/server/service/build.gradle create mode 100644 clustered/server/service/config/checkstyle-suppressions.xml create mode 100644 clustered/server/service/gradle.properties rename clustered/server/{ => service}/src/main/java/org/ehcache/clustered/server/EhcacheStateServiceImpl.java (100%) rename clustered/server/{ => service}/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java (98%) rename clustered/server/{ => service}/src/main/java/org/ehcache/clustered/server/offheap/ChainStorageEngine.java (100%) rename clustered/server/{ => service}/src/main/java/org/ehcache/clustered/server/offheap/LongPortability.java (100%) rename clustered/server/{ => service}/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java (100%) rename clustered/server/{ => service}/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java (100%) rename clustered/server/{ => service}/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java (100%) rename clustered/server/{ => service}/src/main/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMap.java (100%) rename clustered/server/{ => service}/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceDump.java (100%) rename clustered/server/{ => service}/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java (100%) rename clustered/server/{ => service}/src/main/java/org/ehcache/clustered/server/state/InvalidationTrackerImpl.java (100%) rename clustered/server/{ => service}/src/main/resources/META-INF/services/org.terracotta.entity.ServiceProvider (100%) rename clustered/server/{ => service}/src/main/resources/offheap-message.properties (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/EhcacheStateServiceImplTest.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/state/EhcacheStateServiceProviderTest.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/state/InvalidationTrackerImplTest.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/store/ChainBuilder.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/store/ElementBuilder.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainBuilder.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainImpl.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementBuilder.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementImpl.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java (100%) rename clustered/server/{ => service}/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreTest.java (100%) delete mode 100644 clustered/server/src/main/java/org/ehcache/clustered/server/state/MessageTracker.java diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index a7d6b18d2c..0af1840fab 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -35,6 +35,10 @@ gradlePlugin { id = 'org.ehcache.build.pom-mangle' implementationClass = 'EhPomMangle' } + ehVoltron { + id = 'org.ehcache.build.voltron' + implementationClass = 'EhVoltron' + } } } diff --git a/buildSrc/src/main/groovy/EhVoltron.groovy b/buildSrc/src/main/groovy/EhVoltron.groovy new file mode 100644 index 0000000000..552e69156a --- /dev/null +++ b/buildSrc/src/main/groovy/EhVoltron.groovy @@ -0,0 +1,48 @@ +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.artifacts.ModuleDependency +import org.gradle.api.plugins.JavaPlugin +import org.gradle.api.tasks.bundling.Jar + +class EhVoltron implements Plugin { + @Override + void apply(Project project) { + project.plugins.withId('java') { + def voltron = project.configurations.create('voltron') { voltron -> + description "Dependencies provided by Voltron from server/lib" + canBeResolved true + canBeConsumed true + + voltron.dependencies.add(project.dependencies.create(group: 'org.terracotta', name: 'entity-server-api', version: project.terracottaApisVersion)) + voltron.dependencies.add(project.dependencies.create(group: 'org.terracotta', name: 'standard-cluster-services', version: project.terracottaApisVersion)) + voltron.dependencies.add(project.dependencies.create(group: 'org.terracotta', name: 'packaging-support', version: project.terracottaApisVersion)) + voltron.dependencies.add(project.dependencies.create(group: 'org.slf4j', name: 'slf4j-api', version: project.slf4jVersion)) + } + def service = project.configurations.create('service') { service -> + description "Services consumed by this plugin" + canBeResolved true + canBeConsumed true + + service.withDependencies { deps -> + def monitoringServiceApi = deps.find { it.group == 'org.terracotta.management' && it.name == 'monitoring-service-api' } as ModuleDependency + if (monitoringServiceApi != null) { + monitoringServiceApi.transitive = false + } + } + } + + project.configurations.getByName(JavaPlugin.API_CONFIGURATION_NAME) { api -> + api.extendsFrom voltron + api.extendsFrom service + } + + project.tasks.named(JavaPlugin.JAR_TASK_NAME, Jar) { + doFirst { + manifest { + attributes('Class-Path': (project.configurations.runtimeClasspath - project.configurations.voltron - project.configurations.service).collect { it.getName() }.join(' ')) + } + } + } + } + } +} diff --git a/clustered/client/build.gradle b/clustered/client/build.gradle index 87f26c0423..fb73911eba 100644 --- a/clustered/client/build.gradle +++ b/clustered/client/build.gradle @@ -33,9 +33,11 @@ dependencies { testImplementation project(':impl') testImplementation project(':xml') testImplementation project(':transactions') - testImplementation(project(':clustered:server')) { + testImplementation(project(':clustered:server:entity')) { exclude group: 'org.terracotta.internal', module: 'tc-config-parser' } + testImplementation project(':clustered:server:service') + testImplementation "org.terracotta:client-message-tracker:$terracottaPlatformVersion" testImplementation project(':clustered:test-utils') testImplementation "org.terracotta:entity-test-lib:$terracottaPassthroughTestingVersion" testImplementation "org.terracotta:passthrough-server:$terracottaPassthroughTestingVersion" diff --git a/clustered/clustered-dist/build.gradle b/clustered/clustered-dist/build.gradle index e4b0fca250..9b24b8b9ad 100644 --- a/clustered/clustered-dist/build.gradle +++ b/clustered/clustered-dist/build.gradle @@ -41,26 +41,40 @@ dependencies { compileOnly "org.terracotta:runnel:$parent.terracottaPlatformVersion" } +def voltronProvides = { Configuration c -> + c.exclude group:'org.slf4j', module:'slf4j-api' + c.exclude group:'org.terracotta', module:'entity-server-api' + c.exclude group:'org.terracotta', module:'entity-common-api' + c.exclude group:'org.terracotta', module:'packaging-support' + c.exclude group:'org.terracotta', module:'standard-cluster-services' +} + configurations { kit - serverLibs + serverApis(voltronProvides) + serverLibs(voltronProvides) } dependencies { compileOnly "org.terracotta.internal:client-runtime:$terracottaCoreVersion" compileOnly "org.terracotta:lease-api:$terracottaPlatformVersion" - serverLibs(project(':clustered:server')) { - exclude group: 'org.terracotta', module: 'entity-server-api' - exclude group: 'org.terracotta', module: 'entity-common-api' - exclude group: 'org.terracotta', module: 'packaging-support' - exclude group: 'org.terracotta.internal', module: 'tc-config-parser' + serverApis "org.terracotta:statistics:$statisticVersion" + serverApis("org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion") { + transitive = false } + // this is here because monitoring-service-api depends on mnm-common. if that can be unwound, + // mnm-common can go into lib + serverApis "org.terracotta.management.dist:mnm-common:$terracottaPlatformVersion" - // Needed because declared as provided in the different projects - serverLibs "org.terracotta:runnel:$parent.terracottaPlatformVersion" + serverApis project(':clustered:server:service-api') + serverLibs project(':clustered:server:entity') + serverLibs project(':clustered:server:service') - serverLibs "org.terracotta:lease-entity-server:$parent.terracottaPlatformVersion" + serverLibs("org.terracotta:lease-entity-server:$parent.terracottaPlatformVersion") { + transitive = false + } + serverLibs "org.terracotta.management.dist:mnm-server:$terracottaPlatformVersion" kit "org.terracotta.internal:terracotta-kit:$terracottaCoreVersion@tar.gz" @@ -100,8 +114,11 @@ distributions { } includeEmptyDirs = false } + into ("server/plugins/api") { + from configurations.serverApis + } into ("server/plugins/lib") { - from configurations.serverLibs + from (configurations.serverLibs - configurations.serverApis) } into ('client/ehcache') { from jar diff --git a/clustered/common-api/build.gradle b/clustered/common-api/build.gradle new file mode 100644 index 0000000000..454b4fc4f5 --- /dev/null +++ b/clustered/common-api/build.gradle @@ -0,0 +1,24 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id 'org.ehcache.build.deploy' + id 'org.ehcache.build.voltron' +} + +dependencies { + implementation "org.terracotta:runnel:$terracottaPlatformVersion" +} diff --git a/clustered/server/config/checkstyle-suppressions.xml b/clustered/common-api/config/checkstyle-suppressions.xml similarity index 100% rename from clustered/server/config/checkstyle-suppressions.xml rename to clustered/common-api/config/checkstyle-suppressions.xml diff --git a/clustered/server/gradle.properties b/clustered/common-api/gradle.properties similarity index 83% rename from clustered/server/gradle.properties rename to clustered/common-api/gradle.properties index 37b82b87c9..3454901bb0 100644 --- a/clustered/server/gradle.properties +++ b/clustered/common-api/gradle.properties @@ -14,5 +14,5 @@ # limitations under the License. # -subPomName = Ehcache 3 Server Side Clustering module -subPomDesc = The Server Side Clustering module of Ehcache 3 +subPomName = Ehcache 3 Common Clustering API module +subPomDesc = The Common Clustering API module of Ehcache 3 diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/Consistency.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/Consistency.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/Consistency.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/Consistency.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/PoolAllocation.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/PoolAllocation.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/PoolAllocation.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/PoolAllocation.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/ServerSideConfiguration.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/ServerSideConfiguration.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/ServerSideConfiguration.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/ServerSideConfiguration.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/ClusterTierManagerConfiguration.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/ClusterTierManagerConfiguration.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/ClusterTierManagerConfiguration.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/ClusterTierManagerConfiguration.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/ServerStoreConfiguration.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/ServerStoreConfiguration.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/ServerStoreConfiguration.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/ServerStoreConfiguration.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/ClusterException.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/ClusterException.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/ClusterException.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/ClusterException.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/DestroyInProgressException.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/DestroyInProgressException.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/DestroyInProgressException.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/DestroyInProgressException.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationException.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationException.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationException.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationException.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreException.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreException.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreException.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreException.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/LifecycleException.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/LifecycleException.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/LifecycleException.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/LifecycleException.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityMessage.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityMessage.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityMessage.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityMessage.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheOperationMessage.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheOperationMessage.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheOperationMessage.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheOperationMessage.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpMessage.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpMessage.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpMessage.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpMessage.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/Chain.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/Chain.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/Chain.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/Chain.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/Element.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/Element.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/Element.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/Element.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java rename to clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/ServerSideConfigurationTest.java b/clustered/common-api/src/test/java/org/ehcache/clustered/common/ServerSideConfigurationTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/ServerSideConfigurationTest.java rename to clustered/common-api/src/test/java/org/ehcache/clustered/common/ServerSideConfigurationTest.java diff --git a/clustered/common/build.gradle b/clustered/common/build.gradle index af5ff01306..5675a157e6 100644 --- a/clustered/common/build.gradle +++ b/clustered/common/build.gradle @@ -19,6 +19,8 @@ plugins { } dependencies { + api project(':clustered:common-api') + providedImplementation project(':api') providedImplementation "org.terracotta:entity-common-api:$terracottaApisVersion" providedImplementation "org.terracotta:runnel:$terracottaPlatformVersion" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index 846ce29299..3367cd21d9 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -35,7 +35,6 @@ import com.tc.util.Assert; -import java.io.File; import java.net.URI; import java.time.Duration; import java.util.ArrayList; @@ -67,7 +66,7 @@ public class BasicCacheOpsMultiThreadedTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java index e9f19abd82..2aefc0e416 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java @@ -33,7 +33,6 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -62,7 +61,7 @@ public class BasicClusteredCacheOpsTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java index 34b3f306f2..aa99e79049 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java @@ -15,7 +15,6 @@ */ package org.ehcache.clustered; -import java.io.File; import java.net.URI; import org.ehcache.Cache; @@ -63,7 +62,7 @@ public class BasicEntityInteractionTest extends ClusteredTests { "\n"; @ClassRule - public static Cluster CLUSTER = newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private ClusterTierManagerConfiguration blankConfiguration = new ClusterTierManagerConfiguration("identifier", new ServerSideConfiguration(emptyMap())); @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java index abc0c08047..4d419de113 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java @@ -68,7 +68,7 @@ public class CacheManagerLifecycleEhcacheIntegrationTest extends ClusteredTests "\n"; @ClassRule - public static Cluster CLUSTER = newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private static Connection ASSERTION_CONNECTION; @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java index 1198e2b217..ddc47de7d4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java @@ -15,7 +15,6 @@ */ package org.ehcache.clustered; -import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.Map; @@ -55,7 +54,7 @@ public class ClusterTierManagerClientEntityFactoryIntegrationTest extends Cluste @ClassRule public static Cluster CLUSTER = - newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private static Connection CONNECTION; @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java index 622c8578d5..b3dd98e5ac 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java @@ -27,7 +27,6 @@ import org.junit.rules.TestName; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.util.HashSet; import java.util.Iterator; import java.util.NoSuchElementException; @@ -59,7 +58,7 @@ public class ClusteredIterationTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java index 72620af66f..6f6a61260a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java @@ -40,7 +40,6 @@ import org.junit.runners.Parameterized; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.time.Duration; import java.util.HashSet; import java.util.Map; @@ -82,7 +81,7 @@ public static Consistency[] data() { @ClassRule public static Cluster CLUSTER = - newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java index 63e573d6c8..afd91f013f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java @@ -95,4 +95,8 @@ private static String getKitInstallationPath(String diskPrefix) { return null; } } + + protected static Path clusterPath() { + return Paths.get("build", "cluster"); + } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java index e7142cd121..09b750224b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java @@ -32,7 +32,6 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -58,7 +57,7 @@ public class DestroyLoopTest extends ClusteredTests { private static final String CACHE_NAME = "clustered-cache"; @ClassRule - public static Cluster CLUSTER = newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index 379cf1bca9..9bfcf38b0d 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -39,11 +39,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; -import org.junit.rules.TestRule; import org.junit.runner.RunWith; -import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.time.Duration; import java.util.EnumSet; import java.util.HashMap; @@ -73,7 +70,7 @@ public class EventsFailureBehaviorTest extends ClusteredTests { "\n"; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java index 18a43942c0..da4de9e225 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java @@ -33,7 +33,6 @@ import org.terracotta.exception.ConnectionClosedException; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -66,7 +65,7 @@ public class IterationFailureBehaviorTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java index bc27dac2ad..5bf227de73 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java @@ -24,7 +24,6 @@ import org.junit.runner.RunWith; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.net.URL; import java.util.Properties; @@ -57,7 +56,7 @@ public class JCacheClusteredTest extends ClusteredTests { "\n"; @ClassRule - public static Cluster CLUSTER = newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java index 98e92122f4..6163d5510c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java @@ -35,7 +35,6 @@ import org.junit.runners.Parameterized; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.net.URI; import java.time.Duration; import java.util.ArrayList; @@ -69,7 +68,7 @@ public class LeaseTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private final List proxies = new ArrayList<>(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java index 69be2cbe20..e5d08edacc 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java @@ -29,7 +29,6 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.util.Arrays; import static org.hamcrest.Matchers.equalTo; @@ -49,7 +48,7 @@ public class OversizedCacheOpsTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @Test public void overSizedCacheOps() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java index b59047d078..83917b24d8 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -44,7 +44,6 @@ import com.tc.net.proxy.TCPProxy; -import java.io.File; import java.net.URI; import java.util.ArrayList; import java.util.List; @@ -68,7 +67,7 @@ public class ReconnectDuringDestroyTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java index a77f7205ca..627eb0bead 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java @@ -33,8 +33,6 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.io.File; - import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertThat; @@ -52,7 +50,7 @@ public class ResourcePoolAllocationFailureTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java index 9733522d6b..a02044e2cc 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java @@ -41,20 +41,14 @@ import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExternalResource; import org.junit.rules.TestName; -import org.junit.rules.TestRule; -import org.junit.runner.Description; import org.junit.runner.RunWith; -import org.junit.runners.model.Statement; -import org.terracotta.testing.rules.Cluster; import com.tc.net.protocol.transport.ClientMessageTransport; import com.tc.properties.TCProperties; import com.tc.properties.TCPropertiesConsts; import com.tc.properties.TCPropertiesImpl; -import java.io.File; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.HashMap; @@ -67,7 +61,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.junit.Assume.assumeNoException; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; /** @@ -139,7 +132,7 @@ private ThrowableAssertAlternative assertExceptionOccur } @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java index ef9ad659c4..9be9c9fd3c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java @@ -15,7 +15,6 @@ */ package org.ehcache.clustered.lock; -import java.io.File; import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; @@ -43,7 +42,7 @@ public class VoltronReadWriteLockIntegrationTest extends ClusteredTests { @ClassRule - public static Cluster CLUSTER = newCluster().in(new File("build/cluster")).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java index 970417433d..44f225b1df 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java @@ -15,8 +15,6 @@ */ package org.ehcache.clustered.lock; -import java.io.File; -import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -31,10 +29,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; -import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.terracotta.connection.Connection; -import org.terracotta.testing.rules.Cluster; import static org.ehcache.clustered.lock.VoltronReadWriteLockIntegrationTest.async; import static org.junit.Assert.fail; @@ -44,7 +40,7 @@ public class VoltronReadWriteLockPassiveIntegrationTest extends ClusteredTests { @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(new File("build/cluster")).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 6c9dc0cdc2..7b1efcf805 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -31,6 +31,8 @@ import org.junit.Rule; import org.junit.rules.RuleChain; import org.junit.rules.Timeout; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.terracotta.connection.Connection; import org.terracotta.connection.ConnectionException; import org.terracotta.exception.EntityConfigurationException; @@ -49,7 +51,6 @@ import org.terracotta.management.model.stats.ContextualStatistics; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -72,6 +73,8 @@ @SuppressWarnings("rawtypes") // Need to suppress because of a Javac bug giving a rawtype on AbstractManageableNode::isManageable. public abstract class AbstractClusteringManagementTest extends ClusteredTests { + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractClusteringManagementTest.class); + private static final String RESOURCE_CONFIG = "" + "" @@ -95,7 +98,7 @@ public abstract class AbstractClusteringManagementTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = newCluster(2) - .in(new File("build/cluster")) + .in(clusterPath()) .withServiceFragment(RESOURCE_CONFIG) .build(); @@ -333,11 +336,14 @@ public static void waitForAllNotifications(String... notificationTypes) throws I nmsService.waitForMessage(message -> { if (message.getType().equals("NOTIFICATION")) { for (ContextualNotification notification : message.unwrap(ContextualNotification.class)) { - if (waitingFor.remove(notification.getType())) { + if ("org.terracotta.management.entity.nms.client.NmsEntity".equals(notification.getContext().get("entityType"))) { + LOGGER.info("IGNORE:" + notification); // this is the passive NmsEntity, sometimes we catch it, sometimes not + } else if (waitingFor.remove(notification.getType())) { existingOnes.add(notification); -// System.out.println("Remove " + notification.getType()); -// System.out.println("Still waiting for: " + waitingFor); + LOGGER.debug("Remove " + notification); + LOGGER.debug("Still waiting for: " + waitingFor); } else { + LOGGER.debug("Extra: " + notification); missingOnes.add(notification); } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java index 59cb022bda..98702fe300 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java @@ -17,6 +17,7 @@ import org.ehcache.CacheManager; import org.ehcache.Status; +import org.ehcache.clustered.ClusteredTests; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; @@ -26,8 +27,6 @@ import org.terracotta.management.model.notification.ContextualNotification; import org.terracotta.testing.rules.Cluster; -import java.io.File; - import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.clustered.management.AbstractClusteringManagementTest.createNmsService; @@ -40,7 +39,7 @@ import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class CMClosedEventSentTest { +public class CMClosedEventSentTest extends ClusteredTests { private static final String RESOURCE_CONFIG = "" @@ -56,7 +55,7 @@ public class CMClosedEventSentTest { + ""; @ClassRule - public static Cluster CLUSTER = newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @Test(timeout = 60_000) public void test_CACHE_MANAGER_CLOSED() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java index 0ed6918f8c..f1ce37525d 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java @@ -25,8 +25,6 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.io.File; - import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredShared; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; @@ -46,7 +44,7 @@ public class EhcacheConfigWithManagementTest extends ClusteredTests { "\n"; @ClassRule - public static Cluster CLUSTER = newCluster().in(new File("build/cluster")) + public static Cluster CLUSTER = newCluster().in(clusterPath()) .withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index 4e262c97b9..fdbd9b8fc7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -21,6 +21,7 @@ import org.ehcache.Cache; import org.ehcache.CacheManager; import org.ehcache.Status; +import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.util.TCPProxyUtil; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; @@ -34,7 +35,6 @@ import org.terracotta.management.model.capabilities.descriptors.Settings; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; @@ -56,7 +56,7 @@ import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class ManagementClusterConnectionTest { +public class ManagementClusterConnectionTest extends ClusteredTests { private static final String RESOURCE_CONFIG = "" @@ -78,7 +78,7 @@ public class ManagementClusterConnectionTest { @ClassRule public static Cluster CLUSTER = newCluster() - .in(new File("build/cluster")) + .in(clusterPath()) .withServiceFragment(RESOURCE_CONFIG).build(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java index 094c1e311d..af1c4ff96f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java @@ -23,9 +23,7 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.net.URI; -import java.util.concurrent.TimeUnit; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; @@ -46,7 +44,7 @@ public class AutoCreateOnReconnectTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = newCluster(1) - .in(new File("build/cluster")) + .in(clusterPath()) .withServiceFragment(RESOURCE_CONFIG) .build(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java index ac62918a55..25619a4cb1 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java @@ -33,7 +33,6 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.net.URI; import java.util.ArrayList; import java.util.List; @@ -75,7 +74,7 @@ public class BasicCacheReconnectTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java index 30da4a99ed..64164e321e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java @@ -26,7 +26,6 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.net.URI; import java.util.ArrayList; import java.util.List; @@ -44,7 +43,7 @@ public class CacheManagerDestroyReconnectTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index b5ca56aa5a..890bce8bf5 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -37,7 +37,6 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.net.URI; import java.util.ArrayList; import java.util.EnumSet; @@ -110,7 +109,7 @@ final void clear() { @ClassRule public static Cluster CLUSTER = - newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index bd630d6ed1..fab61fc79f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -40,15 +40,12 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; -import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.io.Serializable; import java.time.Duration; import java.util.ArrayList; @@ -105,7 +102,7 @@ public static Consistency[] data() { public Consistency cacheConsistency; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java index f1bf186b91..97a47c6580 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java @@ -38,14 +38,10 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; -import org.junit.rules.TestRule; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; -import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.time.Duration; import java.util.ArrayList; import java.util.HashMap; @@ -82,7 +78,7 @@ public static Consistency[] data() { public Consistency cacheConsistency; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java index 7508454da2..d4de272ea6 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java @@ -39,13 +39,10 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; -import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; -import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.io.Serializable; import java.time.Duration; import java.util.ArrayList; @@ -90,7 +87,7 @@ public static Consistency[] data() { public Consistency cacheConsistency; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java index 0cb870ed12..fb3985c158 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java @@ -34,7 +34,6 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.net.InetSocketAddress; import java.time.Duration; import java.util.ArrayList; @@ -58,7 +57,7 @@ public class BasicClusteredCacheOpsReplicationWithServersApiTest extends Cluster private static Cache CACHE2; @ClassRule - public static Cluster CLUSTER = newCluster(2).in(new File("build/cluster")).withServiceFragment(CONFIG).build(); + public static Cluster CLUSTER = newCluster(2).in(clusterPath()).withServiceFragment(CONFIG).build(); @Before public void setUp() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java index cb957c739e..cbc8ace0bd 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java @@ -27,11 +27,8 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TestRule; import org.junit.runner.RunWith; -import java.io.File; - import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; @@ -54,7 +51,7 @@ public class BasicLifeCyclePassiveReplicationTest extends ClusteredTests { "\n"; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @Before public void startServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java index ab56c9c3e4..b6b6dfe015 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java @@ -35,7 +35,6 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.lang.reflect.Proxy; import java.time.Duration; import java.util.Arrays; @@ -62,7 +61,7 @@ public class DuplicateTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @Before public void startServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java index af056e0ff1..b7bc2347c9 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java @@ -31,7 +31,6 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.nio.file.Paths; import java.util.Arrays; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; @@ -57,7 +56,7 @@ public class OversizedCacheOpsPassiveTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster(2).in(Paths.get("build", "cluster").toFile()) + newCluster(2).in(clusterPath()) .withSystemProperty("ehcache.sync.data.gets.threshold", "2") .withServiceFragment(RESOURCE_CONFIG) .build(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java index 8de289a448..2130e677f7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java @@ -32,7 +32,6 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -51,7 +50,7 @@ public class PassiveSyncTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @Before public void startServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/ParallelTestCluster.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/ParallelTestCluster.java index 7b85ef2009..eb06fca70a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/ParallelTestCluster.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/ParallelTestCluster.java @@ -15,8 +15,6 @@ */ package org.ehcache.clustered.util; -import org.junit.rules.TestRule; -import org.junit.rules.TestWatcher; import org.junit.runner.Description; import org.junit.runners.model.Statement; import org.terracotta.connection.Connection; @@ -69,21 +67,11 @@ public void startOneServer() { request(ClusterTask.START_ONE_SERVER); } - @Override - public void startOneServerWithConsistency() { - request(ClusterTask.START_ONE_SERVER_WITH_CONSISTENCY); - } - @Override public void startAllServers() { request(ClusterTask.START_ALL_SERVERS); } - @Override - public void startAllServersWithConsistency() { - request(ClusterTask.START_ALL_SERVERS_WITH_CONSISTENCY); - } - @Override public void terminateActive() { request(ClusterTask.TERMINATE_ACTIVE); @@ -171,9 +159,7 @@ public void evaluate() throws Throwable { enum ClusterTask implements Consumer { START_ONE_SERVER(IClusterControl::startOneServer), - START_ONE_SERVER_WITH_CONSISTENCY(IClusterControl::startOneServerWithConsistency), START_ALL_SERVERS(IClusterControl::startAllServers), - START_ALL_SERVERS_WITH_CONSISTENCY(IClusterControl::startAllServersWithConsistency), TERMINATE_ACTIVE(IClusterControl::terminateActive), TERMINATE_ONE_PASSIVE(IClusterControl::terminateOnePassive), TERMINATE_ALL_SERVERS(IClusterControl::terminateAllServers); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java index bbc33a5327..d528c8bfa8 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java @@ -24,15 +24,13 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.io.File; - import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; public class BasicClusteredWriteBehindMultiClientTest extends WriteBehindTestBase { @ClassRule public static Cluster CLUSTER = - newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private PersistentCacheManager cacheManager1; private PersistentCacheManager cacheManager2; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java index 3d2d032fd7..0c568970f0 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java @@ -26,7 +26,6 @@ import org.junit.rules.Timeout; import org.terracotta.testing.rules.Cluster; -import java.io.File; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; @@ -46,7 +45,7 @@ public class BasicClusteredWriteBehindTest extends WriteBehindTestBase { @ClassRule public static Cluster CLUSTER = - newCluster().in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private PersistentCacheManager cacheManager; private Cache cache; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java index 1897e70b7e..c1e56c4ef7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java @@ -24,15 +24,13 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.io.File; - import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; public class BasicClusteredWriteBehindWithPassiveMultiClientTest extends WriteBehindTestBase { @ClassRule public static Cluster CLUSTER = - newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private PersistentCacheManager cacheManager1; private PersistentCacheManager cacheManager2; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java index 3a75e2d410..af1b013371 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java @@ -25,11 +25,7 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TestRule; import org.junit.runner.RunWith; -import org.terracotta.testing.rules.Cluster; - -import java.io.File; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; @@ -38,7 +34,7 @@ public class BasicClusteredWriteBehindWithPassiveTest extends WriteBehindTestBas @ClassRule @Rule public static final ParallelTestCluster CLUSTER = new ParallelTestCluster( - newCluster(2).in(new File("build/cluster")).withServiceFragment(RESOURCE_CONFIG).build() + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build() ); private PersistentCacheManager cacheManager; diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java index fc9b3bb4d5..806bc00517 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -153,7 +153,7 @@ public static Cluster startServer(Path serverDirectory) throws IOException { } serverProcess.command().addAll(asList( "-Dtc.install-root=" + serverDir, - "-cp", serverDir.resolve("lib").resolve("tc.jar") + File.pathSeparator + pluginClasspath, + "-cp", serverDir.resolve("lib").resolve("tc.jar").toString(), "com.tc.server.TCServerMain", "-f", configFile.toString())); serverProcess.inheritIO(); diff --git a/clustered/server/build.gradle b/clustered/server/build.gradle deleted file mode 100644 index 5ea9ae374f..0000000000 --- a/clustered/server/build.gradle +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -plugins { - id 'org.ehcache.build.deploy' -} - -dependencies { - api "org.terracotta:client-message-tracker:$terracottaPlatformVersion" - api("org.terracotta:offheap-resource:$terracottaPlatformVersion") { - transitive = false - } - implementation project(':clustered:common') - implementation group: 'org.terracotta', name: 'offheap-store', version: offheapVersion - implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4jVersion - implementation ("org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion") { - transitive = false - } - implementation "org.terracotta.management.dist:mnm-common:$terracottaPlatformVersion" - providedImplementation "org.terracotta:entity-server-api:$terracottaApisVersion" - providedImplementation "org.terracotta:standard-cluster-services:$terracottaApisVersion" - providedImplementation "org.terracotta:runnel:$terracottaPlatformVersion" - - testImplementation project(':clustered:test-utils') - testImplementation ("org.terracotta:passthrough-server:$terracottaPassthroughTestingVersion") -} diff --git a/clustered/server/entity/build.gradle b/clustered/server/entity/build.gradle new file mode 100644 index 0000000000..66c1d2c768 --- /dev/null +++ b/clustered/server/entity/build.gradle @@ -0,0 +1,32 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id 'org.ehcache.build.deploy' + id 'org.ehcache.build.voltron' +} + +dependencies { + service project(':clustered:server:service-api') + service "org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion" + service "org.terracotta.management.dist:mnm-common:$terracottaPlatformVersion" + + implementation project(':clustered:common') + implementation "org.terracotta:client-message-tracker:$terracottaPlatformVersion" + + testImplementation project(':clustered:server:service') + testImplementation project(':clustered:test-utils') +} diff --git a/clustered/server/entity/config/checkstyle-suppressions.xml b/clustered/server/entity/config/checkstyle-suppressions.xml new file mode 100644 index 0000000000..cb41d0baf7 --- /dev/null +++ b/clustered/server/entity/config/checkstyle-suppressions.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/clustered/server/entity/gradle.properties b/clustered/server/entity/gradle.properties new file mode 100644 index 0000000000..0f411f1061 --- /dev/null +++ b/clustered/server/entity/gradle.properties @@ -0,0 +1,18 @@ +# +# Copyright Terracotta, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +subPomName = Ehcache 3 Clustering Server Entity module +subPomDesc = The Server Entity module of Ehcache 3 diff --git a/clustered/server/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntity.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntity.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntity.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntity.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockPassiveEntity.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockPassiveEntity.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockPassiveEntity.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockPassiveEntity.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockServerEntityService.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockServerEntityService.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockServerEntityService.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockServerEntityService.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/lock/server/messages/LockSyncMessaging.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/messages/LockSyncMessaging.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/lock/server/messages/LockSyncMessaging.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/messages/LockSyncMessaging.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntity.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntity.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntity.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntity.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/ClusterTierManagerDump.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerDump.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/ClusterTierManagerDump.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerDump.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntity.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntity.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntity.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntity.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/ClusterTierManagerServerEntityService.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerServerEntityService.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/ClusterTierManagerServerEntityService.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerServerEntityService.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/CommunicatorServiceConfiguration.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/CommunicatorServiceConfiguration.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/CommunicatorServiceConfiguration.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/CommunicatorServiceConfiguration.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/ConcurrencyStrategies.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ConcurrencyStrategies.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/ConcurrencyStrategies.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/ConcurrencyStrategies.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/EhcacheExecutionStrategy.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/EhcacheExecutionStrategy.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/EhcacheExecutionStrategy.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/EhcacheExecutionStrategy.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreCompatibility.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ServerStoreCompatibility.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreCompatibility.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/ServerStoreCompatibility.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheDataSyncMessage.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheDataSyncMessage.java similarity index 95% rename from clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheDataSyncMessage.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheDataSyncMessage.java index 1937f9389f..39a1fc7ad0 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheDataSyncMessage.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheDataSyncMessage.java @@ -18,12 +18,9 @@ import org.ehcache.clustered.common.internal.store.Chain; -import com.tc.classloader.CommonComponent; - import java.util.Collections; import java.util.Map; -@CommonComponent public class EhcacheDataSyncMessage extends EhcacheSyncMessage { private final Map chainMap; diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java similarity index 97% rename from clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java index 855f21f36f..c515efcca4 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java @@ -16,7 +16,6 @@ package org.ehcache.clustered.server.internal.messages; -import com.tc.classloader.CommonComponent; import org.ehcache.clustered.common.internal.messages.EhcacheEntityMessage; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse; import org.terracotta.client.message.tracker.OOOMessageHandler; @@ -30,7 +29,6 @@ * Message sending messages that are tracked for duplication. If a passive becoming active receives * a duplicate, it needs to discard it. */ -@CommonComponent public class EhcacheMessageTrackerMessage extends EhcacheSyncMessage { private final int segmentId; diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessage.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessage.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessage.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessage.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagement.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagement.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagement.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagement.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerBinding.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerBinding.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerBinding.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerBinding.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerSettingsManagementProvider.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerSettingsManagementProvider.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerSettingsManagementProvider.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerSettingsManagementProvider.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/management/Management.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/Management.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/management/Management.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/Management.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/management/Notification.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/Notification.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/management/Notification.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/Notification.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/management/PoolBinding.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/PoolBinding.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/management/PoolBinding.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/PoolBinding.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/management/PoolSettingsManagementProvider.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/PoolSettingsManagementProvider.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/management/PoolSettingsManagementProvider.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/PoolSettingsManagementProvider.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/management/PoolStatisticsManagementProvider.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/PoolStatisticsManagementProvider.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/management/PoolStatisticsManagementProvider.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/PoolStatisticsManagementProvider.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/management/ServerStoreBinding.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreBinding.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/management/ServerStoreBinding.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreBinding.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/management/ServerStoreStatisticsManagementProvider.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreStatisticsManagementProvider.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/management/ServerStoreStatisticsManagementProvider.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreStatisticsManagementProvider.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierDump.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierDump.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierDump.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierDump.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/LockManagerImpl.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/LockManagerImpl.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/store/LockManagerImpl.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/LockManagerImpl.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/MessageToTrackerSegmentFunction.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/MessageToTrackerSegmentFunction.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/store/MessageToTrackerSegmentFunction.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/MessageToTrackerSegmentFunction.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/NoopLockManager.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/NoopLockManager.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/store/NoopLockManager.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/NoopLockManager.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ServerLockManager.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ServerLockManager.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/store/ServerLockManager.java rename to clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ServerLockManager.java diff --git a/clustered/server/src/main/resources/META-INF/services/org.terracotta.entity.EntityServerService b/clustered/server/entity/src/main/resources/META-INF/services/org.terracotta.entity.EntityServerService similarity index 100% rename from clustered/server/src/main/resources/META-INF/services/org.terracotta.entity.EntityServerService rename to clustered/server/entity/src/main/resources/META-INF/services/org.terracotta.entity.EntityServerService diff --git a/clustered/server/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/DefaultConcurrencyStrategyTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/DefaultConcurrencyStrategyTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/DefaultConcurrencyStrategyTest.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/DefaultConcurrencyStrategyTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/TestClientSourceId.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientSourceId.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/TestClientSourceId.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientSourceId.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/TestInvokeContext.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestInvokeContext.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/TestInvokeContext.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestInvokeContext.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessageTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessageTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessageTest.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessageTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodecTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodecTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodecTest.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodecTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/InvalidMessage.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/InvalidMessage.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/store/InvalidMessage.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/InvalidMessage.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java rename to clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java diff --git a/clustered/server/service-api/build.gradle b/clustered/server/service-api/build.gradle new file mode 100644 index 0000000000..b1da4912e2 --- /dev/null +++ b/clustered/server/service-api/build.gradle @@ -0,0 +1,26 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id 'org.ehcache.build.deploy' + id 'org.ehcache.build.voltron' +} + +dependencies { + api project(':clustered:common-api') + api "org.terracotta:offheap-store:$offheapVersion" + api "org.terracotta:runnel:$terracottaPlatformVersion" +} diff --git a/clustered/server/service-api/config/checkstyle-suppressions.xml b/clustered/server/service-api/config/checkstyle-suppressions.xml new file mode 100644 index 0000000000..cb41d0baf7 --- /dev/null +++ b/clustered/server/service-api/config/checkstyle-suppressions.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/clustered/server/service-api/gradle.properties b/clustered/server/service-api/gradle.properties new file mode 100644 index 0000000000..b45711e33d --- /dev/null +++ b/clustered/server/service-api/gradle.properties @@ -0,0 +1,18 @@ +# +# Copyright Terracotta, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +subPomName = Ehcache 3 Clustering Server Storage API module +subPomDesc = The Server Storage API module of Ehcache 3 diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/KeySegmentMapper.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/KeySegmentMapper.java similarity index 93% rename from clustered/server/src/main/java/org/ehcache/clustered/server/KeySegmentMapper.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/KeySegmentMapper.java index 138360f263..202c92c71d 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/KeySegmentMapper.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/KeySegmentMapper.java @@ -16,9 +16,6 @@ package org.ehcache.clustered.server; -import com.tc.classloader.CommonComponent; - -@CommonComponent public class KeySegmentMapper { private final int segments; diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java similarity index 95% rename from clustered/server/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java index 863c785cb2..cbcafcad13 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java @@ -20,12 +20,9 @@ import org.ehcache.clustered.common.internal.store.ServerStore; import org.terracotta.offheapstore.MapInternals; -import com.tc.classloader.CommonComponent; - import java.util.List; import java.util.Set; -@CommonComponent public interface ServerSideServerStore extends ServerStore, MapInternals { void setEventListener(ServerStoreEventListener listener); void enableEvents(boolean enable); diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java similarity index 96% rename from clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java index b2c48c8eee..e161731366 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java @@ -15,7 +15,6 @@ */ package org.ehcache.clustered.server; -import com.tc.classloader.CommonComponent; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.server.offheap.InternalChain; @@ -24,7 +23,6 @@ /** * ServerStore event listener interface */ -@CommonComponent public interface ServerStoreEventListener { /** diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java similarity index 95% rename from clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java index 35afc90552..ddaed046c0 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java @@ -16,14 +16,11 @@ package org.ehcache.clustered.server.internal.messages; -import com.tc.classloader.CommonComponent; - import java.util.concurrent.ConcurrentMap; /** * EhcacheStateRepoSyncMessage */ -@CommonComponent public class EhcacheStateRepoSyncMessage extends EhcacheSyncMessage { private final String cacheId; diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessage.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessage.java similarity index 93% rename from clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessage.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessage.java index 79dd79f908..6882a9574a 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessage.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessage.java @@ -18,9 +18,6 @@ import org.ehcache.clustered.common.internal.messages.EhcacheEntityMessage; -import com.tc.classloader.CommonComponent; - -@CommonComponent public abstract class EhcacheSyncMessage extends EhcacheEntityMessage { public abstract SyncMessageType getMessageType(); diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java similarity index 95% rename from clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java index c6a60d6155..6c325bbda0 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java @@ -18,14 +18,11 @@ import org.terracotta.runnel.EnumMapping; -import com.tc.classloader.CommonComponent; - import static org.terracotta.runnel.EnumMappingBuilder.newEnumMappingBuilder; /** * SyncMessageType */ -@CommonComponent public enum SyncMessageType { STATE_REPO, DATA, diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java similarity index 94% rename from clustered/server/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java index 63faf6cc67..18af113114 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java @@ -18,10 +18,8 @@ import java.io.Closeable; import java.nio.ByteBuffer; -import com.tc.classloader.CommonComponent; import org.ehcache.clustered.common.internal.store.Chain; -@CommonComponent public interface InternalChain extends Closeable { Chain detach(); diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/repo/ServerStateRepository.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/repo/ServerStateRepository.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/repo/ServerStateRepository.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/repo/ServerStateRepository.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/repo/StateRepositoryManager.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/repo/StateRepositoryManager.java similarity index 97% rename from clustered/server/src/main/java/org/ehcache/clustered/server/repo/StateRepositoryManager.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/repo/StateRepositoryManager.java index cdad28f650..67ff72e91b 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/repo/StateRepositoryManager.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/repo/StateRepositoryManager.java @@ -21,15 +21,12 @@ import org.ehcache.clustered.common.internal.messages.StateRepositoryOpMessage; import org.ehcache.clustered.server.internal.messages.EhcacheStateRepoSyncMessage; -import com.tc.classloader.CommonComponent; - import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import static java.util.Collections.emptyList; -@CommonComponent public class StateRepositoryManager { private final ConcurrentMap mapRepositoryMap = new ConcurrentHashMap<>(); diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/state/EhcacheStateContext.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateContext.java similarity index 93% rename from clustered/server/src/main/java/org/ehcache/clustered/server/state/EhcacheStateContext.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateContext.java index 045ff8a7e7..4f895c685e 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/state/EhcacheStateContext.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateContext.java @@ -15,12 +15,9 @@ */ package org.ehcache.clustered.server.state; -import com.tc.classloader.CommonComponent; - /** * Marker interface to pass context between begin and end message processing. */ -@CommonComponent @FunctionalInterface public interface EhcacheStateContext extends AutoCloseable { void close(); diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java similarity index 97% rename from clustered/server/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java index 8309166839..62c9cdf8ab 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java @@ -24,12 +24,9 @@ import org.ehcache.clustered.server.repo.StateRepositoryManager; import org.terracotta.entity.ConfigurationException; -import com.tc.classloader.CommonComponent; - import java.util.Map; import java.util.Set; -@CommonComponent public interface EhcacheStateService { String getDefaultServerResource(); diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/state/InvalidationTracker.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/InvalidationTracker.java similarity index 93% rename from clustered/server/src/main/java/org/ehcache/clustered/server/state/InvalidationTracker.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/InvalidationTracker.java index d3c95d3ba2..fe599f20a9 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/state/InvalidationTracker.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/InvalidationTracker.java @@ -16,11 +16,8 @@ package org.ehcache.clustered.server.state; -import com.tc.classloader.CommonComponent; - import java.util.Set; -@CommonComponent public interface InvalidationTracker { boolean isClearInProgress(); diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java similarity index 97% rename from clustered/server/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java index ceb6e968dd..e77b9c9dde 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java @@ -15,7 +15,6 @@ */ package org.ehcache.clustered.server.state; -import com.tc.classloader.CommonComponent; import org.ehcache.clustered.common.ServerSideConfiguration; import org.terracotta.offheapstore.buffersource.OffHeapBufferSource; import org.terracotta.offheapstore.paging.OffHeapStorageArea; @@ -30,7 +29,6 @@ * Pairs a {@link ServerSideConfiguration.Pool} and an {@link UpfrontAllocatingPageSource} instance providing storage * for the pool. */ -@CommonComponent public class ResourcePageSource implements PageSource { /** * A description of the resource allocation underlying this {@code PageSource}. diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStateServiceConfig.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStateServiceConfig.java similarity index 96% rename from clustered/server/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStateServiceConfig.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStateServiceConfig.java index ab5c5a1b4a..17912bd1a3 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStateServiceConfig.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStateServiceConfig.java @@ -22,9 +22,6 @@ import org.terracotta.entity.ServiceConfiguration; import org.terracotta.entity.ServiceRegistry; -import com.tc.classloader.CommonComponent; - -@CommonComponent public class EhcacheStateServiceConfig implements ServiceConfiguration { private final ClusterTierManagerConfiguration config; diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStoreStateServiceConfig.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStoreStateServiceConfig.java similarity index 95% rename from clustered/server/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStoreStateServiceConfig.java rename to clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStoreStateServiceConfig.java index 3235c18d5b..e736370dd4 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStoreStateServiceConfig.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStoreStateServiceConfig.java @@ -20,9 +20,6 @@ import org.ehcache.clustered.server.state.EhcacheStateService; import org.terracotta.entity.ServiceConfiguration; -import com.tc.classloader.CommonComponent; - -@CommonComponent public class EhcacheStoreStateServiceConfig implements ServiceConfiguration { private final String managerIdentifier; diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/repo/ServerStateRepositoryTest.java b/clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/ServerStateRepositoryTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/repo/ServerStateRepositoryTest.java rename to clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/ServerStateRepositoryTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/repo/StateRepositoryManagerTest.java b/clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/StateRepositoryManagerTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/repo/StateRepositoryManagerTest.java rename to clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/StateRepositoryManagerTest.java diff --git a/clustered/server/service/build.gradle b/clustered/server/service/build.gradle new file mode 100644 index 0000000000..eef4ff78ed --- /dev/null +++ b/clustered/server/service/build.gradle @@ -0,0 +1,31 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id 'org.ehcache.build.deploy' + id 'org.ehcache.build.voltron' +} + +dependencies { + service project(':clustered:server:service-api') + service "org.terracotta:offheap-resource:$terracottaPlatformVersion" + + implementation project(':clustered:common') + + testImplementation project(':clustered:test-utils') + testImplementation "org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion" + testImplementation "org.terracotta:passthrough-server:$terracottaPassthroughTestingVersion" +} diff --git a/clustered/server/service/config/checkstyle-suppressions.xml b/clustered/server/service/config/checkstyle-suppressions.xml new file mode 100644 index 0000000000..cb41d0baf7 --- /dev/null +++ b/clustered/server/service/config/checkstyle-suppressions.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/clustered/server/service/gradle.properties b/clustered/server/service/gradle.properties new file mode 100644 index 0000000000..7a8edd6a46 --- /dev/null +++ b/clustered/server/service/gradle.properties @@ -0,0 +1,18 @@ +# +# Copyright Terracotta, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +subPomName = Ehcache 3 Clustering Server Storage Implementation module +subPomDesc = The Server Storage Implementation module of Ehcache 3 diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/EhcacheStateServiceImpl.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/EhcacheStateServiceImpl.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/EhcacheStateServiceImpl.java rename to clustered/server/service/src/main/java/org/ehcache/clustered/server/EhcacheStateServiceImpl.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java similarity index 98% rename from clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java rename to clustered/server/service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java index 7548741a22..43c7094a46 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java +++ b/clustered/server/service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java @@ -24,15 +24,12 @@ import org.terracotta.offheapstore.exceptions.OversizeMappingException; import org.terracotta.offheapstore.paging.PageSource; -import com.tc.classloader.CommonComponent; - import java.nio.ByteBuffer; import java.util.AbstractList; import java.util.Iterator; import java.util.List; import java.util.Set; -@CommonComponent public class ServerStoreImpl implements ServerSideServerStore { private final ServerStoreConfiguration storeConfiguration; diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/ChainStorageEngine.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/ChainStorageEngine.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/offheap/ChainStorageEngine.java rename to clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/ChainStorageEngine.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/LongPortability.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/LongPortability.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/offheap/LongPortability.java rename to clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/LongPortability.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java rename to clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java rename to clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java rename to clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMap.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMap.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMap.java rename to clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMap.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceDump.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceDump.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceDump.java rename to clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceDump.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java rename to clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/state/InvalidationTrackerImpl.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/InvalidationTrackerImpl.java similarity index 100% rename from clustered/server/src/main/java/org/ehcache/clustered/server/state/InvalidationTrackerImpl.java rename to clustered/server/service/src/main/java/org/ehcache/clustered/server/state/InvalidationTrackerImpl.java diff --git a/clustered/server/src/main/resources/META-INF/services/org.terracotta.entity.ServiceProvider b/clustered/server/service/src/main/resources/META-INF/services/org.terracotta.entity.ServiceProvider similarity index 100% rename from clustered/server/src/main/resources/META-INF/services/org.terracotta.entity.ServiceProvider rename to clustered/server/service/src/main/resources/META-INF/services/org.terracotta.entity.ServiceProvider diff --git a/clustered/server/src/main/resources/offheap-message.properties b/clustered/server/service/src/main/resources/offheap-message.properties similarity index 100% rename from clustered/server/src/main/resources/offheap-message.properties rename to clustered/server/service/src/main/resources/offheap-message.properties diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/EhcacheStateServiceImplTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/EhcacheStateServiceImplTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/EhcacheStateServiceImplTest.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/EhcacheStateServiceImplTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/state/EhcacheStateServiceProviderTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/state/EhcacheStateServiceProviderTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/state/EhcacheStateServiceProviderTest.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/state/EhcacheStateServiceProviderTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/state/InvalidationTrackerImplTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/state/InvalidationTrackerImplTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/state/InvalidationTrackerImplTest.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/state/InvalidationTrackerImplTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ChainBuilder.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ChainBuilder.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/store/ChainBuilder.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ChainBuilder.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ElementBuilder.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ElementBuilder.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/store/ElementBuilder.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ElementBuilder.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainBuilder.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainBuilder.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainBuilder.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainBuilder.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainImpl.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainImpl.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainImpl.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainImpl.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementBuilder.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementBuilder.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementBuilder.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementBuilder.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementImpl.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementImpl.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementImpl.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementImpl.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreTest.java similarity index 100% rename from clustered/server/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreTest.java rename to clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreTest.java diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/state/MessageTracker.java b/clustered/server/src/main/java/org/ehcache/clustered/server/state/MessageTracker.java deleted file mode 100644 index bec386781f..0000000000 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/state/MessageTracker.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.ehcache.clustered.server.state; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.ConcurrentSkipListSet; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - - -/** - * Message Tracker keeps track of messages seen so far in efficient way by keeping track of contiguous and non-contiguous message ids. - * - * Assumption: message ids are generated in contiguous fashion in the increment on 1, starting from 0. - */ -public class MessageTracker { - - private static final Logger LOGGER = LoggerFactory.getLogger(MessageTracker.class); - - // keeping track of highest contiguous message id seen - private volatile long highestContiguousMsgId; - - // Keeping track of non contiguous message Ids higher than highestContiguousMsgId. - private final ConcurrentSkipListSet nonContiguousMsgIds; - - // Lock used for reconciliation. - private final Lock reconciliationLock; - - // Status that the sync is completed. - private volatile boolean isSyncCompleted; - - public MessageTracker(boolean isSyncCompleted) { - this.highestContiguousMsgId = -1L; - this.nonContiguousMsgIds = new ConcurrentSkipListSet<>(); - this.reconciliationLock = new ReentrantLock(); - this.isSyncCompleted = isSyncCompleted; - } - - /** - * Track the given message Id. - * - * @param msgId Message Id to be checked. - */ - public void track(long msgId) { - nonContiguousMsgIds.add(msgId); - tryReconcile(); - } - - /** - * Check wheather the given message id is already seen by track call. - * - * @param msgId Message Identifier to be checked. - * @return true if the given msgId is already tracked otherwise false. - */ - public boolean seen(long msgId) { - boolean seen = nonContiguousMsgIds.contains(msgId) || msgId <= highestContiguousMsgId; - tryReconcile(); - return seen; - } - - /** - * Checks weather non-contiguous message ids set is empty. - * - * @return true if the there is no non contiguous message ids otherwise false - */ - public boolean isEmpty() { - return nonContiguousMsgIds.isEmpty(); - } - - - /** - * Notify Message tracker that the sync is completed. - */ - public void notifySyncCompleted() { - this.isSyncCompleted = true; - } - - /** - * Remove the contiguous seen msgIds from the nonContiguousMsgIds and update highestContiguousMsgId - */ - private void reconcile() { - - // If nonContiguousMsgIds is empty then nothing to reconcile. - if (nonContiguousMsgIds.isEmpty()) { - return; - } - - // This happens when a passive is started after Active has moved on and - // passive starts to see msgIDs starting from a number > 0. - // Once the sync is completed, fast forward highestContiguousMsgId. - // Post sync completion assuming platform will send all msgIds beyond highestContiguousMsgId. - if (highestContiguousMsgId == -1L && isSyncCompleted) { - Long min = nonContiguousMsgIds.last(); - LOGGER.info("Setting highestContiguousMsgId to {} from -1", min); - highestContiguousMsgId = min; - nonContiguousMsgIds.removeIf(msgId -> msgId <= min); - } - - for (long msgId : nonContiguousMsgIds) { - if (msgId <= highestContiguousMsgId) { - nonContiguousMsgIds.remove(msgId); - } else if (msgId > highestContiguousMsgId + 1) { - break; - } else { - // the order is important.. - highestContiguousMsgId = msgId; - nonContiguousMsgIds.remove(msgId); - } - } - - } - - /** - * Try to reconcile, if the lock is available otherwise just return as other thread would have hold the lock and performing reconcile. - */ - private void tryReconcile() { - if (!this.reconciliationLock.tryLock()) { - return; - } - - try { - reconcile(); - - // Keep on warning after every reconcile if nonContiguousMsgIds reaches 500 (kept it a bit higher so that we won't get unnecessary warning due to high concurrency). - if (nonContiguousMsgIds.size() > 500) { - LOGGER.warn("Non - Contiguous Message ID has size : {}, with highestContiguousMsgId as : {}", nonContiguousMsgIds.size(), highestContiguousMsgId); - } - } finally { - this.reconciliationLock.unlock(); - } - } - -} diff --git a/gradle.properties b/gradle.properties index c9b9e102d2..3b98c0418b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,8 +12,8 @@ jaxbVersion = 2.3.1 # Terracotta clustered terracottaPlatformVersion = 5.7.4-pre8 terracottaApisVersion = 1.7.0-pre1 -terracottaCoreVersion = 5.7.0-pre13 -terracottaPassthroughTestingVersion = 1.7.0-pre6 +terracottaCoreVersion = 5.7.0-pre18 +terracottaPassthroughTestingVersion = 1.7.0-pre8 # Test lib versions junitVersion = 4.12 diff --git a/settings.gradle b/settings.gradle index 7480d3c564..5af54e753a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -28,5 +28,8 @@ pluginManagement { } include "api", "spi-tester", "core", "core-spi-test", "impl", "management", "transactions", "107", "xml", - "clustered", "clustered:test-utils", "clustered:common", "clustered:client", "clustered:server", "clustered:integration-test", "clustered:clustered-dist", "clustered:ops-tool", + "clustered", "clustered:common-api", "clustered:common", + "clustered:server:service-api", "clustered:server:service", "clustered:server:entity", + "clustered:client", "clustered:clustered-dist", "clustered:ops-tool", + "clustered:test-utils", "clustered:integration-test", "integration-test", "dist", "osgi-test", "clustered:osgi-test", "demos", "demos:00-NoCache", "demos:01-CacheAside", "docs" From c92bf53386ca31e2c7d21b416f73f45e448bd9ea Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 6 Mar 2020 18:38:55 -0500 Subject: [PATCH 209/372] Remove runnel and offheap-store from plugins/api --- clustered/common-api/build.gradle | 4 - .../internal/messages/EhcacheMessageType.java | 33 ------ .../messages/EhcacheResponseType.java | 25 ---- .../common/internal/messages/BaseCodec.java | 110 ++++++++++++++++++ .../internal/messages/EhcacheCodec.java | 6 +- .../messages/LifeCycleMessageCodec.java | 6 +- .../internal/messages/MessageCodecUtils.java | 4 +- .../internal/messages/ResponseCodec.java | 6 +- .../internal/messages/ServerStoreOpCodec.java | 6 +- .../messages/StateRepositoryOpCodec.java | 6 +- clustered/server/entity/build.gradle | 2 + .../messages/EhcacheSyncMessageCodec.java | 27 +++-- .../PassiveReplicationMessageCodec.java | 6 +- ...ServerStoreSettingsManagementProvider.java | 26 +++-- clustered/server/service-api/build.gradle | 2 - .../server/ServerSideServerStore.java | 3 +- .../internal/messages/SyncMessageType.java | 12 -- .../server/state/EhcacheStateService.java | 4 +- clustered/server/service/build.gradle | 1 + .../clustered/server/ServerStoreImpl.java | 3 +- .../server/state/ResourcePageSource.java | 0 21 files changed, 172 insertions(+), 120 deletions(-) create mode 100644 clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/BaseCodec.java rename clustered/server/{service-api => service}/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java (100%) diff --git a/clustered/common-api/build.gradle b/clustered/common-api/build.gradle index 454b4fc4f5..44a9ebad33 100644 --- a/clustered/common-api/build.gradle +++ b/clustered/common-api/build.gradle @@ -18,7 +18,3 @@ plugins { id 'org.ehcache.build.deploy' id 'org.ehcache.build.voltron' } - -dependencies { - implementation "org.terracotta:runnel:$terracottaPlatformVersion" -} diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java index 5802e615ad..ab1b47ef26 100644 --- a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java +++ b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java @@ -16,12 +16,9 @@ package org.ehcache.clustered.common.internal.messages; -import org.terracotta.runnel.EnumMapping; - import java.util.EnumSet; import static java.util.EnumSet.of; -import static org.terracotta.runnel.EnumMappingBuilder.newEnumMappingBuilder; /** * EhcacheMessageType @@ -59,36 +56,6 @@ public enum EhcacheMessageType { CLEAR_INVALIDATION_COMPLETE, INVALIDATION_COMPLETE; - public static final String MESSAGE_TYPE_FIELD_NAME = "opCode"; - public static final int MESSAGE_TYPE_FIELD_INDEX = 10; - public static final EnumMapping EHCACHE_MESSAGE_TYPES_ENUM_MAPPING = newEnumMappingBuilder(EhcacheMessageType.class) - .mapping(VALIDATE, 1) - .mapping(VALIDATE_SERVER_STORE, 2) - .mapping(PREPARE_FOR_DESTROY, 3) - - .mapping(GET_AND_APPEND, 21) - .mapping(APPEND, 22) - .mapping(REPLACE, 23) - .mapping(CLIENT_INVALIDATION_ACK, 24) - .mapping(CLIENT_INVALIDATION_ALL_ACK, 25) - .mapping(CLEAR, 26) - .mapping(GET_STORE, 27) - .mapping(LOCK, 28) - .mapping(UNLOCK, 29) - .mapping(ITERATOR_OPEN, 30) - .mapping(ITERATOR_CLOSE, 31) - .mapping(ITERATOR_ADVANCE, 32) - .mapping(ENABLE_EVENT_LISTENER, 33) - - .mapping(GET_STATE_REPO, 41) - .mapping(PUT_IF_ABSENT, 42) - .mapping(ENTRY_SET, 43) - - .mapping(CHAIN_REPLICATION_OP, 61) - .mapping(CLEAR_INVALIDATION_COMPLETE, 63) - .mapping(INVALIDATION_COMPLETE, 64) - .build(); - public static final EnumSet LIFECYCLE_MESSAGES = of(VALIDATE, VALIDATE_SERVER_STORE, PREPARE_FOR_DESTROY); public static boolean isLifecycleMessage(EhcacheMessageType value) { return LIFECYCLE_MESSAGES.contains(value); diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java index 59cacfcc3a..90b683b994 100644 --- a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java +++ b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java @@ -16,10 +16,6 @@ package org.ehcache.clustered.common.internal.messages; -import org.terracotta.runnel.EnumMapping; - -import static org.terracotta.runnel.EnumMappingBuilder.newEnumMappingBuilder; - /** * EhcacheResponseType */ @@ -40,25 +36,4 @@ public enum EhcacheResponseType { ITERATOR_BATCH, SERVER_APPEND, ; - - - public static final String RESPONSE_TYPE_FIELD_NAME = "opCode"; - public static final int RESPONSE_TYPE_FIELD_INDEX = 10; - public static final EnumMapping EHCACHE_RESPONSE_TYPES_ENUM_MAPPING = newEnumMappingBuilder(EhcacheResponseType.class) - .mapping(EhcacheResponseType.SUCCESS, 80) - .mapping(EhcacheResponseType.FAILURE, 81) - .mapping(EhcacheResponseType.GET_RESPONSE, 82) - .mapping(EhcacheResponseType.HASH_INVALIDATION_DONE, 83) - .mapping(EhcacheResponseType.ALL_INVALIDATION_DONE, 84) - .mapping(EhcacheResponseType.CLIENT_INVALIDATE_HASH, 85) - .mapping(EhcacheResponseType.CLIENT_INVALIDATE_ALL, 86) - .mapping(EhcacheResponseType.SERVER_INVALIDATE_HASH, 87) - .mapping(EhcacheResponseType.MAP_VALUE, 88) - .mapping(EhcacheResponseType.PREPARE_FOR_DESTROY, 89) - .mapping(EhcacheResponseType.RESOLVE_REQUEST, 90) - .mapping(EhcacheResponseType.LOCK_SUCCESS, 91) - .mapping(EhcacheResponseType.LOCK_FAILURE, 92) - .mapping(EhcacheResponseType.ITERATOR_BATCH, 93) - .mapping(EhcacheResponseType.SERVER_APPEND, 94) - .build(); } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/BaseCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/BaseCodec.java new file mode 100644 index 0000000000..d7f8affffe --- /dev/null +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/BaseCodec.java @@ -0,0 +1,110 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered.common.internal.messages; + +import org.terracotta.runnel.EnumMapping; + +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.APPEND; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.CHAIN_REPLICATION_OP; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.CLEAR; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.CLEAR_INVALIDATION_COMPLETE; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.CLIENT_INVALIDATION_ACK; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.CLIENT_INVALIDATION_ALL_ACK; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.ENABLE_EVENT_LISTENER; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.ENTRY_SET; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.GET_AND_APPEND; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.GET_STATE_REPO; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.GET_STORE; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.INVALIDATION_COMPLETE; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.ITERATOR_ADVANCE; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.ITERATOR_CLOSE; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.ITERATOR_OPEN; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.LOCK; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.PUT_IF_ABSENT; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.REPLACE; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.UNLOCK; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.VALIDATE; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.VALIDATE_SERVER_STORE; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.ALL_INVALIDATION_DONE; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.CLIENT_INVALIDATE_ALL; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.CLIENT_INVALIDATE_HASH; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.FAILURE; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.GET_RESPONSE; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.HASH_INVALIDATION_DONE; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.ITERATOR_BATCH; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.LOCK_FAILURE; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.LOCK_SUCCESS; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.MAP_VALUE; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.RESOLVE_REQUEST; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.SERVER_APPEND; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.SERVER_INVALIDATE_HASH; +import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.SUCCESS; +import static org.terracotta.runnel.EnumMappingBuilder.newEnumMappingBuilder; + +public class BaseCodec { + + public static final String MESSAGE_TYPE_FIELD_NAME = "opCode"; + public static final int MESSAGE_TYPE_FIELD_INDEX = 10; + public static final EnumMapping EHCACHE_MESSAGE_TYPES_ENUM_MAPPING = newEnumMappingBuilder(EhcacheMessageType.class) + .mapping(VALIDATE, 1) + .mapping(VALIDATE_SERVER_STORE, 2) + .mapping(EhcacheMessageType.PREPARE_FOR_DESTROY, 3) + + .mapping(GET_AND_APPEND, 21) + .mapping(APPEND, 22) + .mapping(REPLACE, 23) + .mapping(CLIENT_INVALIDATION_ACK, 24) + .mapping(CLIENT_INVALIDATION_ALL_ACK, 25) + .mapping(CLEAR, 26) + .mapping(GET_STORE, 27) + .mapping(LOCK, 28) + .mapping(UNLOCK, 29) + .mapping(ITERATOR_OPEN, 30) + .mapping(ITERATOR_CLOSE, 31) + .mapping(ITERATOR_ADVANCE, 32) + .mapping(ENABLE_EVENT_LISTENER, 33) + + .mapping(GET_STATE_REPO, 41) + .mapping(PUT_IF_ABSENT, 42) + .mapping(ENTRY_SET, 43) + + .mapping(CHAIN_REPLICATION_OP, 61) + .mapping(CLEAR_INVALIDATION_COMPLETE, 63) + .mapping(INVALIDATION_COMPLETE, 64) + .build(); + + public static final String RESPONSE_TYPE_FIELD_NAME = "opCode"; + public static final int RESPONSE_TYPE_FIELD_INDEX = 10; + public static final EnumMapping EHCACHE_RESPONSE_TYPES_ENUM_MAPPING = newEnumMappingBuilder(EhcacheResponseType.class) + .mapping(SUCCESS, 80) + .mapping(FAILURE, 81) + .mapping(GET_RESPONSE, 82) + .mapping(HASH_INVALIDATION_DONE, 83) + .mapping(ALL_INVALIDATION_DONE, 84) + .mapping(CLIENT_INVALIDATE_HASH, 85) + .mapping(CLIENT_INVALIDATE_ALL, 86) + .mapping(SERVER_INVALIDATE_HASH, 87) + .mapping(MAP_VALUE, 88) + .mapping(EhcacheResponseType.PREPARE_FOR_DESTROY, 89) + .mapping(RESOLVE_REQUEST, 90) + .mapping(LOCK_SUCCESS, 91) + .mapping(LOCK_FAILURE, 92) + .mapping(ITERATOR_BATCH, 93) + .mapping(SERVER_APPEND, 94) + .build(); + +} diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheCodec.java index 69c2c7c879..932735aee1 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheCodec.java @@ -26,9 +26,9 @@ import java.nio.ByteBuffer; import static java.nio.ByteBuffer.wrap; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.EHCACHE_MESSAGE_TYPES_ENUM_MAPPING; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_INDEX; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_NAME; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.EHCACHE_MESSAGE_TYPES_ENUM_MAPPING; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.MESSAGE_TYPE_FIELD_INDEX; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.MESSAGE_TYPE_FIELD_NAME; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.isLifecycleMessage; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.isStateRepoOperationMessage; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.isStoreOperationMessage; diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodec.java index 61edabab5b..0841cfb534 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodec.java @@ -25,9 +25,9 @@ import java.nio.ByteBuffer; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.EHCACHE_MESSAGE_TYPES_ENUM_MAPPING; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_INDEX; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_NAME; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.EHCACHE_MESSAGE_TYPES_ENUM_MAPPING; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.MESSAGE_TYPE_FIELD_INDEX; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.MESSAGE_TYPE_FIELD_NAME; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.SERVER_STORE_NAME_FIELD; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.encodeMandatoryFields; import static org.terracotta.runnel.StructBuilder.newStructBuilder; diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/MessageCodecUtils.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/MessageCodecUtils.java index 2959f5a94b..4b37ece7e1 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/MessageCodecUtils.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/MessageCodecUtils.java @@ -19,6 +19,8 @@ import org.terracotta.runnel.Struct; import org.terracotta.runnel.encoding.StructEncoder; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.MESSAGE_TYPE_FIELD_NAME; + /** * MessageCodecUtils */ @@ -30,6 +32,6 @@ public final class MessageCodecUtils { private MessageCodecUtils() {} public static StructEncoder encodeMandatoryFields(Struct struct, EhcacheOperationMessage message) { - return struct.encoder().enm(EhcacheMessageType.MESSAGE_TYPE_FIELD_NAME, message.getMessageType()); + return struct.encoder().enm(MESSAGE_TYPE_FIELD_NAME, message.getMessageType()); } } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java index 008b2fa3c5..dce4f73493 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java @@ -38,6 +38,9 @@ import java.util.UUID; import static java.nio.ByteBuffer.wrap; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.EHCACHE_RESPONSE_TYPES_ENUM_MAPPING; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.RESPONSE_TYPE_FIELD_INDEX; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.RESPONSE_TYPE_FIELD_NAME; import static org.ehcache.clustered.common.internal.messages.ChainCodec.CHAIN_STRUCT; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.allInvalidationDone; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.clientInvalidateAll; @@ -52,9 +55,6 @@ import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.serverAppend; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.serverInvalidateHash; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.success; -import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.EHCACHE_RESPONSE_TYPES_ENUM_MAPPING; -import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.RESPONSE_TYPE_FIELD_INDEX; -import static org.ehcache.clustered.common.internal.messages.EhcacheResponseType.RESPONSE_TYPE_FIELD_NAME; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.KEY_FIELD; import static org.ehcache.clustered.common.internal.messages.StateRepositoryOpCodec.WHITELIST_PREDICATE; import static org.terracotta.runnel.StructBuilder.newStructBuilder; diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java index a52ce3c9ab..ca5b0ae9ff 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java @@ -30,10 +30,10 @@ import java.nio.ByteBuffer; import java.util.UUID; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.EHCACHE_MESSAGE_TYPES_ENUM_MAPPING; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.MESSAGE_TYPE_FIELD_INDEX; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.MESSAGE_TYPE_FIELD_NAME; import static org.ehcache.clustered.common.internal.messages.ChainCodec.CHAIN_STRUCT; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.EHCACHE_MESSAGE_TYPES_ENUM_MAPPING; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_INDEX; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_NAME; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.KEY_FIELD; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.encodeMandatoryFields; import static org.terracotta.runnel.StructBuilder.newStructBuilder; diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpCodec.java index 8507c64a0a..546e0e12aa 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpCodec.java @@ -26,9 +26,9 @@ import java.util.function.Predicate; import static java.nio.ByteBuffer.wrap; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.EHCACHE_MESSAGE_TYPES_ENUM_MAPPING; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_INDEX; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_NAME; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.EHCACHE_MESSAGE_TYPES_ENUM_MAPPING; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.MESSAGE_TYPE_FIELD_INDEX; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.MESSAGE_TYPE_FIELD_NAME; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.KEY_FIELD; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.SERVER_STORE_NAME_FIELD; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.encodeMandatoryFields; diff --git a/clustered/server/entity/build.gradle b/clustered/server/entity/build.gradle index 66c1d2c768..0eccf996c8 100644 --- a/clustered/server/entity/build.gradle +++ b/clustered/server/entity/build.gradle @@ -25,6 +25,8 @@ dependencies { service "org.terracotta.management.dist:mnm-common:$terracottaPlatformVersion" implementation project(':clustered:common') + implementation "org.terracotta:runnel:$terracottaPlatformVersion" + implementation "org.terracotta:offheap-store:$offheapVersion" implementation "org.terracotta:client-message-tracker:$terracottaPlatformVersion" testImplementation project(':clustered:server:service') diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java index be536b5df5..1618f84cd5 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java @@ -24,6 +24,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.terracotta.entity.SyncMessageCodec; +import org.terracotta.runnel.EnumMapping; import org.terracotta.runnel.Struct; import org.terracotta.runnel.decoding.Enm; import org.terracotta.runnel.decoding.StructArrayDecoder; @@ -47,15 +48,14 @@ import static org.ehcache.clustered.server.internal.messages.SyncMessageType.DATA; import static org.ehcache.clustered.server.internal.messages.SyncMessageType.MESSAGE_TRACKER; import static org.ehcache.clustered.server.internal.messages.SyncMessageType.STATE_REPO; -import static org.ehcache.clustered.server.internal.messages.SyncMessageType.SYNC_MESSAGE_TYPE_FIELD_INDEX; -import static org.ehcache.clustered.server.internal.messages.SyncMessageType.SYNC_MESSAGE_TYPE_FIELD_NAME; -import static org.ehcache.clustered.server.internal.messages.SyncMessageType.SYNC_MESSAGE_TYPE_MAPPING; +import static org.terracotta.runnel.EnumMappingBuilder.newEnumMappingBuilder; import static org.terracotta.runnel.StructBuilder.newStructBuilder; public class EhcacheSyncMessageCodec implements SyncMessageCodec { private static final Logger LOGGER = LoggerFactory.getLogger(EhcacheSyncMessageCodec.class); + private static final String SYNC_MESSAGE_TYPE_FIELD = "msgType"; private static final String CHAIN_FIELD = "chain"; private static final String CHAIN_MAP_ENTRIES_SUB_STRUCT = "entries"; private static final String STATE_REPO_ENTRIES_SUB_STRUCT = "mappings"; @@ -67,13 +67,20 @@ public class EhcacheSyncMessageCodec implements SyncMessageCodec SYNC_MESSAGE_TYPE_MAPPING = newEnumMappingBuilder(SyncMessageType.class) + .mapping(STATE_REPO, 1) + .mapping(DATA, 10) + .mapping(MESSAGE_TRACKER, 20) + .build(); + private static final Struct CHAIN_MAP_ENTRY_STRUCT = newStructBuilder() .int64(KEY_FIELD, 10) .struct(CHAIN_FIELD, 20, CHAIN_STRUCT) .build(); private static final Struct DATA_SYNC_STRUCT = newStructBuilder() - .enm(SYNC_MESSAGE_TYPE_FIELD_NAME, SYNC_MESSAGE_TYPE_FIELD_INDEX, SYNC_MESSAGE_TYPE_MAPPING) + .enm(SYNC_MESSAGE_TYPE_FIELD, SYNC_MESSAGE_TYPE_FIELD_INDEX, SYNC_MESSAGE_TYPE_MAPPING) .structs(CHAIN_MAP_ENTRIES_SUB_STRUCT, 20, CHAIN_MAP_ENTRY_STRUCT) .build(); @@ -83,7 +90,7 @@ public class EhcacheSyncMessageCodec implements SyncMessageCodec encoder = MESSAGE_TRACKER_SYNC_STRUCT.encoder(); encoder - .enm(SYNC_MESSAGE_TYPE_FIELD_NAME, MESSAGE_TRACKER) + .enm(SYNC_MESSAGE_TYPE_FIELD, MESSAGE_TRACKER) .structs(MESSAGE_TRACKER_CLIENTS_STRUCT, syncMessage.getTrackedMessages().entrySet(), (clientEncoder, entry) -> { Map responses = entry.getValue(); @@ -157,7 +164,7 @@ private ByteBuffer encodeResponse(EhcacheEntityResponse response) { private byte[] encodeStateRepoSync(EhcacheStateRepoSyncMessage syncMessage) { StructEncoder encoder = STATE_REPO_SYNC_STRUCT.encoder(); - encoder.enm(SYNC_MESSAGE_TYPE_FIELD_NAME, STATE_REPO) + encoder.enm(SYNC_MESSAGE_TYPE_FIELD, STATE_REPO) .string(SERVER_STORE_NAME_FIELD, syncMessage.getCacheId()) .string(STATE_REPO_MAP_NAME_FIELD, syncMessage.getMapId()); encoder.structs(STATE_REPO_ENTRIES_SUB_STRUCT, syncMessage.getMappings().entrySet(), @@ -169,7 +176,7 @@ private byte[] encodeStateRepoSync(EhcacheStateRepoSyncMessage syncMessage) { private byte[] encodeDataSync(EhcacheDataSyncMessage syncMessage) { StructEncoder encoder; encoder = DATA_SYNC_STRUCT.encoder(); - encoder.enm(SYNC_MESSAGE_TYPE_FIELD_NAME, DATA); + encoder.enm(SYNC_MESSAGE_TYPE_FIELD, DATA); encoder.structs(CHAIN_MAP_ENTRIES_SUB_STRUCT, syncMessage.getChainMap().entrySet(), (entryEncoder, entry) -> { entryEncoder.int64(KEY_FIELD, entry.getKey()); @@ -182,7 +189,7 @@ private byte[] encodeDataSync(EhcacheDataSyncMessage syncMessage) { public EhcacheSyncMessage decode(final int concurrencyKey, final byte[] payload) { ByteBuffer message = wrap(payload); StructDecoder decoder = DATA_SYNC_STRUCT.decoder(message); - Enm enm = decoder.enm(SYNC_MESSAGE_TYPE_FIELD_NAME); + Enm enm = decoder.enm(SYNC_MESSAGE_TYPE_FIELD); if (!enm.isFound()) { throw new AssertionError("Invalid message format - misses the message type field"); } diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java index 929af99b9d..b8f49381c9 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java @@ -25,9 +25,9 @@ import java.nio.ByteBuffer; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.EHCACHE_MESSAGE_TYPES_ENUM_MAPPING; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_INDEX; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_NAME; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.EHCACHE_MESSAGE_TYPES_ENUM_MAPPING; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.MESSAGE_TYPE_FIELD_INDEX; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.MESSAGE_TYPE_FIELD_NAME; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.KEY_FIELD; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.SERVER_STORE_NAME_FIELD; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.encodeMandatoryFields; diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java index 88b953730c..c09c714499 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java @@ -16,12 +16,14 @@ package org.ehcache.clustered.server.management; import org.ehcache.clustered.common.PoolAllocation; +import org.ehcache.clustered.server.ServerSideServerStore; import org.terracotta.management.model.capabilities.descriptors.Descriptor; import org.terracotta.management.model.capabilities.descriptors.Settings; import org.terracotta.management.model.context.Context; import org.terracotta.management.registry.Named; import org.terracotta.management.registry.RequiredContext; import org.terracotta.management.service.monitoring.registry.provider.AliasBindingManagementProvider; +import org.terracotta.offheapstore.MapInternals; import java.util.ArrayList; import java.util.Collection; @@ -66,17 +68,21 @@ public Collection getDescriptors() { Settings getSettings() { // names taken from ServerStoreConfiguration.isCompatible() - PoolAllocation poolAllocation = getBinding().getValue().getStoreConfiguration().getPoolAllocation(); + ServerSideServerStore value = getBinding().getValue(); + PoolAllocation poolAllocation = value.getStoreConfiguration().getPoolAllocation(); Settings settings = new Settings(getContext()) - .set("resourcePoolType", poolAllocation.getClass().getSimpleName().toLowerCase()) - .set("allocatedMemoryAtTime", getBinding().getValue().getAllocatedMemory()) - .set("tableCapacityAtTime", getBinding().getValue().getTableCapacity()) - .set("vitalMemoryAtTime", getBinding().getValue().getVitalMemory()) - .set("longSizeAtTime", getBinding().getValue().getSize()) - .set("dataAllocatedMemoryAtTime", getBinding().getValue().getDataAllocatedMemory()) - .set("dataOccupiedMemoryAtTime", getBinding().getValue().getDataOccupiedMemory()) - .set("dataSizeAtTime", getBinding().getValue().getDataSize()) - .set("dataVitalMemoryAtTime", getBinding().getValue().getDataVitalMemory()); + .set("resourcePoolType", poolAllocation.getClass().getSimpleName().toLowerCase()); + if (value instanceof MapInternals) { + MapInternals internals = (MapInternals) value; + settings.set("allocatedMemoryAtTime", internals.getAllocatedMemory()) + .set("tableCapacityAtTime", internals.getTableCapacity()) + .set("vitalMemoryAtTime", internals.getVitalMemory()) + .set("longSizeAtTime", internals.getSize()) + .set("dataAllocatedMemoryAtTime", internals.getDataAllocatedMemory()) + .set("dataOccupiedMemoryAtTime", internals.getDataOccupiedMemory()) + .set("dataSizeAtTime", internals.getDataSize()) + .set("dataVitalMemoryAtTime", internals.getDataVitalMemory()); + } if (poolAllocation instanceof PoolAllocation.DedicatedPoolAllocation) { settings.set("resourcePoolDedicatedResourceName", ((PoolAllocation.DedicatedPoolAllocation) poolAllocation).getResourceName()); settings.set("resourcePoolDedicatedSize", ((PoolAllocation.DedicatedPoolAllocation) poolAllocation).getSize()); diff --git a/clustered/server/service-api/build.gradle b/clustered/server/service-api/build.gradle index b1da4912e2..dddbdfa46b 100644 --- a/clustered/server/service-api/build.gradle +++ b/clustered/server/service-api/build.gradle @@ -21,6 +21,4 @@ plugins { dependencies { api project(':clustered:common-api') - api "org.terracotta:offheap-store:$offheapVersion" - api "org.terracotta:runnel:$terracottaPlatformVersion" } diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java index cbcafcad13..92400209d2 100644 --- a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java @@ -18,12 +18,11 @@ import org.ehcache.clustered.common.internal.ServerStoreConfiguration; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.ServerStore; -import org.terracotta.offheapstore.MapInternals; import java.util.List; import java.util.Set; -public interface ServerSideServerStore extends ServerStore, MapInternals { +public interface ServerSideServerStore extends ServerStore { void setEventListener(ServerStoreEventListener listener); void enableEvents(boolean enable); ServerStoreConfiguration getStoreConfiguration(); diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java index 6c325bbda0..ca0b75108e 100644 --- a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java @@ -16,10 +16,6 @@ package org.ehcache.clustered.server.internal.messages; -import org.terracotta.runnel.EnumMapping; - -import static org.terracotta.runnel.EnumMappingBuilder.newEnumMappingBuilder; - /** * SyncMessageType */ @@ -27,12 +23,4 @@ public enum SyncMessageType { STATE_REPO, DATA, MESSAGE_TRACKER; - - public static final String SYNC_MESSAGE_TYPE_FIELD_NAME = "msgType"; - public static final int SYNC_MESSAGE_TYPE_FIELD_INDEX = 10; - public static final EnumMapping SYNC_MESSAGE_TYPE_MAPPING = newEnumMappingBuilder(SyncMessageType.class) - .mapping(STATE_REPO, 1) - .mapping(DATA, 10) - .mapping(MESSAGE_TRACKER, 20) - .build(); } diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java index 62c9cdf8ab..2f3e851947 100644 --- a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java +++ b/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java @@ -33,11 +33,11 @@ public interface EhcacheStateService { Map getSharedResourcePools(); - ResourcePageSource getSharedResourcePageSource(String name); + Object getSharedResourcePageSource(String name); ServerSideConfiguration.Pool getDedicatedResourcePool(String name); - ResourcePageSource getDedicatedResourcePageSource(String name); + Object getDedicatedResourcePageSource(String name); ServerSideServerStore getStore(String name); diff --git a/clustered/server/service/build.gradle b/clustered/server/service/build.gradle index eef4ff78ed..8021f9ed32 100644 --- a/clustered/server/service/build.gradle +++ b/clustered/server/service/build.gradle @@ -24,6 +24,7 @@ dependencies { service "org.terracotta:offheap-resource:$terracottaPlatformVersion" implementation project(':clustered:common') + implementation "org.terracotta:offheap-store:$offheapVersion" testImplementation project(':clustered:test-utils') testImplementation "org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion" diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java index 43c7094a46..ed11ea7b2b 100644 --- a/clustered/server/service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java +++ b/clustered/server/service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java @@ -21,6 +21,7 @@ import org.ehcache.clustered.server.offheap.OffHeapChainMap; import org.ehcache.clustered.server.offheap.OffHeapServerStore; import org.ehcache.clustered.server.state.ResourcePageSource; +import org.terracotta.offheapstore.MapInternals; import org.terracotta.offheapstore.exceptions.OversizeMappingException; import org.terracotta.offheapstore.paging.PageSource; @@ -30,7 +31,7 @@ import java.util.List; import java.util.Set; -public class ServerStoreImpl implements ServerSideServerStore { +public class ServerStoreImpl implements ServerSideServerStore, MapInternals { private final ServerStoreConfiguration storeConfiguration; private final ResourcePageSource pageSource; diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java rename to clustered/server/service/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java From c1cb75aa66a45f29c45dcf57dd1b9f83a2cdb7bb Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 19 Mar 2020 13:17:01 -0400 Subject: [PATCH 210/372] Upgrade core and move clustered modules to unique groupId --- buildSrc/src/main/groovy/EhDeploy.groovy | 7 ++++++- buildSrc/src/main/groovy/EhVoltron.groovy | 10 +++++++--- clustered/build.gradle | 3 +++ clustered/common-api/build.gradle | 5 ++++- clustered/server/entity/build.gradle | 2 +- gradle.properties | 2 +- 6 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 clustered/build.gradle diff --git a/buildSrc/src/main/groovy/EhDeploy.groovy b/buildSrc/src/main/groovy/EhDeploy.groovy index 4465ea89ff..2ae5ff59d9 100644 --- a/buildSrc/src/main/groovy/EhDeploy.groovy +++ b/buildSrc/src/main/groovy/EhDeploy.groovy @@ -1,9 +1,9 @@ import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer import org.gradle.api.artifacts.maven.MavenDeployment import org.gradle.api.plugins.MavenPlugin -import org.gradle.plugins.signing.Sign import scripts.Utils /* @@ -54,6 +54,11 @@ class EhDeploy implements Plugin { } pom.scopeMappings.addMapping(MavenPlugin.COMPILE_PRIORITY, project.configurations.providedApi, Conf2ScopeMappingContainer.PROVIDED) pom.scopeMappings.addMapping(MavenPlugin.COMPILE_PRIORITY, project.configurations.providedImplementation, Conf2ScopeMappingContainer.PROVIDED) + project.configurations.configureEach { Configuration conf -> + if (conf.name in [EhVoltron.VOLTRON_CONFIGURATION_NAME, EhVoltron.SERVICE_CONFIGURATION_NAME]) { + pom.scopeMappings.addMapping(MavenPlugin.PROVIDED_COMPILE_PRIORITY, conf, Conf2ScopeMappingContainer.PROVIDED) + } + } utils.pomFiller(pom, project.subPomName, project.subPomDesc) diff --git a/buildSrc/src/main/groovy/EhVoltron.groovy b/buildSrc/src/main/groovy/EhVoltron.groovy index 552e69156a..20b225fee4 100644 --- a/buildSrc/src/main/groovy/EhVoltron.groovy +++ b/buildSrc/src/main/groovy/EhVoltron.groovy @@ -5,10 +5,14 @@ import org.gradle.api.plugins.JavaPlugin import org.gradle.api.tasks.bundling.Jar class EhVoltron implements Plugin { + + static String VOLTRON_CONFIGURATION_NAME = 'voltron' + static String SERVICE_CONFIGURATION_NAME = 'service' + @Override void apply(Project project) { project.plugins.withId('java') { - def voltron = project.configurations.create('voltron') { voltron -> + def voltron = project.configurations.create(VOLTRON_CONFIGURATION_NAME) { voltron -> description "Dependencies provided by Voltron from server/lib" canBeResolved true canBeConsumed true @@ -18,7 +22,7 @@ class EhVoltron implements Plugin { voltron.dependencies.add(project.dependencies.create(group: 'org.terracotta', name: 'packaging-support', version: project.terracottaApisVersion)) voltron.dependencies.add(project.dependencies.create(group: 'org.slf4j', name: 'slf4j-api', version: project.slf4jVersion)) } - def service = project.configurations.create('service') { service -> + def service = project.configurations.create(SERVICE_CONFIGURATION_NAME) { service -> description "Services consumed by this plugin" canBeResolved true canBeConsumed true @@ -39,7 +43,7 @@ class EhVoltron implements Plugin { project.tasks.named(JavaPlugin.JAR_TASK_NAME, Jar) { doFirst { manifest { - attributes('Class-Path': (project.configurations.runtimeClasspath - project.configurations.voltron - project.configurations.service).collect { it.getName() }.join(' ')) + attributes('Class-Path': (project.configurations.runtimeClasspath - voltron - service).collect { it.getName() }.join(' ')) } } } diff --git a/clustered/build.gradle b/clustered/build.gradle new file mode 100644 index 0000000000..5809a2cbcb --- /dev/null +++ b/clustered/build.gradle @@ -0,0 +1,3 @@ +subprojects { + group = 'org.ehcache.modules.clustered' +} diff --git a/clustered/common-api/build.gradle b/clustered/common-api/build.gradle index 44a9ebad33..29537eb300 100644 --- a/clustered/common-api/build.gradle +++ b/clustered/common-api/build.gradle @@ -16,5 +16,8 @@ plugins { id 'org.ehcache.build.deploy' - id 'org.ehcache.build.voltron' +} + +dependencies { + api "org.terracotta:entity-common-api:$terracottaApisVersion" } diff --git a/clustered/server/entity/build.gradle b/clustered/server/entity/build.gradle index 0eccf996c8..c322b53c87 100644 --- a/clustered/server/entity/build.gradle +++ b/clustered/server/entity/build.gradle @@ -24,7 +24,7 @@ dependencies { service "org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion" service "org.terracotta.management.dist:mnm-common:$terracottaPlatformVersion" - implementation project(':clustered:common') + api project(':clustered:common') implementation "org.terracotta:runnel:$terracottaPlatformVersion" implementation "org.terracotta:offheap-store:$offheapVersion" implementation "org.terracotta:client-message-tracker:$terracottaPlatformVersion" diff --git a/gradle.properties b/gradle.properties index 3b98c0418b..8d064ca840 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ jaxbVersion = 2.3.1 # Terracotta clustered terracottaPlatformVersion = 5.7.4-pre8 terracottaApisVersion = 1.7.0-pre1 -terracottaCoreVersion = 5.7.0-pre18 +terracottaCoreVersion = 5.7.0-pre19 terracottaPassthroughTestingVersion = 1.7.0-pre8 # Test lib versions From dd86765adea75b418499868b0db1694ddeb4b57c Mon Sep 17 00:00:00 2001 From: akomakom Date: Fri, 20 Mar 2020 14:54:00 -0400 Subject: [PATCH 211/372] Run windows tests on latest OS version --- azure-pipelines-windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines-windows.yml b/azure-pipelines-windows.yml index 0242a8775b..852f3193ce 100644 --- a/azure-pipelines-windows.yml +++ b/azure-pipelines-windows.yml @@ -26,14 +26,14 @@ resources: jobs: - template: build-templates/gradle-common.yml@templates parameters: - vmImage: 'vs2017-win2016' + vmImage: 'windows-latest' gradleTasks: 'test -x :clustered:integration-test:test' jdkVersion: '1.8' jobName: 'Java8' - template: build-templates/gradle-common.yml@templates parameters: - vmImage: 'vs2017-win2016' + vmImage: 'windows-latest' gradleTasks: 'test -x :clustered:integration-test:test' jdkVersion: '1.8' options: '-PtestVM=java11Home' From 297a18e571d82d30fe01047b77a6f8b99831ad5e Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 25 Mar 2020 14:14:25 -0400 Subject: [PATCH 212/372] Upgrade to latest terracotta-core --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 8d064ca840..9820fd938f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ jaxbVersion = 2.3.1 # Terracotta clustered terracottaPlatformVersion = 5.7.4-pre8 terracottaApisVersion = 1.7.0-pre1 -terracottaCoreVersion = 5.7.0-pre19 +terracottaCoreVersion = 5.7.0-pre21 terracottaPassthroughTestingVersion = 1.7.0-pre8 # Test lib versions From 1aae8e40929383fa683d8e04e3c31ac0b485b928 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 2 Apr 2020 11:33:59 -0400 Subject: [PATCH 213/372] Upgrade to passthrough server 1.7.0-pre12 --- .../clustered/client/internal/UnitTestConnectionService.java | 1 - gradle.properties | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java index f9dc86734c..9037f6ddc8 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java @@ -150,7 +150,6 @@ public static void add(URI uri, PassthroughServer server) { // TODO rework that better server.registerAsynchronousServerCrasher(mock(IAsynchronousServerCrasher.class)); server.start(true, false); - server.addPermanentEntities(); LOGGER.info("Started PassthroughServer at {}", keyURI); } diff --git a/gradle.properties b/gradle.properties index 9820fd938f..1cac1acfa7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ jaxbVersion = 2.3.1 terracottaPlatformVersion = 5.7.4-pre8 terracottaApisVersion = 1.7.0-pre1 terracottaCoreVersion = 5.7.0-pre21 -terracottaPassthroughTestingVersion = 1.7.0-pre8 +terracottaPassthroughTestingVersion = 1.7.0-pre12 # Test lib versions junitVersion = 4.12 From e95cd2b632d0755a62d9b571054d56b8b9dcd89d Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 7 Apr 2020 17:24:29 -0400 Subject: [PATCH 214/372] Ehcache with dynamic config kit --- buildSrc/src/main/groovy/EhVoltron.groovy | 7 - .../internal/UnitTestConnectionService.java | 4 +- clustered/clustered-dist/build.gradle | 37 +++--- .../assemble/server/conf/cluster.properties | 16 +++ .../src/assemble/server/conf/tc-config.xml | 61 --------- clustered/integration-test/build.gradle | 10 +- .../BasicCacheOpsMultiThreadedTest.java | 3 +- .../clustered/BasicClusteredCacheOpsTest.java | 3 +- .../clustered/BasicEntityInteractionTest.java | 3 +- ...anagerLifecycleEhcacheIntegrationTest.java | 3 +- ...gerClientEntityFactoryIntegrationTest.java | 3 +- .../clustered/ClusteredIterationTest.java | 3 +- .../clustered/ClusteredLoaderWriterTest.java | 3 +- .../ehcache/clustered/DestroyLoopTest.java | 3 +- .../clustered/EventsFailureBehaviorTest.java | 3 +- .../IterationFailureBehaviorTest.java | 3 +- .../clustered/JCacheClusteredTest.java | 3 +- .../java/org/ehcache/clustered/LeaseTest.java | 3 +- .../clustered/OversizedCacheOpsTest.java | 3 +- .../clustered/ReconnectDuringDestroyTest.java | 3 +- .../ResourcePoolAllocationFailureTest.java | 3 +- .../clustered/TerminatedServerTest.java | 3 +- .../VoltronReadWriteLockIntegrationTest.java | 3 +- ...onReadWriteLockPassiveIntegrationTest.java | 3 +- .../AbstractClusteringManagementTest.java | 2 + .../management/CMClosedEventSentTest.java | 3 +- .../ClusteringManagementServiceTest.java | 14 +- .../EhcacheConfigWithManagementTest.java | 3 +- .../ManagementClusterConnectionTest.java | 3 +- .../reconnect/AutoCreateOnReconnectTest.java | 2 + .../reconnect/BasicCacheReconnectTest.java | 3 +- .../CacheManagerDestroyReconnectTest.java | 3 +- .../reconnect/EventsReconnectTest.java | 3 +- ...dCacheOpsReplicationMultiThreadedTest.java | 3 +- ...BasicClusteredCacheOpsReplicationTest.java | 3 +- ...OpsReplicationWithMultipleClientsTest.java | 3 +- ...CacheOpsReplicationWithServersApiTest.java | 3 +- .../BasicLifeCyclePassiveReplicationTest.java | 3 +- .../clustered/replication/DuplicateTest.java | 3 +- .../OversizedCacheOpsPassiveTest.java | 2 + .../clustered/sync/PassiveSyncTest.java | 3 +- ...icClusteredWriteBehindMultiClientTest.java | 3 +- .../BasicClusteredWriteBehindTest.java | 3 +- ...WriteBehindWithPassiveMultiClientTest.java | 3 +- ...icClusteredWriteBehindWithPassiveTest.java | 3 +- .../testing/DynamicConfigStartupBuilder.java | 121 ++++++++++++++++++ .../org/ehcache/osgi/ClusteredOsgiTest.java | 1 - .../java/org/ehcache/osgi/OsgiTestUtils.java | 56 ++------ clustered/server/entity/build.gradle | 2 +- clustered/server/service/build.gradle | 1 + .../state/EhcacheStateServiceProvider.java | 7 +- gradle.properties | 6 +- management/build.gradle | 2 +- 53 files changed, 264 insertions(+), 192 deletions(-) create mode 100644 clustered/clustered-dist/src/assemble/server/conf/cluster.properties delete mode 100644 clustered/clustered-dist/src/assemble/server/conf/tc-config.xml create mode 100644 clustered/integration-test/src/test/java/org/ehcache/testing/DynamicConfigStartupBuilder.java diff --git a/buildSrc/src/main/groovy/EhVoltron.groovy b/buildSrc/src/main/groovy/EhVoltron.groovy index 20b225fee4..7c40d28e2a 100644 --- a/buildSrc/src/main/groovy/EhVoltron.groovy +++ b/buildSrc/src/main/groovy/EhVoltron.groovy @@ -26,13 +26,6 @@ class EhVoltron implements Plugin { description "Services consumed by this plugin" canBeResolved true canBeConsumed true - - service.withDependencies { deps -> - def monitoringServiceApi = deps.find { it.group == 'org.terracotta.management' && it.name == 'monitoring-service-api' } as ModuleDependency - if (monitoringServiceApi != null) { - monitoringServiceApi.transitive = false - } - } } project.configurations.getByName(JavaPlugin.API_CONFIGURATION_NAME) { api -> diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java index 9037f6ddc8..93df067ae7 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java @@ -365,9 +365,7 @@ public PassthroughServer build() { newServer.registerClientEntityService(service); } - if (!this.resources.getResource().isEmpty()) { - newServer.registerExtendedConfiguration(new OffHeapResourcesProvider(this.resources)); - } + newServer.registerExtendedConfiguration(new OffHeapResourcesProvider(this.resources)); for (Map.Entry entry : serviceProviders.entrySet()) { newServer.registerServiceProvider(entry.getKey(), entry.getValue()); diff --git a/clustered/clustered-dist/build.gradle b/clustered/clustered-dist/build.gradle index 9b24b8b9ad..f805b17bcd 100644 --- a/clustered/clustered-dist/build.gradle +++ b/clustered/clustered-dist/build.gradle @@ -41,42 +41,37 @@ dependencies { compileOnly "org.terracotta:runnel:$parent.terracottaPlatformVersion" } -def voltronProvides = { Configuration c -> +def kitProvides = { Configuration c -> c.exclude group:'org.slf4j', module:'slf4j-api' c.exclude group:'org.terracotta', module:'entity-server-api' c.exclude group:'org.terracotta', module:'entity-common-api' c.exclude group:'org.terracotta', module:'packaging-support' c.exclude group:'org.terracotta', module:'standard-cluster-services' + c.exclude group:'org.terracotta', module:'statistics' + c.exclude group:'org.terracotta', module:'runnel' + c.exclude group:'org.terracotta', module:'client-message-tracker' + c.exclude group:'org.terracotta.management', module:'monitoring-service-api' + c.exclude group:'org.terracotta.management', module:'management-model' + c.exclude group:'org.terracotta.management', module:'management-registry' + c.exclude group:'org.terracotta.management', module:'cluster-topology' + c.exclude group:'org.terracotta.management', module:'sequence-generator' } configurations { kit - serverApis(voltronProvides) - serverLibs(voltronProvides) + serverApis(kitProvides) + serverLibs(kitProvides) } dependencies { compileOnly "org.terracotta.internal:client-runtime:$terracottaCoreVersion" compileOnly "org.terracotta:lease-api:$terracottaPlatformVersion" - serverApis "org.terracotta:statistics:$statisticVersion" - serverApis("org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion") { - transitive = false - } - // this is here because monitoring-service-api depends on mnm-common. if that can be unwound, - // mnm-common can go into lib - serverApis "org.terracotta.management.dist:mnm-common:$terracottaPlatformVersion" - serverApis project(':clustered:server:service-api') serverLibs project(':clustered:server:entity') serverLibs project(':clustered:server:service') - serverLibs("org.terracotta:lease-entity-server:$parent.terracottaPlatformVersion") { - transitive = false - } - serverLibs "org.terracotta.management.dist:mnm-server:$terracottaPlatformVersion" - - kit "org.terracotta.internal:terracotta-kit:$terracottaCoreVersion@tar.gz" + kit "org.terracotta:platform-kit:$terracottaPlatformVersion@tar.gz" shadowCompile "org.slf4j:slf4j-api:$parent.slf4jVersion" pomOnlyCompile "org.ehcache:ehcache:$parent.baseVersion" @@ -93,7 +88,7 @@ jar { 'Bundle-SymbolicName': 'org.ehcache.clustered', 'Export-Package': '!com.tc.*, !com.terracotta.*, !org.terracotta.*, !org.ehcache.*.internal.*, !sun.misc, ' + 'org.ehcache.clustered.client.*, org.ehcache.clustered.common.*', - 'Import-Package': '!sun.misc.*, org.ehcache.xml.*;resolution:=optional, jdk.jfr.*;resolution:=optional, *' + 'Import-Package': '!sun.misc.*, org.ehcache.xml.*;resolution:=optional, jdk.jfr.*;resolution:=optional, !com.fasterxml.jackson.annotation, *' ) } @@ -101,12 +96,16 @@ distributions { main { baseName = archivesBaseName contents { + filesMatching('**/*.jar') { + // We can safely exclude JAR duplicates as our dependency strategy is fail on conflict + duplicatesStrategy DuplicatesStrategy.EXCLUDE + } //tc kit into ('') { from configurations.kit.files.collect { tarTree(it) } eachFile { f -> // remove top level directory from the kit - f.path = f.path.replace("terracotta-$terracottaCoreVersion/", "") + f.path = f.path.replace("platform-kit-$terracottaPlatformVersion/", "") } exclude { f -> // Exclude tc's client subdir and README.txt - Issue 1273 diff --git a/clustered/clustered-dist/src/assemble/server/conf/cluster.properties b/clustered/clustered-dist/src/assemble/server/conf/cluster.properties new file mode 100644 index 0000000000..221ec16d0c --- /dev/null +++ b/clustered/clustered-dist/src/assemble/server/conf/cluster.properties @@ -0,0 +1,16 @@ +client-lease-duration=150s +client-reconnect-window=120s +cluster-name=default-cluster +failover-priority=availability +offheap-resources=main:512MB +stripe.1.node.1.node-bind-address=0.0.0.0 +stripe.1.node.1.node-group-bind-address=0.0.0.0 +stripe.1.node.1.node-group-port=9430 +stripe.1.node.1.node-hostname=localhost +stripe.1.node.1.node-log-dir=%H/terracotta/logs +stripe.1.node.1.node-logger-overrides= +stripe.1.node.1.node-name=default-server +stripe.1.node.1.node-port=9410 +stripe.1.node.1.node-public-hostname= +stripe.1.node.1.node-public-port= +stripe.1.node.1.tc-properties= diff --git a/clustered/clustered-dist/src/assemble/server/conf/tc-config.xml b/clustered/clustered-dist/src/assemble/server/conf/tc-config.xml deleted file mode 100644 index a342215c9f..0000000000 --- a/clustered/clustered-dist/src/assemble/server/conf/tc-config.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - 512 - - - - - - - - %H/terracotta-logs - - - - - - - - - - - - - - - - 120 - - - - - diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index 5a7cac3389..fa1a77b4d5 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -35,9 +35,9 @@ dependencies { } testImplementation project(':management') - testImplementation "org.terracotta.management.dist:mnm-nms:$terracottaPlatformVersion" - testImplementation "org.terracotta.management.dist:mnm-nms-agent:$terracottaPlatformVersion" - testImplementation "com.fasterxml.jackson.core:jackson-databind:2.8.0" + testImplementation "org.terracotta.management:nms-entity-client:$terracottaPlatformVersion" + testImplementation "org.terracotta.management:nms-agent-entity-client:$terracottaPlatformVersion" + testImplementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" testImplementation "org.awaitility:awaitility:3.1.6" testRuntimeOnly "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" @@ -45,10 +45,6 @@ dependencies { testImplementation (group:'org.terracotta.internal', name:'galvan-support', version: terracottaCoreVersion) testImplementation group: 'javax.cache', name: 'cache-api', version: jcacheVersion - - serverLibs ("org.terracotta.management.dist:mnm-server:$terracottaPlatformVersion") { - exclude group:'org.terracotta.management.dist', module:'mnm-common' - } } task unzipKit(type: Copy) { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index 3367cd21d9..e4b8c18c39 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -28,6 +28,7 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -66,7 +67,7 @@ public class BasicCacheOpsMultiThreadedTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java index 2aefc0e416..9a02acb494 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java @@ -28,6 +28,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -61,7 +62,7 @@ public class BasicClusteredCacheOpsTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java index aa99e79049..543c23979a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java @@ -30,6 +30,7 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.management.cluster.DefaultClusteringManagementService; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.hamcrest.Matchers; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -62,7 +63,7 @@ public class BasicEntityInteractionTest extends ClusteredTests { "\n"; @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); private ClusterTierManagerConfiguration blankConfiguration = new ClusterTierManagerConfiguration("identifier", new ServerSideConfiguration(emptyMap())); @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java index 4d419de113..7c4588fc95 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java @@ -37,6 +37,7 @@ import org.ehcache.clustered.common.EhcacheEntityVersion; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.StateTransitionException; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.ehcache.xml.XmlConfiguration; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -68,7 +69,7 @@ public class CacheManagerLifecycleEhcacheIntegrationTest extends ClusteredTests "\n"; @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); private static Connection ASSERTION_CONNECTION; @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java index ddc47de7d4..35ae8d9864 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java @@ -24,6 +24,7 @@ import org.ehcache.clustered.client.internal.ClusterTierManagerValidationException; import org.ehcache.clustered.common.ServerSideConfiguration; import org.ehcache.clustered.common.ServerSideConfiguration.Pool; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -54,7 +55,7 @@ public class ClusterTierManagerClientEntityFactoryIntegrationTest extends Cluste @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).startupBuilder(DynamicConfigStartupBuilder::new).build(); private static Connection CONNECTION; @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java index b3dd98e5ac..8bebe713c5 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java @@ -18,6 +18,7 @@ import org.ehcache.Cache; import org.ehcache.CacheManager; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; @@ -58,7 +59,7 @@ public class ClusteredIterationTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java index 6f6a61260a..8e1d0054a8 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java @@ -32,6 +32,7 @@ import org.ehcache.management.ManagementRegistryService; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; import org.ehcache.management.registry.DefaultManagementRegistryService; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -81,7 +82,7 @@ public static Consistency[] data() { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java index 09b750224b..d26c545152 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java @@ -27,6 +27,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -57,7 +58,7 @@ public class DestroyLoopTest extends ClusteredTests { private static final String CACHE_NAME = "clustered-cache"; @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index 9bfcf38b0d..85d9814152 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -33,6 +33,7 @@ import org.ehcache.event.CacheEventListener; import org.ehcache.event.EventType; import org.ehcache.expiry.ExpiryPolicy; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -70,7 +71,7 @@ public class EventsFailureBehaviorTest extends ClusteredTests { "\n"; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java index da4de9e225..670f8f44e3 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java @@ -27,6 +27,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.spi.resilience.StoreAccessException; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -65,7 +66,7 @@ public class IterationFailureBehaviorTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java index 5bf227de73..88f2a70071 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java @@ -16,6 +16,7 @@ package org.ehcache.clustered; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.ehcache.testing.ExternalTests; import org.jsr107.tck.spi.CachingProviderTest; import org.junit.AfterClass; @@ -56,7 +57,7 @@ public class JCacheClusteredTest extends ClusteredTests { "\n"; @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java index 6163d5510c..b0bb209739 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java @@ -27,6 +27,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -68,7 +69,7 @@ public class LeaseTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); private final List proxies = new ArrayList<>(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java index e5d08edacc..6af324aa20 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java @@ -25,6 +25,7 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.ClassRule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; @@ -48,7 +49,7 @@ public class OversizedCacheOpsTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @Test public void overSizedCacheOps() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java index 83917b24d8..31740c0910 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -31,6 +31,7 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; @@ -67,7 +68,7 @@ public class ReconnectDuringDestroyTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java index 627eb0bead..2487b0a6d3 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java @@ -28,6 +28,7 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -50,7 +51,7 @@ public class ResourcePoolAllocationFailureTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java index a02044e2cc..0c99cfdc01 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java @@ -34,6 +34,7 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -132,7 +133,7 @@ private ThrowableAssertAlternative assertExceptionOccur } @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java index 9be9c9fd3c..a222a3c4df 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java @@ -28,6 +28,7 @@ import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock.Hold; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -42,7 +43,7 @@ public class VoltronReadWriteLockIntegrationTest extends ClusteredTests { @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).startupBuilder(DynamicConfigStartupBuilder::new).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java index 44f225b1df..c9be3261bb 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java @@ -24,6 +24,7 @@ import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock.Hold; import org.ehcache.clustered.util.ParallelTestCluster; import org.ehcache.clustered.util.runners.Parallel; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; @@ -40,7 +41,7 @@ public class VoltronReadWriteLockPassiveIntegrationTest extends ClusteredTests { @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).startupBuilder(DynamicConfigStartupBuilder::new).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 7b1efcf805..05722289c3 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -25,6 +25,7 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.AfterClass; import org.junit.Before; import org.junit.ClassRule; @@ -100,6 +101,7 @@ public abstract class AbstractClusteringManagementTest extends ClusteredTests { public static Cluster CLUSTER = newCluster(2) .in(clusterPath()) .withServiceFragment(RESOURCE_CONFIG) + .startupBuilder(DynamicConfigStartupBuilder::new) .build(); @Rule diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java index 98702fe300..2f5344b0c4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java @@ -21,6 +21,7 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.ClassRule; import org.junit.Test; import org.terracotta.management.model.message.Message; @@ -55,7 +56,7 @@ public class CMClosedEventSentTest extends ClusteredTests { + ""; @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @Test(timeout = 60_000) public void test_CACHE_MANAGER_CLOSED() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java index 0a9420d5d2..dbabc79e89 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java @@ -263,15 +263,17 @@ public void test_D_server_capabilities_exposed() throws Exception { // tms entity managerCapabilities = readTopology().activeServerEntityStream().filter(serverEntity -> serverEntity.is(tmsServerEntityIdentifier)).findFirst().get().getManagementRegistry().get().getCapabilities().toArray(new Capability[0]); - assertThat(managerCapabilities.length).isEqualTo(3); + assertThat(managerCapabilities.length).isEqualTo(5); - assertThat(managerCapabilities[0].getName()).isEqualTo("OffHeapResourceSettings"); - assertThat(managerCapabilities[1].getName()).isEqualTo("OffHeapResourceStatistics"); - assertThat(managerCapabilities[2].getName()).isEqualTo("StatisticCollectorCapability"); + assertThat(managerCapabilities[0].getName()).isEqualTo("DataRootSettings"); + assertThat(managerCapabilities[1].getName()).isEqualTo("DataRootStatistics"); + assertThat(managerCapabilities[2].getName()).isEqualTo("OffHeapResourceSettings"); + assertThat(managerCapabilities[3].getName()).isEqualTo("OffHeapResourceStatistics"); + assertThat(managerCapabilities[4].getName()).isEqualTo("StatisticCollectorCapability"); - assertThat(managerCapabilities[0].getDescriptors()).hasSize(3); // time + 2 resources + assertThat(managerCapabilities[2].getDescriptors()).hasSize(3); // time + 2 resources - assertThat(managerCapabilities[1].getDescriptors()).containsOnlyElementsOf(OFFHEAP_RES_DESCRIPTORS); + assertThat(managerCapabilities[3].getDescriptors()).containsOnlyElementsOf(OFFHEAP_RES_DESCRIPTORS); } @Test diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java index f1ce37525d..6d7dbfdca4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java @@ -20,6 +20,7 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -45,7 +46,7 @@ public class EhcacheConfigWithManagementTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = newCluster().in(clusterPath()) - .withServiceFragment(RESOURCE_CONFIG).build(); + .withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @BeforeClass public static void beforeClass() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index fdbd9b8fc7..73e5b01606 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -26,6 +26,7 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.hamcrest.Matchers; import org.junit.AfterClass; import org.junit.Assert; @@ -79,7 +80,7 @@ public class ManagementClusterConnectionTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = newCluster() .in(clusterPath()) - .withServiceFragment(RESOURCE_CONFIG).build(); + .withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java index af1c4ff96f..e0f13dd978 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java @@ -19,6 +19,7 @@ import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.ClusteredTests; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.ClassRule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; @@ -46,6 +47,7 @@ public class AutoCreateOnReconnectTest extends ClusteredTests { public static Cluster CLUSTER = newCluster(1) .in(clusterPath()) .withServiceFragment(RESOURCE_CONFIG) + .startupBuilder(DynamicConfigStartupBuilder::new) .build(); @Test diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java index 25619a4cb1..304d066cbf 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java @@ -28,6 +28,7 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -74,7 +75,7 @@ public class BasicCacheReconnectTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java index 64164e321e..4b699f37d7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java @@ -21,6 +21,7 @@ import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.util.TCPProxyUtil; import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -43,7 +44,7 @@ public class CacheManagerDestroyReconnectTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index 890bce8bf5..9a0674e374 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -32,6 +32,7 @@ import org.ehcache.event.CacheEvent; import org.ehcache.event.CacheEventListener; import org.ehcache.event.EventType; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -109,7 +110,7 @@ final void clear() { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index fab61fc79f..9ba36c417f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -33,6 +33,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -102,7 +103,7 @@ public static Consistency[] data() { public Consistency cacheConsistency; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java index 97a47c6580..9be3202337 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java @@ -32,6 +32,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -78,7 +79,7 @@ public static Consistency[] data() { public Consistency cacheConsistency; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java index d4de272ea6..68b57c0403 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java @@ -32,6 +32,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -87,7 +88,7 @@ public static Consistency[] data() { public Consistency cacheConsistency; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java index fb3985c158..b05762007f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java @@ -28,6 +28,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -57,7 +58,7 @@ public class BasicClusteredCacheOpsReplicationWithServersApiTest extends Cluster private static Cache CACHE2; @ClassRule - public static Cluster CLUSTER = newCluster(2).in(clusterPath()).withServiceFragment(CONFIG).build(); + public static Cluster CLUSTER = newCluster(2).in(clusterPath()).withServiceFragment(CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @Before public void setUp() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java index cbc8ace0bd..dc65a7bfbf 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java @@ -22,6 +22,7 @@ import org.ehcache.clustered.util.ParallelTestCluster; import org.ehcache.clustered.util.runners.Parallel; import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -51,7 +52,7 @@ public class BasicLifeCyclePassiveReplicationTest extends ClusteredTests { "\n"; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build()); @Before public void startServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java index b6b6dfe015..6f1a5b2663 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java @@ -29,6 +29,7 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.spi.resilience.ResilienceStrategy; import org.ehcache.spi.resilience.StoreAccessException; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -61,7 +62,7 @@ public class DuplicateTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @Before public void startServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java index b7bc2347c9..fd29b35367 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java @@ -26,6 +26,7 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -59,6 +60,7 @@ public class OversizedCacheOpsPassiveTest extends ClusteredTests { newCluster(2).in(clusterPath()) .withSystemProperty("ehcache.sync.data.gets.threshold", "2") .withServiceFragment(RESOURCE_CONFIG) + .startupBuilder(DynamicConfigStartupBuilder::new) .build(); @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java index 2130e677f7..58740939de 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java @@ -26,6 +26,7 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.Before; import org.junit.ClassRule; import org.junit.Ignore; @@ -50,7 +51,7 @@ public class PassiveSyncTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); @Before public void startServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java index d528c8bfa8..a2d5f3a6aa 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java @@ -18,6 +18,7 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -30,7 +31,7 @@ public class BasicClusteredWriteBehindMultiClientTest extends WriteBehindTestBas @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); private PersistentCacheManager cacheManager1; private PersistentCacheManager cacheManager2; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java index 0c568970f0..d9a0a0d64e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java @@ -18,6 +18,7 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -45,7 +46,7 @@ public class BasicClusteredWriteBehindTest extends WriteBehindTestBase { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); private PersistentCacheManager cacheManager; private Cache cache; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java index c1e56c4ef7..fe00f12ea0 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java @@ -18,6 +18,7 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -30,7 +31,7 @@ public class BasicClusteredWriteBehindWithPassiveMultiClientTest extends WriteBe @ClassRule public static Cluster CLUSTER = - newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); private PersistentCacheManager cacheManager1; private PersistentCacheManager cacheManager2; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java index af1b013371..b86a00d872 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java @@ -20,6 +20,7 @@ import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.util.ParallelTestCluster; import org.ehcache.clustered.util.runners.Parallel; +import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -34,7 +35,7 @@ public class BasicClusteredWriteBehindWithPassiveTest extends WriteBehindTestBas @ClassRule @Rule public static final ParallelTestCluster CLUSTER = new ParallelTestCluster( - newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build() + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build() ); private PersistentCacheManager cacheManager; diff --git a/clustered/integration-test/src/test/java/org/ehcache/testing/DynamicConfigStartupBuilder.java b/clustered/integration-test/src/test/java/org/ehcache/testing/DynamicConfigStartupBuilder.java new file mode 100644 index 0000000000..8cabc88b32 --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/testing/DynamicConfigStartupBuilder.java @@ -0,0 +1,121 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.testing; + +import org.terracotta.ipceventbus.proc.AnyProcess; +import org.terracotta.ipceventbus.proc.AnyProcessBuilder; +import org.terracotta.testing.config.DefaultStartupCommandBuilder; +import org.terracotta.testing.config.StartupCommandBuilder; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import static org.terracotta.testing.config.ConfigConstants.DEFAULT_CLUSTER_NAME; + +public class DynamicConfigStartupBuilder extends DefaultStartupCommandBuilder { + private int stripeId; + private String[] builtCommand; + private int debugPort = Integer.getInteger("serverDebugPortStart", 0); + + @Override + public StartupCommandBuilder stripeName(String stripeName) { + this.stripeId = Integer.parseInt(stripeName.substring(6)); + return this; + } + + @Override + public String[] build() { + if (builtCommand == null) { + try { + installServer(); + Path generatedRepositories = convertConfigFiles(); + // moves the generated files onto the server folder, but only for this server we are building + Files.move(generatedRepositories.resolve("stripe-" + stripeId).resolve(getServerName()), getServerWorkingDir().resolve("repository")); + buildStartupCommand(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + return builtCommand; + } + + private void buildStartupCommand() { + List command = new ArrayList<>(); + String scriptPath = getAbsolutePath(Paths.get("server", "bin", "start-tc-server")); + command.add(scriptPath); + if (isConsistentStartup()) { + command.add("-c"); + } + command.add("-r"); + command.add("repository"); + builtCommand = command.toArray(new String[0]); + } + + private Path convertConfigFiles() { + Path generatedRepositories = getServerWorkingDir().getParent().getParent().resolve("generated-repositories"); + + if (Files.exists(generatedRepositories)) { + // this builder is called fro each server, but the CLI will generate the repositories for all. + return generatedRepositories; + } + + List command = new ArrayList<>(); + String scriptPath = getAbsolutePath(Paths.get("tools", "config-convertor", "bin", "config-convertor")); + command.add(scriptPath); + command.add("convert"); + + command.add("-c"); + command.add(getTcConfig().toString()); + + command.add("-n"); + command.add(DEFAULT_CLUSTER_NAME); + + command.add("-d"); + command.add(getServerWorkingDir().relativize(generatedRepositories).toString()); + + command.add("-f"); //Do not fail for relative paths + + AnyProcess process; + try { + AnyProcessBuilder builder = AnyProcess.newBuilder() + .command(command.toArray(new String[0])) + .workingDir(getServerWorkingDir().toFile()) + .pipeStdout(System.out) + .pipeStderr(System.err); + if (debugPort > 0) { + builder.env("JAVA_OPTS", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=" + debugPort); + } + process = builder.build(); + } catch (Exception e) { + throw new IllegalStateException("Error launching command: " + String.join(" ", command), e); + } + int exitStatus; + try { + exitStatus = process.waitFor(); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + if (exitStatus != 0) { + throw new IllegalStateException("Process: " + process.getCommand() + " exited with status: " + exitStatus); + } + return generatedRepositories; + } +} diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java index b4b46aedcb..7bcefa245a 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java @@ -45,7 +45,6 @@ import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; - import java.io.File; import java.util.ServiceLoader; import java.util.Set; diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java index 806bc00517..2698461087 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -22,25 +22,20 @@ import java.io.Closeable; import java.io.File; -import java.io.FileWriter; import java.io.IOException; -import java.io.PrintWriter; import java.net.InetSocketAddress; import java.net.URI; import java.nio.channels.ServerSocketChannel; import java.nio.file.Path; import java.nio.file.Paths; import java.util.concurrent.TimeUnit; -import java.util.stream.Stream; import static java.lang.Integer.parseInt; import static java.lang.String.join; import static java.lang.System.getProperty; -import static java.nio.file.Files.find; import static java.nio.file.Files.isRegularFile; import static java.util.Arrays.asList; import static java.util.Objects.requireNonNull; -import static java.util.stream.Collectors.joining; import static org.ops4j.pax.exam.CoreOptions.bundle; import static org.ops4j.pax.exam.CoreOptions.cleanCaches; import static org.ops4j.pax.exam.CoreOptions.composite; @@ -52,7 +47,7 @@ public class OsgiTestUtils { - public static Option baseConfiguration(String ... path) { + public static Option baseConfiguration(String... path) { return composite( gradleBundle("org.slf4j:slf4j-api"), gradleBundle("org.slf4j:slf4j-simple").noStart(), @@ -101,51 +96,15 @@ private static Path artifact(String module) { public static Cluster startServer(Path serverDirectory) throws IOException { Path kitLocation = Paths.get(System.getProperty("kitInstallationPath")); - - Path configFile = serverDirectory.resolve("tc-config.xml"); int tsaPort = selectAvailableEphemeralPort(); int tsaGroupPort = selectAvailableEphemeralPort(); - try (PrintWriter writer = new PrintWriter(new FileWriter(configFile.toFile()))) { - writer.println(""); - writer.println(""); - writer.println(""); - writer.println(""); - writer.println(""); - writer.println("32"); - writer.println(""); - writer.println(""); - writer.println(""); - writer.println(""); - writer.println(""); - writer.println("" + serverDirectory.toString() + ""); - writer.println("" + tsaPort + ""); - writer.println("" + tsaGroupPort + ""); - writer.println(""); - writer.println("120"); - writer.println(""); - writer.println(""); - writer.println(""); - } - - Path serverDir = kitLocation.resolve("server"); - String pluginClasspath = Stream.of( - serverDir.resolve("plugins").resolve("lib"), - serverDir.resolve("plugins").resolve("api") - ).flatMap(dir -> { - try { - return find(dir, 10, (p, a) -> a.isRegularFile() && p.getFileName().toString().endsWith(".jar")); - } catch (IOException e) { - return Stream.empty(); - } - }).map(p -> p.toString()).collect(joining(File.pathSeparator)); - ProcessBuilder serverProcess = new ProcessBuilder() .directory(serverDirectory.toFile()) .command(Paths.get(System.getProperty("java.home")).resolve("bin") - .resolve(System.getProperty("os.name").contains("Windows") ? "java.exe" : "java").toString()); + .resolve(System.getProperty("os.name").contains("Windows") ? "java.exe" : "java").toString()); String tcServerOptions = System.getProperty("tc-server-opts"); if (tcServerOptions != null) { @@ -155,7 +114,16 @@ public static Cluster startServer(Path serverDirectory) throws IOException { "-Dtc.install-root=" + serverDir, "-cp", serverDir.resolve("lib").resolve("tc.jar").toString(), "com.tc.server.TCServerMain", - "-f", configFile.toString())); + "--cluster-name=foo", + "--failover-priority=availability", + "--client-reconnect-window=120s", + "--node-name=default-server", + "--node-hostname=localhost", + "--node-port=" + tsaPort, + "--node-group-port=" + tsaGroupPort, + "--node-log-dir=" + serverDirectory.resolve("logs"), + "--node-repository-dir=" + serverDirectory.resolve("repository"), + "--offheap-resources=main:32MB")); serverProcess.inheritIO(); return new Cluster(serverProcess.start(), URI.create("terracotta://localhost:" + tsaPort), serverDirectory); diff --git a/clustered/server/entity/build.gradle b/clustered/server/entity/build.gradle index c322b53c87..3fc3ad6d33 100644 --- a/clustered/server/entity/build.gradle +++ b/clustered/server/entity/build.gradle @@ -22,7 +22,7 @@ plugins { dependencies { service project(':clustered:server:service-api') service "org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion" - service "org.terracotta.management.dist:mnm-common:$terracottaPlatformVersion" + service "org.terracotta.management:management-registry:$terracottaPlatformVersion" api project(':clustered:common') implementation "org.terracotta:runnel:$terracottaPlatformVersion" diff --git a/clustered/server/service/build.gradle b/clustered/server/service/build.gradle index 8021f9ed32..c529c92602 100644 --- a/clustered/server/service/build.gradle +++ b/clustered/server/service/build.gradle @@ -22,6 +22,7 @@ plugins { dependencies { service project(':clustered:server:service-api') service "org.terracotta:offheap-resource:$terracottaPlatformVersion" + service "org.terracotta:statistics:$statisticVersion" implementation project(':clustered:common') implementation "org.terracotta:offheap-store:$offheapVersion" diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java index e0ec5d9bfd..21ba87169b 100644 --- a/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java +++ b/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java @@ -25,7 +25,6 @@ import org.terracotta.entity.PlatformConfiguration; import org.terracotta.entity.ServiceConfiguration; import org.terracotta.entity.ServiceProvider; -import org.terracotta.entity.ServiceProviderCleanupException; import org.terracotta.entity.ServiceProviderConfiguration; import org.terracotta.entity.StateDumpCollector; import org.terracotta.offheapresource.OffHeapResources; @@ -64,16 +63,16 @@ public boolean initialize(ServiceProviderConfiguration configuration, PlatformCo Collection extendedConfiguration = platformConfiguration.getExtendedConfiguration(OffHeapResources.class); if (extendedConfiguration.size() > 1) { throw new UnsupportedOperationException("There are " + extendedConfiguration.size() + " OffHeapResourcesProvider, this is not supported. " + - "There must be only one!"); + "There must be only one!"); } Iterator iterator = extendedConfiguration.iterator(); if (iterator.hasNext()) { offHeapResourcesProvider = iterator.next(); if (offHeapResourcesProvider.getAllIdentifiers().isEmpty()) { - throw new UnsupportedOperationException("There are no offheap-resource defined, this is not supported. There must be at least one!"); + LOGGER.warn("No offheap-resource defined - this will prevent provider from offering any EhcacheStateService."); } } else { - LOGGER.warn("No offheap-resource defined - this will prevent provider from offering any EhcacheStateService."); + throw new UnsupportedOperationException("There are no offheap-resource defined, this is not supported"); } return true; } diff --git a/gradle.properties b/gradle.properties index 1cac1acfa7..3a9ff1226f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.4-pre8 +terracottaPlatformVersion = 5.7.4-pre10 terracottaApisVersion = 1.7.0-pre1 -terracottaCoreVersion = 5.7.0-pre21 +terracottaCoreVersion = 5.7.0-pre24 terracottaPassthroughTestingVersion = 1.7.0-pre12 # Test lib versions @@ -20,7 +20,7 @@ junitVersion = 4.12 assertjVersion = 3.9.0 hamcrestVersion = 1.3 mockitoVersion = 2.23.4 -jacksonVersion = 2.7.5 +jacksonVersion = 2.10.1 jcacheTckVersion = 1.1.0 # Tools diff --git a/management/build.gradle b/management/build.gradle index 12e1251eda..ffa4b3a93e 100644 --- a/management/build.gradle +++ b/management/build.gradle @@ -25,7 +25,7 @@ dependencies { // optional: if we want to use the clustered management layer compileOnly project(':clustered:client') compileOnly "org.terracotta:entity-client-api:$terracottaApisVersion" - compileOnly ("org.terracotta.management.dist:mnm-nms-agent:$terracottaPlatformVersion") { + compileOnly ("org.terracotta.management:nms-agent-entity-client:$terracottaPlatformVersion") { // This is to avoid stats lib being directly used. exclude group:'org.terracotta', module:'statistics' } From e128907daba80216de9db8d4b001bff69aa03de1 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 8 Apr 2020 13:57:54 -0400 Subject: [PATCH 215/372] Management test fix - connection leak --- .../management/AfterFailoverManagementServiceTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AfterFailoverManagementServiceTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AfterFailoverManagementServiceTest.java index 9ee18c315b..234b7bd3c3 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AfterFailoverManagementServiceTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AfterFailoverManagementServiceTest.java @@ -17,7 +17,6 @@ import org.ehcache.clustered.util.BeforeAll; import org.junit.FixMethodOrder; -import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -31,8 +30,6 @@ public void beforeAllTests() throws Exception { CLUSTER.getClusterControl().terminateActive(); CLUSTER.getClusterControl().waitForActive(); - createNmsService(); - initIdentifiers(); sendManagementCallOnEntityToCollectStats(); From 115e3f2ba7c451a818dc124e2943038a4d7e8176 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 8 Apr 2020 13:58:41 -0400 Subject: [PATCH 216/372] tc-platform *-pre11 and core *-pre25 --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 3a9ff1226f..772c5f30ab 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.4-pre10 +terracottaPlatformVersion = 5.7.4-pre11 terracottaApisVersion = 1.7.0-pre1 -terracottaCoreVersion = 5.7.0-pre24 +terracottaCoreVersion = 5.7.0-pre25 terracottaPassthroughTestingVersion = 1.7.0-pre12 # Test lib versions From 9715796070bba8d8038c92e8460f405dddd96e96 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 9 Apr 2020 08:48:57 -0400 Subject: [PATCH 217/372] tc-platform *-pre12 (with new CLI behaviors) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 772c5f30ab..4a7b8d40dd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.4-pre11 +terracottaPlatformVersion = 5.7.4-pre12 terracottaApisVersion = 1.7.0-pre1 terracottaCoreVersion = 5.7.0-pre25 terracottaPassthroughTestingVersion = 1.7.0-pre12 From 57a0ebc2a34d29af01da849e0160984e219c43e1 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 9 Apr 2020 13:08:26 -0400 Subject: [PATCH 218/372] tc-platform pre13 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4a7b8d40dd..af171d6813 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.4-pre12 +terracottaPlatformVersion = 5.7.4-pre13 terracottaApisVersion = 1.7.0-pre1 terracottaCoreVersion = 5.7.0-pre25 terracottaPassthroughTestingVersion = 1.7.0-pre12 From 9262d47a25d6307557f8cbb598ffa0ad4593b8ba Mon Sep 17 00:00:00 2001 From: Saurabh Agarwal Date: Fri, 10 Apr 2020 22:58:54 +0530 Subject: [PATCH 219/372] Ignoring failing tests on linux PRs --- .../org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java | 2 ++ .../java/org/ehcache/clustered/EventsFailureBehaviorTest.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index e4b8c18c39..d105892fe9 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -31,6 +31,7 @@ import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; +import org.junit.Ignore; import org.junit.Test; import org.terracotta.testing.rules.Cluster; @@ -86,6 +87,7 @@ public static void waitForActive() throws Exception { private final AtomicLong idGenerator = new AtomicLong(2L); @Test + @Ignore("Issue#2758: Fails on linux PR builds") public void testMulipleClients() throws Throwable { CountDownLatch latch = new CountDownLatch(NUM_THREADS + 1); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index 85d9814152..09d1c41dac 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -37,6 +37,7 @@ import org.junit.After; import org.junit.Before; import org.junit.ClassRule; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; @@ -58,6 +59,7 @@ import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; @RunWith(Parallel.class) +@Ignore("Issue#2758: Fails on linux PR builds") public class EventsFailureBehaviorTest extends ClusteredTests { private static final int KEYS = 500; From dbdb85205c91a39b2c6be60395fe3b814a28dda0 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 13 Apr 2020 19:39:09 -0400 Subject: [PATCH 220/372] Revert "Ehcache with dynamic config kit" This reverts commit e95cd2b6 --- .../BasicCacheOpsMultiThreadedTest.java | 3 +- .../clustered/BasicClusteredCacheOpsTest.java | 3 +- .../clustered/BasicEntityInteractionTest.java | 3 +- ...anagerLifecycleEhcacheIntegrationTest.java | 3 +- ...gerClientEntityFactoryIntegrationTest.java | 3 +- .../clustered/ClusteredIterationTest.java | 3 +- .../clustered/ClusteredLoaderWriterTest.java | 3 +- .../ehcache/clustered/DestroyLoopTest.java | 3 +- .../clustered/EventsFailureBehaviorTest.java | 3 +- .../IterationFailureBehaviorTest.java | 3 +- .../clustered/JCacheClusteredTest.java | 3 +- .../java/org/ehcache/clustered/LeaseTest.java | 3 +- .../clustered/OversizedCacheOpsTest.java | 3 +- .../clustered/ReconnectDuringDestroyTest.java | 3 +- .../ResourcePoolAllocationFailureTest.java | 3 +- .../clustered/TerminatedServerTest.java | 3 +- .../VoltronReadWriteLockIntegrationTest.java | 3 +- ...onReadWriteLockPassiveIntegrationTest.java | 3 +- .../AbstractClusteringManagementTest.java | 2 - .../management/CMClosedEventSentTest.java | 3 +- .../EhcacheConfigWithManagementTest.java | 3 +- .../ManagementClusterConnectionTest.java | 3 +- .../reconnect/AutoCreateOnReconnectTest.java | 2 - .../reconnect/BasicCacheReconnectTest.java | 3 +- .../CacheManagerDestroyReconnectTest.java | 3 +- .../reconnect/EventsReconnectTest.java | 3 +- ...dCacheOpsReplicationMultiThreadedTest.java | 3 +- ...BasicClusteredCacheOpsReplicationTest.java | 3 +- ...OpsReplicationWithMultipleClientsTest.java | 3 +- ...CacheOpsReplicationWithServersApiTest.java | 3 +- .../BasicLifeCyclePassiveReplicationTest.java | 3 +- .../clustered/replication/DuplicateTest.java | 3 +- .../OversizedCacheOpsPassiveTest.java | 2 - .../clustered/sync/PassiveSyncTest.java | 3 +- ...icClusteredWriteBehindMultiClientTest.java | 3 +- .../BasicClusteredWriteBehindTest.java | 3 +- ...WriteBehindWithPassiveMultiClientTest.java | 3 +- ...icClusteredWriteBehindWithPassiveTest.java | 3 +- .../testing/DynamicConfigStartupBuilder.java | 121 ------------------ 39 files changed, 35 insertions(+), 197 deletions(-) delete mode 100644 clustered/integration-test/src/test/java/org/ehcache/testing/DynamicConfigStartupBuilder.java diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index d105892fe9..2817243761 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -28,7 +28,6 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Ignore; @@ -68,7 +67,7 @@ public class BasicCacheOpsMultiThreadedTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java index 9a02acb494..2aefc0e416 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java @@ -28,7 +28,6 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -62,7 +61,7 @@ public class BasicClusteredCacheOpsTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java index 543c23979a..aa99e79049 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java @@ -30,7 +30,6 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.management.cluster.DefaultClusteringManagementService; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.hamcrest.Matchers; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -63,7 +62,7 @@ public class BasicEntityInteractionTest extends ClusteredTests { "\n"; @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private ClusterTierManagerConfiguration blankConfiguration = new ClusterTierManagerConfiguration("identifier", new ServerSideConfiguration(emptyMap())); @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java index 7c4588fc95..4d419de113 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java @@ -37,7 +37,6 @@ import org.ehcache.clustered.common.EhcacheEntityVersion; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.StateTransitionException; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.ehcache.xml.XmlConfiguration; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -69,7 +68,7 @@ public class CacheManagerLifecycleEhcacheIntegrationTest extends ClusteredTests "\n"; @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private static Connection ASSERTION_CONNECTION; @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java index 35ae8d9864..ddc47de7d4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java @@ -24,7 +24,6 @@ import org.ehcache.clustered.client.internal.ClusterTierManagerValidationException; import org.ehcache.clustered.common.ServerSideConfiguration; import org.ehcache.clustered.common.ServerSideConfiguration.Pool; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -55,7 +54,7 @@ public class ClusterTierManagerClientEntityFactoryIntegrationTest extends Cluste @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private static Connection CONNECTION; @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java index 8bebe713c5..b3dd98e5ac 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java @@ -18,7 +18,6 @@ import org.ehcache.Cache; import org.ehcache.CacheManager; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; @@ -59,7 +58,7 @@ public class ClusteredIterationTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java index 8e1d0054a8..6f6a61260a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java @@ -32,7 +32,6 @@ import org.ehcache.management.ManagementRegistryService; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; import org.ehcache.management.registry.DefaultManagementRegistryService; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -82,7 +81,7 @@ public static Consistency[] data() { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java index d26c545152..09b750224b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java @@ -27,7 +27,6 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -58,7 +57,7 @@ public class DestroyLoopTest extends ClusteredTests { private static final String CACHE_NAME = "clustered-cache"; @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index 09d1c41dac..d23e9b927a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -33,7 +33,6 @@ import org.ehcache.event.CacheEventListener; import org.ehcache.event.EventType; import org.ehcache.expiry.ExpiryPolicy; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -73,7 +72,7 @@ public class EventsFailureBehaviorTest extends ClusteredTests { "\n"; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java index 670f8f44e3..da4de9e225 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java @@ -27,7 +27,6 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.spi.resilience.StoreAccessException; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -66,7 +65,7 @@ public class IterationFailureBehaviorTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java index 88f2a70071..5bf227de73 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java @@ -16,7 +16,6 @@ package org.ehcache.clustered; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.ehcache.testing.ExternalTests; import org.jsr107.tck.spi.CachingProviderTest; import org.junit.AfterClass; @@ -57,7 +56,7 @@ public class JCacheClusteredTest extends ClusteredTests { "\n"; @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java index b0bb209739..6163d5510c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java @@ -27,7 +27,6 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -69,7 +68,7 @@ public class LeaseTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private final List proxies = new ArrayList<>(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java index 6af324aa20..e5d08edacc 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java @@ -25,7 +25,6 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.ClassRule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; @@ -49,7 +48,7 @@ public class OversizedCacheOpsTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @Test public void overSizedCacheOps() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java index 31740c0910..83917b24d8 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -31,7 +31,6 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; @@ -68,7 +67,7 @@ public class ReconnectDuringDestroyTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java index 2487b0a6d3..627eb0bead 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java @@ -28,7 +28,6 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -51,7 +50,7 @@ public class ResourcePoolAllocationFailureTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java index 0c99cfdc01..a02044e2cc 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java @@ -34,7 +34,6 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.statistics.DefaultStatisticsService; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -133,7 +132,7 @@ private ThrowableAssertAlternative assertExceptionOccur } @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java index a222a3c4df..9be9c9fd3c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java @@ -28,7 +28,6 @@ import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock.Hold; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -43,7 +42,7 @@ public class VoltronReadWriteLockIntegrationTest extends ClusteredTests { @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).startupBuilder(DynamicConfigStartupBuilder::new).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java index c9be3261bb..44f225b1df 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java @@ -24,7 +24,6 @@ import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock.Hold; import org.ehcache.clustered.util.ParallelTestCluster; import org.ehcache.clustered.util.runners.Parallel; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; @@ -41,7 +40,7 @@ public class VoltronReadWriteLockPassiveIntegrationTest extends ClusteredTests { @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).startupBuilder(DynamicConfigStartupBuilder::new).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 05722289c3..7b1efcf805 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -25,7 +25,6 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.AfterClass; import org.junit.Before; import org.junit.ClassRule; @@ -101,7 +100,6 @@ public abstract class AbstractClusteringManagementTest extends ClusteredTests { public static Cluster CLUSTER = newCluster(2) .in(clusterPath()) .withServiceFragment(RESOURCE_CONFIG) - .startupBuilder(DynamicConfigStartupBuilder::new) .build(); @Rule diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java index 2f5344b0c4..98702fe300 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java @@ -21,7 +21,6 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.ClassRule; import org.junit.Test; import org.terracotta.management.model.message.Message; @@ -56,7 +55,7 @@ public class CMClosedEventSentTest extends ClusteredTests { + ""; @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @Test(timeout = 60_000) public void test_CACHE_MANAGER_CLOSED() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java index 6d7dbfdca4..f1ce37525d 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java @@ -20,7 +20,6 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -46,7 +45,7 @@ public class EhcacheConfigWithManagementTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = newCluster().in(clusterPath()) - .withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + .withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void beforeClass() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index 73e5b01606..fdbd9b8fc7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -26,7 +26,6 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.hamcrest.Matchers; import org.junit.AfterClass; import org.junit.Assert; @@ -80,7 +79,7 @@ public class ManagementClusterConnectionTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = newCluster() .in(clusterPath()) - .withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + .withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java index e0f13dd978..af1c4ff96f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java @@ -19,7 +19,6 @@ import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.ClusteredTests; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.ClassRule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; @@ -47,7 +46,6 @@ public class AutoCreateOnReconnectTest extends ClusteredTests { public static Cluster CLUSTER = newCluster(1) .in(clusterPath()) .withServiceFragment(RESOURCE_CONFIG) - .startupBuilder(DynamicConfigStartupBuilder::new) .build(); @Test diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java index 304d066cbf..25619a4cb1 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java @@ -28,7 +28,6 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -75,7 +74,7 @@ public class BasicCacheReconnectTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java index 4b699f37d7..64164e321e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java @@ -21,7 +21,6 @@ import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.util.TCPProxyUtil; import org.ehcache.config.builders.CacheManagerBuilder; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -44,7 +43,7 @@ public class CacheManagerDestroyReconnectTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index 9a0674e374..890bce8bf5 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -32,7 +32,6 @@ import org.ehcache.event.CacheEvent; import org.ehcache.event.CacheEventListener; import org.ehcache.event.EventType; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -110,7 +109,7 @@ final void clear() { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass public static void waitForActive() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index 9ba36c417f..fab61fc79f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -33,7 +33,6 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -103,7 +102,7 @@ public static Consistency[] data() { public Consistency cacheConsistency; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java index 9be3202337..97a47c6580 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java @@ -32,7 +32,6 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -79,7 +78,7 @@ public static Consistency[] data() { public Consistency cacheConsistency; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java index 68b57c0403..d4de272ea6 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java @@ -32,7 +32,6 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -88,7 +87,7 @@ public static Consistency[] data() { public Consistency cacheConsistency; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java index b05762007f..fb3985c158 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java @@ -28,7 +28,6 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -58,7 +57,7 @@ public class BasicClusteredCacheOpsReplicationWithServersApiTest extends Cluster private static Cache CACHE2; @ClassRule - public static Cluster CLUSTER = newCluster(2).in(clusterPath()).withServiceFragment(CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + public static Cluster CLUSTER = newCluster(2).in(clusterPath()).withServiceFragment(CONFIG).build(); @Before public void setUp() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java index dc65a7bfbf..cbc8ace0bd 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java @@ -22,7 +22,6 @@ import org.ehcache.clustered.util.ParallelTestCluster; import org.ehcache.clustered.util.runners.Parallel; import org.ehcache.config.builders.CacheManagerBuilder; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -52,7 +51,7 @@ public class BasicLifeCyclePassiveReplicationTest extends ClusteredTests { "\n"; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @Before public void startServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java index 6f1a5b2663..b6b6dfe015 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java @@ -29,7 +29,6 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.spi.resilience.ResilienceStrategy; import org.ehcache.spi.resilience.StoreAccessException; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -62,7 +61,7 @@ public class DuplicateTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @Before public void startServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java index fd29b35367..b7bc2347c9 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java @@ -26,7 +26,6 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -60,7 +59,6 @@ public class OversizedCacheOpsPassiveTest extends ClusteredTests { newCluster(2).in(clusterPath()) .withSystemProperty("ehcache.sync.data.gets.threshold", "2") .withServiceFragment(RESOURCE_CONFIG) - .startupBuilder(DynamicConfigStartupBuilder::new) .build(); @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java index 58740939de..2130e677f7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java @@ -26,7 +26,6 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.Before; import org.junit.ClassRule; import org.junit.Ignore; @@ -51,7 +50,7 @@ public class PassiveSyncTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @Before public void startServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java index a2d5f3a6aa..d528c8bfa8 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java @@ -18,7 +18,6 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -31,7 +30,7 @@ public class BasicClusteredWriteBehindMultiClientTest extends WriteBehindTestBas @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private PersistentCacheManager cacheManager1; private PersistentCacheManager cacheManager2; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java index d9a0a0d64e..0c568970f0 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java @@ -18,7 +18,6 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -46,7 +45,7 @@ public class BasicClusteredWriteBehindTest extends WriteBehindTestBase { @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private PersistentCacheManager cacheManager; private Cache cache; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java index fe00f12ea0..c1e56c4ef7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java @@ -18,7 +18,6 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -31,7 +30,7 @@ public class BasicClusteredWriteBehindWithPassiveMultiClientTest extends WriteBe @ClassRule public static Cluster CLUSTER = - newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build(); + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private PersistentCacheManager cacheManager1; private PersistentCacheManager cacheManager2; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java index b86a00d872..af1b013371 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java @@ -20,7 +20,6 @@ import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.util.ParallelTestCluster; import org.ehcache.clustered.util.runners.Parallel; -import org.ehcache.testing.DynamicConfigStartupBuilder; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -35,7 +34,7 @@ public class BasicClusteredWriteBehindWithPassiveTest extends WriteBehindTestBas @ClassRule @Rule public static final ParallelTestCluster CLUSTER = new ParallelTestCluster( - newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).startupBuilder(DynamicConfigStartupBuilder::new).build() + newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build() ); private PersistentCacheManager cacheManager; diff --git a/clustered/integration-test/src/test/java/org/ehcache/testing/DynamicConfigStartupBuilder.java b/clustered/integration-test/src/test/java/org/ehcache/testing/DynamicConfigStartupBuilder.java deleted file mode 100644 index 8cabc88b32..0000000000 --- a/clustered/integration-test/src/test/java/org/ehcache/testing/DynamicConfigStartupBuilder.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.ehcache.testing; - -import org.terracotta.ipceventbus.proc.AnyProcess; -import org.terracotta.ipceventbus.proc.AnyProcessBuilder; -import org.terracotta.testing.config.DefaultStartupCommandBuilder; -import org.terracotta.testing.config.StartupCommandBuilder; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; - -import static org.terracotta.testing.config.ConfigConstants.DEFAULT_CLUSTER_NAME; - -public class DynamicConfigStartupBuilder extends DefaultStartupCommandBuilder { - private int stripeId; - private String[] builtCommand; - private int debugPort = Integer.getInteger("serverDebugPortStart", 0); - - @Override - public StartupCommandBuilder stripeName(String stripeName) { - this.stripeId = Integer.parseInt(stripeName.substring(6)); - return this; - } - - @Override - public String[] build() { - if (builtCommand == null) { - try { - installServer(); - Path generatedRepositories = convertConfigFiles(); - // moves the generated files onto the server folder, but only for this server we are building - Files.move(generatedRepositories.resolve("stripe-" + stripeId).resolve(getServerName()), getServerWorkingDir().resolve("repository")); - buildStartupCommand(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - return builtCommand; - } - - private void buildStartupCommand() { - List command = new ArrayList<>(); - String scriptPath = getAbsolutePath(Paths.get("server", "bin", "start-tc-server")); - command.add(scriptPath); - if (isConsistentStartup()) { - command.add("-c"); - } - command.add("-r"); - command.add("repository"); - builtCommand = command.toArray(new String[0]); - } - - private Path convertConfigFiles() { - Path generatedRepositories = getServerWorkingDir().getParent().getParent().resolve("generated-repositories"); - - if (Files.exists(generatedRepositories)) { - // this builder is called fro each server, but the CLI will generate the repositories for all. - return generatedRepositories; - } - - List command = new ArrayList<>(); - String scriptPath = getAbsolutePath(Paths.get("tools", "config-convertor", "bin", "config-convertor")); - command.add(scriptPath); - command.add("convert"); - - command.add("-c"); - command.add(getTcConfig().toString()); - - command.add("-n"); - command.add(DEFAULT_CLUSTER_NAME); - - command.add("-d"); - command.add(getServerWorkingDir().relativize(generatedRepositories).toString()); - - command.add("-f"); //Do not fail for relative paths - - AnyProcess process; - try { - AnyProcessBuilder builder = AnyProcess.newBuilder() - .command(command.toArray(new String[0])) - .workingDir(getServerWorkingDir().toFile()) - .pipeStdout(System.out) - .pipeStderr(System.err); - if (debugPort > 0) { - builder.env("JAVA_OPTS", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=" + debugPort); - } - process = builder.build(); - } catch (Exception e) { - throw new IllegalStateException("Error launching command: " + String.join(" ", command), e); - } - int exitStatus; - try { - exitStatus = process.waitFor(); - } catch (InterruptedException e) { - throw new IllegalStateException(e); - } - if (exitStatus != 0) { - throw new IllegalStateException("Process: " + process.getCommand() + " exited with status: " + exitStatus); - } - return generatedRepositories; - } -} From 112cd0da8a8fe14eec7db252290aefef5dbd73a6 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 13 Apr 2020 19:55:27 -0400 Subject: [PATCH 221/372] terracottaPlatformVersion = 5.7.4-pre14 --- clustered/integration-test/build.gradle | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index fa1a77b4d5..2553833d2a 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -43,7 +43,7 @@ dependencies { testRuntimeOnly "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" testRuntimeOnly project(':clustered:clustered-dist') - testImplementation (group:'org.terracotta.internal', name:'galvan-support', version: terracottaCoreVersion) + testImplementation (group:'org.terracotta', name:'galvan-platform-support', version: terracottaPlatformVersion) testImplementation group: 'javax.cache', name: 'cache-api', version: jcacheVersion } diff --git a/gradle.properties b/gradle.properties index af171d6813..bbe7745a17 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.4-pre13 +terracottaPlatformVersion = 5.7.4-pre14 terracottaApisVersion = 1.7.0-pre1 terracottaCoreVersion = 5.7.0-pre25 terracottaPassthroughTestingVersion = 1.7.0-pre12 From b637a76c16192cb30120c18101b7bdd980bdefe9 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 13 Apr 2020 14:08:11 -0400 Subject: [PATCH 222/372] Ensure registering synchronous listeners fails (even when done dynamically). --- .../client/internal/store/ClusteredStore.java | 24 +++++++++---------- .../core/events/NullStoreEventDispatcher.java | 5 ++++ .../spi/store/events/StoreEventSource.java | 13 +++++++++- .../impl/events/CacheEventDispatcherImpl.java | 7 ++++++ .../events/AbstractStoreEventDispatcher.java | 5 ++++ .../impl/internal/store/basic/NopStore.java | 5 ++++ .../events/TestStoreEventDispatcher.java | 5 ++++ .../xa/internal/StoreEventSourceWrapper.java | 5 ++++ 8 files changed, 55 insertions(+), 14 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index 0da2ae3234..25e5212e04 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -623,18 +623,6 @@ public ClusteredStore createStore(Configuration storeConfig, private ClusteredStore createStoreInternal(Configuration storeConfig, Object[] serviceConfigs) { connectLock.lock(); try { - CacheEventListenerConfiguration eventListenerConfiguration = findSingletonAmongst(CacheEventListenerConfiguration.class, serviceConfigs); - if (eventListenerConfiguration != null) { - if (eventListenerConfiguration.firingMode() == EventFiring.SYNCHRONOUS) { - // Forget it. Never. - throw new IllegalStateException("Synchronous CacheEventListener is not supported with clustered tiers"); - } - if (eventListenerConfiguration.orderingMode() == EventOrdering.ORDERED) { - // this could be supported, but at least expiration events would need to be reordered - throw new IllegalStateException("Ordered CacheEventListener is not supported with clustered tiers"); - } - } - if (clusteringService == null) { throw new IllegalStateException(Provider.class.getCanonicalName() + ".createStore called without ClusteringServiceConfiguration"); } @@ -1019,9 +1007,19 @@ public void addEventFilter(StoreEventFilter eventFilter) { delegate.addEventFilter(eventFilter); } @Override - public void setEventOrdering(boolean ordering) { + public void setEventOrdering(boolean ordering) throws IllegalArgumentException { delegate.setEventOrdering(ordering); } + + @Override + public void setSynchronous(boolean synchronous) throws IllegalArgumentException { + if (synchronous) { + throw new IllegalArgumentException("Synchronous CacheEventListener is not supported with clustered tiers"); + } else { + delegate.setSynchronous(synchronous); + } + } + @Override public boolean isEventOrdering() { return delegate.isEventOrdering(); diff --git a/core/src/main/java/org/ehcache/core/events/NullStoreEventDispatcher.java b/core/src/main/java/org/ehcache/core/events/NullStoreEventDispatcher.java index 8bc80d7c4a..ff26a97fd7 100644 --- a/core/src/main/java/org/ehcache/core/events/NullStoreEventDispatcher.java +++ b/core/src/main/java/org/ehcache/core/events/NullStoreEventDispatcher.java @@ -97,6 +97,11 @@ public void setEventOrdering(boolean ordering) { // Do nothing } + @Override + public void setSynchronous(boolean synchronous) { + // Do nothing + } + @Override public boolean isEventOrdering() { return false; diff --git a/core/src/main/java/org/ehcache/core/spi/store/events/StoreEventSource.java b/core/src/main/java/org/ehcache/core/spi/store/events/StoreEventSource.java index 07df024d72..26466e9f4d 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/events/StoreEventSource.java +++ b/core/src/main/java/org/ehcache/core/spi/store/events/StoreEventSource.java @@ -16,6 +16,8 @@ package org.ehcache.core.spi.store.events; +import org.ehcache.event.EventFiring; + /** * Interface to enable listening on and configuring the {@link org.ehcache.core.spi.store.Store} eventing system. */ @@ -41,7 +43,16 @@ public interface StoreEventSource { * * @param ordering {@code true} if ordering is desired, {@code false} for no ordering */ - void setEventOrdering(boolean ordering); + void setEventOrdering(boolean ordering) throws IllegalArgumentException; + + /** + * Toggles event synchronicity. + *

+ * If {@code true} it means events will be fire synchronously. + * + * @param synchronous {@code true} if synchronicity is desired, {@code false} for asynchronous. + */ + void setSynchronous(boolean synchronous) throws IllegalArgumentException; /** * Indicates if the related {@link org.ehcache.core.spi.store.Store} is delivering events ordered or not. diff --git a/impl/src/main/java/org/ehcache/impl/events/CacheEventDispatcherImpl.java b/impl/src/main/java/org/ehcache/impl/events/CacheEventDispatcherImpl.java index 0eaf85435f..283f074797 100644 --- a/impl/src/main/java/org/ehcache/impl/events/CacheEventDispatcherImpl.java +++ b/impl/src/main/java/org/ehcache/impl/events/CacheEventDispatcherImpl.java @@ -107,6 +107,9 @@ private synchronized void registerCacheEventListener(EventListenerWrapper aSyncListenersList.add(wrapper); break; case SYNCHRONOUS: + if (syncListenersList.isEmpty()) { + storeEventSource.setSynchronous(true); + } syncListenersList.add(wrapper); break; default: @@ -148,6 +151,9 @@ private synchronized boolean removeWrapperFromList(EventListenerWrapper wr if (--listenersCount == 0) { storeEventSource.removeEventListener(eventListener); } + if (syncListenersList.isEmpty()) { + storeEventSource.setSynchronous(false); + } return true; } return false; @@ -160,6 +166,7 @@ private synchronized boolean removeWrapperFromList(EventListenerWrapper wr public synchronized void shutdown() { storeEventSource.removeEventListener(eventListener); storeEventSource.setEventOrdering(false); + storeEventSource.setSynchronous(false); syncListenersList.clear(); aSyncListenersList.clear(); unOrderedExectuor.shutdown(); diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/AbstractStoreEventDispatcher.java b/impl/src/main/java/org/ehcache/impl/internal/events/AbstractStoreEventDispatcher.java index 2e44eccea1..f2bc22432d 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/events/AbstractStoreEventDispatcher.java +++ b/impl/src/main/java/org/ehcache/impl/internal/events/AbstractStoreEventDispatcher.java @@ -124,6 +124,11 @@ public void setEventOrdering(boolean ordering) { this.ordered = ordering; } + @Override + public void setSynchronous(boolean synchronous) throws IllegalArgumentException { + //dispatcher is synchronous by default + } + @Override public boolean isEventOrdering() { return ordered; diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java index 2da5ea55be..8ff6b2af6c 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java @@ -135,6 +135,11 @@ public void setEventOrdering(boolean ordering) { } + @Override + public void setSynchronous(boolean synchronous) throws IllegalArgumentException { + + } + @Override public boolean isEventOrdering() { return false; diff --git a/impl/src/test/java/org/ehcache/impl/internal/events/TestStoreEventDispatcher.java b/impl/src/test/java/org/ehcache/impl/internal/events/TestStoreEventDispatcher.java index 6292adc84d..51bc63a89e 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/events/TestStoreEventDispatcher.java +++ b/impl/src/test/java/org/ehcache/impl/internal/events/TestStoreEventDispatcher.java @@ -85,6 +85,11 @@ public void setEventOrdering(boolean ordering) { throw new UnsupportedOperationException("Test impl cannot be made ordered"); } + @Override + public void setSynchronous(boolean synchronous) throws IllegalArgumentException { + throw new UnsupportedOperationException("Test impl cannot be made synchronous"); + } + @Override public boolean isEventOrdering() { return false; diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/StoreEventSourceWrapper.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/StoreEventSourceWrapper.java index adaccc5c78..cc8c0ef442 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/StoreEventSourceWrapper.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/StoreEventSourceWrapper.java @@ -83,6 +83,11 @@ public void setEventOrdering(boolean ordering) { underlying.setEventOrdering(ordering); } + @Override + public void setSynchronous(boolean synchronous) throws IllegalArgumentException { + underlying.setSynchronous(synchronous); + } + @Override public boolean isEventOrdering() { return underlying.isEventOrdering(); From 72e3df69d555fcf00cc90649ad80ebc09e421dcb Mon Sep 17 00:00:00 2001 From: Saurabh Agarwal Date: Mon, 20 Apr 2020 13:36:02 +0530 Subject: [PATCH 223/372] Bumped up tc-platform --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index bbe7745a17..04e237bfae 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.4-pre14 +terracottaPlatformVersion = 5.7.4-pre16 terracottaApisVersion = 1.7.0-pre1 terracottaCoreVersion = 5.7.0-pre25 terracottaPassthroughTestingVersion = 1.7.0-pre12 From cea855257803f28844d44408ec583de0016b799f Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 20 Apr 2020 07:47:33 -0400 Subject: [PATCH 224/372] Updated ParallelTestCluster --- .../org/ehcache/clustered/util/ParallelTestCluster.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/ParallelTestCluster.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/ParallelTestCluster.java index eb06fca70a..6fb37df56a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/ParallelTestCluster.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/ParallelTestCluster.java @@ -15,6 +15,7 @@ */ package org.ehcache.clustered.util; +import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; import org.terracotta.connection.Connection; @@ -27,7 +28,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; -public class ParallelTestCluster extends Cluster { +public class ParallelTestCluster implements TestRule { private final Cluster cluster; private final IClusterControl control; @@ -109,22 +110,18 @@ private void request(ClusterTask task) { }; } - @Override public URI getConnectionURI() { return cluster.getConnectionURI(); } - @Override public String[] getClusterHostPorts() { return cluster.getClusterHostPorts(); } - @Override public Connection newConnection() throws ConnectionException { return cluster.newConnection(); } - @Override public IClusterControl getClusterControl() { return control; } @@ -169,6 +166,7 @@ enum ClusterTask implements Consumer { ClusterTask(Task task) { this.task = task; } + public void accept(IClusterControl control) { try { task.run(control); From 262593449a5fafa2e62d6ec5fe9c7c7f2439cab9 Mon Sep 17 00:00:00 2001 From: Saurabh Agarwal Date: Wed, 22 Apr 2020 23:24:20 +0530 Subject: [PATCH 225/372] Bumped-up platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 04e237bfae..3ad54ffa2b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.4-pre16 +terracottaPlatformVersion = 5.7.4-pre18 terracottaApisVersion = 1.7.0-pre1 terracottaCoreVersion = 5.7.0-pre25 terracottaPassthroughTestingVersion = 1.7.0-pre12 From 3cc2d0316a1d9fc822f1d7317a103b610026f2f7 Mon Sep 17 00:00:00 2001 From: Saurabh Agarwal Date: Fri, 24 Apr 2020 10:06:49 +0530 Subject: [PATCH 226/372] Bumped-up platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 3ad54ffa2b..b57e193ac4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.4-pre18 +terracottaPlatformVersion = 5.7.4-pre19 terracottaApisVersion = 1.7.0-pre1 terracottaCoreVersion = 5.7.0-pre25 terracottaPassthroughTestingVersion = 1.7.0-pre12 From f464932680a01151e346bcd04bff1f2749267067 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 29 Apr 2020 07:15:43 -0400 Subject: [PATCH 227/372] terracottaPlatformVersion = 5.8.0-pre1 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index b57e193ac4..5114ca9b48 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.7.4-pre19 +terracottaPlatformVersion = 5.8.0-pre1 terracottaApisVersion = 1.7.0-pre1 terracottaCoreVersion = 5.7.0-pre25 terracottaPassthroughTestingVersion = 1.7.0-pre12 From 89c65277c445c1ff98aa27ad2072d11e14cbda38 Mon Sep 17 00:00:00 2001 From: 0xflotus <0xflotus@gmail.com> Date: Sun, 26 Apr 2020 23:45:04 +0200 Subject: [PATCH 228/372] Update caching-terms.adoc --- docs/src/docs/asciidoc/user/caching-terms.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/docs/asciidoc/user/caching-terms.adoc b/docs/src/docs/asciidoc/user/caching-terms.adoc index f53ed79af7..2b2754db5b 100644 --- a/docs/src/docs/asciidoc/user/caching-terms.adoc +++ b/docs/src/docs/asciidoc/user/caching-terms.adoc @@ -62,7 +62,7 @@ http://gee.cs.oswego.edu/dl/html/malloc.html[dlmalloc] to Java backed by NIO dir === Hot Data Data that has recently been used by an application is very likely to be accessed again soon. Such data is considered -_hot_. A cache may attempt to keep the _hottest_ data most quickly available, while attemping to choose the +_hot_. A cache may attempt to keep the _hottest_ data most quickly available, while attempting to choose the _least hot_ data for eviction. Following the Pareto Distribution, you ideally want all your hot data to fit into your caches. From fa4bc3f28044c3eeec62058eb861874bff498488 Mon Sep 17 00:00:00 2001 From: 0xflotus <0xflotus@gmail.com> Date: Sun, 26 Apr 2020 23:50:55 +0200 Subject: [PATCH 229/372] Update osgi.adoc --- docs/src/docs/asciidoc/user/osgi.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/docs/asciidoc/user/osgi.adoc b/docs/src/docs/asciidoc/user/osgi.adoc index 65f7785a38..4173bc0344 100644 --- a/docs/src/docs/asciidoc/user/osgi.adoc +++ b/docs/src/docs/asciidoc/user/osgi.adoc @@ -86,7 +86,7 @@ org.ehcache[org.ehcache.core.osgi.EhcacheActivator] : JDK Service Loading Sees: ---- In this configuration only features in the bundle with the Ehcache core classes are available. Using this service lookup -mechanism only the `org.ehcache:ehcache` (bundle symbolic name: `org.ehcache`) bundle can be succesfully deployed. Use +mechanism only the `org.ehcache:ehcache` (bundle symbolic name: `org.ehcache`) bundle can be successfully deployed. Use of this bundle provides for most of the regular Ehcache features, but *does not support transactional or clustered caching*. From 0ef862a150f2d929a665a2eb321c6600eca07c65 Mon Sep 17 00:00:00 2001 From: 0xflotus <0xflotus@gmail.com> Date: Sun, 26 Apr 2020 23:53:31 +0200 Subject: [PATCH 230/372] Update tiering.adoc --- docs/src/docs/asciidoc/user/tiering.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/docs/asciidoc/user/tiering.adoc b/docs/src/docs/asciidoc/user/tiering.adoc index 720e2c1f1d..ec88015acf 100644 --- a/docs/src/docs/asciidoc/user/tiering.adoc +++ b/docs/src/docs/asciidoc/user/tiering.adoc @@ -336,5 +336,5 @@ You should then notice the following: * A full cache miss (the value isn't on any tier) will always go all the way down to the authoritative tier. NOTE: The slower your authoritative tier, the slower your `put` operations will be. -For a normal cache usage, it usually doesn't matter since`get` operations are much more frequent than`put` opreations. +For a normal cache usage, it usually doesn't matter since`get` operations are much more frequent than`put` operations. The opposite would mean you probably shouldn't be using a cache in the first place. From d0d372ec656796adbd7fb930511e3c089e9e5cb5 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 10 Apr 2020 14:41:20 -0400 Subject: [PATCH 231/372] Incoming server messages should not be handled in thread. --- ...ClusterTierManagerClientEntityFactory.java | 15 ++++++---- .../internal/service/ConnectionState.java | 9 ++++-- .../service/DefaultClusteringService.java | 17 +++++++++-- .../store/ClusterTierClientEntity.java | 2 +- .../store/ClusterTierClientEntityService.java | 2 +- .../internal/store/ClusterTierUserData.java | 10 ++++++- .../store/CommonServerStoreProxy.java | 7 ++--- .../store/SimpleClusterTierClientEntity.java | 25 +++++++++++++++-- ...terTierManagerClientEntityFactoryTest.java | 16 +++++------ .../service/ConnectionClosedTest.java | 1 - .../internal/service/ConnectionStateTest.java | 4 +-- .../internal/service/ReconnectTest.java | 5 ++-- .../store/AbstractServerStoreProxyTest.java | 2 +- .../internal/store/ClusteredStoreTest.java | 2 +- .../SimpleClusterTierClientEntityTest.java | 4 +-- ...gerClientEntityFactoryIntegrationTest.java | 28 +++++++++---------- 16 files changed, 100 insertions(+), 49 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java index 0ba843cbc3..b2cdeca7ee 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java @@ -44,10 +44,13 @@ import org.terracotta.exception.PermanentEntityException; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; import java.util.concurrent.TimeoutException; +import static java.util.Objects.requireNonNull; import static org.ehcache.clustered.common.EhcacheEntityVersion.ENTITY_VERSION; public class ClusterTierManagerClientEntityFactory { @@ -58,14 +61,16 @@ public class ClusterTierManagerClientEntityFactory { private final Map maintenanceHolds = new ConcurrentHashMap<>(); private final Map fetchHolds = new ConcurrentHashMap<>(); + private final Executor asyncWorker; private final Timeouts entityTimeouts; - public ClusterTierManagerClientEntityFactory(Connection connection) { - this(connection, TimeoutsBuilder.timeouts().build()); + public ClusterTierManagerClientEntityFactory(Connection connection, Executor asyncWorker) { + this(connection, asyncWorker, TimeoutsBuilder.timeouts().build()); } - public ClusterTierManagerClientEntityFactory(Connection connection, Timeouts entityTimeouts) { + public ClusterTierManagerClientEntityFactory(Connection connection, Executor asyncWorker, Timeouts entityTimeouts) { this.connection = connection; + this.asyncWorker = requireNonNull(asyncWorker); this.entityTimeouts = entityTimeouts; } @@ -292,7 +297,7 @@ public ClusterTierClientEntity fetchOrCreateClusteredStoreEntity(String clusterT throw new AssertionError(e); } try { - return entityRef.fetchEntity(new ClusterTierUserData(entityTimeouts, storeIdentifier)); + return entityRef.fetchEntity(new ClusterTierUserData(entityTimeouts, storeIdentifier, asyncWorker)); } catch (EntityNotFoundException e) { // Ignore - will try to create again } catch (EntityException e) { @@ -319,7 +324,7 @@ private ClusterTierClientEntity fetchClusterTierClientEntity(String storeIdentif EntityRef entityRef) throws EntityNotFoundException { try { - return entityRef.fetchEntity(new ClusterTierUserData(entityTimeouts, storeIdentifier)); + return entityRef.fetchEntity(new ClusterTierUserData(entityTimeouts, storeIdentifier, asyncWorker)); } catch (EntityNotFoundException e) { throw e; } catch (EntityException e) { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java index 6f3f8edec8..8d01068f1f 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java @@ -42,15 +42,19 @@ import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Executor; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; +import static java.util.Objects.requireNonNull; + class ConnectionState { private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionState.class); private static final String CONNECTION_PREFIX = "Ehcache:"; + private volatile Executor asyncWorker; private volatile Connection clusterConnection = null; private volatile ClusterTierManagerClientEntityFactory entityFactory = null; private volatile ClusterTierManagerClientEntity entity = null; @@ -120,7 +124,8 @@ public void removeClusterTierClientEntity(String cacheId) { clusterTierEntities.remove(cacheId); } - public void initClusterConnection() { + public void initClusterConnection(Executor asyncWorker) { + this.asyncWorker = requireNonNull(asyncWorker); try { connect(); } catch (ConnectionException ex) { @@ -143,7 +148,7 @@ private void reconnect() { private void connect() throws ConnectionException { clusterConnection = connectionSource.connect(connectionProperties); - entityFactory = new ClusterTierManagerClientEntityFactory(clusterConnection, timeouts); + entityFactory = new ClusterTierManagerClientEntityFactory(clusterConnection, asyncWorker, timeouts); } public void closeConnection() { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java index e590cc84be..a1a5978cef 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java @@ -48,6 +48,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.TimeoutException; import java.util.stream.Stream; @@ -68,6 +70,7 @@ class DefaultClusteringService implements ClusteringService, EntityService { private final Collection connectionRecoveryListeners = new CopyOnWriteArrayList<>(); private volatile boolean inMaintenance = false; + private ExecutorService asyncExecutor; DefaultClusteringService(ClusteringServiceConfiguration configuration) { this.configuration = configuration; @@ -111,13 +114,15 @@ public boolean isConnected() { @Override public void start(final ServiceProvider serviceProvider) { - connectionState.initClusterConnection(); + asyncExecutor = createAsyncWorker(); + connectionState.initClusterConnection(asyncExecutor); connectionState.initializeState(); } @Override public void startForMaintenance(ServiceProvider serviceProvider, MaintenanceScope maintenanceScope) { - connectionState.initClusterConnection(); + asyncExecutor = createAsyncWorker(); + connectionState.initClusterConnection(asyncExecutor); if(maintenanceScope == MaintenanceScope.CACHE_MANAGER) { connectionState.acquireLeadership(); } @@ -137,6 +142,7 @@ public void stop() { */ connectionState.destroyState(true); inMaintenance = false; + asyncExecutor.shutdown(); connectionState.closeConnection(); } @@ -330,4 +336,11 @@ private static class ClusteredSpace { } } + private static ExecutorService createAsyncWorker() { + return Executors.newSingleThreadExecutor(r -> { + Thread t = new Thread(r, "Async DefaultClusteringService Worker"); + t.setDaemon(true); + return t; + }); + } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntity.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntity.java index dad2f36924..bfda297b9d 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntity.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntity.java @@ -56,7 +56,7 @@ public interface ClusterTierClientEntity extends Entity { void setReconnectListener(ReconnectListener reconnectListener); interface ResponseListener { - void onResponse(T response); + void onResponse(T response) throws TimeoutException; } interface DisconnectionListener { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java index 3353342ba6..2829d1dd7f 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java @@ -55,7 +55,7 @@ public ClusterTierEntityConfiguration deserializeConfiguration(byte[] configurat @Override public ClusterTierClientEntity create(EntityClientEndpoint endpoint, ClusterTierUserData userData) { - return new SimpleClusterTierClientEntity(endpoint, userData.getTimeouts(), userData.getStoreIdentifier()); + return new SimpleClusterTierClientEntity(endpoint, userData.getTimeouts(), userData.getStoreIdentifier(), userData.getAsyncWorker()); } @Override diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierUserData.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierUserData.java index c41a598410..cf5e014c2e 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierUserData.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierUserData.java @@ -17,6 +17,8 @@ import org.ehcache.clustered.client.config.Timeouts; +import java.util.concurrent.Executor; + /** * ClusterTierUserData * @@ -25,10 +27,12 @@ public class ClusterTierUserData { private final Timeouts timeouts; private final String storeIdentifier; + private final Executor asyncWorker; - public ClusterTierUserData(Timeouts timeouts, String storeIdentifier) { + public ClusterTierUserData(Timeouts timeouts, String storeIdentifier, Executor asyncWorker) { this.timeouts = timeouts; this.storeIdentifier = storeIdentifier; + this.asyncWorker = asyncWorker; } public Timeouts getTimeouts() { @@ -38,4 +42,8 @@ public Timeouts getTimeouts() { public String getStoreIdentifier() { return storeIdentifier; } + + public Executor getAsyncWorker() { + return asyncWorker; + } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java index c8e0f93636..a16abb5ac9 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java @@ -16,6 +16,7 @@ package org.ehcache.clustered.client.internal.store; +import org.ehcache.clustered.common.internal.exceptions.ClusterException; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.ClientInvalidateAll; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.ClientInvalidateHash; @@ -69,8 +70,7 @@ class CommonServerStoreProxy implements ServerStoreProxy { try { LOGGER.debug("CLIENT: ack'ing invalidation of hash {} from cache {} (ID {})", key, cacheId, invalidationId); entity.invokeAndWaitForSend(new ClientInvalidationAck(key, invalidationId), false); - } catch (Exception e) { - //TODO: what should be done here? + } catch (ClusterException e) { LOGGER.error("error acking client invalidation of hash {} on cache {}", key, cacheId, e); } }); @@ -83,8 +83,7 @@ class CommonServerStoreProxy implements ServerStoreProxy { try { LOGGER.debug("CLIENT: ack'ing invalidation of all from cache {} (ID {})", cacheId, invalidationId); entity.invokeAndWaitForSend(new ClientInvalidationAllAck(invalidationId), false); - } catch (Exception e) { - //TODO: what should be done here? + } catch (ClusterException e) { LOGGER.error("error acking client invalidation of all on cache {}", cacheId, e); } }); diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java index 13c0f44ce4..b149a38c2a 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java @@ -50,9 +50,12 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; +import java.util.concurrent.Executor; +import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeoutException; import java.util.function.LongSupplier; +import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static org.ehcache.clustered.client.config.Timeouts.nanosStartingFromNow; @@ -83,11 +86,14 @@ public class SimpleClusterTierClientEntity implements InternalClusterTierClientE private volatile boolean connected = true; + private final Executor asyncWorker; + public SimpleClusterTierClientEntity(EntityClientEndpoint endpoint, - Timeouts timeouts, String storeIdentifier) { + Timeouts timeouts, String storeIdentifier, Executor asyncWorker) { this.endpoint = endpoint; this.timeouts = timeouts; this.storeIdentifier = storeIdentifier; + this.asyncWorker = requireNonNull(asyncWorker); this.messageFactory = new LifeCycleMessageFactory(); endpoint.setDelegate(new EndpointDelegate() { @Override @@ -131,7 +137,22 @@ private void fireResponseEvent(T response) { } LOGGER.debug("{} registered response listener(s) for {}", responseListeners.size(), response.getClass()); for (ResponseListener responseListener : responseListeners) { - responseListener.onResponse(response); + Runnable responseProcessing = () -> { + try { + responseListener.onResponse(response); + } catch (TimeoutException e) { + LOGGER.debug("Timeout exception processing: {} - resubmitting", response, e); + fireResponseEvent(response); + } catch (Exception e) { + LOGGER.warn("Unhandled failure processing: {}", response, e); + } + }; + try { + asyncWorker.execute(responseProcessing); + } catch (RejectedExecutionException f) { + LOGGER.warn("Response task execution rejected using inline execution: {}", response, f); + responseProcessing.run(); + } } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java index 89d4fc6b52..81084e56a1 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java @@ -67,7 +67,7 @@ public void testCreate() throws Exception { addMockUnlockedLock(connection, "VoltronReadWriteLock-ClusterTierManagerClientEntityFactory-AccessLock-test"); - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection, Runnable::run); factory.create("test", null); verify(entityRef).create(isA(ClusterTierManagerConfiguration.class)); verifyNoMoreInteractions(entityRef); @@ -79,7 +79,7 @@ public void testCreateBadConfig() throws Exception { when(getEntityRef(ClusterTierManagerClientEntity.class)).thenReturn(entityRef); addMockUnlockedLock(connection, "VoltronReadWriteLock-ClusterTierManagerClientEntityFactory-AccessLock-test"); - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection, Runnable::run); try { factory.create("test", null); fail("Expecting ClusterTierManagerCreationException"); @@ -95,7 +95,7 @@ public void testCreateWhenExisting() throws Exception { addMockUnlockedLock(connection, "VoltronReadWriteLock-ClusterTierManagerClientEntityFactory-AccessLock-test"); - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection, Runnable::run); try { factory.create("test", null); fail("Expected EntityAlreadyExistsException"); @@ -111,7 +111,7 @@ public void testRetrieve() throws Exception { addMockUnlockedLock(connection, "VoltronReadWriteLock-ClusterTierManagerClientEntityFactory-AccessLock-test"); - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection, Runnable::run); assertThat(factory.retrieve("test", null), is(entity)); verify(entity).validate(isNull()); verify(entity, never()).close(); @@ -125,7 +125,7 @@ public void testRetrieveFailedValidate() throws Exception { addMockUnlockedLock(connection, "VoltronReadWriteLock-ClusterTierManagerClientEntityFactory-AccessLock-test"); - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection, Runnable::run); try { factory.retrieve("test", null); fail("Expecting IllegalArgumentException"); @@ -145,7 +145,7 @@ public void testRetrieveWhenNotExisting() throws Exception { addMockUnlockedLock(connection, "VoltronReadWriteLock-ClusterTierManagerClientEntityFactory-AccessLock-test"); - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection, Runnable::run); try { factory.retrieve("test", null); fail("Expected EntityNotFoundException"); @@ -163,7 +163,7 @@ public void testDestroy() throws Exception { addMockUnlockedLock(connection, "VoltronReadWriteLock-ClusterTierManagerClientEntityFactory-AccessLock-test"); - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection, Runnable::run); factory.destroy("test"); verify(entityRef).destroy(); } @@ -177,7 +177,7 @@ public void testDestroyWhenNotExisting() throws Exception { addMockUnlockedLock(connection, "VoltronReadWriteLock-ClusterTierManagerClientEntityFactory-AccessLock-test"); - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection, Runnable::run); factory.destroy("test"); verify(entityRef).destroy(); } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java index ea417720cf..722b7fe5b6 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java @@ -118,7 +118,6 @@ public void testCacheOperationThrowsAfterConnectionClosed() throws Exception { }); assertThat(future.get(5, TimeUnit.SECONDS), is("value")); - } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java index c9dcd5af49..de8982488e 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java @@ -73,7 +73,7 @@ public void removePassthrough() { public void testInitializeStateAfterConnectionCloses() throws Exception { ConnectionState connectionState = new ConnectionState(Timeouts.DEFAULT, new Properties(), serviceConfiguration); - connectionState.initClusterConnection(); + connectionState.initClusterConnection(Runnable::run); closeConnection(); @@ -93,7 +93,7 @@ public void testInitializeStateAfterConnectionCloses() throws Exception { public void testCreateClusterTierEntityAfterConnectionCloses() throws Exception { ConnectionState connectionState = new ConnectionState(Timeouts.DEFAULT, new Properties(), serviceConfiguration); - connectionState.initClusterConnection(); + connectionState.initClusterConnection(Runnable::run); connectionState.initializeState(); closeConnection(); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java index c2607aaf9b..55e4648664 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java @@ -30,6 +30,7 @@ import java.util.Properties; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; public class ReconnectTest { @@ -45,7 +46,7 @@ public void testInitialConnectDoesNotRetryAfterConnectionException() { MockConnectionService.mockConnection = null; ConnectionState connectionState = new ConnectionState(Timeouts.DEFAULT, new Properties(), serviceConfiguration); - connectionState.initClusterConnection(); + connectionState.initClusterConnection(Runnable::run); } @Test @@ -59,7 +60,7 @@ public void testAfterConnectionReconnectHappensEvenAfterConnectionException() th ConnectionState connectionState = new ConnectionState(Timeouts.DEFAULT, new Properties(), serviceConfiguration); - connectionState.initClusterConnection(); + connectionState.initClusterConnection(Runnable::run); CompletableFuture future = CompletableFuture.runAsync(() -> connectionState.initializeState()); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java index 519ab7b140..f2f43f6b03 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java @@ -68,7 +68,7 @@ protected static SimpleClusterTierClientEntity createClientEntity(String name, // Create ClusterTierManagerClientEntity if needed ClusterTierManagerClientEntityFactory entityFactory = new ClusterTierManagerClientEntityFactory( - connection, + connection, Runnable::run, TimeoutsBuilder.timeouts().write(Duration.ofSeconds(30)).build()); if (create) { entityFactory.create(name, new ServerSideConfiguration("defaultResource", Collections.emptyMap())); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java index bd2901beec..d2ee9cd53c 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java @@ -142,7 +142,7 @@ public void setup() throws Exception { ); Connection connection = new UnitTestConnectionService().connect(CLUSTER_URI, new Properties()); - ClusterTierManagerClientEntityFactory entityFactory = new ClusterTierManagerClientEntityFactory(connection); + ClusterTierManagerClientEntityFactory entityFactory = new ClusterTierManagerClientEntityFactory(connection, Runnable::run); ServerSideConfiguration serverConfig = new ServerSideConfiguration("defaultResource", Collections.emptyMap()); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntityTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntityTest.java index e7ebc4712f..c9f4f9e288 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntityTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntityTest.java @@ -54,7 +54,7 @@ public class SimpleClusterTierClientEntityTest { public void testFireWithInit() throws Exception { MockEndpointBuilder eb = new MockEndpointBuilder(); SimpleClusterTierClientEntity entity = new SimpleClusterTierClientEntity(eb.mockEndpoint, - TimeoutsBuilder.timeouts().build(), "store1"); + TimeoutsBuilder.timeouts().build(), "store1", Runnable::run); AtomicBoolean responseRcvd = new AtomicBoolean(false); entity.addResponseListener(MockedEntityResponse.class, response -> responseRcvd.set(true)); entity.validate(mock(ServerStoreConfiguration.class)); @@ -66,7 +66,7 @@ public void testFireWithInit() throws Exception { public void testFireWithDelayedInit() throws Exception { MockEndpointBuilder eb = new MockEndpointBuilder(); SimpleClusterTierClientEntity entity = new SimpleClusterTierClientEntity(eb.mockEndpoint, - TimeoutsBuilder.timeouts().build(), "store1"); + TimeoutsBuilder.timeouts().build(), "store1", Runnable::run); AtomicBoolean responseRcvd = new AtomicBoolean(false); entity.addResponseListener(MockedEntityResponse.class, response -> responseRcvd.set(true)); CountDownLatch beforeLatch = new CountDownLatch(1); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java index 8678e0b8e0..84d58f06ba 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java @@ -71,14 +71,14 @@ public static void closeConnection() throws IOException { @Test public void testCreate() throws Exception { - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION, Runnable::run); factory.create("testCreate", new ServerSideConfiguration(EMPTY_RESOURCE_MAP)); } @Test public void testCreateWhenExisting() throws Exception { - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION, Runnable::run); factory.create("testCreateWhenExisting", new ServerSideConfiguration(EMPTY_RESOURCE_MAP)); try { factory.create("testCreateWhenExisting", @@ -91,7 +91,7 @@ public void testCreateWhenExisting() throws Exception { @Test public void testCreateWithBadConfigCleansUp() throws Exception { - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION, Runnable::run); try { factory.create("testCreateWithBadConfigCleansUp", new ServerSideConfiguration("flargle", EMPTY_RESOURCE_MAP)); @@ -108,7 +108,7 @@ public void testCreateWithBadConfigCleansUp() throws Exception { @Test public void testRetrieveWithGoodConfig() throws Exception { - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION, Runnable::run); factory.create("testRetrieveWithGoodConfig", new ServerSideConfiguration(Collections.singletonMap("foo", new Pool(43L, "primary")))); assertThat(factory.retrieve("testRetrieveWithGoodConfig", @@ -117,7 +117,7 @@ public void testRetrieveWithGoodConfig() throws Exception { @Test public void testRetrieveWithBadConfig() throws Exception { - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION, Runnable::run); factory.create("testRetrieveWithBadConfig", new ServerSideConfiguration(Collections.singletonMap("foo", new Pool(42L, "primary")))); try { @@ -131,7 +131,7 @@ public void testRetrieveWithBadConfig() throws Exception { @Test public void testRetrieveWhenNotExisting() throws Exception { - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION, Runnable::run); try { factory.retrieve("testRetrieveWhenNotExisting", null); fail("Expected EntityNotFoundException"); @@ -142,48 +142,48 @@ public void testRetrieveWhenNotExisting() throws Exception { @Test public void testDestroy() throws Exception { - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION, Runnable::run); factory.create("testDestroy", new ServerSideConfiguration(Collections.emptyMap())); factory.destroy("testDestroy"); } @Test public void testDestroyWhenNotExisting() throws Exception { - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION, Runnable::run); factory.destroy("testDestroyWhenNotExisting"); } @Test public void testAbandonLeadershipWhenNotOwning() throws Exception { - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION, Runnable::run); assertFalse(factory.abandonLeadership("testAbandonLeadershipWhenNotOwning")); } @Test public void testAcquireLeadershipWhenAlone() throws Exception { - ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION); + ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(CONNECTION, Runnable::run); assertThat(factory.acquireLeadership("testAcquireLeadershipWhenAlone"), is(true)); } @Test public void testAcquireLeadershipWhenTaken() throws Exception { - ClusterTierManagerClientEntityFactory factoryA = new ClusterTierManagerClientEntityFactory(CONNECTION); + ClusterTierManagerClientEntityFactory factoryA = new ClusterTierManagerClientEntityFactory(CONNECTION, Runnable::run); assertThat(factoryA.acquireLeadership("testAcquireLeadershipWhenTaken"), is(true)); try (Connection clientB = CLUSTER.newConnection()) { - ClusterTierManagerClientEntityFactory factoryB = new ClusterTierManagerClientEntityFactory(clientB); + ClusterTierManagerClientEntityFactory factoryB = new ClusterTierManagerClientEntityFactory(clientB, Runnable::run); assertThat(factoryB.acquireLeadership("testAcquireLeadershipWhenTaken"), is(false)); } } @Test public void testAcquireLeadershipAfterAbandoned() throws Exception { - ClusterTierManagerClientEntityFactory factoryA = new ClusterTierManagerClientEntityFactory(CONNECTION); + ClusterTierManagerClientEntityFactory factoryA = new ClusterTierManagerClientEntityFactory(CONNECTION, Runnable::run); factoryA.acquireLeadership("testAcquireLeadershipAfterAbandoned"); assertTrue(factoryA.abandonLeadership("testAcquireLeadershipAfterAbandoned")); try (Connection clientB = CLUSTER.newConnection()) { - ClusterTierManagerClientEntityFactory factoryB = new ClusterTierManagerClientEntityFactory(clientB); + ClusterTierManagerClientEntityFactory factoryB = new ClusterTierManagerClientEntityFactory(clientB, Runnable::run); assertThat(factoryB.acquireLeadership("testAcquireLeadershipAfterAbandoned"), is(true)); } } From 45b543237e9d2c43c212599d7c9b9388478eb35a Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 14 Apr 2020 13:23:16 -0400 Subject: [PATCH 232/372] bump some management timeouts --- .../ehcache/clustered/management/ClusterWithManagement.java | 2 +- .../java/org/ehcache/clustered/management/DiagnosticTest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusterWithManagement.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusterWithManagement.java index 0a65f31c36..5603c629e5 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusterWithManagement.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusterWithManagement.java @@ -119,7 +119,7 @@ private static NmsService createNmsService(Connection connection) throws Connect NmsEntity tmsAgentEntity = entityFactory.retrieveOrCreate(new NmsConfig()); NmsService nmsService = new DefaultNmsService(tmsAgentEntity); - nmsService.setOperationTimeout(5, TimeUnit.SECONDS); + nmsService.setOperationTimeout(10, TimeUnit.SECONDS); return nmsService; } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/DiagnosticTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/DiagnosticTest.java index fb1fdd6114..7b94d69697 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/DiagnosticTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/DiagnosticTest.java @@ -51,9 +51,9 @@ public void test_CACHE_MANAGER_CLOSED() throws Exception { int activePort = readTopology().serverStream().filter(Server::isActive).findFirst().get().getBindPort(); Properties properties = new Properties(); - properties.setProperty(ConnectionPropertyNames.CONNECTION_TIMEOUT, String.valueOf("5000")); + properties.setProperty(ConnectionPropertyNames.CONNECTION_TIMEOUT, String.valueOf("10000")); properties.setProperty(ConnectionPropertyNames.CONNECTION_NAME, "diagnostic"); - properties.setProperty(PROP_REQUEST_TIMEOUT, "5000"); + properties.setProperty(PROP_REQUEST_TIMEOUT, "10000"); properties.setProperty(PROP_REQUEST_TIMEOUTMESSAGE, "timed out"); URI uri = URI.create("diagnostic://localhost:" + activePort); From f09d3fbf3531cf8389a576e54489acf8fde94e19 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 2 Apr 2020 17:31:01 -0400 Subject: [PATCH 233/372] Adopt files utility --- .../org/ehcache/osgi/ClusteredOsgiTest.java | 1 + gradle.properties | 1 + impl/build.gradle | 1 + .../DefaultLocalPersistenceService.java | 18 ++--- .../ehcache/impl/persistence/FileUtils.java | 76 ++++--------------- .../builders/PersistentCacheManagerTest.java | 3 +- .../ehcache/osgi/ByteSizedOnHeapOsgiTest.java | 1 + .../java/org/ehcache/osgi/Jsr107OsgiTest.java | 1 + .../org/ehcache/osgi/OffHeapOsgiTest.java | 1 + .../java/org/ehcache/osgi/SimpleOsgiTest.java | 1 + .../ehcache/osgi/TransactionalOsgiTest.java | 1 + 11 files changed, 32 insertions(+), 73 deletions(-) diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java index 7bcefa245a..bfeb2df1a8 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java @@ -90,6 +90,7 @@ public Option[] individualModules() { wrappedGradleBundle("org.terracotta:statistics"), wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), + wrappedGradleBundle("org.terracotta:terracotta-utilities-tools"), baseConfiguration("ClusteredOsgiTest", "individualModules") ); diff --git a/gradle.properties b/gradle.properties index 5114ca9b48..c82f4fbe50 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,6 +14,7 @@ terracottaPlatformVersion = 5.8.0-pre1 terracottaApisVersion = 1.7.0-pre1 terracottaCoreVersion = 5.7.0-pre25 terracottaPassthroughTestingVersion = 1.7.0-pre12 +terracottaUtilitiesVersion = 0.0.2 # Test lib versions junitVersion = 4.12 diff --git a/impl/build.gradle b/impl/build.gradle index 29ca869ec6..b393167fd0 100644 --- a/impl/build.gradle +++ b/impl/build.gradle @@ -34,6 +34,7 @@ dependencies { implementation (group: 'org.ehcache', name: 'sizeof', version: parent.sizeofVersion) { exclude group:'org.slf4j', module:'slf4j-api' } + implementation group: 'org.terracotta', name: 'terracotta-utilities-tools', version: parent.terracottaUtilitiesVersion compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':core-spi-test') testImplementation 'org.ow2.asm:asm:6.2' diff --git a/impl/src/main/java/org/ehcache/impl/persistence/DefaultLocalPersistenceService.java b/impl/src/main/java/org/ehcache/impl/persistence/DefaultLocalPersistenceService.java index f2f85ab871..81f05f4554 100644 --- a/impl/src/main/java/org/ehcache/impl/persistence/DefaultLocalPersistenceService.java +++ b/impl/src/main/java/org/ehcache/impl/persistence/DefaultLocalPersistenceService.java @@ -24,6 +24,7 @@ import org.ehcache.spi.service.ServiceProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.terracotta.utilities.io.Files; import java.io.File; import java.io.FileNotFoundException; @@ -33,7 +34,6 @@ import java.nio.channels.OverlappingFileLockException; import static org.ehcache.impl.persistence.FileUtils.createLocationIfRequiredAndVerify; -import static org.ehcache.impl.persistence.FileUtils.recursiveDeleteDirectoryContent; import static org.ehcache.impl.persistence.FileUtils.safeIdentifier; import static org.ehcache.impl.persistence.FileUtils.tryRecursiveDelete; import static org.ehcache.impl.persistence.FileUtils.validateName; @@ -121,7 +121,9 @@ public synchronized void stop() { // org.ehcache.internal.persistence.DefaultLocalPersistenceServiceTest.testLocksDirectoryAndUnlocks() // passes on windows rw.close(); - if (!lockFile.delete()) { + try { + Files.delete(lockFile.toPath()); + } catch (IOException e) { LOGGER.debug("Lock file was not deleted {}.", lockFile.getPath()); } } catch (IOException e) { @@ -185,16 +187,14 @@ public void destroySafeSpace(SafeSpaceIdentifier safeSpaceId, boolean verbose) { */ public void destroyAll(String owner) { File ownerDirectory = new File(rootDirectory, owner); - boolean cleared = true; if (ownerDirectory.exists() && ownerDirectory.isDirectory()) { - cleared = false; - if (recursiveDeleteDirectoryContent(ownerDirectory)) { + if (tryRecursiveDelete(ownerDirectory)) { LOGGER.debug("Destroyed all file based persistence contexts owned by {}", owner); - cleared = ownerDirectory.delete(); + } else { + LOGGER.warn("Could not delete all file based persistence contexts owned by {}", owner); } - } - if (!cleared) { - LOGGER.warn("Could not delete all file based persistence contexts owned by {}", owner); + } else { + LOGGER.warn("Could not delete all file based persistence contexts owned by {} - is not a directory!", owner); } } diff --git a/impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java b/impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java index 33ce48bbb7..4a1ff25b34 100644 --- a/impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java +++ b/impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java @@ -17,23 +17,22 @@ package org.ehcache.impl.persistence; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - import org.ehcache.CachePersistenceException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.terracotta.utilities.io.Files; import java.io.File; -import java.nio.charset.Charset; +import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.ArrayDeque; -import java.util.Deque; +import java.time.Duration; import java.util.HashSet; import java.util.Locale; import java.util.Set; import static java.lang.Integer.toHexString; -import static java.nio.charset.Charset.forName; +import static java.nio.charset.StandardCharsets.UTF_8; /** * A bunch of utility functions, mainly used by {@link DefaultLocalPersistenceService} and @@ -41,7 +40,6 @@ */ final class FileUtils { private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class); - private static final Charset UTF8 = forName("UTF8"); private static final int DEL = 0x7F; private static final char ESCAPE = '%'; @@ -99,67 +97,19 @@ static void create(File directory) throws CachePersistenceException { } } - static boolean recursiveDeleteDirectoryContent(File file) { - File[] contents = file.listFiles(); - if (contents == null) { - throw new IllegalArgumentException("File " + file.getAbsolutePath() + " is not a directory"); - } else { - boolean deleteSuccessful = true; - for (File f : contents) { - deleteSuccessful &= tryRecursiveDelete(f); - } - return deleteSuccessful; - } - } - - private static boolean recursiveDelete(File file) { - Deque toDelete = new ArrayDeque<>(); - toDelete.push(file); - while (!toDelete.isEmpty()) { - File target = toDelete.pop(); - File[] contents = target.listFiles(); - if (contents == null || contents.length == 0) { - if (target.exists() && !target.delete()) { - return false; - } - } else { - toDelete.push(target); - for (File f : contents) { - toDelete.push(f); - } - } - } - return true; - } - - @SuppressFBWarnings("DM_GC") static boolean tryRecursiveDelete(File file) { - boolean interrupted = false; try { - for (int i = 0; i < 5; i++) { - if (recursiveDelete(file) || !isWindows()) { - return true; - } else { - System.gc(); - System.runFinalization(); - - try { - Thread.sleep(50); - } catch (InterruptedException e) { - interrupted = true; - } - } - } - } finally { - if (interrupted) { - Thread.currentThread().interrupt(); - } + Files.deleteTree(file.toPath(), Duration.ofMillis(250), FileUtils::gc); + return true; + } catch (IOException ioe) { + return false; } - return false; } - private static boolean isWindows() { - return System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("windows"); + @SuppressFBWarnings("DM_GC") + private static void gc() { + System.gc(); + System.runFinalization(); } /** @@ -192,7 +142,7 @@ static String safeIdentifier(String name, boolean withSha1) { private static String sha1(String input) { StringBuilder sb = new StringBuilder(); - for (byte b : getSha1Digest().digest(input.getBytes(UTF8))) { + for (byte b : getSha1Digest().digest(input.getBytes(UTF_8))) { sb.append(toHexString((b & 0xf0) >>> 4)); sb.append(toHexString((b & 0xf))); } diff --git a/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java b/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java index aa6326391e..2fe4fa7efd 100644 --- a/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java +++ b/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java @@ -37,6 +37,7 @@ import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.terracotta.utilities.io.Files.delete; /** * @author Alex Snaps @@ -57,7 +58,7 @@ public class PersistentCacheManagerTest { @Before public void setup() throws IOException { rootDirectory = folder.newFolder("testInitializesDiskResourceService"); - assertTrue(rootDirectory.delete()); + delete(rootDirectory.toPath()); builder = newCacheManagerBuilder().with(new CacheManagerPersistenceConfiguration(rootDirectory)); } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java index 34603e7af0..959a94960e 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java @@ -53,6 +53,7 @@ public Option[] individualModules() { wrappedGradleBundle("org.terracotta:statistics"), wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), + wrappedGradleBundle("org.terracotta:terracotta-utilities-tools"), baseConfiguration("ByteSizedOnHeapOsgiTest", "individualModules") ); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java index 042267c7b1..f6b4b82be5 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java @@ -72,6 +72,7 @@ public Option[] individualModules() { wrappedGradleBundle("org.terracotta:statistics"), wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), + wrappedGradleBundle("org.terracotta:terracotta-utilities-tools"), baseConfiguration("Jsr107OsgiTest", "individualModules") ); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java index 7f0fe5bda9..bd36d46737 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java @@ -60,6 +60,7 @@ public Option[] individualModules() { wrappedGradleBundle("org.terracotta:statistics"), wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), + wrappedGradleBundle("org.terracotta:terracotta-utilities-tools"), baseConfiguration("OffHeapOsgiTest", "individualModules") ); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java index 697a2ed0f7..a2ec69224c 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java @@ -74,6 +74,7 @@ public Option[] individualModules() { wrappedGradleBundle("org.terracotta:statistics"), wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), + wrappedGradleBundle("org.terracotta:terracotta-utilities-tools"), baseConfiguration("SimpleOsgiTest", "individualModules") ); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java index ba1fa31f58..313d0cc39f 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java @@ -65,6 +65,7 @@ public Option[] individualModules() { wrappedGradleBundle("org.terracotta:statistics"), wrappedGradleBundle("org.ehcache:sizeof"), wrappedGradleBundle("org.terracotta:offheap-store"), + wrappedGradleBundle("org.terracotta:terracotta-utilities-tools"), baseConfiguration("TransactionalOsgiTest", "individualModules") ); From 81c40300fffaaa4ab3e637da1411762a7af7446b Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 17 Apr 2020 14:51:56 -0400 Subject: [PATCH 234/372] Iterators can fail in two ways --- .../clustered/IterationFailureBehaviorTest.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java index 3316135bd7..28819b4ea8 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java @@ -21,6 +21,7 @@ import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.internal.store.ServerStoreProxyException; +import org.ehcache.clustered.common.internal.exceptions.InvalidOperationException; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; @@ -49,6 +50,7 @@ import static java.util.stream.Collectors.toMap; import static java.util.stream.LongStream.range; import static org.ehcache.clustered.client.config.builders.TimeoutsBuilder.timeouts; +import static org.hamcrest.Matchers.either; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.core.IsNull.notNullValue; @@ -126,7 +128,9 @@ public void testIteratorFailover() throws Exception { } catch (CacheIterationException e) { assertThat(e.getCause(), instanceOf(StoreAccessException.class)); assertThat(e.getCause().getCause(), instanceOf(ServerStoreProxyException.class)); - assertThat(e.getCause().getCause().getCause(), instanceOf(ConnectionClosedException.class)); + assertThat(e.getCause().getCause().getCause(), + either(instanceOf(ConnectionClosedException.class)) //lost in the space between active and passive + .or(instanceOf(InvalidOperationException.class))); //picked up by the passive - it doesn't have our iterator } //small iterator completes... it fetched the entire batch in one shot @@ -182,7 +186,9 @@ public void testIteratorReconnect() throws Exception { } catch (CacheIterationException e) { assertThat(e.getCause(), instanceOf(StoreAccessException.class)); assertThat(e.getCause().getCause(), instanceOf(ServerStoreProxyException.class)); - assertThat(e.getCause().getCause().getCause(), instanceOf(ConnectionClosedException.class)); + assertThat(e.getCause().getCause().getCause(), + either(instanceOf(ConnectionClosedException.class)) //lost in the space between the two cluster executions + .or(instanceOf(InvalidOperationException.class))); //picked up by the new cluster - it doesn't have our iterator } //small iterator completes... it fetched the entire batch in one shot From 02acf17619705b1125cd1122ad64838143fd92ca Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 8 Apr 2020 09:38:48 -0400 Subject: [PATCH 235/372] Adopt new terracotta testing utilities --- ...che107ConfigurationIntegrationDocTest.java | 2 +- .../jsr107/ResourceCombinationsTest.java | 2 +- .../org/ehcache/jsr107/StatisticsTest.java | 35 +-- build.gradle | 1 + clustered/client/build.gradle | 1 - .../clustered/client/ClusteredEventsTest.java | 18 +- ...ManagerServiceConfigurationParserTest.java | 3 +- .../service/ConnectionClosedTest.java | 19 +- clustered/integration-test/build.gradle | 1 - .../test/java/org/ehcache/Diagnostics.java | 241 ------------------ .../BasicCacheOpsMultiThreadedTest.java | 17 +- .../clustered/EventsFailureBehaviorTest.java | 45 ++-- .../java/org/ehcache/clustered/LeaseTest.java | 23 +- .../clustered/ReconnectDuringDestroyTest.java | 26 +- .../clustered/TerminatedServerTest.java | 2 +- .../AbstractClusteringManagementTest.java | 27 +- .../ManagementClusterConnectionTest.java | 28 +- .../reconnect/AutoCreateOnReconnectTest.java | 10 +- .../reconnect/EventsReconnectTest.java | 9 +- .../OversizedCacheOpsPassiveTest.java | 3 +- .../clustered/sync/PassiveSyncTest.java | 8 +- clustered/osgi-test/build.gradle | 1 + .../org/ehcache/osgi/ClusteredOsgiTest.java | 2 +- .../java/org/ehcache/osgi/OsgiTestUtils.java | 1 + .../EhcacheRuntimeConfigurationTest.java | 2 +- .../builders/PersistentCacheManagerTest.java | 2 +- .../core/events/CacheManagerListenerTest.java | 2 +- .../java/org/ehcache/docs/GettingStarted.java | 2 +- .../java/org/ehcache/docs/ThreadPools.java | 2 +- .../test/java/org/ehcache/docs/Tiering.java | 2 +- .../org/ehcache/docs/UserManagedCaches.java | 5 +- .../serializer/SerializerCountingTest.java | 2 +- ...eManagerDestroyRemovesPersistenceTest.java | 4 +- .../persistence/TestDiskResourceService.java | 2 +- .../DefaultSerializationProviderTest.java | 2 +- ...istentConcurrentOffHeapClockCacheTest.java | 3 +- .../store/disk/OffHeapDiskStoreSPITest.java | 2 +- .../store/disk/OffHeapDiskStoreTest.java | 4 +- .../EhcachePersistentSegmentTest.java | 2 +- .../TieredStoreFlushWhileShutdownTest.java | 2 +- .../store/tiering/TieredStoreSPITest.java | 2 +- .../tiering/TieredStoreWith3TiersSPITest.java | 2 +- .../util/FileExistenceMatchersTest.java | 2 +- .../DefaultLocalPersistenceServiceTest.java | 2 +- .../FileBasedStateRepositoryTest.java | 2 +- .../ehcache/integration/ExpiryEventsTest.java | 2 +- .../integration/PersistentCacheTest.java | 2 +- .../PersistentUserManagedCacheTest.java | 2 +- .../ehcache/integration/SerializersTest.java | 2 +- ...efulSerializerWithStateRepositoryTest.java | 2 +- .../integration/StoreStatisticsTest.java | 2 +- .../statistics/AbstractCalculationTest.java | 2 +- .../transactions/xa/XACacheTest.java | 2 +- .../settings/EhcacheSettingsProviderTest.java | 2 +- .../StandardEhCacheStatisticsQueryTest.java | 2 +- .../DefaultManagementRegistryServiceTest.java | 2 +- .../transactions/xa/XAGettingStarted.java | 2 +- .../journal/PersistentJournalTest.java | 2 +- .../java/org/ehcache/docs/GettingStarted.java | 2 +- 59 files changed, 133 insertions(+), 470 deletions(-) delete mode 100644 clustered/integration-test/src/test/java/org/ehcache/Diagnostics.java diff --git a/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java b/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java index ca4b570f72..e46b2af60d 100644 --- a/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java +++ b/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java @@ -29,12 +29,12 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.pany.domain.Client; import com.pany.domain.Product; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; import java.util.Random; diff --git a/107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java b/107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java index e2790f82b7..5bb6f8bb57 100644 --- a/107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java +++ b/107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java @@ -30,10 +30,10 @@ import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import org.terracotta.org.junit.rules.TemporaryFolder; import static java.util.Arrays.asList; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; diff --git a/107/src/test/java/org/ehcache/jsr107/StatisticsTest.java b/107/src/test/java/org/ehcache/jsr107/StatisticsTest.java index 8c88118b5b..1bb909d7c8 100644 --- a/107/src/test/java/org/ehcache/jsr107/StatisticsTest.java +++ b/107/src/test/java/org/ehcache/jsr107/StatisticsTest.java @@ -15,7 +15,6 @@ */ package org.ehcache.jsr107; -import org.hamcrest.Matcher; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -26,15 +25,15 @@ import javax.cache.configuration.MutableConfiguration; import javax.cache.spi.CachingProvider; +import java.time.Duration; import java.util.HashSet; -import java.util.concurrent.Callable; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.lessThan; -import static org.hamcrest.Matchers.not; +import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; /** * @author Ludovic Orban @@ -210,8 +209,7 @@ public void test_getAverageGetTime() throws Exception { heapCache.get("key"); heapCache.get("key"); - assertFor(1100L, () -> heapStatistics.getAverageGetTime(), is(not(0.0f))); - assertThat(heapStatistics.getAverageGetTime(), greaterThan(0.0f)); + assertThatEventually(() -> heapStatistics.getAverageGetTime(), greaterThan(0.0f)).within(Duration.ofMillis(1100)); } @Test @@ -224,8 +222,7 @@ public void test_getAveragePutTime() throws Exception { heapCache.put("key", "value"); heapCache.put("key", "value"); - assertFor(1100L, () -> heapStatistics.getAveragePutTime(), is(not(0.0f))); - assertThat(heapStatistics.getAveragePutTime(), greaterThan(0.0f)); + assertThatEventually(() -> heapStatistics.getAveragePutTime(), greaterThan(0.0f)).within(Duration.ofMillis(1100)); } @Test @@ -244,28 +241,6 @@ public void test_getAverageRemoveTime() throws Exception { heapCache.remove("key3"); heapCache.remove("key4"); - assertFor(1100L, () -> heapStatistics.getAverageRemoveTime(), is(not(0.0f))); - assertThat(heapStatistics.getAverageRemoveTime(), greaterThan(0.0f)); + assertThatEventually(() -> heapStatistics.getAverageRemoveTime(), greaterThan(0.0f)).within(Duration.ofMillis(1100)); } - - private static void assertFor(long timeoutInMs, Callable callable, Matcher matcher) throws Exception { - long timeLeftInMs = timeoutInMs; - - while (timeLeftInMs > 0) { - try { - assertThat(callable.call(), matcher); - return; - } catch (AssertionError assertionError) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - timeLeftInMs -= 100; - } - } - - assertThat(callable.call(), matcher); - } - } diff --git a/build.gradle b/build.gradle index a311421249..f649d3576c 100644 --- a/build.gradle +++ b/build.gradle @@ -135,6 +135,7 @@ subprojects { testImplementation "org.assertj:assertj-core:$assertjVersion" testImplementation "org.hamcrest:hamcrest-library:$hamcrestVersion" testImplementation "org.mockito:mockito-core:$mockitoVersion" + testImplementation "org.terracotta:terracotta-utilities-test-tools:$terracottaUtilitiesVersion" testRuntimeOnly "org.slf4j:slf4j-simple:$parent.slf4jVersion" } diff --git a/clustered/client/build.gradle b/clustered/client/build.gradle index fb73911eba..c62e6b3b5a 100644 --- a/clustered/client/build.gradle +++ b/clustered/client/build.gradle @@ -48,6 +48,5 @@ dependencies { } testImplementation 'org.xmlunit:xmlunit-core:2.6.0' testImplementation 'org.xmlunit:xmlunit-matchers:2.6.0' - testImplementation "org.awaitility:awaitility:3.1.6" testImplementation ("org.terracotta:statistics:$parent.statisticVersion") } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java index 2466c50453..167004f779 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java @@ -40,10 +40,9 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import static java.util.EnumSet.allOf; -import static org.awaitility.Awaitility.await; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; @@ -53,6 +52,7 @@ import static org.hamcrest.collection.IsIterableContainingInOrder.contains; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertThat; +import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; public class ClusteredEventsTest { @@ -75,7 +75,7 @@ public void removePassthroughServer() { } @Test - public void testNonExpiringEventSequence() { + public void testNonExpiringEventSequence() throws TimeoutException { CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() .with(cluster(CLUSTER_URI).autoCreate(s -> s.defaultServerResource("primary-server-resource"))) @@ -112,16 +112,13 @@ public void testNonExpiringEventSequence() { updated(1L, "bat", "bag"), removed(1L, "bag")); - await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { - assertThat(driverEvents, expectedSequence); - assertThat(observerEvents, expectedSequence); - }); + assertThatEventually(() -> driverEvents, expectedSequence).and(() -> observerEvents, expectedSequence).within(Duration.ofSeconds(10)); } } } @Test - public void testExpiringEventSequence() { + public void testExpiringEventSequence() throws TimeoutException { TestTimeSource timeSource = new TestTimeSource(); CacheManagerBuilder clusteredCacheManagerBuilder = @@ -162,10 +159,7 @@ public void testExpiringEventSequence() { created(1L, "baz"), expired(1L, "baz")); - await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { - assertThat(driverEvents, expectedSequence); - assertThat(observerEvents, expectedSequence); - }); + assertThatEventually(() -> driverEvents, expectedSequence).and(() -> observerEvents, expectedSequence).within(Duration.ofSeconds(10)); } } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java index fdbbde4aa7..213dfee054 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java @@ -22,7 +22,6 @@ import org.ehcache.clustered.client.internal.ConnectionSource; import org.ehcache.config.Configuration; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.spi.service.ServiceUtils; import org.ehcache.core.util.ClassLoading; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.xml.CacheManagerServiceConfigurationParser; @@ -33,8 +32,8 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.junit.rules.TestName; +import org.terracotta.org.junit.rules.TemporaryFolder; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.xmlunit.diff.DefaultNodeMatcher; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java index faaccd34e9..ee08c2b20f 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java @@ -33,8 +33,6 @@ import java.time.Duration; import java.util.Collection; import java.util.Properties; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; @@ -42,6 +40,7 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; +import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; public class ConnectionClosedTest { @@ -102,21 +101,7 @@ public void testCacheOperationThrowsAfterConnectionClosed() throws Exception { connection.close(); - CompletableFuture future = CompletableFuture.supplyAsync(() -> { - while (true) { - try { - Thread.sleep(200); - } catch (InterruptedException e) { - // - } - String result; - if ((result = cache.get(1L)) != null) { - return result; - } - } - }); - - assertThat(future.get(5, TimeUnit.SECONDS), is("value")); + assertThatEventually(() -> cache.get(1L), is("value")).within(Duration.ofSeconds(5)); } } diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index 2553833d2a..b8b8276bdb 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -38,7 +38,6 @@ dependencies { testImplementation "org.terracotta.management:nms-entity-client:$terracottaPlatformVersion" testImplementation "org.terracotta.management:nms-agent-entity-client:$terracottaPlatformVersion" testImplementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" - testImplementation "org.awaitility:awaitility:3.1.6" testRuntimeOnly "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" testRuntimeOnly project(':clustered:clustered-dist') diff --git a/clustered/integration-test/src/test/java/org/ehcache/Diagnostics.java b/clustered/integration-test/src/test/java/org/ehcache/Diagnostics.java deleted file mode 100644 index 1891c1fbb3..0000000000 --- a/clustered/integration-test/src/test/java/org/ehcache/Diagnostics.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.ehcache; - -import com.sun.management.HotSpotDiagnosticMXBean; - -import java.io.File; -import java.io.IOException; -import java.io.PrintStream; -import java.lang.management.LockInfo; -import java.lang.management.ManagementFactory; -import java.lang.management.MonitorInfo; -import java.lang.management.ThreadInfo; -import java.lang.management.ThreadMXBean; -import java.util.Calendar; -import java.util.Date; - -import javax.management.MBeanServer; - -/** - * Provides methods to produce diagnostic output. - */ -@SuppressWarnings({ "UnusedDeclaration", "WeakerAccess" }) -public final class Diagnostics { - - private static final String HOTSPOT_DIAGNOSTIC_MXBEAN_NAME = "com.sun.management:type=HotSpotDiagnostic"; - private static final String HEAP_DUMP_FILENAME_TEMPLATE = "java_%1$04d_%2$tFT%2$tH%2$tM%2$tS.%2$tL.hprof"; - private static final File WORKING_DIRECTORY = new File(System.getProperty("user.dir")); - - /** - * Private niladic constructor to prevent instantiation. - */ - private Diagnostics() { - } - - /** - * Writes a complete thread dump to {@code System.err}. - */ - public static void threadDump() { - threadDump(System.err); - } - - /** - * Writes a complete thread dump to the designated {@code PrintStream}. - * - * @param out the {@code PrintStream} to which the thread dump is written - */ - public static void threadDump(final PrintStream out) { - if (out == null) { - throw new NullPointerException("out"); - } - - final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); - - final Calendar when = Calendar.getInstance(); - final ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads( - threadMXBean.isObjectMonitorUsageSupported(), threadMXBean.isSynchronizerUsageSupported()); - - out.format("%nFull thread dump %1$tF %1$tT.%1$tL %1$tz%n", when); - for (final ThreadInfo threadInfo : threadInfos) { - out.print(format(threadInfo)); - } - } - - /** - * Format a {@code ThreadInfo} instance without a stack depth limitation. This method reproduces the - * formatting performed in {@code java.lang.management.ThreadInfo.toString()} without the stack depth limit. - * - * @param threadInfo the {@code ThreadInfo} instance to foramt - * - * @return a {@code CharSequence} instance containing the formatted {@code ThreadInfo} - */ - private static CharSequence format(final ThreadInfo threadInfo) { - StringBuilder sb = new StringBuilder(4096); - - Thread.State threadState = threadInfo.getThreadState(); - sb.append('"') - .append(threadInfo.getThreadName()) - .append('"') - .append(" Id=") - .append(threadInfo.getThreadId()) - .append(' ') - .append(threadState); - - if (threadInfo.getLockName() != null) { - sb.append(" on ").append(threadInfo.getLockName()); - } - if (threadInfo.getLockOwnerName() != null) { - sb.append(" owned by ").append('"').append(threadInfo.getLockOwnerName()).append('"') - .append(" Id=").append(threadInfo.getLockOwnerId()); - } - - if (threadInfo.isSuspended()) { - sb.append(" (suspended)"); - } - if (threadInfo.isInNative()) { - sb.append(" (in native)"); - } - sb.append('\n'); - - StackTraceElement[] stackTrace = threadInfo.getStackTrace(); - for (int i = 0; i < stackTrace.length; i++) { - StackTraceElement element = stackTrace[i]; - sb.append("\tat ").append(element); - sb.append('\n'); - if (i == 0) { - if (threadInfo.getLockInfo() != null) { - switch (threadState) { - case BLOCKED: - sb.append("\t- blocked on ").append(threadInfo.getLockInfo()); - sb.append('\n'); - break; - case WAITING: - sb.append("\t- waiting on ").append(threadInfo.getLockInfo()); - sb.append('\n'); - break; - case TIMED_WAITING: - sb.append("\t- waiting on ").append(threadInfo.getLockInfo()); - sb.append('\n'); - break; - default: - } - } - } - - for (MonitorInfo monitorInfo : threadInfo.getLockedMonitors()) { - if (monitorInfo.getLockedStackDepth() == i) { - sb.append("\t- locked ").append(monitorInfo); - sb.append('\n'); - } - } - } - - LockInfo[] lockedSynchronizers = threadInfo.getLockedSynchronizers(); - if (lockedSynchronizers.length > 0) { - sb.append("\n\tNumber of locked synchronizers = ").append(lockedSynchronizers.length); - sb.append('\n'); - for (LockInfo lockedSynchronizer : lockedSynchronizers) { - sb.append("\t- ").append(lockedSynchronizer); - sb.append('\n'); - } - } - - sb.append('\n'); - return sb; - } - - /** - * Take a Java heap dump into a file whose name is produced from the template - * {@value #HEAP_DUMP_FILENAME_TEMPLATE} where {@code 1$} is the PID of - * the current process obtained from {@link #getPid()}. - * - * @param dumpLiveObjects if {@code true}, only "live" (reachable) objects are dumped; - * if {@code false}, all objects in the heap are dumped - * - * @return the name of the dump file; the file is written to the current directory (generally {@code user.dir}) - */ - public static String dumpHeap(final boolean dumpLiveObjects) { - - String dumpName; - final int pid = getPid(); - final Date currentTime = new Date(); - if (pid > 0) { - dumpName = String.format(HEAP_DUMP_FILENAME_TEMPLATE, pid, currentTime); - } else { - dumpName = String.format(HEAP_DUMP_FILENAME_TEMPLATE, 0, currentTime); - } - - dumpName = new File(WORKING_DIRECTORY, dumpName).getAbsolutePath(); - - try { - dumpHeap(dumpLiveObjects, dumpName); - } catch (IOException e) { - System.err.printf("Unable to write heap dump to %s: %s%n", dumpName, e); - e.printStackTrace(System.err); - return null; - } - - return dumpName; - } - - /** - * Write a Java heap dump to the named file. If the dump file exists, this method will - * fail. - * - * @param dumpLiveObjects if {@code true}, only "live" (reachable) objects are dumped; - * if {@code false}, all objects in the heap are dumped - * @param dumpName the name of the file to which the heap dump is written; relative names - * are relative to the current directory ({@code user.dir}). If the value - * of {@code dumpName} does not end in {@code .hprof}, it is appended. - * - * @throws IOException if thrown while loading the HotSpot Diagnostic MXBean or writing the heap dump - * - * @see - * com.sun.management.HotSpotDiagnosticMXBean - */ - public static void dumpHeap(final boolean dumpLiveObjects, String dumpName) throws IOException { - if (dumpName == null) { - throw new NullPointerException("dumpName"); - } - - if (!dumpName.endsWith(".hprof")) { - dumpName += ".hprof"; - } - - final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); - final HotSpotDiagnosticMXBean hotSpotDiagnosticMXBean = - ManagementFactory.newPlatformMXBeanProxy(server, HOTSPOT_DIAGNOSTIC_MXBEAN_NAME, HotSpotDiagnosticMXBean.class); - hotSpotDiagnosticMXBean.dumpHeap(dumpName, dumpLiveObjects); - } - - /** - * Gets the PID of the current process. This method is dependent upon "common" - * operation of the {@code java.lang.management.RuntimeMXBean#getName()} method. - * - * @return the PID of the current process or {@code -1} if the PID can not be determined - */ - public static int getPid() { - // Expected to be of the form "@" - final String jvmProcessName = ManagementFactory.getRuntimeMXBean().getName(); - try { - return Integer.valueOf(jvmProcessName.substring(0, jvmProcessName.indexOf('@'))); - } catch (NumberFormatException | IndexOutOfBoundsException e) { - return -1; - } - } -} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index 2817243761..0c442e60fa 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -34,22 +34,23 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import com.tc.util.Assert; - import java.net.URI; import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; /** * Simulate multiple clients starting up the same cache manager simultaneously and ensure that puts and gets works just @@ -130,7 +131,7 @@ private Runnable content(CountDownLatch latch) { }; } - private void doSyncAndPut(PersistentCacheManager cacheManager) throws InterruptedException { + private void doSyncAndPut(PersistentCacheManager cacheManager) throws InterruptedException, TimeoutException { String customValue = "value"; Cache synCache = cacheManager.getCache(SYN_CACHE_NAME, String.class, Boolean.class); Cache customValueCache = cacheManager.getCache(CLUSTERED_CACHE_NAME, Long.class, String.class); @@ -141,15 +142,7 @@ private void doSyncAndPut(PersistentCacheManager cacheManager) throws Interrupte assertThat(customValueCache.get(1L), is(customValue)); synCache.put(firstClientEndKey, true); } else { - int retry = 0, maxRetryCount = 30; - while (++retry <= maxRetryCount && synCache.get(firstClientEndKey) == null) { - Thread.sleep(1000L); - } - - if (retry > maxRetryCount) { - Assert.fail("Couldn't find " + firstClientEndKey + " in synCache after " + maxRetryCount + " retries!"); - } - + assertThatEventually(() -> synCache.get(firstClientEndKey), notNullValue()).within(Duration.ofSeconds(30)); assertThat(customValueCache.get(1L), is(customValue)); } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index d23e9b927a..953a8025aa 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -50,19 +50,20 @@ import java.util.concurrent.CopyOnWriteArrayList; import static java.util.stream.LongStream.range; -import static org.awaitility.Awaitility.await; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; @RunWith(Parallel.class) @Ignore("Issue#2758: Fails on linux PR builds") public class EventsFailureBehaviorTest extends ClusteredTests { private static final int KEYS = 500; - private static final org.awaitility.Duration TIMEOUT = org.awaitility.Duration.FIVE_SECONDS; + private static final Duration TIMEOUT = Duration.ofSeconds(5); private static final String RESOURCE_CONFIG = "" @@ -120,7 +121,7 @@ private void failover(Cache cache1, Cache cache2) th CLUSTER.getClusterControl().waitForActive(); // wait for clients to be back in business - await().atMost(TIMEOUT).until(() -> { + assertThatEventually(() -> { try { cache1.replace(1L, new byte[0], new byte[0]); cache2.replace(1L, new byte[0], new byte[0]); @@ -128,7 +129,7 @@ private void failover(Cache cache1, Cache cache2) th } catch (Exception e) { return false; } - }); + }, is(true)).within(TIMEOUT); } @Test @@ -144,10 +145,10 @@ public void testEventsFailover() throws Exception { range(0, KEYS).forEach(k -> { cache1.put(k, value); }); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.CREATED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.EVICTED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.CREATED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.EVICTED).size(), greaterThan(0)); + assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.CREATED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.EVICTED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.CREATED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.EVICTED), hasSize(greaterThan(0))).within(TIMEOUT); // failover passive -> active failover(cache1, cache2); @@ -155,20 +156,20 @@ public void testEventsFailover() throws Exception { range(0, KEYS).forEach(k -> { cache1.put(k, value); }); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.UPDATED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.UPDATED).size(), greaterThan(0)); + assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.UPDATED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.UPDATED), hasSize(greaterThan(0))).within(TIMEOUT); range(0, KEYS).forEach(cache1::remove); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.REMOVED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.REMOVED).size(), greaterThan(0)); + assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.REMOVED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.REMOVED), hasSize(greaterThan(0))).within(TIMEOUT); range(KEYS, KEYS * 2).forEach(k -> { cache1.put(k, value); }); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.CREATED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.EVICTED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.CREATED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.EVICTED).size(), greaterThan(0)); + assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.CREATED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.EVICTED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.CREATED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.EVICTED), hasSize(greaterThan(0))).within(TIMEOUT); } @Test @@ -184,10 +185,10 @@ public void testExpirationFailover() throws Exception { range(0, KEYS).forEach(k -> { cache1.put(k, value); }); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.CREATED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.EVICTED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.CREATED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.EVICTED).size(), greaterThan(0)); + assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.CREATED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.EVICTED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.CREATED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.EVICTED), hasSize(greaterThan(0))).within(TIMEOUT); // failover passive -> active failover(cache1, cache2); @@ -195,8 +196,8 @@ public void testExpirationFailover() throws Exception { range(0, KEYS).forEach(k -> { assertThat(cache1.get(k), is(nullValue())); }); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.EXPIRED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.EXPIRED).size(), greaterThan(0)); + assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.EXPIRED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.EXPIRED), hasSize(greaterThan(0))).within(TIMEOUT); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java index 6163d5510c..2e365f1090 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java @@ -50,6 +50,7 @@ import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; @RunWith(Parameterized.class) public class LeaseTest extends ClusteredTests { @@ -124,27 +125,7 @@ public void leaseExpiry() throws Exception { setDelay(0L, proxies); - AtomicBoolean timedout = new AtomicBoolean(false); - - CompletableFuture future = CompletableFuture.supplyAsync(() -> { - while (!timedout.get()) { - try { - Thread.sleep(200); - } catch (InterruptedException e) { - throw new AssertionError(e); - } - String result = cache.get(1L); - if (result != null) { - return result; - } - } - return null; - }); - - assertThat(future.get(30, TimeUnit.SECONDS), is("The one")); - - timedout.set(true); - + assertThatEventually(() -> cache.get(1L), is("The one")).within(Duration.ofSeconds(30)); assertThat(cache.get(2L), equalTo("The two")); assertThat(cache.get(3L), equalTo("The three")); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java index 83917b24d8..b0923b3d1c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -45,6 +45,7 @@ import com.tc.net.proxy.TCPProxy; import java.net.URI; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Properties; @@ -55,6 +56,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; /** * ReconnectDuringDestroyTest @@ -165,25 +167,11 @@ public void reconnectAfterDestroyOneOfTheCache() throws Exception { Thread.sleep(6000); setDelay(0L, proxies); - cache2 = cacheManager.getCache("clustered-cache-2", Long.class, String.class); - int count = 0; - while (count < 5) { - Thread.sleep(2000); - count++; - try { - cache2.get(1L); - break; - } catch (Exception e) { - // Can happen during reconnect - } - } - if (count == 5) { - Assert.fail("Unexpected reconnection exception"); - } - assertThat(cache2.get(1L), equalTo("The one")); - assertThat(cache2.get(2L), equalTo("The two")); - cache2.put(3L, "The three"); - assertThat(cache2.get(3L), equalTo("The three")); + Cache cache2Again = cacheManager.getCache("clustered-cache-2", Long.class, String.class); + assertThatEventually(() -> cache2Again.get(1L), equalTo("The one")).within(Duration.ofSeconds(10)); + assertThat(cache2Again.get(2L), equalTo("The two")); + cache2Again.put(3L, "The three"); + assertThat(cache2Again.get(3L), equalTo("The three")); } finally { cacheManager.close(); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java index a02044e2cc..6045a71b97 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java @@ -20,7 +20,6 @@ import org.ehcache.Cache; import org.ehcache.CacheManager; import org.ehcache.CachePersistenceException; -import org.ehcache.Diagnostics; import org.ehcache.PersistentCacheManager; import org.ehcache.StateTransitionException; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; @@ -43,6 +42,7 @@ import org.junit.Test; import org.junit.rules.TestName; import org.junit.runner.RunWith; +import org.terracotta.utilities.test.Diagnostics; import com.tc.net.protocol.transport.ClientMessageTransport; import com.tc.properties.TCProperties; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 7b1efcf805..40cf7be984 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -204,38 +204,35 @@ public static void initIdentifiers() throws Exception { ehcacheClientIdentifier = null; clusterTierManagerEntityIdentifier = null; - do { - tmsServerEntityIdentifier = readTopology() + while ((tmsServerEntityIdentifier = readTopology() .activeServerEntityStream() .filter(serverEntity -> serverEntity.getType().equals(NmsConfig.ENTITY_TYPE)) .filter(AbstractManageableNode::isManageable) .map(ServerEntity::getServerEntityIdentifier) .findFirst() - .orElse(null); - sleep(500); - } while (tmsServerEntityIdentifier == null && !Thread.currentThread().isInterrupted()); + .orElse(null)) == null) { + sleep(200); + } - do { - ehcacheClientIdentifier = readTopology().getClients().values() + while ((ehcacheClientIdentifier = readTopology().getClients().values() .stream() .filter(client -> client.getName().equals("Ehcache:my-server-entity-1")) .filter(AbstractManageableNode::isManageable) .findFirst() .map(Client::getClientIdentifier) - .orElse(null); - sleep(500); - } while (ehcacheClientIdentifier == null && !Thread.currentThread().isInterrupted()); + .orElse(null)) == null) { + sleep(200); + } - do { - clusterTierManagerEntityIdentifier = readTopology() + while ((clusterTierManagerEntityIdentifier = readTopology() .activeServerEntityStream() .filter(serverEntity -> serverEntity.getName().equals("my-server-entity-1")) .filter(AbstractManageableNode::isManageable) .map(ServerEntity::getServerEntityIdentifier) .findFirst() - .orElse(null); - sleep(500); - } while (clusterTierManagerEntityIdentifier == null && !Thread.currentThread().isInterrupted()); + .orElse(null)) == null) { + sleep(200); + } } public static void tearDownCacheManagerAndStatsCollector() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index fdbd9b8fc7..dae63a4167 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -36,6 +36,7 @@ import org.terracotta.testing.rules.Cluster; import java.net.URI; +import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -55,6 +56,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; public class ManagementClusterConnectionTest extends ClusteredTests { @@ -161,23 +163,17 @@ public void test_reconnection() throws Exception { assertThat(initiate_reconnect, Matchers.nullValue()); - while (!Thread.currentThread().isInterrupted()) { -// System.out.println(mapper.writeValueAsString(readTopology().toMap())); - - count = readTopology().clientStream() - .filter(client -> client.getName() - .startsWith("Ehcache:") && client.isManageable() && client.getTags() - .containsAll(Arrays.asList("webapp-1", "server-node-1"))) - .count(); - - if (count == 1) { - break; - } else { - Thread.sleep(1_000); + assertThatEventually(() -> { + try { + return readTopology().clientStream() + .filter(client -> client.getName() + .startsWith("Ehcache:") && client.isManageable() && client.getTags() + .containsAll(Arrays.asList("webapp-1", "server-node-1"))) + .count(); + } catch (Exception e) { + throw new AssertionError(e); } - } - - assertThat(Thread.currentThread().isInterrupted(), is(false)); + }, is(1L)).within(Duration.ofSeconds(30)); assertThat(getInstanceId(), equalTo(instanceId)); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java index af1c4ff96f..b0f5e862be 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java @@ -24,6 +24,7 @@ import org.terracotta.testing.rules.Cluster; import java.net.URI; +import java.time.Duration; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; @@ -31,8 +32,8 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; public class AutoCreateOnReconnectTest extends ClusteredTests { public static final String RESOURCE_CONFIG = @@ -67,11 +68,10 @@ public void cacheManagerCanReconnect() throws Exception { CLUSTER.getClusterControl().terminateAllServers(); CLUSTER.getClusterControl().startAllServers(); - while (cache.get(1L) == null) { - Thread.sleep(100); + assertThatEventually(() -> { cache.put(1L, "two"); - } - assertThat(cache.get(1L), is("two")); + return cache.get(1L); + }, is("two")).within(Duration.ofSeconds(30)); } } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index 890bce8bf5..5623dc5978 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -38,6 +38,7 @@ import org.terracotta.testing.rules.Cluster; import java.net.URI; +import java.time.Duration; import java.util.ArrayList; import java.util.EnumSet; import java.util.HashMap; @@ -49,16 +50,16 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; -import static org.awaitility.Awaitility.await; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; public class EventsReconnectTest extends ClusteredTests { - private static final org.awaitility.Duration TIMEOUT = org.awaitility.Duration.FIVE_SECONDS; + private static final Duration TIMEOUT = Duration.ofSeconds(5); public static final String RESOURCE_CONFIG = "" + "" @@ -160,7 +161,7 @@ public void eventsFlowAgainAfterReconnection() throws Exception { getSucceededFuture.get(20000, TimeUnit.MILLISECONDS); - await().atMost(TIMEOUT).until(() -> cacheEventListener.events.get(EventType.CREATED).size(), is(beforeDisconnectionEventCounter + 1)); + assertThatEventually(() -> cacheEventListener.events.get(EventType.CREATED), hasSize(beforeDisconnectionEventCounter + 1)).within(TIMEOUT); } finally { cacheManager.destroyCache("clustered-cache"); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java index b7bc2347c9..12b957bf62 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java @@ -106,7 +106,8 @@ private void doPuts(CacheManagerBuilder clusteredCacheMa // a small pause try { Thread.sleep(10); - } catch (InterruptedException ignored) { + } catch (InterruptedException e) { + throw new AssertionError(e); } } cache.put(i, LARGE_VALUE); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java index 2130e677f7..d0c48d5808 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java @@ -32,13 +32,15 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; +import java.time.Duration; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; public class PassiveSyncTest extends ClusteredTests { private static final String RESOURCE_CONFIG = @@ -86,10 +88,8 @@ public void testSync() throws Exception { CLUSTER.getClusterControl().terminateActive(); CLUSTER.getClusterControl().waitForActive(); - for (long end = System.nanoTime() + TimeUnit.SECONDS.toNanos(130); cache.get(0L) == null && System.nanoTime() < end; ) { - Thread.sleep(100); - } + assertThatEventually(() -> cache.get(0L), notNullValue()).within(Duration.ofSeconds(130)); for (long i = -5; i < 5; i++) { assertThat(cache.get(i), equalTo("value" + i)); } diff --git a/clustered/osgi-test/build.gradle b/clustered/osgi-test/build.gradle index 7ba026a083..90fe431e38 100644 --- a/clustered/osgi-test/build.gradle +++ b/clustered/osgi-test/build.gradle @@ -29,6 +29,7 @@ dependencies { osgiModule project(':clustered:clustered-dist') osgiModule "javax.cache:cache-api:$parent.jcacheVersion" osgiModule "org.slf4j:slf4j-simple:$parent.slf4jVersion" + osgiModule "org.terracotta:terracotta-utilities-test-tools:$terracottaUtilitiesVersion" osgiModule 'org.apache.felix:org.apache.felix.scr:2.1.6' osgiModule 'com.sun.activation:javax.activation:1.2.0' osgiModule 'org.glassfish.hk2:osgi-resource-locator:1.0.2' diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java index bfeb2df1a8..84330f8f7d 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java @@ -26,7 +26,6 @@ import org.ehcache.xml.XmlConfiguration; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Configuration; import org.ops4j.pax.exam.Option; @@ -34,6 +33,7 @@ import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerMethod; import org.osgi.framework.wiring.BundleWiring; +import org.terracotta.org.junit.rules.TemporaryFolder; import org.w3c.dom.Document; import org.w3c.dom.Node; diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java index 2698461087..a55d6e3c02 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -49,6 +49,7 @@ public class OsgiTestUtils { public static Option baseConfiguration(String... path) { return composite( + wrappedGradleBundle("org.terracotta:terracotta-utilities-test-tools"), gradleBundle("org.slf4j:slf4j-api"), gradleBundle("org.slf4j:slf4j-simple").noStart(), gradleBundle("org.apache.felix:org.apache.felix.scr"), diff --git a/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java b/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java index b3e818b95f..9b827e270a 100644 --- a/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java @@ -28,7 +28,7 @@ import org.junit.Test; import org.ehcache.config.units.MemoryUnit; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; diff --git a/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java b/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java index 2fe4fa7efd..deba017529 100644 --- a/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java +++ b/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java @@ -24,7 +24,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java b/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java index 19dc820aff..c20957f381 100644 --- a/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java +++ b/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java @@ -27,7 +27,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import static org.ehcache.config.units.MemoryUnit.MB; import static org.mockito.Mockito.mock; diff --git a/impl/src/test/java/org/ehcache/docs/GettingStarted.java b/impl/src/test/java/org/ehcache/docs/GettingStarted.java index 039f967283..4b97f7c127 100644 --- a/impl/src/test/java/org/ehcache/docs/GettingStarted.java +++ b/impl/src/test/java/org/ehcache/docs/GettingStarted.java @@ -39,7 +39,7 @@ import org.ehcache.impl.copy.ReadWriteCopier; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/docs/ThreadPools.java b/impl/src/test/java/org/ehcache/docs/ThreadPools.java index 9a8e07a2ae..12f3faf63e 100644 --- a/impl/src/test/java/org/ehcache/docs/ThreadPools.java +++ b/impl/src/test/java/org/ehcache/docs/ThreadPools.java @@ -32,7 +32,7 @@ import org.ehcache.config.builders.PooledExecutionServiceConfigurationBuilder; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/docs/Tiering.java b/impl/src/test/java/org/ehcache/docs/Tiering.java index 69932f5554..e647084165 100644 --- a/impl/src/test/java/org/ehcache/docs/Tiering.java +++ b/impl/src/test/java/org/ehcache/docs/Tiering.java @@ -36,7 +36,7 @@ import org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; diff --git a/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java b/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java index 1419f344ca..02b73fa964 100644 --- a/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java +++ b/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java @@ -31,15 +31,12 @@ import org.ehcache.impl.config.persistence.UserManagedPersistenceContext; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; -import java.net.URISyntaxException; import java.util.concurrent.Executors; -import javax.print.URIException; - import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; diff --git a/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java b/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java index 3275454657..6a436f3bbe 100644 --- a/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java @@ -31,7 +31,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.Serializable; import java.nio.ByteBuffer; diff --git a/impl/src/test/java/org/ehcache/impl/internal/persistence/CacheManagerDestroyRemovesPersistenceTest.java b/impl/src/test/java/org/ehcache/impl/internal/persistence/CacheManagerDestroyRemovesPersistenceTest.java index 7502152174..4b95bfb10b 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/persistence/CacheManagerDestroyRemovesPersistenceTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/persistence/CacheManagerDestroyRemovesPersistenceTest.java @@ -16,7 +16,6 @@ package org.ehcache.impl.internal.persistence; import org.ehcache.Cache; -import org.ehcache.CachePersistenceException; import org.ehcache.PersistentCacheManager; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; @@ -25,11 +24,10 @@ import org.ehcache.impl.config.persistence.CacheManagerPersistenceConfiguration; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; -import java.net.URISyntaxException; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.impl.internal.util.FileExistenceMatchers.containsCacheDirectory; diff --git a/impl/src/test/java/org/ehcache/impl/internal/persistence/TestDiskResourceService.java b/impl/src/test/java/org/ehcache/impl/internal/persistence/TestDiskResourceService.java index 2538215160..d3a5199598 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/persistence/TestDiskResourceService.java +++ b/impl/src/test/java/org/ehcache/impl/internal/persistence/TestDiskResourceService.java @@ -30,8 +30,8 @@ import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceProvider; import org.junit.rules.ExternalResource; -import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java index 763cd6dd42..ebedffeb8a 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java @@ -40,7 +40,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.Closeable; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java index 34babc8d49..40bb6539cd 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java @@ -16,7 +16,6 @@ package org.ehcache.impl.internal.store.disk; -import org.ehcache.config.Eviction; import org.ehcache.config.EvictionAdvisor; import org.ehcache.impl.internal.store.disk.factories.EhcachePersistentSegmentFactory; import org.ehcache.impl.internal.store.offheap.AbstractEhcacheOffHeapBackingMapTest; @@ -30,11 +29,11 @@ import org.ehcache.spi.serialization.Serializer; import org.ehcache.spi.serialization.UnsupportedTypeException; import org.junit.Rule; -import org.junit.rules.TemporaryFolder; import org.terracotta.offheapstore.disk.paging.MappedPageSource; import org.terracotta.offheapstore.disk.persistent.PersistentPortability; import org.terracotta.offheapstore.disk.storage.FileBackedStorageEngine; import org.terracotta.offheapstore.util.Factory; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java index c93f088128..1a1c5dd58d 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java @@ -47,7 +47,7 @@ import org.ehcache.spi.test.After; import org.junit.Before; import org.junit.Rule; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.IOException; import java.util.Arrays; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java index 38310e0b2e..9cc393d631 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java @@ -55,12 +55,11 @@ import org.ehcache.test.MockitoUtil; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.mockito.Answers; -import org.mockito.Mockito; import org.terracotta.context.query.Matcher; import org.terracotta.context.query.Query; import org.terracotta.context.query.QueryBuilder; +import org.terracotta.org.junit.rules.TemporaryFolder; import org.terracotta.statistics.OperationStatistic; import java.io.IOException; @@ -89,7 +88,6 @@ import static org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration.DEFAULT_DISK_SEGMENTS; import static org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration.DEFAULT_WRITER_CONCURRENCY; import static org.ehcache.impl.internal.spi.TestServiceProvider.providerContaining; -import static org.ehcache.test.MockitoUtil.mock; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.core.Is.is; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java index ab44863c2c..99eb4f7a42 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java @@ -29,11 +29,11 @@ import org.ehcache.spi.serialization.UnsupportedTypeException; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.terracotta.offheapstore.disk.paging.MappedPageSource; import org.terracotta.offheapstore.disk.persistent.PersistentPortability; import org.terracotta.offheapstore.disk.storage.FileBackedStorageEngine; import org.terracotta.offheapstore.util.Factory; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java index 7cd315ebaf..341cb5f56b 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java @@ -38,9 +38,9 @@ import org.ehcache.spi.persistence.PersistableResourceService.PersistenceSpaceIdentifier; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.mockito.Answers; import org.mockito.Mockito; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java index e51e7f849f..6d0bad8aed 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java @@ -58,7 +58,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Rule; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.IOException; import java.util.Arrays; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java index 6474aef6cc..a725c2be0e 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java @@ -61,7 +61,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Rule; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.IOException; import java.util.Arrays; diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java b/impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java index 67f03f6464..55b46db5f0 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java @@ -18,7 +18,7 @@ import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java b/impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java index ad22995665..a3f468a6f7 100644 --- a/impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java +++ b/impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java @@ -23,7 +23,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java b/impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java index 87ebfce900..8c71667cbd 100644 --- a/impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java +++ b/impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java @@ -20,7 +20,7 @@ import org.ehcache.spi.persistence.StateHolder; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; import java.io.FileInputStream; diff --git a/integration-test/src/test/java/org/ehcache/integration/ExpiryEventsTest.java b/integration-test/src/test/java/org/ehcache/integration/ExpiryEventsTest.java index 30fd427980..38f2f98dc6 100644 --- a/integration-test/src/test/java/org/ehcache/integration/ExpiryEventsTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/ExpiryEventsTest.java @@ -35,7 +35,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.IOException; import java.time.Duration; diff --git a/integration-test/src/test/java/org/ehcache/integration/PersistentCacheTest.java b/integration-test/src/test/java/org/ehcache/integration/PersistentCacheTest.java index 21fcb7ca57..29adf0d7c0 100644 --- a/integration-test/src/test/java/org/ehcache/integration/PersistentCacheTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/PersistentCacheTest.java @@ -26,8 +26,8 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.junit.rules.TestName; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; import java.io.Serializable; diff --git a/integration-test/src/test/java/org/ehcache/integration/PersistentUserManagedCacheTest.java b/integration-test/src/test/java/org/ehcache/integration/PersistentUserManagedCacheTest.java index 73f5827fe1..f394d7fba8 100644 --- a/integration-test/src/test/java/org/ehcache/integration/PersistentUserManagedCacheTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/PersistentUserManagedCacheTest.java @@ -27,7 +27,7 @@ import org.ehcache.impl.persistence.DefaultLocalPersistenceService; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; import java.io.Serializable; diff --git a/integration-test/src/test/java/org/ehcache/integration/SerializersTest.java b/integration-test/src/test/java/org/ehcache/integration/SerializersTest.java index 6d022b0ff4..472c6351a0 100644 --- a/integration-test/src/test/java/org/ehcache/integration/SerializersTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/SerializersTest.java @@ -30,7 +30,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.nio.ByteBuffer; diff --git a/integration-test/src/test/java/org/ehcache/integration/StatefulSerializerWithStateRepositoryTest.java b/integration-test/src/test/java/org/ehcache/integration/StatefulSerializerWithStateRepositoryTest.java index 5ec4928041..d21d13860a 100644 --- a/integration-test/src/test/java/org/ehcache/integration/StatefulSerializerWithStateRepositoryTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/StatefulSerializerWithStateRepositoryTest.java @@ -24,7 +24,7 @@ import org.ehcache.integration.domain.Person; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; diff --git a/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java b/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java index 4f11501ae5..934d0ff37a 100644 --- a/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java @@ -29,12 +29,12 @@ import org.ehcache.impl.config.persistence.CacheManagerPersistenceConfiguration; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.terracotta.context.ContextManager; import org.terracotta.context.TreeNode; import org.terracotta.context.query.Matcher; import org.terracotta.context.query.Matchers; import org.terracotta.context.query.Query; +import org.terracotta.org.junit.rules.TemporaryFolder; import org.terracotta.statistics.OperationStatistic; import java.io.File; diff --git a/integration-test/src/test/java/org/ehcache/integration/statistics/AbstractCalculationTest.java b/integration-test/src/test/java/org/ehcache/integration/statistics/AbstractCalculationTest.java index 5d96210727..f9a7dfaa51 100644 --- a/integration-test/src/test/java/org/ehcache/integration/statistics/AbstractCalculationTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/statistics/AbstractCalculationTest.java @@ -27,11 +27,11 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.junit.Rule; -import org.junit.rules.TemporaryFolder; import org.junit.rules.TestWatcher; import org.junit.runner.Description; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.terracotta.org.junit.rules.TemporaryFolder; import static org.assertj.core.api.Assertions.assertThat; diff --git a/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java b/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java index a8f2e4db6d..d6ecad0dfe 100644 --- a/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java @@ -39,7 +39,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import javax.transaction.RollbackException; import javax.transaction.Status; diff --git a/management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java b/management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java index 2e97b92a45..31215470c1 100644 --- a/management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java +++ b/management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java @@ -32,11 +32,11 @@ import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.terracotta.management.model.capabilities.Capability; import org.terracotta.management.model.capabilities.context.CapabilityContext; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.FileNotFoundException; import java.io.IOException; diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java index 27834e37e2..3bce9d8470 100755 --- a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java @@ -36,7 +36,6 @@ import org.junit.Assert; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.junit.rules.Timeout; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -44,6 +43,7 @@ import org.terracotta.management.model.stats.ContextualStatistics; import org.terracotta.management.registry.ResultSet; import org.terracotta.management.registry.StatisticQuery; +import org.terracotta.org.junit.rules.TemporaryFolder; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; diff --git a/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java b/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java index cbecaf2cf2..e7f239e73d 100644 --- a/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java +++ b/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java @@ -38,7 +38,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; import org.junit.rules.Timeout; import org.terracotta.management.model.call.ContextualReturn; import org.terracotta.management.model.capabilities.Capability; @@ -49,6 +48,7 @@ import org.terracotta.management.model.stats.ContextualStatistics; import org.terracotta.management.registry.ResultSet; import org.terracotta.management.registry.StatisticQuery.Builder; +import org.terracotta.org.junit.rules.TemporaryFolder; import static org.assertj.core.api.Assertions.assertThat; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; diff --git a/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java b/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java index 168e3c0e21..e670f5cca9 100644 --- a/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java +++ b/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java @@ -37,9 +37,9 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java index acbb274054..0028025b0d 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java @@ -21,7 +21,7 @@ import org.ehcache.transactions.xa.utils.TestXid; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.util.Arrays; diff --git a/xml/src/test/java/org/ehcache/docs/GettingStarted.java b/xml/src/test/java/org/ehcache/docs/GettingStarted.java index f4a8f1516f..584790cb5d 100644 --- a/xml/src/test/java/org/ehcache/docs/GettingStarted.java +++ b/xml/src/test/java/org/ehcache/docs/GettingStarted.java @@ -27,7 +27,7 @@ import org.ehcache.xml.XmlConfiguration; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.IOException; import java.net.URL; From a4f8a3068b69b8ace3dffbc03871c7150a85c0a1 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Sat, 18 Apr 2020 22:11:52 -0400 Subject: [PATCH 236/372] Increase read timeouts on EventsFailureBehaviorTest --- .../java/org/ehcache/clustered/EventsFailureBehaviorTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index d1d910bb9b..89348652a2 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -52,6 +52,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import static java.util.stream.LongStream.range; +import static org.ehcache.clustered.client.config.builders.TimeoutsBuilder.timeouts; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; @@ -91,10 +92,12 @@ public void waitForActive() throws Exception { cacheManager1 = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve(testName.getMethodName())) + .timeouts(timeouts().read(Duration.ofSeconds(20)).write(Duration.ofSeconds(20))) .autoCreate(s -> s.defaultServerResource("primary-server-resource"))).build(true); cacheManager2 = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve(testName.getMethodName())) + .timeouts(timeouts().read(Duration.ofSeconds(20)).write(Duration.ofSeconds(20))) .autoCreate(s -> s.defaultServerResource("primary-server-resource"))).build(true); } From 945ae6f7fb64e69c1c44354f9b5899e447c735d0 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Sun, 19 Apr 2020 09:18:02 -0400 Subject: [PATCH 237/372] import-fixup --- .../clustered/client/internal/service/ReconnectTest.java | 1 - .../org/ehcache/core/spi/store/events/StoreEventSource.java | 2 -- 2 files changed, 3 deletions(-) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java index 421fa7d662..70f253f99e 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java @@ -30,7 +30,6 @@ import java.util.Properties; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import java.util.concurrent.ForkJoinPool; public class ReconnectTest { diff --git a/core/src/main/java/org/ehcache/core/spi/store/events/StoreEventSource.java b/core/src/main/java/org/ehcache/core/spi/store/events/StoreEventSource.java index 26466e9f4d..d49187d70b 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/events/StoreEventSource.java +++ b/core/src/main/java/org/ehcache/core/spi/store/events/StoreEventSource.java @@ -16,8 +16,6 @@ package org.ehcache.core.spi.store.events; -import org.ehcache.event.EventFiring; - /** * Interface to enable listening on and configuring the {@link org.ehcache.core.spi.store.Store} eventing system. */ From dc70426301908357e56cf8e25c82ff5dcfd93088 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 8 Apr 2020 09:42:10 -0400 Subject: [PATCH 238/372] Turn on windows testing --- azure-pipelines-windows.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/azure-pipelines-windows.yml b/azure-pipelines-windows.yml index 852f3193ce..a8df8998e6 100644 --- a/azure-pipelines-windows.yml +++ b/azure-pipelines-windows.yml @@ -27,14 +27,12 @@ jobs: - template: build-templates/gradle-common.yml@templates parameters: vmImage: 'windows-latest' - gradleTasks: 'test -x :clustered:integration-test:test' jdkVersion: '1.8' jobName: 'Java8' - template: build-templates/gradle-common.yml@templates parameters: vmImage: 'windows-latest' - gradleTasks: 'test -x :clustered:integration-test:test' jdkVersion: '1.8' options: '-PtestVM=java11Home' jobName: 'Java11' From 9900421223b48c452efcd164be9e8c054b403245 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 8 Apr 2020 09:39:05 -0400 Subject: [PATCH 239/372] Windows test fixes --- .../BasicCacheOpsMultiThreadedTest.java | 140 +++++++----------- .../clustered/EventsFailureBehaviorTest.java | 20 ++- .../StandardEhcacheStatisticsTest.java | 48 +++--- .../registry/DefaultCollectorServiceTest.java | 4 +- 4 files changed, 92 insertions(+), 120 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index 0c442e60fa..079d810dda 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -19,14 +19,8 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.client.config.ClusteredStoreConfiguration; -import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; -import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; -import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.common.Consistency; -import org.ehcache.config.ResourcePool; -import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; -import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -36,19 +30,25 @@ import java.net.URI; import java.time.Duration; -import java.util.ArrayList; import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import java.util.Optional; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; +import static java.util.Collections.nCopies; +import static java.util.stream.Collectors.toList; +import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; +import static org.ehcache.clustered.client.config.builders.TimeoutsBuilder.timeouts; +import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; +import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; +import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; @@ -83,94 +83,66 @@ public static void waitForActive() throws Exception { private static final int NUM_THREADS = 8; private static final int MAX_WAIT_TIME_SECONDS = 30; - private final AtomicReference exception = new AtomicReference<>(); private final AtomicLong idGenerator = new AtomicLong(2L); @Test @Ignore("Issue#2758: Fails on linux PR builds") - public void testMulipleClients() throws Throwable { - CountDownLatch latch = new CountDownLatch(NUM_THREADS + 1); + public void testMultipleClients() { + ExecutorService executorService = Executors.newFixedThreadPool(NUM_THREADS); + try { + List> results = nCopies(NUM_THREADS, content()).stream().map(executorService::submit).collect(toList()); - List threads = new ArrayList<>(NUM_THREADS); - for (int i = 0; i < NUM_THREADS; i++) { - Thread t1 = new Thread(content(latch)); - t1.start(); - threads.add(t1); - } - - latch.countDown(); - assertTrue(latch.await(MAX_WAIT_TIME_SECONDS, TimeUnit.SECONDS)); - - for (Thread t : threads) { - t.join(); - } - - Throwable throwable = exception.get(); - if (throwable != null) { - throw throwable; + results.stream().map(f -> { + try { + f.get(); + return Optional.empty(); + } catch (Exception e) { + return Optional.of(e); + } + }).filter(Optional::isPresent).map(Optional::get).reduce((a, b) -> { + a.addSuppressed(b); + return a; + } + ).ifPresent(t -> { + throw new AssertionError(t); + }); + } finally { + executorService.shutdownNow(); } } - private Runnable content(CountDownLatch latch) { + private Callable content() { return () -> { try (PersistentCacheManager cacheManager = createCacheManager(CLUSTER.getConnectionURI())) { - latch.countDown(); - try { - assertTrue(latch.await(MAX_WAIT_TIME_SECONDS, TimeUnit.SECONDS)); - } catch (InterruptedException e) { - // continue - } - - cacheManager.init(); - doSyncAndPut(cacheManager); - } catch (Throwable t) { - if (!exception.compareAndSet(null, t)) { - exception.get().addSuppressed(t); + Cache synCache = cacheManager.getCache(SYN_CACHE_NAME, String.class, Boolean.class); + Cache customValueCache = cacheManager.getCache(CLUSTERED_CACHE_NAME, Long.class, String.class); + parallelPuts(customValueCache); + String firstClientStartKey = "first_client_start", firstClientEndKey = "first_client_end"; + if (synCache.putIfAbsent(firstClientStartKey, true) == null) { + customValueCache.put(1L, "value"); + assertThat(customValueCache.get(1L), is("value")); + synCache.put(firstClientEndKey, true); + } else { + assertThatEventually(() -> synCache.get(firstClientEndKey), notNullValue()).within(Duration.ofSeconds(30)); + assertThat(customValueCache.get(1L), is("value")); } + return null; } }; } - private void doSyncAndPut(PersistentCacheManager cacheManager) throws InterruptedException, TimeoutException { - String customValue = "value"; - Cache synCache = cacheManager.getCache(SYN_CACHE_NAME, String.class, Boolean.class); - Cache customValueCache = cacheManager.getCache(CLUSTERED_CACHE_NAME, Long.class, String.class); - parallelPuts(customValueCache); - String firstClientStartKey = "first_client_start", firstClientEndKey = "first_client_end"; - if (synCache.putIfAbsent(firstClientStartKey, true) == null) { - customValueCache.put(1L, customValue); - assertThat(customValueCache.get(1L), is(customValue)); - synCache.put(firstClientEndKey, true); - } else { - assertThatEventually(() -> synCache.get(firstClientEndKey), notNullValue()).within(Duration.ofSeconds(30)); - assertThat(customValueCache.get(1L), is(customValue)); - } - } - private static PersistentCacheManager createCacheManager(URI clusterURI) { - ClusteringServiceConfigurationBuilder clusteringConfig = cluster(clusterURI.resolve(CACHE_MANAGER_NAME)) - .timeouts(TimeoutsBuilder.timeouts().read(Duration.ofSeconds(20)).write(Duration.ofSeconds(30))) - .autoCreate(server -> server.defaultServerResource(PRIMARY_SERVER_RESOURCE_NAME)); - - ResourcePool resourcePool = ClusteredResourcePoolBuilder - .clusteredDedicated(PRIMARY_SERVER_RESOURCE_NAME, PRIMARY_SERVER_RESOURCE_SIZE, MemoryUnit.MB); - - CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder - .newCacheManagerBuilder() - .with(clusteringConfig) - .withCache(CLUSTERED_CACHE_NAME, - CacheConfigurationBuilder - .newCacheConfigurationBuilder(Long.class, String.class, - ResourcePoolsBuilder.newResourcePoolsBuilder() - .with(resourcePool)) - .withService(new ClusteredStoreConfiguration(Consistency.STRONG))) - .withCache(SYN_CACHE_NAME, - CacheConfigurationBuilder - .newCacheConfigurationBuilder(String.class, Boolean.class, - ResourcePoolsBuilder.newResourcePoolsBuilder() - .with(resourcePool)) - .withService(new ClusteredStoreConfiguration(Consistency.STRONG))); - return clusteredCacheManagerBuilder.build(false); + CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() + .with(cluster(clusterURI.resolve(CACHE_MANAGER_NAME)) + .timeouts(timeouts().read(Duration.ofSeconds(MAX_WAIT_TIME_SECONDS)).write(Duration.ofSeconds(MAX_WAIT_TIME_SECONDS))) + .autoCreate(server -> server.defaultServerResource(PRIMARY_SERVER_RESOURCE_NAME))) + .withCache(CLUSTERED_CACHE_NAME, newCacheConfigurationBuilder(Long.class, String.class, newResourcePoolsBuilder() + .with(clusteredDedicated(PRIMARY_SERVER_RESOURCE_SIZE, MemoryUnit.MB))) + .withService(new ClusteredStoreConfiguration(Consistency.STRONG))) + .withCache(SYN_CACHE_NAME, newCacheConfigurationBuilder(String.class, Boolean.class, newResourcePoolsBuilder() + .with(clusteredDedicated(PRIMARY_SERVER_RESOURCE_SIZE, MemoryUnit.MB))) + .withService(new ClusteredStoreConfiguration(Consistency.STRONG))); + return clusteredCacheManagerBuilder.build(true); } private void parallelPuts(Cache customValueCache) { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index 953a8025aa..65967c3465 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -18,6 +18,7 @@ import org.ehcache.Cache; import org.ehcache.CacheManager; import org.ehcache.PersistentCacheManager; +import org.ehcache.StateTransitionException; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.reconnect.ThrowingResiliencyStrategy; @@ -41,6 +42,8 @@ import org.junit.Test; import org.junit.rules.TestName; import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.time.Duration; import java.util.EnumSet; @@ -62,8 +65,11 @@ @Ignore("Issue#2758: Fails on linux PR builds") public class EventsFailureBehaviorTest extends ClusteredTests { + private static final Logger LOGGER = LoggerFactory.getLogger(EventsFailureBehaviorTest.class); + private static final int KEYS = 500; private static final Duration TIMEOUT = Duration.ofSeconds(5); + private static final Duration FAILOVER_TIMEOUT = Duration.ofMinutes(1); private static final String RESOURCE_CONFIG = "" @@ -97,9 +103,17 @@ public void waitForActive() throws Exception { @After public void tearDown() { try { - cacheManager1.close(); + try { + cacheManager1.close(); + } catch (StateTransitionException e) { + LOGGER.warn("Failed to shutdown cache manager", e); + } } finally { - cacheManager2.close(); + try { + cacheManager2.close(); + } catch (StateTransitionException e) { + LOGGER.warn("Failed to shutdown cache manager", e); + } } } @@ -129,7 +143,7 @@ private void failover(Cache cache1, Cache cache2) th } catch (Exception e) { return false; } - }, is(true)).within(TIMEOUT); + }, is(true)).within(FAILOVER_TIMEOUT); } @Test diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java index e4683f1ad1..83560a2430 100755 --- a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java @@ -15,7 +15,6 @@ */ package org.ehcache.management.providers.statistics; -import org.assertj.core.api.AbstractLongAssert; import org.ehcache.Cache; import org.ehcache.CacheManager; import org.ehcache.config.CacheConfiguration; @@ -32,9 +31,7 @@ import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.Timeout; import org.terracotta.management.model.context.Context; import org.terracotta.management.model.stats.ContextualStatistics; import org.terracotta.statistics.OperationStatistic; @@ -51,6 +48,7 @@ import java.util.function.Consumer; import java.util.stream.IntStream; +import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.ehcache.core.statistics.StatsUtils.findOperationStatisticOnChildren; @@ -59,9 +57,6 @@ public class StandardEhcacheStatisticsTest { private static final int HISTOGRAM_WINDOW_MILLIS = 400; private static final int NEXT_WINDOW_SLEEP_MILLIS = 500; - @Rule - public final Timeout globalTimeout = Timeout.seconds(10); - private CacheManager cacheManager; private Cache cache; private ManagementRegistryService managementRegistry; @@ -134,25 +129,19 @@ public void statTest() throws InterruptedException { cache.get(1L); // hit cache.remove(1L); // removal - IntStream.of(50, 95, 99, 100) - .forEach(i -> { - assertStatistic("Cache:MissCount").isEqualTo(1L); - assertStatistic("Cache:GetMissLatency#" + i).isGreaterThan(0); - - assertStatistic("Cache:HitCount").isEqualTo(1L); - assertStatistic("Cache:GetHitLatency#" + i).isGreaterThan(0); - - assertStatistic("Cache:PutCount").isEqualTo(1L); - assertStatistic("Cache:PutLatency#" + i).isGreaterThan(0); - - assertStatistic("Cache:RemovalCount").isEqualTo(1L); - assertStatistic("Cache:RemoveLatency#" + i).isGreaterThan(0); - }); - } - - private AbstractLongAssert assertStatistic(String statName) { - long value = getStatistic(statName); - return assertThat(value).describedAs(statName); + assertThat(getStatistic("Cache:MissCount")).isEqualTo(1L); + assertThat(getStatistic("Cache:HitCount")).isEqualTo(1L); + assertThat(getStatistic("Cache:PutCount")).isEqualTo(1L); + assertThat(getStatistic("Cache:RemovalCount")).isEqualTo(1L); + + for (String statistic : asList("GetMiss", "GetHit", "Put", "Remove")) { + long last = 0L; + for (String percentile : asList("50", "95", "99", "100")) { + long value = getStatistic("Cache:" + statistic + "Latency#" + percentile); + assertThat(value).isGreaterThanOrEqualTo(last); + last = value; + } + } } private long getStatistic(String statName) { @@ -229,11 +218,9 @@ private > LatencyHistogramStatistic getHistogram(T type, Strin // accurate to ~16ms), the inaccuracy of which compounds when invoked multiple times, as in this method. private void minimumSleep(long millis) { - long nanos = TimeUnit.MILLISECONDS.toNanos(millis); - long start = System.nanoTime(); - + long end = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(millis); while (true) { - long nanosLeft = nanos - (System.nanoTime() - start); + long nanosLeft = end - System.nanoTime(); if (nanosLeft <= 0) { break; @@ -242,8 +229,7 @@ private void minimumSleep(long millis) { try { TimeUnit.NANOSECONDS.sleep(nanosLeft); } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - return; + throw new AssertionError(e); } } } diff --git a/management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java b/management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java index 7366a88b78..71b3c9b4ad 100644 --- a/management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java +++ b/management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java @@ -45,7 +45,7 @@ public class DefaultCollectorServiceTest { - @Test(timeout = 6000) + @Test public void test_collector() throws Exception { final Queue messages = new ConcurrentLinkedQueue<>(); final List notifs = new ArrayList<>(7); @@ -104,7 +104,7 @@ void onEvent(Object event) { cache.put("key", "val"); cache.clear(); - num.await(); + num.await(10, TimeUnit.SECONDS); cacheManager.removeCache("my-cache"); cacheManager.close(); From 7ffcbd1c904ed2a1cacc753d596608c98b3bfde2 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 13 Apr 2020 10:25:48 -0400 Subject: [PATCH 240/372] Collapse everything to one job --- azure-pipelines-windows.yml | 38 ------------------------------------- azure-pipelines.yml | 17 +++++++++++++++-- 2 files changed, 15 insertions(+), 40 deletions(-) delete mode 100644 azure-pipelines-windows.yml diff --git a/azure-pipelines-windows.yml b/azure-pipelines-windows.yml deleted file mode 100644 index a8df8998e6..0000000000 --- a/azure-pipelines-windows.yml +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# See shared code location for steps and parameters: -# https://dev.azure.com/TerracottaCI/_git/terracotta - -resources: - repositories: - - repository: templates - type: git - name: terracotta/terracotta - -jobs: -- template: build-templates/gradle-common.yml@templates - parameters: - vmImage: 'windows-latest' - jdkVersion: '1.8' - jobName: 'Java8' - -- template: build-templates/gradle-common.yml@templates - parameters: - vmImage: 'windows-latest' - jdkVersion: '1.8' - options: '-PtestVM=java11Home' - jobName: 'Java11' diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 09e2981ac8..590980b08b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -27,10 +27,23 @@ jobs: - template: build-templates/gradle-common.yml@templates parameters: jdkVersion: '1.8' - jobName: 'Java8' + jobName: 'LinuxJava8' - template: build-templates/gradle-common.yml@templates parameters: jdkVersion: '1.8' options: '-PtestVM=java11Home' - jobName: 'Java11' + jobName: 'LinuxJava11' + +- template: build-templates/gradle-common.yml@templates + parameters: + vmImage: 'windows-latest' + jdkVersion: '1.8' + jobName: 'WindowsJava8' + +- template: build-templates/gradle-common.yml@templates + parameters: + vmImage: 'windows-latest' + jdkVersion: '1.8' + options: '-PtestVM=java11Home' + jobName: 'WindowsJava11' From a9ed790c8a44d5381ae2c27fb735569282fdbbe7 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 8 Apr 2020 14:38:39 -0400 Subject: [PATCH 241/372] Cleanup management tests to prevent accidental connection leaks --- .../AbstractClusteringManagementTest.java | 115 +++------------- .../AfterFailoverManagementServiceTest.java | 11 +- .../management/CMClosedEventSentTest.java | 12 +- .../management/ClusterWithManagement.java | 130 ++++++++++++++++++ .../ClusteringManagementServiceTest.java | 4 +- .../EhcacheManagerToStringTest.java | 2 +- .../ManagementClusterConnectionTest.java | 38 ++--- 7 files changed, 168 insertions(+), 144 deletions(-) create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusterWithManagement.java diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 40cf7be984..1c41d457b5 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -33,13 +33,6 @@ import org.junit.rules.Timeout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.terracotta.connection.Connection; -import org.terracotta.connection.ConnectionException; -import org.terracotta.exception.EntityConfigurationException; -import org.terracotta.management.entity.nms.NmsConfig; -import org.terracotta.management.entity.nms.client.DefaultNmsService; -import org.terracotta.management.entity.nms.client.NmsEntity; -import org.terracotta.management.entity.nms.client.NmsEntityFactory; import org.terracotta.management.entity.nms.client.NmsService; import org.terracotta.management.model.cluster.AbstractManageableNode; import org.terracotta.management.model.cluster.Client; @@ -49,7 +42,6 @@ import org.terracotta.management.model.context.Context; import org.terracotta.management.model.notification.ContextualNotification; import org.terracotta.management.model.stats.ContextualStatistics; -import org.terracotta.testing.rules.Cluster; import java.util.ArrayList; import java.util.Arrays; @@ -68,6 +60,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.junit.rules.RuleChain.outerRule; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; @SuppressWarnings("rawtypes") // Need to suppress because of a Javac bug giving a rawtype on AbstractManageableNode::isManageable. @@ -86,48 +79,24 @@ public abstract class AbstractClusteringManagementTest extends ClusteredTests { protected static CacheManager cacheManager; protected static ClientIdentifier ehcacheClientIdentifier; protected static ServerEntityIdentifier clusterTierManagerEntityIdentifier; - protected static ObjectMapper mapper = new ObjectMapper(); - - static NmsService nmsService; - protected static ServerEntityIdentifier tmsServerEntityIdentifier; - protected static Connection managementConnection; - - static { - mapper.configure(SerializationFeature.INDENT_OUTPUT, true); - } + protected static final ObjectMapper mapper = new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true); @ClassRule - public static Cluster CLUSTER = newCluster(2) - .in(clusterPath()) - .withServiceFragment(RESOURCE_CONFIG) - .build(); + public static final ClusterWithManagement CLUSTER = new ClusterWithManagement(newCluster(2) + .in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @Rule - public final RuleChain rules = RuleChain.emptyRuleChain() - .around(Timeout.seconds(90)) - .around(new BeforeAllRule(this)); + public final RuleChain rules = outerRule(Timeout.seconds(90)).around(new BeforeAllRule(this)); @BeforeAll public void beforeAllTests() throws Exception { - CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); - - // simulate a TMS client - createNmsService(); - initCM(); - initIdentifiers(); - - sendManagementCallOnEntityToCollectStats(); } @Before public void init() { - if (nmsService != null) { - // this call clear the CURRENT arrived messages, but be aware that some other messages can arrive just after the drain - nmsService.readMessages(); - } + CLUSTER.getNmsService().readMessages(); } @AfterClass @@ -135,10 +104,10 @@ public static void afterClass() throws Exception { tearDownCacheManagerAndStatsCollector(); } - protected void initCM() throws InterruptedException { + private static void initCM() throws InterruptedException { cacheManager = newCacheManagerBuilder() // cluster config - .with(cluster(CLUSTER.getConnectionURI().resolve("/my-server-entity-1")) + .with(cluster(CLUSTER.getCluster().getConnectionURI().resolve("/my-server-entity-1")) .autoCreate(server -> server .defaultServerResource("primary-server-resource") .resourcePool("resource-pool-a", 10, MemoryUnit.MB, "secondary-server-resource") // <2> @@ -199,21 +168,7 @@ protected void initCM() throws InterruptedException { ); } - public static void initIdentifiers() throws Exception { - tmsServerEntityIdentifier = null; - ehcacheClientIdentifier = null; - clusterTierManagerEntityIdentifier = null; - - while ((tmsServerEntityIdentifier = readTopology() - .activeServerEntityStream() - .filter(serverEntity -> serverEntity.getType().equals(NmsConfig.ENTITY_TYPE)) - .filter(AbstractManageableNode::isManageable) - .map(ServerEntity::getServerEntityIdentifier) - .findFirst() - .orElse(null)) == null) { - sleep(200); - } - + private static void initIdentifiers() throws Exception { while ((ehcacheClientIdentifier = readTopology().getClients().values() .stream() .filter(client -> client.getName().equals("Ehcache:my-server-entity-1")) @@ -235,53 +190,24 @@ public static void initIdentifiers() throws Exception { } } - public static void tearDownCacheManagerAndStatsCollector() throws Exception { + private static void tearDownCacheManagerAndStatsCollector() throws Exception { if (cacheManager != null && cacheManager.getStatus() == Status.AVAILABLE) { - if (nmsService != null) { - readTopology().getClient(ehcacheClientIdentifier) - .ifPresent(client -> { - try { - nmsService.stopStatisticCollector(client.getContext().with("cacheManagerName", "my-super-cache-manager")).waitForReturn(); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } - - cacheManager.close(); - } - - if (nmsService != null) { - readTopology().getSingleStripe().getActiveServerEntity(tmsServerEntityIdentifier) + readTopology().getClient(ehcacheClientIdentifier) .ifPresent(client -> { try { - nmsService.stopStatisticCollector(client.getContext()); + CLUSTER.getNmsService().stopStatisticCollector(client.getContext().with("cacheManagerName", "my-super-cache-manager")).waitForReturn(); } catch (Exception e) { throw new RuntimeException(e); } }); - managementConnection.close(); + cacheManager.close(); } } - public static void createNmsService() throws ConnectionException, EntityConfigurationException { - createNmsService(CLUSTER); - } - - public static void createNmsService(Cluster cluster) throws ConnectionException, EntityConfigurationException { - managementConnection = cluster.newConnection(); - - NmsEntityFactory entityFactory = new NmsEntityFactory(managementConnection, AbstractClusteringManagementTest.class.getName()); - NmsEntity tmsAgentEntity = entityFactory.retrieveOrCreate(new NmsConfig()); - - nmsService = new DefaultNmsService(tmsAgentEntity); - nmsService.setOperationTimeout(5, TimeUnit.SECONDS); - } - public static org.terracotta.management.model.cluster.Cluster readTopology() throws Exception { - org.terracotta.management.model.cluster.Cluster cluster = nmsService.readTopology(); + org.terracotta.management.model.cluster.Cluster cluster = CLUSTER.getNmsService().readTopology(); //System.out.println(mapper.writeValueAsString(cluster.toMap())); return cluster; } @@ -291,12 +217,12 @@ public static void sendManagementCallOnClientToCollectStats() throws Exception { Client manageableClient = topology.getClient(ehcacheClientIdentifier).filter(AbstractManageableNode::isManageable).get(); Context cmContext = manageableClient.getContext() .with("cacheManagerName", "my-super-cache-manager"); - nmsService.startStatisticCollector(cmContext, 1, TimeUnit.SECONDS).waitForReturn(); + CLUSTER.getNmsService().startStatisticCollector(cmContext, 1, TimeUnit.SECONDS).waitForReturn(); } public static List waitForNextStats() throws Exception { // uses the monitoring to get the content of the stat buffer when some stats are collected - return nmsService.waitForMessage(message -> message.getType().equals("STATISTICS")) + return CLUSTER.getNmsService().waitForMessage(message -> message.getType().equals("STATISTICS")) .stream() .filter(message -> message.getType().equals("STATISTICS")) .flatMap(message -> message.unwrap(ContextualStatistics.class).stream()) @@ -313,14 +239,11 @@ protected static String normalizeForLineEndings(String stringToNormalize) { return stringToNormalize.replace("\r\n", "\n").replace("\r", "\n"); } - public static void sendManagementCallOnEntityToCollectStats() throws Exception { - org.terracotta.management.model.cluster.Cluster topology = readTopology(); - ServerEntity manageableEntity = topology.getSingleStripe().getActiveServerEntity(tmsServerEntityIdentifier).filter(AbstractManageableNode::isManageable).get(); - Context context = manageableEntity.getContext(); - nmsService.startStatisticCollector(context, 1, TimeUnit.SECONDS).waitForReturn(); + public static void waitForAllNotifications(String... notificationTypes) throws InterruptedException { + waitForAllNotifications(CLUSTER.getNmsService(), notificationTypes); } - public static void waitForAllNotifications(String... notificationTypes) throws InterruptedException { + public static void waitForAllNotifications(NmsService nmsService, String... notificationTypes) throws InterruptedException { List waitingFor = new ArrayList<>(Arrays.asList(notificationTypes)); List missingOnes = new ArrayList<>(); List existingOnes = new ArrayList<>(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AfterFailoverManagementServiceTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AfterFailoverManagementServiceTest.java index 234b7bd3c3..499bc0697a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AfterFailoverManagementServiceTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AfterFailoverManagementServiceTest.java @@ -26,13 +26,8 @@ public class AfterFailoverManagementServiceTest extends ClusteringManagementServ @Override public void beforeAllTests() throws Exception { super.beforeAllTests(); - - CLUSTER.getClusterControl().terminateActive(); - CLUSTER.getClusterControl().waitForActive(); - - initIdentifiers(); - - sendManagementCallOnEntityToCollectStats(); + CLUSTER.getCluster().getClusterControl().terminateActive(); + CLUSTER.getCluster().getClusterControl().waitForActive(); + CLUSTER.startCollectingServerEntityStats(); } - } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java index 98702fe300..cf0ed9b677 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java @@ -25,12 +25,9 @@ import org.junit.Test; import org.terracotta.management.model.message.Message; import org.terracotta.management.model.notification.ContextualNotification; -import org.terracotta.testing.rules.Cluster; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; -import static org.ehcache.clustered.management.AbstractClusteringManagementTest.createNmsService; -import static org.ehcache.clustered.management.AbstractClusteringManagementTest.nmsService; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; @@ -55,13 +52,12 @@ public class CMClosedEventSentTest extends ClusteredTests { + ""; @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static ClusterWithManagement CLUSTER = new ClusterWithManagement(newCluster() + .in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @Test(timeout = 60_000) public void test_CACHE_MANAGER_CLOSED() throws Exception { - createNmsService(CLUSTER); - - try (CacheManager cacheManager = newCacheManagerBuilder().with(cluster(CLUSTER.getConnectionURI().resolve("/my-server-entity-1")) + try (CacheManager cacheManager = newCacheManagerBuilder().with(cluster(CLUSTER.getCluster().getConnectionURI().resolve("/my-server-entity-1")) .autoCreate(server -> server .defaultServerResource("primary-server-resource") .resourcePool("resource-pool-a", 10, MemoryUnit.MB, "secondary-server-resource") // <2> @@ -89,7 +85,7 @@ public void test_CACHE_MANAGER_CLOSED() throws Exception { private void waitFor(String notifType) throws InterruptedException { while (!Thread.currentThread().isInterrupted()) { - Message message = nmsService.waitForMessage(); + Message message = CLUSTER.getNmsService().waitForMessage(); if (message.getType().equals("NOTIFICATION")) { ContextualNotification notification = message.unwrap(ContextualNotification.class).get(0); if (notification.getType().equals(notifType)) { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusterWithManagement.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusterWithManagement.java new file mode 100644 index 0000000000..0a65f31c36 --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusterWithManagement.java @@ -0,0 +1,130 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered.management; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.MultipleFailureException; +import org.junit.runners.model.Statement; +import org.terracotta.connection.Connection; +import org.terracotta.connection.ConnectionException; +import org.terracotta.exception.EntityConfigurationException; +import org.terracotta.management.entity.nms.NmsConfig; +import org.terracotta.management.entity.nms.client.DefaultNmsService; +import org.terracotta.management.entity.nms.client.IllegalManagementCallException; +import org.terracotta.management.entity.nms.client.NmsEntity; +import org.terracotta.management.entity.nms.client.NmsEntityFactory; +import org.terracotta.management.entity.nms.client.NmsService; +import org.terracotta.management.model.cluster.ServerEntity; +import org.terracotta.management.model.cluster.ServerEntityIdentifier; +import org.terracotta.testing.rules.Cluster; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import static java.lang.Thread.sleep; +import static java.util.Arrays.asList; + +public final class ClusterWithManagement implements TestRule { + + private final Cluster cluster; + + private Connection managementConnection; + private NmsService nmsService; + private ServerEntityIdentifier tmsServerEntityIdentifier; + + public ClusterWithManagement(Cluster cluster) { + this.cluster = cluster; + } + + protected void before() throws Throwable { + this.managementConnection = cluster.newConnection(); + this.nmsService = createNmsService(managementConnection); + while ((tmsServerEntityIdentifier = nmsService.readTopology() + .activeServerEntityStream() + .filter(serverEntity -> serverEntity.getType().equals(NmsConfig.ENTITY_TYPE)) + .filter(ServerEntity::isManageable) + .map(ServerEntity::getServerEntityIdentifier) + .findFirst() + .orElse(null)) == null) { + sleep(100); + } + startCollectingServerEntityStats(); + } + + protected void after() throws Exception { + try { + nmsService.readTopology().getSingleStripe().getActiveServerEntity(tmsServerEntityIdentifier) + .ifPresent(client -> { + try { + nmsService.stopStatisticCollector(client.getContext()); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } finally { + managementConnection.close(); + } + } + + @Override + public Statement apply(Statement base, Description description) { + return cluster.apply(new Statement() { + @Override + public void evaluate() throws Throwable { + before(); + try { + base.evaluate(); + after(); + } catch (Throwable t) { + try { + after(); + throw t; + } catch (Exception e) { + throw new MultipleFailureException(asList(t, e)); + } + } + } + }, description); + } + + public Cluster getCluster() { + return cluster; + } + + public NmsService getNmsService() { + return nmsService; + } + + public ServerEntityIdentifier getTmsServerEntityIdentifier() { + return tmsServerEntityIdentifier; + } + + private static NmsService createNmsService(Connection connection) throws ConnectionException, EntityConfigurationException { + NmsEntityFactory entityFactory = new NmsEntityFactory(connection, AbstractClusteringManagementTest.class.getName()); + NmsEntity tmsAgentEntity = entityFactory.retrieveOrCreate(new NmsConfig()); + + NmsService nmsService = new DefaultNmsService(tmsAgentEntity); + nmsService.setOperationTimeout(5, TimeUnit.SECONDS); + return nmsService; + } + + public void startCollectingServerEntityStats() throws InterruptedException, ExecutionException, TimeoutException, IllegalManagementCallException { + ServerEntity manageableEntity = nmsService.readTopology().getSingleStripe().getActiveServerEntity(tmsServerEntityIdentifier).filter(ServerEntity::isManageable).get(); + nmsService.startStatisticCollector(manageableEntity.getContext(), 1, TimeUnit.SECONDS).waitForReturn(); + } +} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java index dbabc79e89..7cc3e07ebe 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java @@ -133,7 +133,7 @@ public class ClusteringManagementServiceTest extends AbstractClusteringManagemen @Test @Ignore("This is not a test, but something useful to show a json print of a cluster topology with all management metadata inside") public void test_A_topology() throws Exception { - Cluster cluster = nmsService.readTopology(); + Cluster cluster = CLUSTER.getNmsService().readTopology(); String json = mapper.writeValueAsString(cluster.toMap()); //System.out.println(json); } @@ -262,7 +262,7 @@ public void test_D_server_capabilities_exposed() throws Exception { // tms entity - managerCapabilities = readTopology().activeServerEntityStream().filter(serverEntity -> serverEntity.is(tmsServerEntityIdentifier)).findFirst().get().getManagementRegistry().get().getCapabilities().toArray(new Capability[0]); + managerCapabilities = readTopology().activeServerEntityStream().filter(serverEntity -> serverEntity.is(CLUSTER.getTmsServerEntityIdentifier())).findFirst().get().getManagementRegistry().get().getCapabilities().toArray(new Capability[0]); assertThat(managerCapabilities.length).isEqualTo(5); assertThat(managerCapabilities[0].getName()).isEqualTo("DataRootSettings"); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java index aa54307367..356fcc0f65 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java @@ -82,7 +82,7 @@ public void simpleOnHeapToString() throws Exception { @Test public void clusteredToString() throws Exception { - URI uri = CLUSTER.getConnectionURI().resolve("/my-server-entity-2"); + URI uri = CLUSTER.getCluster().getConnectionURI().resolve("/my-server-entity-2"); try (CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() // cluster config diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index dae63a4167..8786af138f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -27,13 +27,11 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; import org.hamcrest.Matchers; -import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.terracotta.management.model.capabilities.descriptors.Settings; -import org.terracotta.testing.rules.Cluster; import java.net.URI; import java.time.Duration; @@ -43,11 +41,7 @@ import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; -import static org.ehcache.clustered.management.AbstractClusteringManagementTest.createNmsService; -import static org.ehcache.clustered.management.AbstractClusteringManagementTest.initIdentifiers; -import static org.ehcache.clustered.management.AbstractClusteringManagementTest.readTopology; -import static org.ehcache.clustered.management.AbstractClusteringManagementTest.sendManagementCallOnEntityToCollectStats; -import static org.ehcache.clustered.management.AbstractClusteringManagementTest.tearDownCacheManagerAndStatsCollector; +import static org.ehcache.clustered.management.AbstractClusteringManagementTest.waitForAllNotifications; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; @@ -79,9 +73,8 @@ public class ManagementClusterConnectionTest extends ClusteredTests { private static final List proxies = new ArrayList<>(); @ClassRule - public static Cluster CLUSTER = newCluster() - .in(clusterPath()) - .withServiceFragment(RESOURCE_CONFIG).build(); + public static ClusterWithManagement CLUSTER = new ClusterWithManagement(newCluster() + .in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); @BeforeClass @@ -89,12 +82,9 @@ public static void beforeClass() throws Exception { mapper.configure(SerializationFeature.INDENT_OUTPUT, true); - CLUSTER.getClusterControl().waitForActive(); + CLUSTER.getCluster().getClusterControl().waitForActive(); - // simulate a TMS client - createNmsService(CLUSTER); - - URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.getConnectionURI(), proxies); + URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.getCluster().getConnectionURI(), proxies); cacheManager = newCacheManagerBuilder() // cluster config @@ -121,7 +111,7 @@ public static void beforeClass() throws Exception { assertThat(cacheManager.getStatus(), equalTo(Status.AVAILABLE)); // test_notifs_sent_at_CM_init - AbstractClusteringManagementTest.waitForAllNotifications( + waitForAllNotifications(CLUSTER.getNmsService(), "CLIENT_CONNECTED", "CLIENT_PROPERTY_ADDED", "CLIENT_PROPERTY_ADDED", @@ -135,15 +125,11 @@ public static void beforeClass() throws Exception { "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_UNFETCHED" ); - - initIdentifiers(); - - sendManagementCallOnEntityToCollectStats(); } @Test public void test_reconnection() throws Exception { - long count = readTopology().clientStream() + long count = CLUSTER.getNmsService().readTopology().clientStream() .filter(client -> client.getName() .startsWith("Ehcache:") && client.isManageable() && client.getTags() .containsAll(Arrays.asList("webapp-1", "server-node-1"))) @@ -165,7 +151,7 @@ public void test_reconnection() throws Exception { assertThatEventually(() -> { try { - return readTopology().clientStream() + return CLUSTER.getNmsService().readTopology().clientStream() .filter(client -> client.getName() .startsWith("Ehcache:") && client.isManageable() && client.getTags() .containsAll(Arrays.asList("webapp-1", "server-node-1"))) @@ -178,7 +164,7 @@ public void test_reconnection() throws Exception { } private String getInstanceId() throws Exception { - return readTopology().clientStream() + return CLUSTER.getNmsService().readTopology().clientStream() .filter(client -> client.getName().startsWith("Ehcache:") && client.isManageable()) .findFirst().get() .getManagementRegistry().get() @@ -188,10 +174,4 @@ private String getInstanceId() throws Exception { .map(settings -> settings.getString("instanceId")) .findFirst().get(); } - - @AfterClass - public static void afterClass() throws Exception { - tearDownCacheManagerAndStatsCollector(); - } - } From d344ea5c7b7bb25b610b8a28b81871dc2b5d8425 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 30 Apr 2020 13:00:17 -0400 Subject: [PATCH 242/372] Users won't wait for actives - we shouldn't either --- .../clustered/BasicCacheOpsMultiThreadedTest.java | 5 ----- .../ehcache/clustered/BasicClusteredCacheOpsTest.java | 5 ----- .../ehcache/clustered/BasicEntityInteractionTest.java | 5 ----- .../CacheManagerLifecycleEhcacheIntegrationTest.java | 1 - ...TierManagerClientEntityFactoryIntegrationTest.java | 3 +-- .../ehcache/clustered/ClusteredLoaderWriterTest.java | 3 +-- .../java/org/ehcache/clustered/DestroyLoopTest.java | 5 ----- .../ehcache/clustered/EventsFailureBehaviorTest.java | 2 +- .../clustered/IterationFailureBehaviorTest.java | 9 +++++---- .../org/ehcache/clustered/JCacheClusteredTest.java | 3 +-- .../test/java/org/ehcache/clustered/LeaseTest.java | 5 ----- .../ehcache/clustered/ReconnectDuringDestroyTest.java | 3 +-- .../clustered/ResourcePoolAllocationFailureTest.java | 5 ----- .../org/ehcache/clustered/TerminatedServerTest.java | 3 +-- .../lock/VoltronReadWriteLockIntegrationTest.java | 5 ----- .../VoltronReadWriteLockPassiveIntegrationTest.java | 11 +++++------ .../management/EhcacheConfigWithManagementTest.java | 5 ----- .../clustered/reconnect/BasicCacheReconnectTest.java | 4 +--- .../reconnect/CacheManagerDestroyReconnectTest.java | 4 +--- .../clustered/reconnect/EventsReconnectTest.java | 4 +--- ...ClusteredCacheOpsReplicationMultiThreadedTest.java | 9 ++++----- .../BasicClusteredCacheOpsReplicationTest.java | 6 ++++-- ...redCacheOpsReplicationWithMultipleClientsTest.java | 5 +++-- ...lusteredCacheOpsReplicationWithServersApiTest.java | 3 +-- .../BasicLifeCyclePassiveReplicationTest.java | 11 ++--------- .../ehcache/clustered/replication/DuplicateTest.java | 3 +-- .../replication/OversizedCacheOpsPassiveTest.java | 8 +------- .../org/ehcache/clustered/sync/PassiveSyncTest.java | 9 +-------- .../BasicClusteredWriteBehindMultiClientTest.java | 1 - .../writebehind/BasicClusteredWriteBehindTest.java | 1 - ...lusteredWriteBehindWithPassiveMultiClientTest.java | 4 +--- .../BasicClusteredWriteBehindWithPassiveTest.java | 6 ++---- 32 files changed, 39 insertions(+), 117 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index c96e704f59..baaa3a314c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -69,11 +69,6 @@ public class BasicCacheOpsMultiThreadedTest extends ClusteredTests { public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); - @BeforeClass - public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); - } - private static final String CLUSTERED_CACHE_NAME = "clustered-cache"; private static final String SYN_CACHE_NAME = "syn-cache"; private static final String PRIMARY_SERVER_RESOURCE_NAME = "primary-server-resource"; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java index 2aefc0e416..6f1129136e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java @@ -63,11 +63,6 @@ public class BasicClusteredCacheOpsTest extends ClusteredTests { public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); - @BeforeClass - public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); - } - @Test public void basicCacheCRUD() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java index aa99e79049..086797455d 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java @@ -65,11 +65,6 @@ public class BasicEntityInteractionTest extends ClusteredTests { public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); private ClusterTierManagerConfiguration blankConfiguration = new ClusterTierManagerConfiguration("identifier", new ServerSideConfiguration(emptyMap())); - @BeforeClass - public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); - } - @Rule public TestName testName= new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java index 4d419de113..abab2af19e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java @@ -73,7 +73,6 @@ public class CacheManagerLifecycleEhcacheIntegrationTest extends ClusteredTests @BeforeClass public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); ASSERTION_CONNECTION = CLUSTER.newConnection(); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java index e5a1ba1d30..7eb38c6b98 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java @@ -58,8 +58,7 @@ public class ClusterTierManagerClientEntityFactoryIntegrationTest extends Cluste private static Connection CONNECTION; @BeforeClass - public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); + public static void initConnection() throws Exception { CONNECTION = CLUSTER.newConnection(); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java index 6f6a61260a..28b738d0f3 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java @@ -84,8 +84,7 @@ public static Consistency[] data() { newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass - public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); + public static void initCacheManager() throws Exception { cacheManager = newCacheManager(); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java index 09b750224b..8e6502b1ff 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java @@ -59,11 +59,6 @@ public class DestroyLoopTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); - @BeforeClass - public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); - } - @Test public void testDestroyLoop() throws Exception { for (int i = 0; i < 10; i++) { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index 89348652a2..98664afc5e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -132,8 +132,8 @@ private static Cache createCache(CacheManager cacheManager, CacheE private void failover(Cache cache1, Cache cache2) throws Exception { // failover passive -> active + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); - CLUSTER.getClusterControl().waitForActive(); // wait for clients to be back in business assertThatEventually(() -> { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java index 28819b4ea8..02c3298eeb 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java @@ -30,6 +30,7 @@ import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.testing.TestRetryer; import org.ehcache.testing.TestRetryer.OutputIs; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; @@ -78,10 +79,9 @@ public class IterationFailureBehaviorTest extends ClusteredTests { + "").build(), of(OutputIs.CLASS_RULE)); - @BeforeClass - public static void waitForActive() throws Exception { + @Before + public void startAllServers() throws Exception { CLUSTER.get().getClusterControl().startAllServers(); - CLUSTER.get().getClusterControl().waitForRunningPassivesInStandby(); } @Test @@ -119,6 +119,7 @@ public void testIteratorFailover() throws Exception { Cache.Entry largeNext = largeIterator.next(); assertThat(largeCache.get(largeNext.getKey()), notNullValue()); + CLUSTER.get().getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.get().getClusterControl().terminateActive(); //large iterator fails @@ -174,10 +175,10 @@ public void testIteratorReconnect() throws Exception { Cache.Entry largeNext = largeIterator.next(); assertThat(largeCache.get(largeNext.getKey()), notNullValue()); + CLUSTER.get().getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.get().getClusterControl().terminateAllServers(); Thread.sleep(CLUSTER.input().multipliedBy(2L).toMillis()); CLUSTER.get().getClusterControl().startAllServers(); - CLUSTER.get().getClusterControl().waitForActive(); //large iterator fails try { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java index 7c4762b6ac..d7b2e6d120 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java @@ -63,12 +63,11 @@ public class JCacheClusteredTest extends ClusteredTests { public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); @BeforeClass - public static void waitForActive() throws Exception { + public static void configureEnvironment() throws Exception { URL xml = CacheManagerLifecycleEhcacheIntegrationTest.class.getResource("/configs/jcache-clustered.xml"); URL substitutedXml = substitute(xml, "cluster-uri", CLUSTER.getConnectionURI().toString()); System.setProperty("ehcache.jsr107.config.default", substitutedXml.toURI().toString()); TCK_PROPERTIES.forEach((k, v) -> System.setProperty(k.toString(), v.toString())); - CLUSTER.getClusterControl().waitForActive(); } @AfterClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java index 4ede97a7e4..e47b3687ae 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java @@ -79,11 +79,6 @@ public class LeaseTest extends ClusteredTests { private final List proxies = new ArrayList<>(); - @BeforeClass - public static void waitForActive() throws Exception { - CLUSTER.get().getClusterControl().waitForActive(); - } - @After public void after() { proxies.forEach(TCPProxy::stop); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java index 7a4a5548be..b6f774702c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -91,8 +91,7 @@ public class ReconnectDuringDestroyTest extends ClusteredTests { of(OutputIs.CLASS_RULE)); @BeforeClass - public static void waitForActive() throws Exception { - CLUSTER.get().getClusterControl().waitForActive(); + public static void initializeProxy() throws Exception { proxies = new ArrayList<>(); connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getConnectionURI(), proxies); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java index 627eb0bead..75173e9007 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java @@ -52,11 +52,6 @@ public class ResourcePoolAllocationFailureTest extends ClusteredTests { public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); - @BeforeClass - public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); - } - @Test public void testTooLowResourceException() throws InterruptedException { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java index fdfe286290..f6e6afbfa3 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java @@ -147,9 +147,8 @@ private ThrowableAssertAlternative assertExceptionOccur public final TestName testName = new TestName(); @Before - public void waitForActive() throws Exception { + public void startAllServers() throws Exception { CLUSTER.get().getClusterControl().startAllServers(); - CLUSTER.get().getClusterControl().waitForActive(); } /** diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java index 9be9c9fd3c..0fbde0ca69 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java @@ -44,11 +44,6 @@ public class VoltronReadWriteLockIntegrationTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = newCluster().in(clusterPath()).build(); - @BeforeClass - public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); - } - @Test public void testSingleThreadSingleClientInteraction() throws Throwable { try (Connection client = CLUSTER.newConnection()) { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java index 44f225b1df..a297868c94 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java @@ -45,9 +45,8 @@ public class VoltronReadWriteLockPassiveIntegrationTest extends ClusteredTests { public final TestName testName = new TestName(); @Before - public void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); + public void startAllServers() throws Exception { + CLUSTER.getClusterControl().startAllServers(); } @Test @@ -57,8 +56,8 @@ public void testSingleThreadSingleClientInteraction() throws Throwable { Hold hold = lock.writeLock(); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); - CLUSTER.getClusterControl().startOneServer(); hold.unlock(); } @@ -83,8 +82,8 @@ public void testMultipleThreadsSingleConnection() throws Throwable { //expected } + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); - CLUSTER.getClusterControl().startOneServer(); try { waiter.get(100, TimeUnit.MILLISECONDS); @@ -119,8 +118,8 @@ public void testMultipleClients() throws Throwable { //expected } + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); - CLUSTER.getClusterControl().startOneServer(); try { waiter.get(100, TimeUnit.MILLISECONDS); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java index f1ce37525d..619efd562a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java @@ -47,11 +47,6 @@ public class EhcacheConfigWithManagementTest extends ClusteredTests { public static Cluster CLUSTER = newCluster().in(clusterPath()) .withServiceFragment(RESOURCE_CONFIG).build(); - @BeforeClass - public static void beforeClass() throws Exception { - CLUSTER.getClusterControl().waitForActive(); - } - @Test public void create_cache_manager() throws Exception { CacheManager cacheManager = newCacheManagerBuilder() diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java index 6bfb47fa3d..d3365ea220 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java @@ -87,9 +87,7 @@ public class BasicCacheReconnectTest extends ClusteredTests { of(OutputIs.CLASS_RULE)); @BeforeClass - public static void waitForActive() throws Exception { - CLUSTER.get().getClusterControl().waitForActive(); - + public static void initializeCacheManager() throws Exception { URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getConnectionURI(), proxies); CacheManagerBuilder clusteredCacheManagerBuilder diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java index 00c606491e..4d91042ed9 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java @@ -66,9 +66,7 @@ public class CacheManagerDestroyReconnectTest extends ClusteredTests { of(OutputIs.CLASS_RULE)); @BeforeClass - public static void waitForActive() throws Exception { - CLUSTER.get().getClusterControl().waitForActive(); - + public static void initializeCacheManager() throws Exception { URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getConnectionURI(), proxies); CacheManagerBuilder clusteredCacheManagerBuilder diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index 34291fe8ab..140b3e5b67 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -122,9 +122,7 @@ final void clear() { of(OutputIs.CLASS_RULE)); @BeforeClass - public static void waitForActive() throws Exception { - CLUSTER.get().getClusterControl().waitForActive(); - + public static void initializeCacheManager() throws Exception { URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getConnectionURI(), proxies); CacheManagerBuilder clusteredCacheManagerBuilder diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index fab61fc79f..169e9d9e17 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -45,6 +45,7 @@ import org.junit.runners.Parameterized.Parameters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.terracotta.utilities.test.WaitForAssert; import java.io.Serializable; import java.time.Duration; @@ -117,8 +118,6 @@ public static Consistency[] data() { @Before public void startServers() throws Exception { CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/crud-cm-replication")) @@ -143,9 +142,6 @@ public void startServers() throws Exception { @After public void tearDown() throws Exception { - CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); - List unprocessed = executorService.shutdownNow(); if(!unprocessed.isEmpty()) { log.warn("Tearing down with {} unprocess task", unprocessed); @@ -178,6 +174,7 @@ public void testCRUD() throws Exception { cache2.get(x); }))); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); drainTasks(futures); @@ -222,6 +219,7 @@ public void testBulkOps() throws Exception { }); })); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); drainTasks(futures); @@ -270,6 +268,7 @@ public void testClear() throws Exception { Future clearFuture = executorService.submit(() -> cache1.clear()); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); clearFuture.get(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java index 97a47c6580..168d67cd37 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java @@ -86,8 +86,6 @@ public static Consistency[] data() { @Before public void startServers() throws Exception { CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/cm-replication")) @@ -128,6 +126,7 @@ public void testCRUD() throws Exception { x.remove(4L); }); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); caches.forEach(x -> { @@ -153,6 +152,7 @@ public void testBulkOps() throws Exception { entriesMap.put(6L, "six"); caches.forEach(cache -> cache.putAll(entriesMap)); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); Set keySet = entriesMap.keySet(); @@ -180,6 +180,7 @@ public void testCAS() throws Exception { assertThat(cache.replace(3L, "another one", "yet another one"), is(false)); }); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); caches.forEach(cache -> { @@ -220,6 +221,7 @@ public void testClear() throws Exception { cacheOne.clear(); cacheTwo.clear(); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); keySet.forEach(x -> assertThat(cacheOne.get(x), nullValue())); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java index d4de272ea6..8296f56718 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java @@ -95,8 +95,6 @@ public static Consistency[] data() { @Before public void startServers() throws Exception { CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/crud-cm-replication")) @@ -137,6 +135,7 @@ public void testCRUD() throws Exception { } }); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); Set readKeysByCache1AfterFailOver = new HashSet<>(); @@ -176,6 +175,7 @@ public void testBulkOps() throws Exception { } }); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); Set readKeysByCache1AfterFailOver = new HashSet<>(); @@ -216,6 +216,7 @@ public void testClear() throws Exception { cache1.clear(); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); if (cacheConsistency == Consistency.STRONG) { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java index fb3985c158..51ebee189f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java @@ -62,8 +62,6 @@ public class BasicClusteredCacheOpsReplicationWithServersApiTest extends Cluster @Before public void setUp() throws Exception { CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() @@ -115,6 +113,7 @@ public void testCRUD() throws Exception { x.remove(4L); }); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); caches.forEach(x -> { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java index cbc8ace0bd..e7a23ccaee 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java @@ -56,13 +56,6 @@ public class BasicLifeCyclePassiveReplicationTest extends ClusteredTests { @Before public void startServers() throws Exception { CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); - } - - @After - public void tearDown() throws Exception { - CLUSTER.getClusterControl().terminateActive(); } @Test @@ -81,8 +74,8 @@ public void testDestroyCacheManager() throws Exception { e.printStackTrace(); } + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); - CLUSTER.getClusterControl().waitForActive(); cacheManager1.createCache("test", newCacheConfigurationBuilder(Long.class, String.class, heap(10).with(clusteredDedicated(10, MB)))); } @@ -95,8 +88,8 @@ public void testDestroyLockEntity() throws Exception { VoltronReadWriteLock lock2 = new VoltronReadWriteLock(CLUSTER.newConnection(), "my-lock"); assertThat(lock2.tryWriteLock(), nullValue()); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); - CLUSTER.getClusterControl().waitForActive(); hold1.unlock(); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java index b6b6dfe015..7f0ccfb7e8 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java @@ -66,8 +66,6 @@ public class DuplicateTest extends ClusteredTests { @Before public void startServers() throws Exception { CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); } @After @@ -113,6 +111,7 @@ public void duplicateAfterFailoverAreReturningTheCorrectResponse() throws Except while (currentEntry.get() < 100); // wait to make sure some entries are added before shutdown // Failover to mirror when put & replication are in progress + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); puts.get(30, TimeUnit.SECONDS); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java index 12b957bf62..2f3997bd6c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java @@ -61,12 +61,6 @@ public class OversizedCacheOpsPassiveTest extends ClusteredTests { .withServiceFragment(RESOURCE_CONFIG) .build(); - @BeforeClass - public static void waitForServers() throws Exception { - CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); - } - @Test public void oversizedPuts() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder @@ -80,10 +74,10 @@ public void oversizedPuts() throws Exception { syncLatch.await(); for (int i = 0; i < MAX_SWITCH_OVER; i++) { + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); CLUSTER.getClusterControl().waitForActive(); CLUSTER.getClusterControl().startOneServer(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); Thread.sleep(2000); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java index d0c48d5808..b96c427e64 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java @@ -56,15 +56,11 @@ public class PassiveSyncTest extends ClusteredTests { @Before public void startServers() throws Exception { - CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); + CLUSTER.getClusterControl().terminateOnePassive(); } @Test(timeout = 150000) public void testSync() throws Exception { - CLUSTER.getClusterControl().terminateOnePassive(); - final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/op-sync")) @@ -86,7 +82,6 @@ public void testSync() throws Exception { CLUSTER.getClusterControl().startOneServer(); CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); - CLUSTER.getClusterControl().waitForActive(); assertThatEventually(() -> cache.get(0L), notNullValue()).within(Duration.ofSeconds(130)); @@ -101,8 +96,6 @@ public void testSync() throws Exception { @Ignore @Test public void testLifeCycleOperationsOnSync() throws Exception { - CLUSTER.getClusterControl().terminateOnePassive(); - final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/lifecycle-sync")) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java index d528c8bfa8..4ed3264dc8 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java @@ -43,7 +43,6 @@ public void setUp() throws Exception { super.setUp(); CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForActive(); cacheManager1 = createCacheManager(CLUSTER.getConnectionURI()); cacheManager2 = createCacheManager(CLUSTER.getConnectionURI()); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java index 0c568970f0..87378678ad 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java @@ -55,7 +55,6 @@ public void setUp() throws Exception { super.setUp(); CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForActive(); cacheManager = createCacheManager(CLUSTER.getConnectionURI()); cache = cacheManager.getCache(testName.getMethodName(), Long.class, String.class); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java index c1e56c4ef7..64f25d21df 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java @@ -43,8 +43,6 @@ public void setUp() throws Exception { super.setUp(); CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); cacheManager1 = createCacheManager(CLUSTER.getConnectionURI()); cacheManager2 = createCacheManager(CLUSTER.getConnectionURI()); @@ -85,8 +83,8 @@ public void testWriteBehindMultipleClients() throws Exception { client2.put(KEY, "The one one from client2"); assertValue(client1, "The one one from client2"); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); - CLUSTER.getClusterControl().waitForActive(); assertValue(client1, "The one one from client2"); assertValue(client2, "The one one from client2"); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java index af1b013371..58026e6df5 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java @@ -45,8 +45,6 @@ public void setUp() throws Exception { super.setUp(); CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForActive(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); cacheManager = createCacheManager(CLUSTER.getConnectionURI()); cache = cacheManager.getCache(testName.getMethodName(), Long.class, String.class); @@ -67,8 +65,8 @@ public void testBasicClusteredWriteBehind() throws Exception { assertValue(cache, "9"); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); - CLUSTER.getClusterControl().waitForActive(); assertValue(cache, "9"); checkValueFromLoaderWriter(cache, String.valueOf(9)); @@ -95,8 +93,8 @@ public void testClusteredWriteBehindCAS() throws Exception { cache.put(KEY, "new value"); assertValue(cache, "new value"); + CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); - CLUSTER.getClusterControl().waitForActive(); assertValue(cache, "new value"); checkValueFromLoaderWriter(cache,"new value"); From 957f2265caa6e769eb938a0122488b69740dda06 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 9 Apr 2020 14:10:36 -0400 Subject: [PATCH 243/372] Cleanup a bunch of memory and connection leaks. --- build.gradle | 8 +- .../ClusteredResourcePoolUpdationTest.java | 10 +- .../client/BasicClusteredCacheExpiryTest.java | 67 +++--- .../client/BasicClusteredCacheTest.java | 145 ++++++------ .../client/CacheManagerDestroyTest.java | 77 ++++--- .../client/ClusteredCacheDestroyTest.java | 149 ++++++------ .../client/ClusteredConcurrencyTest.java | 2 +- .../clustered/client/EntityServiceTest.java | 43 ++-- .../client/NonClusteredCacheTest.java | 10 +- ...tedCombinationsWithClusteredCacheTest.java | 8 +- .../clustered/client/docs/GettingStarted.java | 52 ++--- ...terTierManagerClientEntityFactoryTest.java | 4 +- .../internal/UnitTestConnectionService.java | 45 ++-- ...ClusterStateRepositoryReplicationTest.java | 90 ++++---- .../service/ConnectionClosedTest.java | 27 ++- .../internal/service/ConnectionStateTest.java | 4 +- .../store/ClusteredStoreEventsTest.java | 2 +- .../internal/store/ClusteredStoreTest.java | 2 +- .../store/CommonServerStoreProxyTest.java | 17 +- .../store/EventualServerStoreProxyTest.java | 17 +- ...ltiThreadedStrongServerStoreProxyTest.java | 6 +- .../store/StrongServerStoreProxyTest.java | 26 ++- .../lock/LockRetentionDuringFailoverTest.java | 11 +- .../BasicClusteredLoaderWriterTest.java | 212 +++++++++--------- .../BasicCacheOpsMultiThreadedTest.java | 2 - .../clustered/EventsFailureBehaviorTest.java | 2 - .../clustered/JCacheClusteredTest.java | 10 +- .../java/org/ehcache/osgi/OsgiTestUtils.java | 1 + .../state/EhcacheStateServiceProvider.java | 9 +- .../store/disk/OffHeapDiskStoreSPITest.java | 2 + .../ByteSizedOnHeapStoreByRefSPITest.java | 2 + .../ByteSizedOnHeapStoreByValueSPITest.java | 3 + .../store/heap/OnHeapStoreByRefSPITest.java | 2 + .../store/heap/OnHeapStoreByValueSPITest.java | 3 + .../offheap/OffHeapStoreLifecycleHelper.java | 3 + .../store/offheap/OffHeapStoreSPITest.java | 3 + .../store/offheap/OffHeapStoreTest.java | 2 + transactions/build.gradle | 1 + .../offheap/OffHeapStoreLifecycleHelper.java | 3 + 39 files changed, 566 insertions(+), 516 deletions(-) diff --git a/build.gradle b/build.gradle index f649d3576c..1d6fa0fc5e 100644 --- a/build.gradle +++ b/build.gradle @@ -68,7 +68,6 @@ ext { utils = new Utils(baseVersion, logger) isReleaseVersion = !baseVersion.endsWith('SNAPSHOT') - isCloudbees = System.getenv('JENKINS_URL')?.contains('cloudbees') } @@ -145,11 +144,6 @@ subprojects { } test { - maxHeapSize = "1408m" - systemProperty 'java.awt.headless', 'true' - if (parent.isCloudbees) { - systemProperty 'disable.concurrent.tests', 'true' - } jacoco { excludes += "org.terracotta.tripwire.*" } @@ -226,7 +220,9 @@ subprojects { } tasks.withType(Test) { executable = testJava.javaExecutable + maxHeapSize = "256m" maxParallelForks 64 + systemProperty 'java.awt.headless', 'true' } tasks.withType(Javadoc) { options.addStringOption('Xdoclint:none', '-quiet') diff --git a/clustered/client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java index 1509ff8c70..5f2ce743b0 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java @@ -72,8 +72,14 @@ public static void setUp() throws Exception { @AfterClass public static void tearDown() throws Exception { - cacheManager.close(); - UnitTestConnectionService.remove(CLUSTER_URI); + try { + cacheManager.close(); + UnitTestConnectionService.remove(CLUSTER_URI); + } finally { + cacheManager = null; + dedicatedCache = null; + sharedCache = null; + } } @Test diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java index aad2ca8b25..a883387e98 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java @@ -79,19 +79,17 @@ public void testGetExpiredSingleClient() { final CacheManagerBuilder clusteredCacheManagerBuilder = commonClusteredCacheManagerBuilder.using(timeSourceConfiguration); - final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); + try (PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true)) { - final Cache cache = cacheManager.getCache("clustered-cache", Long.class, String.class); + final Cache cache = cacheManager.getCache("clustered-cache", Long.class, String.class); - cache.put(1L, "value"); - assertThat(cache.get(1L), is("value")); + cache.put(1L, "value"); + assertThat(cache.get(1L), is("value")); - timeSource.advanceTime(1); - - assertThat(cache.get(1L), nullValue()); - - cacheManager.close(); + timeSource.advanceTime(1); + assertThat(cache.get(1L), nullValue()); + } } @Test @@ -103,22 +101,21 @@ public void testGetExpiredTwoClients() { final CacheManagerBuilder clusteredCacheManagerBuilder = commonClusteredCacheManagerBuilder.using(timeSourceConfiguration); - final PersistentCacheManager cacheManager1 = clusteredCacheManagerBuilder.build(true); - final PersistentCacheManager cacheManager2 = clusteredCacheManagerBuilder.build(true); - - final Cache cache1 = cacheManager1.getCache("clustered-cache", Long.class, String.class); - final Cache cache2 = cacheManager2.getCache("clustered-cache", Long.class, String.class); + try (PersistentCacheManager cacheManager1 = clusteredCacheManagerBuilder.build(true)) { + try (PersistentCacheManager cacheManager2 = clusteredCacheManagerBuilder.build(true)) { - assertThat(cache2.get(1L), nullValue()); - cache1.put(1L, "value1"); - assertThat(cache1.get(1L), is("value1")); - timeSource.advanceTime(1L); + final Cache cache1 = cacheManager1.getCache("clustered-cache", Long.class, String.class); + final Cache cache2 = cacheManager2.getCache("clustered-cache", Long.class, String.class); - assertThat(cache2.get(1L), nullValue()); - assertThat(cache1.get(1L), nullValue()); + assertThat(cache2.get(1L), nullValue()); + cache1.put(1L, "value1"); + assertThat(cache1.get(1L), is("value1")); + timeSource.advanceTime(1L); - cacheManager2.close(); - cacheManager1.close(); + assertThat(cache2.get(1L), nullValue()); + assertThat(cache1.get(1L), nullValue()); + } + } } @Test @@ -130,23 +127,21 @@ public void testContainsKeyExpiredTwoClients() { final CacheManagerBuilder clusteredCacheManagerBuilder = commonClusteredCacheManagerBuilder.using(timeSourceConfiguration); - final PersistentCacheManager cacheManager1 = clusteredCacheManagerBuilder.build(true); - final PersistentCacheManager cacheManager2 = clusteredCacheManagerBuilder.build(true); - - final Cache cache1 = cacheManager1.getCache("clustered-cache", Long.class, String.class); - final Cache cache2 = cacheManager2.getCache("clustered-cache", Long.class, String.class); - - assertThat(cache2.get(1L), nullValue()); - cache1.put(1L, "value1"); - assertThat(cache1.containsKey(1L), is(true)); - timeSource.advanceTime(1L); + try (PersistentCacheManager cacheManager1 = clusteredCacheManagerBuilder.build(true)) { + try (PersistentCacheManager cacheManager2 = clusteredCacheManagerBuilder.build(true)) { - assertThat(cache1.containsKey(1L), is(false)); - assertThat(cache2.containsKey(1L), is(false)); + final Cache cache1 = cacheManager1.getCache("clustered-cache", Long.class, String.class); + final Cache cache2 = cacheManager2.getCache("clustered-cache", Long.class, String.class); - cacheManager2.close(); - cacheManager1.close(); + assertThat(cache2.get(1L), nullValue()); + cache1.put(1L, "value1"); + assertThat(cache1.containsKey(1L), is(true)); + timeSource.advanceTime(1L); + assertThat(cache1.containsKey(1L), is(false)); + assertThat(cache2.containsKey(1L), is(false)); + } + } } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java index 7cbdd6315a..f51c75ca8d 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java @@ -76,14 +76,13 @@ public void testClusteredCacheSingleClient() throws Exception { .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB)))); - final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); + try (PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true)) { - final Cache cache = cacheManager.getCache("clustered-cache", Long.class, String.class); + final Cache cache = cacheManager.getCache("clustered-cache", Long.class, String.class); - cache.put(1L, "value"); - assertThat(cache.get(1L), is("value")); - - cacheManager.close(); + cache.put(1L, "value"); + assertThat(cache.get(1L), is("value")); + } } @Test @@ -96,22 +95,21 @@ public void testClusteredCacheTwoClients() throws Exception { .with(clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) .withService(new ClusteredStoreConfiguration(Consistency.STRONG))); - final PersistentCacheManager cacheManager1 = clusteredCacheManagerBuilder.build(true); - final PersistentCacheManager cacheManager2 = clusteredCacheManagerBuilder.build(true); + try (PersistentCacheManager cacheManager1 = clusteredCacheManagerBuilder.build(true)) { + try (PersistentCacheManager cacheManager2 = clusteredCacheManagerBuilder.build(true)) { - final Cache cache1 = cacheManager1.getCache("clustered-cache", Long.class, String.class); - final Cache cache2 = cacheManager2.getCache("clustered-cache", Long.class, String.class); + final Cache cache1 = cacheManager1.getCache("clustered-cache", Long.class, String.class); + final Cache cache2 = cacheManager2.getCache("clustered-cache", Long.class, String.class); - assertThat(cache2.get(1L), nullValue()); - cache1.put(1L, "value1"); - assertThat(cache2.get(1L), is("value1")); - assertThat(cache1.get(1L), is("value1")); - cache1.put(1L, "value2"); - assertThat(cache2.get(1L), is("value2")); - assertThat(cache1.get(1L), is("value2")); - - cacheManager2.close(); - cacheManager1.close(); + assertThat(cache2.get(1L), nullValue()); + cache1.put(1L, "value1"); + assertThat(cache2.get(1L), is("value1")); + assertThat(cache1.get(1L), is("value1")); + cache1.put(1L, "value2"); + assertThat(cache2.get(1L), is("value2")); + assertThat(cache1.get(1L), is("value2")); + } + } } @Test @@ -124,46 +122,45 @@ public void testClustered3TierCacheTwoClients() throws Exception { .with(clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) .withService(new ClusteredStoreConfiguration(Consistency.STRONG))); - final PersistentCacheManager cacheManager1 = clusteredCacheManagerBuilder.build(true); - final PersistentCacheManager cacheManager2 = clusteredCacheManagerBuilder.build(true); - - final Cache cache1 = cacheManager1.getCache("clustered-cache", Long.class, String.class); - final Cache cache2 = cacheManager2.getCache("clustered-cache", Long.class, String.class); - - assertThat(cache2.get(1L), nullValue()); - cache1.put(1L, "value1"); - cache1.put(2L, "value2"); - cache1.put(3L, "value3"); - assertThat(cache2.get(1L), is("value1")); - assertThat(cache2.get(2L), is("value2")); - assertThat(cache2.get(3L), is("value3")); - assertThat(cache2.get(1L), is("value1")); - assertThat(cache2.get(2L), is("value2")); - assertThat(cache2.get(3L), is("value3")); - assertThat(cache1.get(1L), is("value1")); - assertThat(cache1.get(2L), is("value2")); - assertThat(cache1.get(3L), is("value3")); - assertThat(cache1.get(1L), is("value1")); - assertThat(cache1.get(2L), is("value2")); - assertThat(cache1.get(3L), is("value3")); - cache1.put(1L, "value11"); - cache1.put(2L, "value12"); - cache1.put(3L, "value13"); - assertThat(cache2.get(1L), is("value11")); - assertThat(cache2.get(2L), is("value12")); - assertThat(cache2.get(3L), is("value13")); - assertThat(cache2.get(1L), is("value11")); - assertThat(cache2.get(2L), is("value12")); - assertThat(cache2.get(3L), is("value13")); - assertThat(cache1.get(1L), is("value11")); - assertThat(cache1.get(2L), is("value12")); - assertThat(cache1.get(3L), is("value13")); - assertThat(cache1.get(1L), is("value11")); - assertThat(cache1.get(2L), is("value12")); - assertThat(cache1.get(3L), is("value13")); - - cacheManager2.close(); - cacheManager1.close(); + try (PersistentCacheManager cacheManager1 = clusteredCacheManagerBuilder.build(true)) { + try (PersistentCacheManager cacheManager2 = clusteredCacheManagerBuilder.build(true)) { + + final Cache cache1 = cacheManager1.getCache("clustered-cache", Long.class, String.class); + final Cache cache2 = cacheManager2.getCache("clustered-cache", Long.class, String.class); + + assertThat(cache2.get(1L), nullValue()); + cache1.put(1L, "value1"); + cache1.put(2L, "value2"); + cache1.put(3L, "value3"); + assertThat(cache2.get(1L), is("value1")); + assertThat(cache2.get(2L), is("value2")); + assertThat(cache2.get(3L), is("value3")); + assertThat(cache2.get(1L), is("value1")); + assertThat(cache2.get(2L), is("value2")); + assertThat(cache2.get(3L), is("value3")); + assertThat(cache1.get(1L), is("value1")); + assertThat(cache1.get(2L), is("value2")); + assertThat(cache1.get(3L), is("value3")); + assertThat(cache1.get(1L), is("value1")); + assertThat(cache1.get(2L), is("value2")); + assertThat(cache1.get(3L), is("value3")); + cache1.put(1L, "value11"); + cache1.put(2L, "value12"); + cache1.put(3L, "value13"); + assertThat(cache2.get(1L), is("value11")); + assertThat(cache2.get(2L), is("value12")); + assertThat(cache2.get(3L), is("value13")); + assertThat(cache2.get(1L), is("value11")); + assertThat(cache2.get(2L), is("value12")); + assertThat(cache2.get(3L), is("value13")); + assertThat(cache1.get(1L), is("value11")); + assertThat(cache1.get(2L), is("value12")); + assertThat(cache1.get(3L), is("value13")); + assertThat(cache1.get(1L), is("value11")); + assertThat(cache1.get(2L), is("value12")); + assertThat(cache1.get(3L), is("value13")); + } + } } @Test @@ -174,14 +171,13 @@ public void testTieredClusteredCache() throws Exception { .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, heap(2) .with(clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB)))); - final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); + try (PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true)) { - final Cache cache = cacheManager.getCache("clustered-cache", Long.class, String.class); + final Cache cache = cacheManager.getCache("clustered-cache", Long.class, String.class); - cache.put(1L, "value"); - assertThat(cache.get(1L), is("value")); - - cacheManager.close(); + cache.put(1L, "value"); + assertThat(cache.get(1L), is("value")); + } } @Test @@ -190,18 +186,17 @@ public void testClusteredCacheWithSerializableValue() throws Exception { newCacheManagerBuilder().with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, Person.class, newResourcePoolsBuilder().with(clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB)))); - PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); - - Cache cache = cacheManager.getCache("clustered-cache", Long.class, Person.class); + try (PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true)) { + Cache cache = cacheManager.getCache("clustered-cache", Long.class, Person.class); - cache.put(38L, new Person("Clustered Joe", 28)); - - cacheManager.close(); + cache.put(38L, new Person("Clustered Joe", 28)); + } - cacheManager = clusteredCacheManagerBuilder.build(true); - cache = cacheManager.getCache("clustered-cache", Long.class, Person.class); + try (PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true)) { + Cache cache = cacheManager.getCache("clustered-cache", Long.class, Person.class); - assertThat(cache.get(38L).name, is("Clustered Joe")); + assertThat(cache.get(38L).name, is("Clustered Joe")); + } } @Test diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java index 3fb323beff..a46bb39da2 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java @@ -84,35 +84,36 @@ public void testCreateDestroyCreate() throws Exception { cacheManager.destroy(); cacheManager.init(); + + cacheManager.close(); } @Test public void testDestroyCacheManagerWithMultipleClients() throws CachePersistenceException { PersistentCacheManager persistentCacheManager1 = clusteredCacheManagerBuilder.build(true); - PersistentCacheManager persistentCacheManager2 = clusteredCacheManagerBuilder.build(true); + try (PersistentCacheManager persistentCacheManager2 = clusteredCacheManagerBuilder.build(true)) { - persistentCacheManager1.close(); + persistentCacheManager1.close(); - try { - persistentCacheManager1.destroy(); - fail("StateTransitionException expected"); - } catch (StateTransitionException e) { - assertThat(e.getMessage(), is("Couldn't acquire cluster-wide maintenance lease")); - } + try { + persistentCacheManager1.destroy(); + fail("StateTransitionException expected"); + } catch (StateTransitionException e) { + assertThat(e.getMessage(), is("Couldn't acquire cluster-wide maintenance lease")); + } - assertThat(persistentCacheManager1.getStatus(), is(Status.UNINITIALIZED)); + assertThat(persistentCacheManager1.getStatus(), is(Status.UNINITIALIZED)); - assertThat(persistentCacheManager2.getStatus(), is(Status.AVAILABLE)); + assertThat(persistentCacheManager2.getStatus(), is(Status.AVAILABLE)); - Cache cache = persistentCacheManager2.createCache("test", newCacheConfigurationBuilder(Long.class, String.class, + Cache cache = persistentCacheManager2.createCache("test", newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() - .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB)))); - - cache.put(1L, "One"); + .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB)))); - assertThat(cache.get(1L), is("One")); + cache.put(1L, "One"); - persistentCacheManager2.close(); + assertThat(cache.get(1L), is("One")); + } } @Test @@ -124,23 +125,22 @@ public void testDestroyCacheManagerDoesNotAffectsExistingCacheWithExistingClient .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB)))); PersistentCacheManager persistentCacheManager1 = cacheManagerBuilder.build(true); - PersistentCacheManager persistentCacheManager2 = cacheManagerBuilder.build(true); - - persistentCacheManager1.close(); - try { - persistentCacheManager1.destroy(); - fail("StateTransitionException expected"); - } catch (StateTransitionException e) { - assertThat(e.getMessage(), is("Couldn't acquire cluster-wide maintenance lease")); - } + try (PersistentCacheManager persistentCacheManager2 = cacheManagerBuilder.build(true)) { - Cache cache = persistentCacheManager2.getCache("test", Long.class, String.class); + persistentCacheManager1.close(); + try { + persistentCacheManager1.destroy(); + fail("StateTransitionException expected"); + } catch (StateTransitionException e) { + assertThat(e.getMessage(), is("Couldn't acquire cluster-wide maintenance lease")); + } - cache.put(1L, "One"); + Cache cache = persistentCacheManager2.getCache("test", Long.class, String.class); - assertThat(cache.get(1L), is("One")); + cache.put(1L, "One"); - persistentCacheManager2.close(); + assertThat(cache.get(1L), is("One")); + } } @Test @@ -172,21 +172,20 @@ public void testCloseCacheManagerMultipleClients() { .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB)))); PersistentCacheManager persistentCacheManager1 = cacheManagerBuilder.build(true); - PersistentCacheManager persistentCacheManager2 = cacheManagerBuilder.build(true); - - Cache cache = persistentCacheManager1.getCache("test", Long.class, String.class); - cache.put(1L, "One"); + try (PersistentCacheManager persistentCacheManager2 = cacheManagerBuilder.build(true)) { - assertThat(cache.get(1L), is("One")); + Cache cache = persistentCacheManager1.getCache("test", Long.class, String.class); + cache.put(1L, "One"); - persistentCacheManager1.close(); - assertThat(persistentCacheManager1.getStatus(), is(Status.UNINITIALIZED)); + assertThat(cache.get(1L), is("One")); - Cache cache2 = persistentCacheManager2.getCache("test", Long.class, String.class); + persistentCacheManager1.close(); + assertThat(persistentCacheManager1.getStatus(), is(Status.UNINITIALIZED)); - assertThat(cache2.get(1L), is("One")); + Cache cache2 = persistentCacheManager2.getCache("test", Long.class, String.class); - persistentCacheManager2.close(); + assertThat(cache2.get(1L), is("One")); + } } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java index 808cd71982..224db1b73a 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java @@ -79,108 +79,97 @@ public void removePassthroughServer() throws Exception { @Test public void testDestroyCacheWhenSingleClientIsConnected() throws CachePersistenceException { - PersistentCacheManager persistentCacheManager = clusteredCacheManagerBuilder.build(true); - - persistentCacheManager.destroyCache(CLUSTERED_CACHE); + try (PersistentCacheManager persistentCacheManager = clusteredCacheManagerBuilder.build(true)) { - final Cache cache = persistentCacheManager.getCache(CLUSTERED_CACHE, Long.class, String.class); + persistentCacheManager.destroyCache(CLUSTERED_CACHE); - assertThat(cache, nullValue()); + final Cache cache = persistentCacheManager.getCache(CLUSTERED_CACHE, Long.class, String.class); - persistentCacheManager.close(); + assertThat(cache, nullValue()); + } } @Test public void testDestroyFreesUpTheAllocatedResource() throws CachePersistenceException { + try (PersistentCacheManager persistentCacheManager = clusteredCacheManagerBuilder.build(true)) { - PersistentCacheManager persistentCacheManager = clusteredCacheManagerBuilder.build(true); - - CacheConfigurationBuilder configBuilder = newCacheConfigurationBuilder(Long.class, String.class, + CacheConfigurationBuilder configBuilder = newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() - .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 10, MemoryUnit.MB))); + .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 10, MemoryUnit.MB))); - try { - Cache anotherCache = persistentCacheManager.createCache("another-cache", configBuilder); - fail(); - } catch (IllegalStateException e) { - assertThat(e.getMessage(), is("Cache 'another-cache' creation in EhcacheManager failed.")); - } + try { + Cache anotherCache = persistentCacheManager.createCache("another-cache", configBuilder); + fail(); + } catch (IllegalStateException e) { + assertThat(e.getMessage(), is("Cache 'another-cache' creation in EhcacheManager failed.")); + } - persistentCacheManager.destroyCache(CLUSTERED_CACHE); - - Cache anotherCache = persistentCacheManager.createCache("another-cache", configBuilder); + persistentCacheManager.destroyCache(CLUSTERED_CACHE); - anotherCache.put(1L, "One"); - assertThat(anotherCache.get(1L), is("One")); + Cache anotherCache = persistentCacheManager.createCache("another-cache", configBuilder); - persistentCacheManager.close(); + anotherCache.put(1L, "One"); + assertThat(anotherCache.get(1L), is("One")); + } } @Test public void testDestroyUnknownCacheAlias() throws Exception { clusteredCacheManagerBuilder.build(true).close(); - PersistentCacheManager cacheManager = newCacheManagerBuilder().with(cluster(CLUSTER_URI).expecting(c -> c)).build(true); + try (PersistentCacheManager cacheManager = newCacheManagerBuilder().with(cluster(CLUSTER_URI).expecting(c -> c)).build(true)) { - cacheManager.destroyCache(CLUSTERED_CACHE); + cacheManager.destroyCache(CLUSTERED_CACHE); - try { - cacheManager.createCache(CLUSTERED_CACHE, newCacheConfigurationBuilder(Long.class, String.class, newResourcePoolsBuilder() + try { + cacheManager.createCache(CLUSTERED_CACHE, newCacheConfigurationBuilder(Long.class, String.class, newResourcePoolsBuilder() .with(clustered()))); - fail("Expected exception as clustered store no longer exists"); - } catch (IllegalStateException e) { - assertThat(e.getMessage(), containsString(CLUSTERED_CACHE)); + fail("Expected exception as clustered store no longer exists"); + } catch (IllegalStateException e) { + assertThat(e.getMessage(), containsString(CLUSTERED_CACHE)); + } } - cacheManager.close(); } @Test public void testDestroyNonExistentCache() throws CachePersistenceException { - PersistentCacheManager persistentCacheManager = clusteredCacheManagerBuilder.build(true); + try (PersistentCacheManager persistentCacheManager = clusteredCacheManagerBuilder.build(true)) { - String nonExistent = "this-is-not-the-cache-you-are-looking-for"; - assertThat(persistentCacheManager.getCache(nonExistent, Long.class, String.class), nullValue()); - persistentCacheManager.destroyCache(nonExistent); - persistentCacheManager.close(); + String nonExistent = "this-is-not-the-cache-you-are-looking-for"; + assertThat(persistentCacheManager.getCache(nonExistent, Long.class, String.class), nullValue()); + persistentCacheManager.destroyCache(nonExistent); + } } @Test public void testDestroyCacheWhenMultipleClientsConnected() { - PersistentCacheManager persistentCacheManager1 = clusteredCacheManagerBuilder.build(true); - PersistentCacheManager persistentCacheManager2 = clusteredCacheManagerBuilder.build(true); + try (PersistentCacheManager persistentCacheManager1 = clusteredCacheManagerBuilder.build(true)) { + try (PersistentCacheManager persistentCacheManager2 = clusteredCacheManagerBuilder.build(true)) { - final Cache cache1 = persistentCacheManager1.getCache(CLUSTERED_CACHE, Long.class, String.class); + final Cache cache1 = persistentCacheManager1.getCache(CLUSTERED_CACHE, Long.class, String.class); - final Cache cache2 = persistentCacheManager2.getCache(CLUSTERED_CACHE, Long.class, String.class); + final Cache cache2 = persistentCacheManager2.getCache(CLUSTERED_CACHE, Long.class, String.class); - try { - persistentCacheManager1.destroyCache(CLUSTERED_CACHE); - fail(); - } catch (CachePersistenceException e) { - assertThat(e.getMessage(), containsString("Cannot destroy cluster tier")); - } - - try { - cache1.put(1L, "One"); - } catch (IllegalStateException e) { - assertThat(e.getMessage(), is("State is UNINITIALIZED")); - } + try { + persistentCacheManager1.destroyCache(CLUSTERED_CACHE); + fail(); + } catch (CachePersistenceException e) { + assertThat(e.getMessage(), containsString("Cannot destroy cluster tier")); + } - assertThat(cache2.get(1L), nullValue()); + try { + cache1.put(1L, "One"); + } catch (IllegalStateException e) { + assertThat(e.getMessage(), is("State is UNINITIALIZED")); + } - cache2.put(1L, "One"); + assertThat(cache2.get(1L), nullValue()); - assertThat(cache2.get(1L), is("One")); + cache2.put(1L, "One"); - persistentCacheManager1.close(); - persistentCacheManager2.close(); - } - - private static Throwable getRootCause(Throwable t) { - if (t.getCause() == null || t.getCause() == t) { - return t; + assertThat(cache2.get(1L), is("One")); + } } - return getRootCause(t.getCause()); } @Test @@ -208,34 +197,36 @@ public void testDestroyCacheOnNonExistentCacheManager() throws CachePersistenceE persistentCacheManager.destroyCache("this-is-not-the-cache-you-are-looking-for"); assertThat(persistentCacheManager.getStatus(), is(Status.UNINITIALIZED)); } + @Test + @SuppressWarnings("try") public void testDestroyCacheWithTwoCacheManagerOnSameCache_forbiddenWhenInUse() throws CachePersistenceException { - PersistentCacheManager persistentCacheManager1 = clusteredCacheManagerBuilder.build(true); - PersistentCacheManager persistentCacheManager2 = clusteredCacheManagerBuilder.build(true); - - expectedException.expect(CachePersistenceException.class); - expectedException.expectMessage("Cannot destroy cluster tier 'clustered-cache': in use by other client(s)"); - persistentCacheManager1.destroyCache(CLUSTERED_CACHE); + try (PersistentCacheManager persistentCacheManager1 = clusteredCacheManagerBuilder.build(true)) { + try (PersistentCacheManager persistentCacheManager2 = clusteredCacheManagerBuilder.build(true)) { + expectedException.expect(CachePersistenceException.class); + expectedException.expectMessage("Cannot destroy cluster tier 'clustered-cache': in use by other client(s)"); + persistentCacheManager1.destroyCache(CLUSTERED_CACHE); + } + } } @Test public void testDestroyCacheWithTwoCacheManagerOnSameCache_firstRemovesSecondDestroy() throws CachePersistenceException { - PersistentCacheManager persistentCacheManager1 = clusteredCacheManagerBuilder.build(true); - PersistentCacheManager persistentCacheManager2 = clusteredCacheManagerBuilder.build(true); - - persistentCacheManager2.removeCache(CLUSTERED_CACHE); - - persistentCacheManager1.destroyCache(CLUSTERED_CACHE); + try (PersistentCacheManager persistentCacheManager1 = clusteredCacheManagerBuilder.build(true)) { + try (PersistentCacheManager persistentCacheManager2 = clusteredCacheManagerBuilder.build(true)) { + persistentCacheManager2.removeCache(CLUSTERED_CACHE); + persistentCacheManager1.destroyCache(CLUSTERED_CACHE); + } + } } @Test public void testDestroyCacheWithTwoCacheManagerOnSameCache_secondDoesntHaveTheCacheButPreventExclusiveAccessToCluster() throws CachePersistenceException { PersistentCacheManager persistentCacheManager1 = clusteredCacheManagerBuilder.build(false); - PersistentCacheManager persistentCacheManager2 = clusteredCacheManagerBuilder.build(true); - - persistentCacheManager2.removeCache(CLUSTERED_CACHE); - - persistentCacheManager1.destroyCache(CLUSTERED_CACHE); + try (PersistentCacheManager persistentCacheManager2 = clusteredCacheManagerBuilder.build(true)) { + persistentCacheManager2.removeCache(CLUSTERED_CACHE); + persistentCacheManager1.destroyCache(CLUSTERED_CACHE); + } } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java index 8a015d870a..ea4d8952f3 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java @@ -110,7 +110,7 @@ private Runnable content(final CountDownLatch latch) { // continue } - clusteredCacheManagerBuilder.build(true); + clusteredCacheManagerBuilder.build(true).close(); } catch (Throwable t) { exception.compareAndSet(null, t); // only keep the first exception } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java index 5e4002f84d..f52553467b 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java @@ -58,41 +58,40 @@ public void removePassthroughServer() throws Exception { UnitTestConnectionService.remove(CLUSTER_URI); } - @Test + @Test @SuppressWarnings("try") public void test() throws Exception { ClusteredManagementService clusteredManagementService = new ClusteredManagementService(); - CacheManager cacheManager = newCacheManagerBuilder() + try (CacheManager cacheManager = newCacheManagerBuilder() .using(clusteredManagementService) .with(cluster(CLUSTER_URI).autoCreate(c -> c)) - .build(true); + .build(true)) { - assertThat(clusteredManagementService.clientEntityFactory, is(notNullValue())); + assertThat(clusteredManagementService.clientEntityFactory, is(notNullValue())); - clusteredManagementService.clientEntityFactory.create(); - - try { clusteredManagementService.clientEntityFactory.create(); - fail(); - } catch (Exception e) { - assertThat(e, instanceOf(EntityAlreadyExistsException.class)); - } - VoltronReadWriteLockClient entity = clusteredManagementService.clientEntityFactory.retrieve(); - assertThat(entity, is(notNullValue())); + try { + clusteredManagementService.clientEntityFactory.create(); + fail(); + } catch (Exception e) { + assertThat(e, instanceOf(EntityAlreadyExistsException.class)); + } - try { - clusteredManagementService.clientEntityFactory.destroy(); - fail(); - } catch (Exception e) { - assertThat(e, instanceOf(EntityBusyException.class)); - } + VoltronReadWriteLockClient entity = clusteredManagementService.clientEntityFactory.retrieve(); + assertThat(entity, is(notNullValue())); - entity.close(); + try { + clusteredManagementService.clientEntityFactory.destroy(); + fail(); + } catch (Exception e) { + assertThat(e, instanceOf(EntityBusyException.class)); + } - clusteredManagementService.clientEntityFactory.destroy(); + entity.close(); - cacheManager.close(); + clusteredManagementService.clientEntityFactory.destroy(); + } } @ServiceDependencies(EntityService.class) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java index 4f7df21b3c..b57236f2ae 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java @@ -61,11 +61,9 @@ public void testNonClustered() throws Exception { .build(); - CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(true); - - cacheManager.createCache("cache-1", cacheConfiguration); - cacheManager.createCache("cache-2", cacheConfiguration); - - cacheManager.close(); + try (CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(true)) { + cacheManager.createCache("cache-1", cacheConfiguration); + cacheManager.createCache("cache-2", cacheConfiguration); + } } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java index fb172717bf..600d1c3465 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java @@ -77,9 +77,7 @@ public void testClusteredCacheWithSynchronousEventListeners() { = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) .autoCreate(c -> c)); - final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); - - try { + try (PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true)) { CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) @@ -91,7 +89,6 @@ public void testClusteredCacheWithSynchronousEventListeners() { } catch (IllegalStateException e){ assertThat(e.getCause().getMessage(), is("Synchronous CacheEventListener is not supported with clustered tiers")); } - cacheManager.close(); } @Test @@ -101,7 +98,6 @@ public void testClusteredCacheWithXA() throws Exception { BitronixTransactionManager transactionManager = TransactionManagerServices.getTransactionManager(); - PersistentCacheManager persistentCacheManager = null; try { CacheManagerBuilder.newCacheManagerBuilder() .using(new LookupTransactionManagerProviderConfiguration(BitronixTransactionManagerLookup.class)) @@ -113,7 +109,7 @@ public void testClusteredCacheWithXA() throws Exception { .withService(new XAStoreConfiguration("xaCache")) .build() ) - .build(true); + .build(true).close(); } catch (StateTransitionException e) { assertThat(e.getCause().getCause().getMessage(), is("Unsupported resource type : interface org.ehcache.clustered.client.config.DedicatedClusteredResourcePool")); } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java index 2a7e7b73e3..7f7ef7b0ee 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java @@ -229,35 +229,37 @@ public void unknownClusteredCacheExample() PersistentCacheManager cacheManager1 = cacheManagerBuilderAutoCreate.build(false); cacheManager1.init(); + try { + CacheConfiguration cacheConfigDedicated = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, + ResourcePoolsBuilder.newResourcePoolsBuilder() + .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) // <2> + .withService(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG)) + .build(); - CacheConfiguration cacheConfigDedicated = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, - ResourcePoolsBuilder.newResourcePoolsBuilder() - .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) // <2> - .withService(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG)) - .build(); - - Cache cacheDedicated = cacheManager1.createCache("my-dedicated-cache", cacheConfigDedicated); // <3> - - CacheManagerBuilder cacheManagerBuilderExpecting = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) - .expecting(server -> server // <4> - .resourcePool("resource-pool", 8, MemoryUnit.MB, "primary-server-resource"))); - - PersistentCacheManager cacheManager2 = cacheManagerBuilderExpecting.build(false); - cacheManager2.init(); + Cache cacheDedicated = cacheManager1.createCache("my-dedicated-cache", cacheConfigDedicated); // <3> - CacheConfiguration cacheConfigUnspecified = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, - ResourcePoolsBuilder.newResourcePoolsBuilder() - .with(ClusteredResourcePoolBuilder.clustered())) // <5> - .withService(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG)) - .build(); + CacheManagerBuilder cacheManagerBuilderExpecting = CacheManagerBuilder.newCacheManagerBuilder() + .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) + .expecting(server -> server // <4> + .resourcePool("resource-pool", 8, MemoryUnit.MB, "primary-server-resource"))); - Cache cacheUnspecified = cacheManager2.createCache("my-dedicated-cache", cacheConfigUnspecified); // <6> + PersistentCacheManager cacheManager2 = cacheManagerBuilderExpecting.build(false); + cacheManager2.init(); + try { + CacheConfiguration cacheConfigUnspecified = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, + ResourcePoolsBuilder.newResourcePoolsBuilder() + .with(ClusteredResourcePoolBuilder.clustered())) // <5> + .withService(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG)) + .build(); + Cache cacheUnspecified = cacheManager2.createCache("my-dedicated-cache", cacheConfigUnspecified); // <6> + } finally { + cacheManager2.close(); + } + } finally { + cacheManager1.close(); + } // end::unspecifiedClusteredCacheExample[] - - cacheManager1.close(); - cacheManager2.close(); - } + } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java index 81084e56a1..f2cc7ee340 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java @@ -127,7 +127,7 @@ public void testRetrieveFailedValidate() throws Exception { ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection, Runnable::run); try { - factory.retrieve("test", null); + factory.retrieve("test", null).close(); fail("Expecting IllegalArgumentException"); } catch (IllegalArgumentException e) { // expected @@ -147,7 +147,7 @@ public void testRetrieveWhenNotExisting() throws Exception { ClusterTierManagerClientEntityFactory factory = new ClusterTierManagerClientEntityFactory(connection, Runnable::run); try { - factory.retrieve("test", null); + factory.retrieve("test", null).close(); fail("Expected EntityNotFoundException"); } catch (EntityNotFoundException e) { //expected diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java index 93df067ae7..643d8cad8b 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java @@ -221,35 +221,34 @@ public static PassthroughServer remove(URI uri) { try { LOGGER.warn("Force close {}", formatConnectionId(connection)); connection.close(); - } catch (AssertionError | IOException e) { - // Ignored -- https://github.com/Terracotta-OSS/terracotta-apis/issues/102 + } catch (IOException e) { + throw new AssertionError(e); } } //open destroy connection. You need to make sure connection doesn't have any entities associated with it. - PassthroughConnection connection = serverDescriptor.server.connectNewClient("destroy-connection"); - - // destroy in reverse order of the creation to keep coherence - List> keys = new ArrayList<>(serverDescriptor.knownEntities.keySet()); - Collections.reverse(keys); - for(Class type : keys) { - Object[] args = serverDescriptor.knownEntities.get(type); - - Long version = (Long) args[0]; - String stringArg = (String) args[1]; - - try { - EntityRef entityRef = connection.getEntityRef(type, version, stringArg); - entityRef.destroy(); - } catch (EntityNotProvidedException ex) { - LOGGER.error("Entity destroy failed (not provided???): ", ex); - } catch (EntityNotFoundException ex) { - LOGGER.error("Entity destroy failed: ", ex); - } catch (PermanentEntityException ex) { - LOGGER.error("Entity destroy failed (permanent???): ", ex); + try (PassthroughConnection connection = serverDescriptor.server.connectNewClient("destroy-connection")) { + // destroy in reverse order of the creation to keep coherence + List> keys = new ArrayList<>(serverDescriptor.knownEntities.keySet()); + Collections.reverse(keys); + for (Class type : keys) { + Object[] args = serverDescriptor.knownEntities.get(type); + + Long version = (Long) args[0]; + String stringArg = (String) args[1]; + + try { + EntityRef entityRef = connection.getEntityRef(type, version, stringArg); + entityRef.destroy(); + } catch (EntityNotProvidedException ex) { + LOGGER.error("Entity destroy failed (not provided???): ", ex); + } catch (EntityNotFoundException ex) { + LOGGER.error("Entity destroy failed: ", ex); + } catch (PermanentEntityException ex) { + LOGGER.error("Entity destroy failed (permanent???): ", ex); + } } } - serverDescriptor.server.stop(); LOGGER.info("Stopped PassthroughServer at {}", keyURI); return serverDescriptor.server; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java index ac032505be..a8bc384c3d 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java @@ -97,29 +97,30 @@ public void testClusteredStateRepositoryReplication() throws Exception { ClusteringService service = new ClusteringServiceFactory().create(configuration); service.start(null); + try { + BaseCacheConfiguration config = new BaseCacheConfiguration<>(Long.class, String.class, noAdvice(), null, noExpiration(), + newResourcePoolsBuilder().with(clusteredDedicated("test", 2, org.ehcache.config.units.MemoryUnit.MB)).build()); + ClusteringService.ClusteredCacheIdentifier spaceIdentifier = (ClusteringService.ClusteredCacheIdentifier) service.getPersistenceSpaceIdentifier("test", + config); - BaseCacheConfiguration config = new BaseCacheConfiguration<>(Long.class, String.class, noAdvice(), null, noExpiration(), - newResourcePoolsBuilder().with(clusteredDedicated("test", 2, org.ehcache.config.units.MemoryUnit.MB)).build()); - ClusteringService.ClusteredCacheIdentifier spaceIdentifier = (ClusteringService.ClusteredCacheIdentifier) service.getPersistenceSpaceIdentifier("test", - config); + ServerStoreProxy serverStoreProxy = service.getServerStoreProxy(spaceIdentifier, new StoreConfigurationImpl<>(config, 1, null, null), Consistency.STRONG, mock(ServerCallback.class)); - ServerStoreProxy serverStoreProxy = service.getServerStoreProxy(spaceIdentifier, new StoreConfigurationImpl<>(config, 1, null, null), Consistency.STRONG, mock(ServerCallback.class)); + SimpleClusterTierClientEntity clientEntity = getEntity(serverStoreProxy); - SimpleClusterTierClientEntity clientEntity = getEntity(serverStoreProxy); + ClusterStateRepository stateRepository = new ClusterStateRepository(spaceIdentifier, "test", clientEntity); - ClusterStateRepository stateRepository = new ClusterStateRepository(spaceIdentifier, "test", clientEntity); + StateHolder testHolder = stateRepository.getPersistentStateHolder("testHolder", String.class, String.class, c -> true, null); + testHolder.putIfAbsent("One", "One"); + testHolder.putIfAbsent("Two", "Two"); - StateHolder testHolder = stateRepository.getPersistentStateHolder("testHolder", String.class, String.class, c -> true, null); - testHolder.putIfAbsent("One", "One"); - testHolder.putIfAbsent("Two", "Two"); + clusterControl.terminateActive(); + clusterControl.waitForActive(); - clusterControl.terminateActive(); - clusterControl.waitForActive(); - - assertThat(testHolder.get("One"), is("One")); - assertThat(testHolder.get("Two"), is("Two")); - - service.stop(); + assertThat(testHolder.get("One"), is("One")); + assertThat(testHolder.get("Two"), is("Two")); + } finally { + service.stop(); + } } @Test @@ -132,41 +133,42 @@ public void testClusteredStateRepositoryReplicationWithSerializableKV() throws E ClusteringService service = new ClusteringServiceFactory().create(configuration); service.start(null); + try { + BaseCacheConfiguration config = new BaseCacheConfiguration<>(Long.class, String.class, noAdvice(), null, noExpiration(), + newResourcePoolsBuilder().with(clusteredDedicated("test", 2, org.ehcache.config.units.MemoryUnit.MB)).build()); + ClusteringService.ClusteredCacheIdentifier spaceIdentifier = (ClusteringService.ClusteredCacheIdentifier) service.getPersistenceSpaceIdentifier("test", + config); - BaseCacheConfiguration config = new BaseCacheConfiguration<>(Long.class, String.class, noAdvice(), null, noExpiration(), - newResourcePoolsBuilder().with(clusteredDedicated("test", 2, org.ehcache.config.units.MemoryUnit.MB)).build()); - ClusteringService.ClusteredCacheIdentifier spaceIdentifier = (ClusteringService.ClusteredCacheIdentifier) service.getPersistenceSpaceIdentifier("test", - config); - - ServerStoreProxy serverStoreProxy = service.getServerStoreProxy(spaceIdentifier, new StoreConfigurationImpl<>(config, 1, null, null), Consistency.STRONG, mock(ServerCallback.class)); + ServerStoreProxy serverStoreProxy = service.getServerStoreProxy(spaceIdentifier, new StoreConfigurationImpl<>(config, 1, null, null), Consistency.STRONG, mock(ServerCallback.class)); - SimpleClusterTierClientEntity clientEntity = getEntity(serverStoreProxy); + SimpleClusterTierClientEntity clientEntity = getEntity(serverStoreProxy); - ClusterStateRepository stateRepository = new ClusterStateRepository(new ClusteringService.ClusteredCacheIdentifier() { - @Override - public String getId() { - return "testStateRepo"; - } + ClusterStateRepository stateRepository = new ClusterStateRepository(new ClusteringService.ClusteredCacheIdentifier() { + @Override + public String getId() { + return "testStateRepo"; + } - @Override - public Class getServiceType() { - return ClusteringService.class; - } - }, "test", clientEntity); + @Override + public Class getServiceType() { + return ClusteringService.class; + } + }, "test", clientEntity); - StateHolder testMap = stateRepository.getPersistentStateHolder("testMap", TestVal.class, TestVal.class, c -> true, null); - testMap.putIfAbsent(new TestVal("One"), new TestVal("One")); - testMap.putIfAbsent(new TestVal("Two"), new TestVal("Two")); + StateHolder testMap = stateRepository.getPersistentStateHolder("testMap", TestVal.class, TestVal.class, c -> true, null); + testMap.putIfAbsent(new TestVal("One"), new TestVal("One")); + testMap.putIfAbsent(new TestVal("Two"), new TestVal("Two")); - clusterControl.terminateActive(); - clusterControl.waitForActive(); + clusterControl.terminateActive(); + clusterControl.waitForActive(); - assertThat(testMap.get(new TestVal("One")), is(new TestVal("One"))); - assertThat(testMap.get(new TestVal("Two")), is(new TestVal("Two"))); + assertThat(testMap.get(new TestVal("One")), is(new TestVal("One"))); + assertThat(testMap.get(new TestVal("Two")), is(new TestVal("Two"))); - assertThat(testMap.entrySet(), hasSize(2)); - - service.stop(); + assertThat(testMap.entrySet(), hasSize(2)); + } finally { + service.stop(); + } } private static SimpleClusterTierClientEntity getEntity(ServerStoreProxy clusteringService) throws NoSuchFieldException, IllegalAccessException { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java index ee08c2b20f..d804bab4e7 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java @@ -79,29 +79,28 @@ public void testCacheOperationThrowsAfterConnectionClosed() throws Exception { .autoCreate(c -> c)) .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, resourcePoolsBuilder)); - PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); + try (PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true)) { - Cache cache = cacheManager.getCache("clustered-cache", Long.class, String.class); + Cache cache = cacheManager.getCache("clustered-cache", Long.class, String.class); - Collection connectionProperties = UnitTestConnectionService.getConnectionProperties(CLUSTER_URI); + Collection connectionProperties = UnitTestConnectionService.getConnectionProperties(CLUSTER_URI); - assertThat(connectionProperties.size(), is(1)); - Properties properties = connectionProperties.iterator().next(); + assertThat(connectionProperties.size(), is(1)); + Properties properties = connectionProperties.iterator().next(); - assertThat(properties.getProperty(ConnectionPropertyNames.CONNECTION_TIMEOUT), is("20000")); + assertThat(properties.getProperty(ConnectionPropertyNames.CONNECTION_TIMEOUT), is("20000")); - cache.put(1L, "value"); - assertThat(cache.get(1L), is("value")); + cache.put(1L, "value"); + assertThat(cache.get(1L), is("value")); - Collection connections = UnitTestConnectionService.getConnections(CLUSTER_URI); + Collection connections = UnitTestConnectionService.getConnections(CLUSTER_URI); - assertThat(connections.size(), is(1)); + assertThat(connections.size(), is(1)); - Connection connection = connections.iterator().next(); + connections.iterator().next().close(); - connection.close(); - - assertThatEventually(() -> cache.get(1L), is("value")).within(Duration.ofSeconds(5)); + assertThatEventually(() -> cache.get(1L), is("value")).within(Duration.ofSeconds(60)); + } } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java index 036d2a99b8..f6e27fcf25 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java @@ -114,9 +114,7 @@ private void closeConnection() throws IOException { assertThat(connections.size(), is(1)); - Connection connection = connections.iterator().next(); - - connection.close(); + connections.iterator().next().close(); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java index 5a830dd901..afd1f8b62f 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java @@ -175,7 +175,7 @@ public void setup() throws Exception { @After public void tearDown() throws Exception { - UnitTestConnectionService.remove("terracotta://localhost/my-application"); + UnitTestConnectionService.remove(CLUSTER_URI); } private ByteBuffer op(Operation operation) { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java index 4fb2e494ff..b4fda00755 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java @@ -173,7 +173,7 @@ public void setup() throws Exception { @After public void tearDown() throws Exception { - UnitTestConnectionService.remove("terracotta://localhost/my-application"); + UnitTestConnectionService.remove(CLUSTER_URI); } private void assertTimeoutOccurred(ThrowableAssert.ThrowingCallable throwingCallable) { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java index b5a9360a1d..14cb53765b 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicBoolean; import static org.ehcache.clustered.ChainUtils.chainOf; import static org.ehcache.clustered.ChainUtils.createPayload; @@ -57,8 +58,10 @@ public void testInvalidationsContainChains() throws Exception { final List store1InvalidatedHashes = new CopyOnWriteArrayList<>(); final List store1InvalidatedChains = new CopyOnWriteArrayList<>(); + final AtomicBoolean store1InvalidatedAll = new AtomicBoolean(); final List store2InvalidatedHashes = new CopyOnWriteArrayList<>(); final List store2InvalidatedChains = new CopyOnWriteArrayList<>(); + final AtomicBoolean store2InvalidatedAll = new AtomicBoolean(); EventualServerStoreProxy serverStoreProxy1 = new EventualServerStoreProxy("testInvalidationsContainChains", clientEntity1, new ServerCallback() { @Override @@ -75,7 +78,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - fail("should not be called"); + store1InvalidatedAll.set(true); } @Override @@ -109,7 +112,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - fail("should not be called"); + store2InvalidatedAll.set(true); } @Override @@ -158,6 +161,8 @@ public void compact(ServerStoreProxy.ChainEntry chain) { MatcherAssert.assertThat(store2InvalidatedChains.size(), is(store1InvalidatedChains.size())); assertThatClientsWaitingForInvalidationIsEmpty("testInvalidationsContainChains"); + assertThat(store1InvalidatedAll.get(), is(false)); + assertThat(store2InvalidatedAll.get(), is(false)); } @Test @@ -167,8 +172,10 @@ public void testAppendFireEvents() throws Exception { final List store1AppendedBuffers = new CopyOnWriteArrayList<>(); final List store1Chains = new CopyOnWriteArrayList<>(); + final AtomicBoolean store1InvalidatedAll = new AtomicBoolean(); final List store2AppendedBuffers = new CopyOnWriteArrayList<>(); final List store2Chains = new CopyOnWriteArrayList<>(); + final AtomicBoolean store2InvalidatedAll = new AtomicBoolean(); EventualServerStoreProxy serverStoreProxy1 = new EventualServerStoreProxy("testAppendFireEvents", clientEntity1, new ServerCallback() { @Override @@ -178,7 +185,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - fail("should not be called"); + store1InvalidatedAll.set(true); } @Override @@ -208,7 +215,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - fail("should not be called"); + store2InvalidatedAll.set(true); } @Override @@ -242,12 +249,14 @@ public void compact(ServerStoreProxy.ChainEntry chain) { assertThat(store1Chains.size(), is(2)); assertThat(store1Chains.get(0).length(), is(0)); assertThat(store1Chains.get(1).length(), is(1)); + assertThat(store1InvalidatedAll.get(), is(false)); assertThat(store2AppendedBuffers.size(), is(2)); assertThat(store2AppendedBuffers.get(0).asLongBuffer().get(), is(1L)); assertThat(store2AppendedBuffers.get(1).asLongBuffer().get(), is(2L)); assertThat(store2Chains.size(), is(2)); assertThat(store2Chains.get(0).length(), is(0)); assertThat(store2Chains.get(1).length(), is(1)); + assertThat(store2InvalidatedAll.get(), is(false)); } private static void assertThatClientsWaitingForInvalidationIsEmpty(String name) throws Exception { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java index 8291a482c4..776fe2c93a 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java @@ -45,7 +45,9 @@ public void testServerSideEvictionFiresInvalidations() throws Exception { SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testServerSideEvictionFiresInvalidations", Consistency.EVENTUAL, false); final List store1InvalidatedHashes = new CopyOnWriteArrayList<>(); + final AtomicBoolean store1InvalidatedAll = new AtomicBoolean(); final List store2InvalidatedHashes = new CopyOnWriteArrayList<>(); + final AtomicBoolean store2InvalidatedAll = new AtomicBoolean(); EventualServerStoreProxy serverStoreProxy1 = new EventualServerStoreProxy("testServerSideEvictionFiresInvalidations", clientEntity1, new ServerCallback() { @Override @@ -55,7 +57,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - fail("should not be called"); + store1InvalidatedAll.set(true); } @Override @@ -76,7 +78,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - fail("should not be called"); + store2InvalidatedAll.set(true); } @Override @@ -115,6 +117,9 @@ public void compact(ServerStoreProxy.ChainEntry chain) { assertThat(store2InvalidatedHashes.size(), is(ITERATIONS + evictionCount)); assertThatClientsWaitingForInvalidationIsEmpty("testServerSideEvictionFiresInvalidations"); + + assertThat(store1InvalidatedAll.get(), is(false)); + assertThat(store2InvalidatedAll.get(), is(false)); } @Test @@ -124,6 +129,7 @@ public void testHashInvalidationListenerWithAppend() throws Exception { final CountDownLatch latch = new CountDownLatch(1); final AtomicReference invalidatedHash = new AtomicReference<>(); + final AtomicBoolean invalidatedAll = new AtomicBoolean(); EventualServerStoreProxy serverStoreProxy1 = new EventualServerStoreProxy("testHashInvalidationListenerWithAppend", clientEntity1, new ServerCallback() { @@ -135,7 +141,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - throw new AssertionError("Should not be called"); + invalidatedAll.set(true); } @Override @@ -155,6 +161,7 @@ public void compact(ServerStoreProxy.ChainEntry chain) { latch.await(5, TimeUnit.SECONDS); assertThat(invalidatedHash.get(), is(1L)); assertThatClientsWaitingForInvalidationIsEmpty("testHashInvalidationListenerWithAppend"); + assertThat(invalidatedAll.get(), is(false)); } @Test @@ -164,6 +171,7 @@ public void testHashInvalidationListenerWithGetAndAppend() throws Exception { final CountDownLatch latch = new CountDownLatch(1); final AtomicReference invalidatedHash = new AtomicReference<>(); + final AtomicBoolean invalidatedAll = new AtomicBoolean(); EventualServerStoreProxy serverStoreProxy1 = new EventualServerStoreProxy("testHashInvalidationListenerWithGetAndAppend", clientEntity1, new ServerCallback() { @@ -175,7 +183,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - throw new AssertionError("Should not be called"); + invalidatedAll.set(true); } @Override @@ -195,6 +203,7 @@ public void compact(ServerStoreProxy.ChainEntry chain) { latch.await(5, TimeUnit.SECONDS); assertThat(invalidatedHash.get(), is(1L)); assertThatClientsWaitingForInvalidationIsEmpty("testHashInvalidationListenerWithGetAndAppend"); + assertThat(invalidatedAll.get(), is(false)); } @Test diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java index c03d933856..344567685c 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java @@ -31,6 +31,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import static org.ehcache.clustered.ChainUtils.createPayload; @@ -59,6 +60,7 @@ public void testConcurrentHashInvalidationListenerWithAppend() throws Exception final AtomicReference invalidatedHash = new AtomicReference<>(); SimpleClusterTierClientEntity clientEntity1 = createClientEntity(ENTITY_NAME, getServerStoreConfiguration(), true, true); StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy(ENTITY_NAME, clientEntity1, mock(ServerCallback.class)); + AtomicBoolean invalidatedAll = new AtomicBoolean(); ExecutorService executor = Executors.newSingleThreadExecutor(); CountDownLatch beforeValidationLatch = new CountDownLatch(1); @@ -74,7 +76,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - throw new AssertionError("Should not be called"); + invalidatedAll.set(true); } @Override @@ -103,7 +105,7 @@ public void compact(ServerStoreProxy.ChainEntry chain) { assertTrue(afterValidationLatch.await(MAX_WAIT_TIME_SECONDS, TimeUnit.SECONDS)); serverStoreProxy1.append(1L, createPayload(1L)); assertThat(invalidatedHash.get(), is(1L)); - + assertThat(invalidatedAll.get(), is(false)); executor.shutdownNow(); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java index 0ecf4dae20..feb10da5b5 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java @@ -53,7 +53,9 @@ public void testServerSideEvictionFiresInvalidations() throws Exception { SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testServerSideEvictionFiresInvalidations", Consistency.STRONG, false); final List store1InvalidatedHashes = new CopyOnWriteArrayList<>(); + final AtomicBoolean store1InvalidatedAll = new AtomicBoolean(); final List store2InvalidatedHashes = new CopyOnWriteArrayList<>(); + final AtomicBoolean store2InvalidatedAll = new AtomicBoolean(); StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testServerSideEvictionFiresInvalidations", clientEntity1, new ServerCallback() { @Override @@ -63,7 +65,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - fail("should not be called"); + store1InvalidatedAll.set(true); } @Override @@ -84,7 +86,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - fail("should not be called"); + store2InvalidatedAll.set(true); } @Override @@ -121,6 +123,8 @@ public void compact(ServerStoreProxy.ChainEntry chain) { assertThat(store1InvalidatedHashes.size(), is(ITERATIONS - entryCount)); // test that each time the server evicted, the other client got notified on top of normal invalidations assertThat(store2InvalidatedHashes.size(), is(ITERATIONS + evictionCount)); + assertThat(store1InvalidatedAll.get(), is(false)); + assertThat(store2InvalidatedAll.get(), is(false)); } @Test @@ -129,6 +133,7 @@ public void testHashInvalidationListenerWithAppend() throws Exception { SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testHashInvalidationListenerWithAppend", Consistency.STRONG, false); final AtomicReference invalidatedHash = new AtomicReference<>(); + final AtomicBoolean invalidatedAll = new AtomicBoolean(); StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testHashInvalidationListenerWithAppend", clientEntity1, mock(ServerCallback.class)); StrongServerStoreProxy serverStoreProxy2 = new StrongServerStoreProxy("testHashInvalidationListenerWithAppend", clientEntity2, new ServerCallback() { @@ -139,7 +144,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - throw new AssertionError("Should not be called"); + invalidatedAll.set(true); } @Override @@ -156,6 +161,7 @@ public void compact(ServerStoreProxy.ChainEntry chain) { serverStoreProxy1.append(1L, createPayload(1L)); assertThat(invalidatedHash.get(), is(1L)); + assertThat(invalidatedAll.get(), is(false)); } @Test @@ -164,6 +170,7 @@ public void testConcurrentHashInvalidationListenerWithAppend() throws Exception SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testConcurrentHashInvalidationListenerWithAppend", Consistency.STRONG, false); final AtomicBoolean invalidating = new AtomicBoolean(); + final AtomicBoolean invalidatedAll = new AtomicBoolean(); final CountDownLatch latch = new CountDownLatch(2); StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testConcurrentHashInvalidationListenerWithAppend", clientEntity1, mock(ServerCallback.class)); StrongServerStoreProxy serverStoreProxy2 = new StrongServerStoreProxy("testConcurrentHashInvalidationListenerWithAppend", clientEntity2, new ServerCallback() { @@ -183,7 +190,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - throw new AssertionError("Should not be called"); + invalidatedAll.set(true); } @Override @@ -214,6 +221,7 @@ public void compact(ServerStoreProxy.ChainEntry chain) { } finally { executor.shutdown(); } + assertThat(invalidatedAll.get(), is(false)); } @Test @@ -222,7 +230,7 @@ public void testHashInvalidationListenerWithGetAndAppend() throws Exception { SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testHashInvalidationListenerWithGetAndAppend", Consistency.STRONG, false); final AtomicReference invalidatedHash = new AtomicReference<>(); - + final AtomicBoolean invalidatedAll = new AtomicBoolean(); StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testHashInvalidationListenerWithGetAndAppend", clientEntity1, mock(ServerCallback.class)); StrongServerStoreProxy serverStoreProxy2 = new StrongServerStoreProxy("testHashInvalidationListenerWithGetAndAppend", clientEntity2, new ServerCallback() { @Override @@ -232,7 +240,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - throw new AssertionError("Should not be called"); + invalidatedAll.set(true); } @Override @@ -249,6 +257,7 @@ public void compact(ServerStoreProxy.ChainEntry chain) { serverStoreProxy1.getAndAppend(1L, createPayload(1L)); assertThat(invalidatedHash.get(), is(1L)); + assertThat(invalidatedAll.get(), is(false)); } @Test @@ -350,6 +359,8 @@ public void testAppendInvalidationUnblockedByDisconnection() throws Exception { SimpleClusterTierClientEntity clientEntity1 = createClientEntity("testAppendInvalidationUnblockedByDisconnection", Consistency.STRONG, true); SimpleClusterTierClientEntity clientEntity2 = createClientEntity("testAppendInvalidationUnblockedByDisconnection", Consistency.STRONG, false); + final AtomicBoolean invalidatedAll = new AtomicBoolean(); + StrongServerStoreProxy serverStoreProxy1 = new StrongServerStoreProxy("testAppendInvalidationUnblockedByDisconnection", clientEntity1, mock(ServerCallback.class)); StrongServerStoreProxy serverStoreProxy2 = new StrongServerStoreProxy("testAppendInvalidationUnblockedByDisconnection", clientEntity2, new ServerCallback() { @Override @@ -359,7 +370,7 @@ public void onInvalidateHash(long hash, Chain evictedChain) { @Override public void onInvalidateAll() { - throw new AssertionError("Should not be called"); + invalidatedAll.set(true); } @Override @@ -379,6 +390,7 @@ public void compact(ServerStoreProxy.ChainEntry chain) { } catch (RuntimeException re) { assertThat(re.getCause(), instanceOf(IllegalStateException.class)); } + assertThat(invalidatedAll.get(), is(false)); } @Test diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java index 09c492d949..03a2e0b5e5 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java @@ -59,6 +59,7 @@ public class LockRetentionDuringFailoverTest { private CountDownLatch latch; private LatchedLoaderWriter loaderWriter; + private CacheManager cacheManager; private Cache cache; @Before @@ -90,7 +91,7 @@ public void setUp() throws Exception { .withLoaderWriter(loaderWriter) .build(); - CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().with(cluster(URI.create(STRIPE_URI)).autoCreate(c -> c)) + cacheManager = CacheManagerBuilder.newCacheManagerBuilder().with(cluster(URI.create(STRIPE_URI)).autoCreate(c -> c)) .withCache("cache-1", config) .build(true); @@ -100,8 +101,12 @@ public void setUp() throws Exception { @After public void tearDown() throws Exception { - UnitTestConnectionService.removeStripe(STRIPENAME); - clusterControl.tearDown(); + try { + cacheManager.close(); + } finally { + UnitTestConnectionService.removeStripe(STRIPENAME); + clusterControl.tearDown(); + } } @Test diff --git a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java index 4569fff991..83d76d712c 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java @@ -61,33 +61,33 @@ public void removePassthroughServer() throws Exception { UnitTestConnectionService.remove(CLUSTER_URI); } - @Test + @Test @SuppressWarnings("try") public void testAllClientsNeedToHaveLoaderWriterConfigured() { TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); CacheConfiguration cacheConfiguration = getCacheConfiguration(loaderWriter); - CacheManager cacheManager = CacheManagerBuilder + try (CacheManager cacheManager = CacheManagerBuilder .newCacheManagerBuilder() .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) - .build(true); - - CacheConfiguration withoutLoaderWriter = newCacheConfigurationBuilder(Long.class, String.class, - ResourcePoolsBuilder - .newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).offheap(1, MemoryUnit.MB) - .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) - .withResilienceStrategy(new ThrowingResilienceStrategy<>()) - .build(); - - try { - CacheManager anotherManager = CacheManagerBuilder - .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate(c -> c)) - .withCache("cache-1", withoutLoaderWriter) - .build(true); - } catch (RuntimeException e) { - assertThat(e.getCause().getCause().getCause().getCause(), instanceOf(CachePersistenceException.class)); - assertThat(e.getCause().getCause().getCause().getCause().getCause(), instanceOf(ClusterTierValidationException.class)); + .build(true)) { + + CacheConfiguration withoutLoaderWriter = newCacheConfigurationBuilder(Long.class, String.class, + ResourcePoolsBuilder + .newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).offheap(1, MemoryUnit.MB) + .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB))) + .withResilienceStrategy(new ThrowingResilienceStrategy<>()) + .build(); + + try (CacheManager anotherManager = CacheManagerBuilder + .newCacheManagerBuilder() + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) + .withCache("cache-1", withoutLoaderWriter) + .build(true)) { + } catch (RuntimeException e) { + assertThat(e.getCause().getCause().getCause().getCause(), instanceOf(CachePersistenceException.class)); + assertThat(e.getCause().getCause().getCause().getCause().getCause(), instanceOf(ClusterTierValidationException.class)); + } } } @@ -97,20 +97,20 @@ public void testBasicClusteredCacheLoaderWriter() { TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); CacheConfiguration cacheConfiguration = getCacheConfiguration(loaderWriter); - CacheManager cacheManager = CacheManagerBuilder + try (CacheManager cacheManager = CacheManagerBuilder .newCacheManagerBuilder() .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) - .build(true); - - Cache cache = cacheManager.getCache("cache-1", Long.class, String.class); + .build(true)) { - cache.put(1L, "1"); + Cache cache = cacheManager.getCache("cache-1", Long.class, String.class); - assertThat(cache.get(1L), is("1")); + cache.put(1L, "1"); - assertThat(loaderWriter.storeMap.get(1L), is("1")); + assertThat(cache.get(1L), is("1")); + assertThat(loaderWriter.storeMap.get(1L), is("1")); + } } @Test @@ -120,32 +120,33 @@ public void testLoaderWriterMultipleClients() { CacheConfiguration cacheConfiguration = getCacheConfiguration(loaderWriter); - CacheManager cacheManager1 = CacheManagerBuilder - .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate(c -> c)) - .withCache("cache-1", cacheConfiguration) - .build(true); - - CacheManager cacheManager2 = CacheManagerBuilder + try (CacheManager cacheManager1 = CacheManagerBuilder .newCacheManagerBuilder() .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) - .build(true); + .build(true)) { - Cache client1 = cacheManager1.getCache("cache-1", Long.class, String.class); - Cache client2 = cacheManager2.getCache("cache-1", Long.class, String.class); + try (CacheManager cacheManager2 = CacheManagerBuilder + .newCacheManagerBuilder() + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) + .withCache("cache-1", cacheConfiguration) + .build(true)) { - client1.put(1L, "1"); - client2.put(1L, "2"); + Cache client1 = cacheManager1.getCache("cache-1", Long.class, String.class); + Cache client2 = cacheManager2.getCache("cache-1", Long.class, String.class); - assertThat(client1.get(1L), is("2")); - assertThat(loaderWriter.storeMap.get(1L), is("2")); + client1.put(1L, "1"); + client2.put(1L, "2"); - client1.remove(1L); + assertThat(client1.get(1L), is("2")); + assertThat(loaderWriter.storeMap.get(1L), is("2")); - assertThat(client2.get(1L), nullValue()); - assertThat(loaderWriter.storeMap.get(1L), nullValue()); + client1.remove(1L); + assertThat(client2.get(1L), nullValue()); + assertThat(loaderWriter.storeMap.get(1L), nullValue()); + } + } } @Test @@ -154,42 +155,43 @@ public void testCASOpsMultipleClients() { CacheConfiguration cacheConfiguration = getCacheConfiguration(loaderWriter); - CacheManager cacheManager1 = CacheManagerBuilder + try (CacheManager cacheManager1 = CacheManagerBuilder .newCacheManagerBuilder() .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) - .build(true); + .build(true)) { - CacheManager cacheManager2 = CacheManagerBuilder - .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate(c -> c)) - .withCache("cache-1", cacheConfiguration) - .build(true); + try (CacheManager cacheManager2 = CacheManagerBuilder + .newCacheManagerBuilder() + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) + .withCache("cache-1", cacheConfiguration) + .build(true)) { - Cache client1 = cacheManager1.getCache("cache-1", Long.class, String.class); - Cache client2 = cacheManager2.getCache("cache-1", Long.class, String.class); + Cache client1 = cacheManager1.getCache("cache-1", Long.class, String.class); + Cache client2 = cacheManager2.getCache("cache-1", Long.class, String.class); - assertThat(client1.putIfAbsent(1L, "1"), nullValue()); - assertThat(client2.putIfAbsent(1L, "2"), is("1")); + assertThat(client1.putIfAbsent(1L, "1"), nullValue()); + assertThat(client2.putIfAbsent(1L, "2"), is("1")); - assertThat(client1.get(1L), is("1")); - assertThat(loaderWriter.storeMap.get(1L), is("1")); + assertThat(client1.get(1L), is("1")); + assertThat(loaderWriter.storeMap.get(1L), is("1")); - assertThat(client1.replace(1L, "2"), is("1")); - assertThat(client2.replace(1L, "3"), is("2")); + assertThat(client1.replace(1L, "2"), is("1")); + assertThat(client2.replace(1L, "3"), is("2")); - assertThat(client1.get(1L), is("3")); - assertThat(loaderWriter.storeMap.get(1L), is("3")); + assertThat(client1.get(1L), is("3")); + assertThat(loaderWriter.storeMap.get(1L), is("3")); - assertThat(client1.replace(1L, "2", "4"), is(false)); - assertThat(client2.replace(1L, "3", "4"), is(true)); + assertThat(client1.replace(1L, "2", "4"), is(false)); + assertThat(client2.replace(1L, "3", "4"), is(true)); - assertThat(client1.get(1L), is("4")); - assertThat(loaderWriter.storeMap.get(1L), is("4")); - - assertThat(client1.remove(1L, "5"), is(false)); - assertThat(client2.remove(1L, "4"), is(true)); + assertThat(client1.get(1L), is("4")); + assertThat(loaderWriter.storeMap.get(1L), is("4")); + assertThat(client1.remove(1L, "5"), is(false)); + assertThat(client2.remove(1L, "4"), is(true)); + } + } } @Test @@ -197,33 +199,34 @@ public void testBulkOps() { TestCacheLoaderWriter loaderWriter = new TestCacheLoaderWriter(); CacheConfiguration cacheConfiguration = getCacheConfiguration(loaderWriter); - CacheManager cacheManager = CacheManagerBuilder + try (CacheManager cacheManager = CacheManagerBuilder .newCacheManagerBuilder() .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) - .build(true); + .build(true)) { - Cache cache = cacheManager.getCache("cache-1", Long.class, String.class); + Cache cache = cacheManager.getCache("cache-1", Long.class, String.class); - Map mappings = new HashMap<>(); + Map mappings = new HashMap<>(); - for (int i = 1; i <= 5; i++) { - mappings.put((long) i, "" + i); - } + for (int i = 1; i <= 5; i++) { + mappings.put((long) i, "" + i); + } - cache.putAll(mappings); + cache.putAll(mappings); - assertThat(loaderWriter.storeMap.keySet(), containsInAnyOrder(mappings.keySet().toArray())); + assertThat(loaderWriter.storeMap.keySet(), containsInAnyOrder(mappings.keySet().toArray())); - cache.clear(); + cache.clear(); - Map loadedData = cache.getAll(mappings.keySet()); + Map loadedData = cache.getAll(mappings.keySet()); - assertThat(mappings.keySet(), containsInAnyOrder(loadedData.keySet().toArray())); + assertThat(mappings.keySet(), containsInAnyOrder(loadedData.keySet().toArray())); - cache.removeAll(mappings.keySet()); + cache.removeAll(mappings.keySet()); - assertThat(loaderWriter.storeMap.isEmpty(), is(true)); + assertThat(loaderWriter.storeMap.isEmpty(), is(true)); + } } @Test @@ -232,40 +235,41 @@ public void testCASOps() { CacheConfiguration cacheConfiguration = getCacheConfiguration(loaderWriter); - CacheManager cacheManager1 = CacheManagerBuilder - .newCacheManagerBuilder() - .with(cluster(CLUSTER_URI).autoCreate(c -> c)) - .withCache("cache-1", cacheConfiguration) - .build(true); - - CacheManager cacheManager2 = CacheManagerBuilder + try (CacheManager cacheManager1 = CacheManagerBuilder .newCacheManagerBuilder() .with(cluster(CLUSTER_URI).autoCreate(c -> c)) .withCache("cache-1", cacheConfiguration) - .build(true); + .build(true)) { - Cache client1 = cacheManager1.getCache("cache-1", Long.class, String.class); - Cache client2 = cacheManager2.getCache("cache-1", Long.class, String.class); + try (CacheManager cacheManager2 = CacheManagerBuilder + .newCacheManagerBuilder() + .with(cluster(CLUSTER_URI).autoCreate(c -> c)) + .withCache("cache-1", cacheConfiguration) + .build(true)) { - assertThat(loaderWriter.storeMap.isEmpty(), is(true)); + Cache client1 = cacheManager1.getCache("cache-1", Long.class, String.class); + Cache client2 = cacheManager2.getCache("cache-1", Long.class, String.class); - Set keys = new HashSet<>(); - ThreadLocalRandom.current().longs(10).forEach(x -> { - keys.add(x); - client1.put(x, Long.toString(x)); - }); - assertThat(loaderWriter.storeMap.size(), is(10)); + assertThat(loaderWriter.storeMap.isEmpty(), is(true)); + Set keys = new HashSet<>(); + ThreadLocalRandom.current().longs(10).forEach(x -> { + keys.add(x); + client1.put(x, Long.toString(x)); + }); + assertThat(loaderWriter.storeMap.size(), is(10)); - keys.forEach(x -> assertThat(client2.putIfAbsent(x, "Again" + x), is(Long.toString(x)))); - keys.stream().limit(5).forEach(x -> - assertThat(client2.replace(x , "Replaced" + x), is(Long.toString(x)))); + keys.forEach(x -> assertThat(client2.putIfAbsent(x, "Again" + x), is(Long.toString(x)))); - keys.forEach(x -> client1.remove(x, Long.toString(x))); + keys.stream().limit(5).forEach(x -> + assertThat(client2.replace(x, "Replaced" + x), is(Long.toString(x)))); - assertThat(loaderWriter.storeMap.size(), is(5)); + keys.forEach(x -> client1.remove(x, Long.toString(x))); + assertThat(loaderWriter.storeMap.size(), is(5)); + } + } } private CacheConfiguration getCacheConfiguration(TestCacheLoaderWriter loaderWriter) { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index 079d810dda..c96e704f59 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -24,7 +24,6 @@ import org.ehcache.config.units.MemoryUnit; import org.junit.BeforeClass; import org.junit.ClassRule; -import org.junit.Ignore; import org.junit.Test; import org.terracotta.testing.rules.Cluster; @@ -86,7 +85,6 @@ public static void waitForActive() throws Exception { private final AtomicLong idGenerator = new AtomicLong(2L); @Test - @Ignore("Issue#2758: Fails on linux PR builds") public void testMultipleClients() { ExecutorService executorService = Executors.newFixedThreadPool(NUM_THREADS); try { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index 65967c3465..d1d910bb9b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -37,7 +37,6 @@ import org.junit.After; import org.junit.Before; import org.junit.ClassRule; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; @@ -62,7 +61,6 @@ import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; @RunWith(Parallel.class) -@Ignore("Issue#2758: Fails on linux PR builds") public class EventsFailureBehaviorTest extends ClusteredTests { private static final Logger LOGGER = LoggerFactory.getLogger(EventsFailureBehaviorTest.class); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java index 7bc4f1995b..7c4762b6ac 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java @@ -25,6 +25,8 @@ import org.junit.runner.RunWith; import org.terracotta.testing.rules.Cluster; +import javax.cache.Caching; +import javax.cache.spi.CachingProvider; import java.net.URL; import java.util.Properties; @@ -71,7 +73,11 @@ public static void waitForActive() throws Exception { @AfterClass public static void cleanup() { - System.clearProperty("ehcache.jsr107.config.default"); - TCK_PROPERTIES.forEach((k, v) -> System.clearProperty(k.toString())); + try { + Caching.getCachingProviders().forEach(CachingProvider::close); + } finally { + System.clearProperty("ehcache.jsr107.config.default"); + TCK_PROPERTIES.forEach((k, v) -> System.clearProperty(k.toString())); + } } } diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java index a55d6e3c02..4762385814 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -112,6 +112,7 @@ public static Cluster startServer(Path serverDirectory) throws IOException { serverProcess.command().addAll(asList(tcServerOptions.split("\\s"))); } serverProcess.command().addAll(asList( + "-Xmx128m", "-Dtc.install-root=" + serverDir, "-cp", serverDir.resolve("lib").resolve("tc.jar").toString(), "com.tc.server.TCServerMain", diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java index 21ba87169b..dc5d2693ce 100644 --- a/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java +++ b/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java @@ -29,6 +29,7 @@ import org.terracotta.entity.StateDumpCollector; import org.terracotta.offheapresource.OffHeapResources; +import java.io.Closeable; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -42,7 +43,7 @@ * {@link ServiceProvider} for {@link EhcacheStateService} */ @BuiltinService -public class EhcacheStateServiceProvider implements ServiceProvider { +public class EhcacheStateServiceProvider implements ServiceProvider, Closeable { private static final Logger LOGGER = LoggerFactory.getLogger(EhcacheStateServiceProvider.class); @@ -115,6 +116,12 @@ public void prepareForSynchronization() { serviceMap.clear(); } + @Override + public void close() { + //passthrough test cleanup + serviceMap.values().forEach(EhcacheStateService::destroy); + } + public interface DestroyCallback { void destroy(EhcacheStateService service); } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java index 1a1c5dd58d..20244a7ca4 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java @@ -48,6 +48,7 @@ import org.junit.Before; import org.junit.Rule; import org.terracotta.org.junit.rules.TemporaryFolder; +import org.terracotta.statistics.StatisticsManager; import java.io.IOException; import java.util.Arrays; @@ -195,6 +196,7 @@ public void close(final Store store) { String spaceName = createdStores.get(store); try { OffHeapDiskStore.Provider.close((OffHeapDiskStore)store); + StatisticsManager.nodeFor(store).clean(); } catch (IOException ex) { throw new RuntimeException(ex); } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java index fe44f8c421..5844075517 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java @@ -35,6 +35,7 @@ import org.ehcache.core.spi.store.Store; import org.ehcache.spi.service.ServiceConfiguration; import org.junit.Before; +import org.terracotta.statistics.StatisticsManager; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.core.spi.ServiceLocator.dependencySet; @@ -123,6 +124,7 @@ public String createValue(long seed) { @Override public void close(final Store store) { OnHeapStore.Provider.close((OnHeapStore)store); + StatisticsManager.nodeFor(store).clean(); } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java index c65e210c89..6d6506a67c 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java @@ -38,6 +38,7 @@ import org.ehcache.spi.serialization.Serializer; import org.ehcache.spi.service.ServiceConfiguration; import org.junit.Before; +import org.terracotta.statistics.StatisticsManager; import static java.lang.ClassLoader.getSystemClassLoader; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; @@ -131,6 +132,7 @@ public String createValue(long seed) { @Override public void close(final Store store) { OnHeapStore.Provider.close((OnHeapStore)store); + StatisticsManager.nodeFor(store).clean(); } @Override @@ -148,6 +150,7 @@ public ServiceLocator getServiceProvider() { public static void closeStore(OnHeapStore store) { OnHeapStore.Provider.close(store); + StatisticsManager.nodeFor(store).clean(); } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java index e3bcdcc536..232056b134 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java @@ -35,6 +35,7 @@ import org.ehcache.core.spi.store.Store; import org.ehcache.spi.service.ServiceConfiguration; import org.junit.Before; +import org.terracotta.statistics.StatisticsManager; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.core.spi.ServiceLocator.dependencySet; @@ -130,6 +131,7 @@ public String createValue(long seed) { @Override public void close(final Store store) { OnHeapStore.Provider.close((OnHeapStore)store); + StatisticsManager.nodeFor(store).clean(); } @Override diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java index 29bda73d6e..78253ed98d 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java @@ -38,6 +38,7 @@ import org.ehcache.spi.serialization.Serializer; import org.ehcache.spi.service.ServiceConfiguration; import org.junit.Before; +import org.terracotta.statistics.StatisticsManager; import static java.lang.ClassLoader.getSystemClassLoader; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; @@ -136,6 +137,7 @@ public String createValue(long seed) { @Override public void close(final Store store) { OnHeapStore.Provider.close((OnHeapStore)store); + StatisticsManager.nodeFor(store).clean(); } @Override @@ -153,6 +155,7 @@ public ServiceLocator getServiceProvider() { public static void closeStore(OnHeapStore store) { OnHeapStore.Provider.close(store); + StatisticsManager.nodeFor(store).clean(); } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java index 93f26c4a96..7ba4f0bf90 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java @@ -15,6 +15,8 @@ */ package org.ehcache.impl.internal.store.offheap; +import org.terracotta.statistics.StatisticsManager; + /** * @author Ludovic Orban */ @@ -29,6 +31,7 @@ public static void init(OffHeapStore offHeapStore) { public static void close(OffHeapStore offHeapStore) { OffHeapStore.Provider.close(offHeapStore); + StatisticsManager.nodeFor(offHeapStore).clean(); } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java index f6aab61a20..df502f9ffc 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java @@ -38,6 +38,7 @@ import org.ehcache.spi.serialization.Serializer; import org.ehcache.spi.service.ServiceConfiguration; import org.junit.Before; +import org.terracotta.statistics.StatisticsManager; import java.util.Arrays; @@ -144,6 +145,7 @@ public String createValue(long seed) { @Override public void close(final Store store) { OffHeapStore.Provider.close((OffHeapStore)store); + StatisticsManager.nodeFor(store).clean(); } }; } @@ -164,6 +166,7 @@ public static void initStore(OffHeapStore offHeapStore) { public static void closeStore(OffHeapStore offHeapStore) { OffHeapStore.Provider.close(offHeapStore); + StatisticsManager.nodeFor(offHeapStore).clean(); } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java index 788230cfae..2329630cf9 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java @@ -34,6 +34,7 @@ import org.ehcache.spi.serialization.UnsupportedTypeException; import org.ehcache.spi.service.ServiceConfiguration; import org.junit.Test; +import org.terracotta.statistics.StatisticsManager; import java.util.Arrays; import java.util.Collections; @@ -129,5 +130,6 @@ private void assertRank(final Store.Provider provider, final int expectedRank, f @Override protected void destroyStore(AbstractOffHeapStore store) { OffHeapStore.Provider.close((OffHeapStore) store); + StatisticsManager.nodeFor(store).clean(); } } diff --git a/transactions/build.gradle b/transactions/build.gradle index f1d1616668..9143371a5b 100644 --- a/transactions/build.gradle +++ b/transactions/build.gradle @@ -32,6 +32,7 @@ dependencies { } compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':core-spi-test') + testImplementation "org.terracotta:statistics:$statisticVersion" testImplementation 'org.xmlunit:xmlunit-core:2.6.0' testImplementation 'org.xmlunit:xmlunit-matchers:2.6.0' } diff --git a/transactions/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java b/transactions/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java index 781e18cad6..54f5114622 100644 --- a/transactions/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java +++ b/transactions/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java @@ -16,6 +16,8 @@ package org.ehcache.impl.internal.store.offheap; +import org.terracotta.statistics.StatisticsManager; + /** * @author Ludovic Orban */ @@ -30,6 +32,7 @@ public static void init(OffHeapStore offHeapStore) { public static void close(OffHeapStore offHeapStore) { OffHeapStore.Provider.close(offHeapStore); + StatisticsManager.nodeFor(offHeapStore).clean(); } } From 585b85916c392c3737d947f3ee0343aac862d59d Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 6 May 2020 11:11:51 -0400 Subject: [PATCH 244/372] missing fail --- .../client/UnSupportedCombinationsWithClusteredCacheTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java index 600d1c3465..e6071c57a2 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java @@ -110,6 +110,7 @@ public void testClusteredCacheWithXA() throws Exception { .build() ) .build(true).close(); + fail("Expected StateTransitionException"); } catch (StateTransitionException e) { assertThat(e.getCause().getCause().getMessage(), is("Unsupported resource type : interface org.ehcache.clustered.client.config.DedicatedClusteredResourcePool")); } From b74348d26dae89547eab75f1582a5279a4813cc7 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 13 Apr 2020 10:53:26 -0400 Subject: [PATCH 245/372] IterationFailureBehaviorTest cleanup --- .../IterationFailureBehaviorTest.java | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java index da4de9e225..ac8a78da2a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java @@ -37,9 +37,11 @@ import java.util.Iterator; import java.util.Map; +import static java.time.Duration.ofSeconds; import static java.util.function.Function.identity; import static java.util.stream.Collectors.toMap; import static java.util.stream.LongStream.range; +import static org.ehcache.clustered.client.config.builders.TimeoutsBuilder.timeouts; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.core.IsNull.notNullValue; @@ -78,11 +80,9 @@ public void testIteratorFailover() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/iterator-cm")) - .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); - final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); - cacheManager.init(); - - try { + .autoCreate(server -> server.defaultServerResource("primary-server-resource")) + .timeouts(timeouts().read(ofSeconds(10)))); + try (PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true)) { CacheConfiguration smallConfig = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB))).build(); @@ -126,8 +126,6 @@ public void testIteratorFailover() throws Exception { smallIterator.forEachRemaining(k -> smallMap.put(k.getKey(), k.getValue())); assertThat(smallMap, is(range(0, KEYS).boxed().collect(toMap(identity(), k -> Long.toString(k))))); - } finally { - cacheManager.close(); } } @@ -137,10 +135,7 @@ public void testIteratorReconnect() throws Exception { = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/iterator-cm")) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); - final PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); - cacheManager.init(); - - try { + try (PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true)) { CacheConfiguration smallConfig = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB))).build(); @@ -187,8 +182,6 @@ public void testIteratorReconnect() throws Exception { smallIterator.forEachRemaining(k -> smallMap.put(k.getKey(), k.getValue())); assertThat(smallMap, is(range(0, KEYS).boxed().collect(toMap(identity(), k -> Long.toString(k))))); - } finally { - cacheManager.close(); } } } From 04408db5234a1f1e9a3b52d3a824112bcd74ba06 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 6 May 2020 11:15:24 -0400 Subject: [PATCH 246/372] Extract commonality in test cluster configurations --- .../BasicCacheOpsMultiThreadedTest.java | 9 +------ .../clustered/BasicClusteredCacheOpsTest.java | 11 ++------ .../clustered/BasicEntityInteractionTest.java | 10 ++----- ...anagerLifecycleEhcacheIntegrationTest.java | 10 ++----- ...gerClientEntityFactoryIntegrationTest.java | 11 ++------ .../clustered/ClusteredIterationTest.java | 11 ++------ .../clustered/ClusteredLoaderWriterTest.java | 11 ++------ .../org/ehcache/clustered/ClusteredTests.java | 26 +++++++++++++++++++ .../ehcache/clustered/DestroyLoopTest.java | 10 ++----- .../clustered/EventsFailureBehaviorTest.java | 10 ++----- .../IterationFailureBehaviorTest.java | 11 +------- .../clustered/JCacheClusteredTest.java | 10 ++----- .../java/org/ehcache/clustered/LeaseTest.java | 11 +------- .../clustered/OversizedCacheOpsTest.java | 11 ++------ .../clustered/ReconnectDuringDestroyTest.java | 11 +------- .../ResourcePoolAllocationFailureTest.java | 11 ++------ .../clustered/TerminatedServerTest.java | 11 +------- .../AbstractClusteringManagementTest.java | 19 ++++++++------ .../management/CMClosedEventSentTest.java | 20 +++++++++----- .../EhcacheConfigWithManagementTest.java | 20 ++++++++------ .../ManagementClusterConnectionTest.java | 23 ++++++++-------- .../reconnect/AutoCreateOnReconnectTest.java | 12 ++------- .../reconnect/BasicCacheReconnectTest.java | 11 +------- .../CacheManagerDestroyReconnectTest.java | 11 +------- .../reconnect/EventsReconnectTest.java | 11 +------- ...dCacheOpsReplicationMultiThreadedTest.java | 10 +++---- ...BasicClusteredCacheOpsReplicationTest.java | 10 ++----- ...OpsReplicationWithMultipleClientsTest.java | 10 ++----- ...CacheOpsReplicationWithServersApiTest.java | 9 ++----- .../BasicLifeCyclePassiveReplicationTest.java | 10 ++----- .../clustered/replication/DuplicateTest.java | 9 +------ .../OversizedCacheOpsPassiveTest.java | 9 +------ .../clustered/sync/PassiveSyncTest.java | 10 ++----- .../writebehind/WriteBehindTestBase.java | 7 +---- 34 files changed, 122 insertions(+), 284 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index baaa3a314c..f8606959ed 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -58,16 +58,9 @@ */ public class BasicCacheOpsMultiThreadedTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" + - "\n"; - @ClassRule public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster().in(clusterPath()).withServiceFragment(offheapResource("primary-server-resource", 64)).build(); private static final String CLUSTERED_CACHE_NAME = "clustered-cache"; private static final String SYN_CACHE_NAME = "syn-cache"; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java index 6f1129136e..19dd4439af 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java @@ -52,16 +52,9 @@ public class BasicClusteredCacheOpsTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" + - "\n"; - @ClassRule - public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 64)).build(); @Test public void basicCacheCRUD() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java index 086797455d..133515ec44 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java @@ -54,15 +54,9 @@ public class BasicEntityInteractionTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "4" - + "" + - "\n"; - @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 4)).build(); private ClusterTierManagerConfiguration blankConfiguration = new ClusterTierManagerConfiguration("identifier", new ServerSideConfiguration(emptyMap())); @Rule diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java index abab2af19e..369727cef0 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java @@ -60,15 +60,9 @@ public class CacheManagerLifecycleEhcacheIntegrationTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" + - "\n"; - @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 64)).build(); private static Connection ASSERTION_CONNECTION; @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java index 7eb38c6b98..f4a0b8643a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java @@ -45,16 +45,9 @@ public class ClusterTierManagerClientEntityFactoryIntegrationTest extends Cluste private static final Map EMPTY_RESOURCE_MAP = Collections.emptyMap(); - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" + - "\n"; - @ClassRule - public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()) + .withServiceFragment(offheapResource("primary", 64)).build(); private static Connection CONNECTION; @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java index b3dd98e5ac..75cdfde622 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java @@ -49,16 +49,9 @@ public class ClusteredIterationTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" + - "\n"; - @ClassRule - public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 64)).build(); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java index 28b738d0f3..15c9140f3e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java @@ -58,13 +58,6 @@ @RunWith(Parameterized.class) public class ClusteredLoaderWriterTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" + - "\n"; - @Parameterized.Parameters(name = "consistency={0}") public static Consistency[] data() { return Consistency.values(); @@ -80,8 +73,8 @@ public static Consistency[] data() { private ConcurrentMap sor; @ClassRule - public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 64)).build(); @BeforeClass public static void initCacheManager() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java index afd91f013f..7fb2cea56c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java @@ -20,8 +20,12 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.time.Duration; import java.util.Comparator; +import java.util.Map; +import static java.time.temporal.ChronoUnit.SECONDS; +import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; @@ -99,4 +103,26 @@ private static String getKitInstallationPath(String diskPrefix) { protected static Path clusterPath() { return Paths.get("build", "cluster"); } + + protected static String offheapResource(String name, long size) { + return offheapResources(singletonMap(name, size)); + } + + protected static String offheapResources(Map resources) { + StringBuilder sb = new StringBuilder(""); + sb.append(""); + for (Map.Entry e : resources.entrySet()) { + sb.append("").append(e.getValue()).append(""); + } + sb.append(""); + return sb.append("\n").toString(); + } + + protected static String leaseLength(Duration leaseLength) { + return "" + + "" + + "" + leaseLength.get(SECONDS) + "" + + "" + + ""; + } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java index 8e6502b1ff..8e7ef4c528 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java @@ -46,18 +46,12 @@ public class DestroyLoopTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" + - "\n"; - private static final String CACHE_MANAGER_NAME = "/destroy-cm"; private static final String CACHE_NAME = "clustered-cache"; @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 64)).build(); @Test public void testDestroyLoop() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index 98664afc5e..3a94aa862f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -70,15 +70,9 @@ public class EventsFailureBehaviorTest extends ClusteredTests { private static final Duration TIMEOUT = Duration.ofSeconds(5); private static final Duration FAILOVER_TIMEOUT = Duration.ofMinutes(1); - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" + - "\n"; - @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 64)).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java index 02c3298eeb..1535db5e3b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java @@ -67,16 +67,7 @@ public class IterationFailureBehaviorTest extends ClusteredTests { public static final TestRetryer CLUSTER = TestRetryer.tryValues( Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), leaseLength -> newCluster(2).in(clusterPath()).withServiceFragment( - "" - + "" - + "64" - + "" - + "\n" - + "" - + "" - + "" + leaseLength.get(SECONDS) + "" - + "" - + "").build(), + offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build(), of(OutputIs.CLASS_RULE)); @Before diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java index d7b2e6d120..84c03a9300 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java @@ -52,15 +52,9 @@ public class JCacheClusteredTest extends ClusteredTests { TCK_PROPERTIES.setProperty("javax.cache.Cache.Entry", "org.ehcache.Cache$Entry"); TCK_PROPERTIES.setProperty("javax.cache.annotation.CacheInvocationContext", "javax.cache.annotation.impl.cdi.CdiCacheKeyInvocationContextImpl"); } - private static final String RESOURCE_CONFIG = - "" - + "" - + "256" - + "" + - "\n"; - @ClassRule - public static Cluster CLUSTER = newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()) + .withServiceFragment(offheapResource("primary", 256)).build(); @BeforeClass public static void configureEnvironment() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java index e47b3687ae..c70c6a3d3b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java @@ -65,16 +65,7 @@ public class LeaseTest extends ClusteredTests { public static final TestRetryer CLUSTER = tryValues( Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), leaseLength -> newCluster().in(clusterPath()).withServiceFragment( - "" - + "" - + "64" - + "" - + "\n" - + "" - + "" - + "" + leaseLength.get(SECONDS) + "" - + "" - + "").build(), + offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build(), of(OutputIs.CLASS_RULE)); private final List proxies = new ArrayList<>(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java index e5d08edacc..399e4f83fb 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java @@ -39,16 +39,9 @@ public class OversizedCacheOpsTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "2" - + "" + - "\n"; - @ClassRule - public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 2)).build(); @Test public void overSizedCacheOps() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java index b6f774702c..0e87f4b178 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -78,16 +78,7 @@ public class ReconnectDuringDestroyTest extends ClusteredTests { public static final TestRetryer CLUSTER = tryValues( Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(3)), leaseLength -> newCluster().in(clusterPath()).withServiceFragment( - "" - + "" - + "64" - + "" - + "\n" - + "" - + "" - + "" + leaseLength.get(SECONDS) + "" - + "" - + "").build(), + offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build(), of(OutputIs.CLASS_RULE)); @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java index 75173e9007..5b01130706 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java @@ -41,16 +41,9 @@ public class ResourcePoolAllocationFailureTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" + - "\n"; - @ClassRule - public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster().in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 64)).build(); @Test public void testTooLowResourceException() throws InterruptedException { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java index f6e6afbfa3..9c4d80bddd 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java @@ -131,16 +131,7 @@ private ThrowableAssertAlternative assertExceptionOccur Stream.of(ofSeconds(2), ofSeconds(10), ofSeconds(30)), leaseLength -> new ParallelTestCluster( newCluster().in(clusterPath()).withServiceFragment( - "" - + "" - + "64" - + "" - + "" - + "" - + "" - + "" + leaseLength.get(SECONDS) + "" - + "" - + "\n").build()), + offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build()), of(OutputIs.CLASS_RULE, OutputIs.RULE)); @Rule diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 1c41d457b5..96e1afecdb 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -45,12 +45,15 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Scanner; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import static java.lang.Thread.sleep; +import static java.util.Collections.unmodifiableMap; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredShared; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; @@ -68,13 +71,13 @@ public abstract class AbstractClusteringManagementTest extends ClusteredTests { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractClusteringManagementTest.class); - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "64" - + "" + - "\n"; + private static final Map resources; + static { + HashMap map = new HashMap<>(); + map.put("primary-server-resource", 64L); + map.put("secondary-server-resource", 64L); + resources = unmodifiableMap(map); + } protected static CacheManager cacheManager; protected static ClientIdentifier ehcacheClientIdentifier; @@ -83,7 +86,7 @@ public abstract class AbstractClusteringManagementTest extends ClusteredTests { @ClassRule public static final ClusterWithManagement CLUSTER = new ClusterWithManagement(newCluster(2) - .in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); + .in(clusterPath()).withServiceFragment(offheapResources(resources)).build()); @Rule public final RuleChain rules = outerRule(Timeout.seconds(90)).around(new BeforeAllRule(this)); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java index 381c9daef3..2c0037066c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java @@ -26,6 +26,10 @@ import org.terracotta.management.model.message.Message; import org.terracotta.management.model.notification.ContextualNotification; +import java.util.HashMap; +import java.util.Map; + +import static java.util.Collections.unmodifiableMap; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; @@ -38,15 +42,17 @@ public class CMClosedEventSentTest extends ClusteredTests { + private static final Map resources; + static { + HashMap map = new HashMap<>(); + map.put("primary-server-resource", 64L); + map.put("secondary-server-resource", 64L); + resources = unmodifiableMap(map); + } + @ClassRule public static ClusterWithManagement CLUSTER = new ClusterWithManagement( - newCluster().in(clusterPath()).withServiceFragment( - "" - + "" - + "64" - + "64" - + "" - + "").build()); + newCluster().in(clusterPath()).withServiceFragment(offheapResources(resources)).build()); @Test(timeout = 60_000) public void test_CACHE_MANAGER_CLOSED() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java index 619efd562a..4793b5ad80 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java @@ -25,6 +25,10 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; +import java.util.HashMap; +import java.util.Map; + +import static java.util.Collections.unmodifiableMap; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredShared; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; @@ -35,17 +39,17 @@ public class EhcacheConfigWithManagementTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "64" - + "" + - "\n"; + private static final Map resources; + static { + HashMap map = new HashMap<>(); + map.put("primary-server-resource", 64L); + map.put("secondary-server-resource", 64L); + resources = unmodifiableMap(map); + } @ClassRule public static Cluster CLUSTER = newCluster().in(clusterPath()) - .withServiceFragment(RESOURCE_CONFIG).build(); + .withServiceFragment(offheapResources(resources)).build(); @Test public void create_cache_manager() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index 5c61934511..6d7a1511aa 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -40,11 +40,15 @@ import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Stream; import static java.time.Duration.ofSeconds; import static java.time.temporal.ChronoUnit.SECONDS; +import static java.util.Collections.unmodifiableMap; import static java.util.EnumSet.of; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; @@ -66,23 +70,20 @@ public class ManagementClusterConnectionTest extends ClusteredTests { protected static ObjectMapper mapper = new ObjectMapper(); private static final List proxies = new ArrayList<>(); + private static final Map resources; + static { + HashMap map = new HashMap<>(); + map.put("primary-server-resource", 64L); + map.put("secondary-server-resource", 64L); + resources = unmodifiableMap(map); + } @ClassRule @Rule public static TestRetryer CLUSTER = tryValues( Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), leaseLength -> new ClusterWithManagement( newCluster().in(clusterPath()).withServiceFragment( - "" - + "" - + "64" - + "64" - + "" - + "\n" - + "" - + "" - + "" + leaseLength.get(SECONDS) + "" - + "" - + "").build()), + offheapResources(resources) + leaseLength(leaseLength)).build()), of(OutputIs.CLASS_RULE)); @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java index b0f5e862be..d24fd2b52c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java @@ -36,18 +36,10 @@ import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; public class AutoCreateOnReconnectTest extends ClusteredTests { - public static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" - + "\n"; @ClassRule - public static Cluster CLUSTER = newCluster(1) - .in(clusterPath()) - .withServiceFragment(RESOURCE_CONFIG) - .build(); + public static Cluster CLUSTER = newCluster(1).in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 64)).build(); @Test public void cacheManagerCanReconnect() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java index d3365ea220..4a6c2a7a02 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java @@ -74,16 +74,7 @@ public class BasicCacheReconnectTest extends ClusteredTests { public static final TestRetryer CLUSTER = tryValues( Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), leaseLength -> newCluster().in(clusterPath()).withServiceFragment( - "" - + "" - + "64" - + "" - + "\n" - + "" - + "" - + "" + leaseLength.get(SECONDS) + "" - + "" - + "").build(), + offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build(), of(OutputIs.CLASS_RULE)); @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java index 4d91042ed9..1d87a60904 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java @@ -53,16 +53,7 @@ public class CacheManagerDestroyReconnectTest extends ClusteredTests { public static final TestRetryer CLUSTER = tryValues( Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), leaseLength -> newCluster().in(clusterPath()).withServiceFragment( - "" - + "" - + "64" - + "" - + "\n" - + "" - + "" - + "" + leaseLength.get(SECONDS) + "" - + "" - + "").build(), + offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build(), of(OutputIs.CLASS_RULE)); @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index 140b3e5b67..d1e09534a6 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -109,16 +109,7 @@ final void clear() { public static final TestRetryer CLUSTER = tryValues( Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), leaseLength -> newCluster().in(clusterPath()).withServiceFragment( - "" - + "" - + "64" - + "" - + "\n" - + "" - + "" - + "" + leaseLength.get(SECONDS) + "" - + "" - + "").build(), + offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build(), of(OutputIs.CLASS_RULE)); @BeforeClass diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index 169e9d9e17..f6f137eb12 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -82,12 +82,6 @@ public class BasicClusteredCacheOpsReplicationMultiThreadedTest extends Clustere private static final int NUM_OF_THREADS = 10; private static final int JOB_SIZE = 100; - private static final String RESOURCE_CONFIG = - "" - + "" - + "16" - + "" + - "\n"; private PersistentCacheManager cacheManager1; private PersistentCacheManager cacheManager2; @@ -103,7 +97,9 @@ public static Consistency[] data() { public Consistency cacheConsistency; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 16)).build()); + @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java index 168d67cd37..cf76ef8983 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java @@ -58,13 +58,6 @@ @RunWith(ParallelParameterized.class) public class BasicClusteredCacheOpsReplicationTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "32" - + "" + - "\n"; - private PersistentCacheManager cacheManager; private Cache cacheOne; private Cache cacheTwo; @@ -78,7 +71,8 @@ public static Consistency[] data() { public Consistency cacheConsistency; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 32)).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java index 8296f56718..32f2f8c481 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java @@ -66,13 +66,6 @@ @RunWith(ParallelParameterized.class) public class BasicClusteredCacheOpsReplicationWithMultipleClientsTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "16" - + "" + - "\n"; - private PersistentCacheManager cacheManager1; private PersistentCacheManager cacheManager2; private Cache cache1; @@ -87,7 +80,8 @@ public static Consistency[] data() { public Consistency cacheConsistency; @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 16)).build()); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java index 51ebee189f..0108cbc55e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java @@ -45,19 +45,14 @@ import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; public class BasicClusteredCacheOpsReplicationWithServersApiTest extends ClusteredTests { - private static final String CONFIG = - "" - + "" - + "16" - + "" + - "\n"; private static PersistentCacheManager CACHE_MANAGER; private static Cache CACHE1; private static Cache CACHE2; @ClassRule - public static Cluster CLUSTER = newCluster(2).in(clusterPath()).withServiceFragment(CONFIG).build(); + public static Cluster CLUSTER = newCluster(2).in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 16)).build(); @Before public void setUp() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java index e7a23ccaee..cd4cd3f519 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java @@ -43,15 +43,9 @@ @RunWith(Parallel.class) public class BasicLifeCyclePassiveReplicationTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "16" - + "" + - "\n"; - @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); + public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 16)).build()); @Before public void startServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java index 7f0ccfb7e8..39a2c8f297 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java @@ -50,18 +50,11 @@ public class DuplicateTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "512" - + "" + - "\n"; - private PersistentCacheManager cacheManager; @ClassRule public static Cluster CLUSTER = - newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + newCluster(2).in(clusterPath()).withServiceFragment(offheapResource("primary-server-resource", 512)).build(); @Before public void startServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java index 2f3997bd6c..9f53d8f867 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java @@ -47,18 +47,11 @@ public class OversizedCacheOpsPassiveTest extends ClusteredTests { private static final int CACHE_SIZE_IN_MB = 2; private static final String LARGE_VALUE = buildLargeString(); - private static final String RESOURCE_CONFIG = - "" - + "" - + "2" - + "" + - "\n"; - @ClassRule public static Cluster CLUSTER = newCluster(2).in(clusterPath()) .withSystemProperty("ehcache.sync.data.gets.threshold", "2") - .withServiceFragment(RESOURCE_CONFIG) + .withServiceFragment(offheapResource("primary-server-resource", 2)) .build(); @Test diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java index b96c427e64..fcb96b6f6f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java @@ -43,16 +43,10 @@ import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; public class PassiveSyncTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "16" - + "" + - "\n"; @ClassRule - public static Cluster CLUSTER = - newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + public static Cluster CLUSTER = newCluster(2).in(clusterPath()) + .withServiceFragment(offheapResource("primary-server-resource", 16)).build(); @Before public void startServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java index 69739db8ef..cb16fcd4f0 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java @@ -46,12 +46,7 @@ public class WriteBehindTestBase extends ClusteredTests { - static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" + - "\n"; + static final String RESOURCE_CONFIG = offheapResource("primary-server-resource", 64); static final long KEY = 1L; From d075b940a829a20dd0275698dab6088c2425f5c9 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 14 Apr 2020 11:58:35 -0400 Subject: [PATCH 247/372] Move to 'retrying' short lease length tests --- clustered/integration-test/build.gradle | 1 + .../IterationFailureBehaviorTest.java | 55 +++-- .../java/org/ehcache/clustered/LeaseTest.java | 68 +++--- .../clustered/ReconnectDuringDestroyTest.java | 53 +++-- .../clustered/TerminatedServerTest.java | 141 ++++++------ .../management/CMClosedEventSentTest.java | 23 +- .../ClusteringManagementServiceTest.java | 12 +- .../ManagementClusterConnectionTest.java | 65 +++--- .../reconnect/BasicCacheReconnectTest.java | 55 +++-- .../CacheManagerDestroyReconnectTest.java | 43 +++- .../reconnect/EventsReconnectTest.java | 55 +++-- .../util/runners/ExecutorScheduler.java | 20 +- .../clustered/util/runners/Parallel.java | 2 +- .../util/runners/ParallelParameterized.java | 4 +- management/build.gradle | 1 + .../StandardEhcacheStatisticsTest.java | 33 +-- settings.gradle | 2 +- test-utilities/build.gradle | 3 + .../config/checkstyle-suppressions.xml | 9 + .../java/org/ehcache/testing/TestRetryer.java | 214 ++++++++++++++++++ .../org/ehcache/testing/TestRetryerTest.java | 191 ++++++++++++++++ 21 files changed, 795 insertions(+), 255 deletions(-) create mode 100644 test-utilities/build.gradle create mode 100644 test-utilities/config/checkstyle-suppressions.xml create mode 100644 test-utilities/src/main/java/org/ehcache/testing/TestRetryer.java create mode 100644 test-utilities/src/test/java/org/ehcache/testing/TestRetryerTest.java diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index b8b8276bdb..ee58f478b9 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -44,6 +44,7 @@ dependencies { testImplementation (group:'org.terracotta', name:'galvan-platform-support', version: terracottaPlatformVersion) testImplementation group: 'javax.cache', name: 'cache-api', version: jcacheVersion + testImplementation project(':test-utilities') } task unzipKit(type: Copy) { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java index ac8a78da2a..3316135bd7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java @@ -27,17 +27,24 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.spi.resilience.StoreAccessException; +import org.ehcache.testing.TestRetryer; +import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.BeforeClass; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.terracotta.exception.ConnectionClosedException; import org.terracotta.testing.rules.Cluster; +import java.time.Duration; import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.stream.Stream; import static java.time.Duration.ofSeconds; +import static java.time.temporal.ChronoUnit.SECONDS; +import static java.util.EnumSet.of; import static java.util.function.Function.identity; import static java.util.stream.Collectors.toMap; import static java.util.stream.LongStream.range; @@ -53,33 +60,33 @@ public class IterationFailureBehaviorTest extends ClusteredTests { private static final int KEYS = 100; - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" - + "" - + "" - + "" - + "5" - + "" - + ""; - - @ClassRule - public static Cluster CLUSTER = - newCluster(2).in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + @ClassRule @Rule + public static final TestRetryer CLUSTER = TestRetryer.tryValues( + Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), + leaseLength -> newCluster(2).in(clusterPath()).withServiceFragment( + "" + + "" + + "64" + + "" + + "\n" + + "" + + "" + + "" + leaseLength.get(SECONDS) + "" + + "" + + "").build(), + of(OutputIs.CLASS_RULE)); @BeforeClass public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); + CLUSTER.get().getClusterControl().startAllServers(); + CLUSTER.get().getClusterControl().waitForRunningPassivesInStandby(); } @Test public void testIteratorFailover() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/iterator-cm")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/iterator-cm")) .autoCreate(server -> server.defaultServerResource("primary-server-resource")) .timeouts(timeouts().read(ofSeconds(10)))); try (PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true)) { @@ -110,7 +117,7 @@ public void testIteratorFailover() throws Exception { Cache.Entry largeNext = largeIterator.next(); assertThat(largeCache.get(largeNext.getKey()), notNullValue()); - CLUSTER.getClusterControl().terminateActive(); + CLUSTER.get().getClusterControl().terminateActive(); //large iterator fails try { @@ -133,7 +140,7 @@ public void testIteratorFailover() throws Exception { public void testIteratorReconnect() throws Exception { final CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/iterator-cm")) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/iterator-cm")) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); try (PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true)) { CacheConfiguration smallConfig = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, @@ -163,10 +170,10 @@ public void testIteratorReconnect() throws Exception { Cache.Entry largeNext = largeIterator.next(); assertThat(largeCache.get(largeNext.getKey()), notNullValue()); - CLUSTER.getClusterControl().terminateAllServers(); - Thread.sleep(10000); - CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForActive(); + CLUSTER.get().getClusterControl().terminateAllServers(); + Thread.sleep(CLUSTER.input().multipliedBy(2L).toMillis()); + CLUSTER.get().getClusterControl().startAllServers(); + CLUSTER.get().getClusterControl().waitForActive(); //large iterator fails try { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java index 2e365f1090..4ede97a7e4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java @@ -27,9 +27,12 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.TestRetryer; +import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.After; import org.junit.BeforeClass; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -39,13 +42,15 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Stream; +import static java.time.Duration.ofSeconds; +import static java.time.temporal.ChronoUnit.SECONDS; +import static java.util.EnumSet.of; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; +import static org.ehcache.testing.TestRetryer.tryValues; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; @@ -55,27 +60,28 @@ @RunWith(Parameterized.class) public class LeaseTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" - + "\n" - + "" - + "" - + "5" - + "" - + ""; - @ClassRule - public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + @Rule + public static final TestRetryer CLUSTER = tryValues( + Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), + leaseLength -> newCluster().in(clusterPath()).withServiceFragment( + "" + + "" + + "64" + + "" + + "\n" + + "" + + "" + + "" + leaseLength.get(SECONDS) + "" + + "" + + "").build(), + of(OutputIs.CLASS_RULE)); private final List proxies = new ArrayList<>(); @BeforeClass public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); + CLUSTER.get().getClusterControl().waitForActive(); } @After @@ -86,11 +92,11 @@ public void after() { @Parameterized.Parameters public static ResourcePoolsBuilder[] data() { return new ResourcePoolsBuilder[]{ - ResourcePoolsBuilder.newResourcePoolsBuilder() - .with(clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB)), - ResourcePoolsBuilder.newResourcePoolsBuilder() - .heap(10, EntryUnit.ENTRIES) - .with(clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB)) + ResourcePoolsBuilder.newResourcePoolsBuilder() + .with(clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB)), + ResourcePoolsBuilder.newResourcePoolsBuilder() + .heap(10, EntryUnit.ENTRIES) + .with(clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB)) }; } @@ -99,7 +105,7 @@ public static ResourcePoolsBuilder[] data() { @Test public void leaseExpiry() throws Exception { - URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.getConnectionURI(), proxies); + URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getConnectionURI(), proxies); CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(connectionURI.resolve("/crud-cm")) @@ -109,7 +115,7 @@ public void leaseExpiry() throws Exception { cacheManager.init(); CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, - resourcePoolsBuilder).build(); + resourcePoolsBuilder).build(); Cache cache = cacheManager.createCache("clustered-cache", config); cache.put(1L, "The one"); @@ -119,11 +125,13 @@ public void leaseExpiry() throws Exception { assertThat(cache.get(2L), equalTo("The two")); assertThat(cache.get(3L), equalTo("The three")); - setDelay(6000, proxies); - Thread.sleep(6000); - // We will now have lost the lease - - setDelay(0L, proxies); + long delay = CLUSTER.input().plusSeconds(1L).toMillis(); + setDelay(delay, proxies); + try { + Thread.sleep(delay); + } finally { + setDelay(0L, proxies); + } assertThatEventually(() -> cache.get(1L), is("The one")).within(Duration.ofSeconds(30)); assertThat(cache.get(2L), equalTo("The two")); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java index b0923b3d1c..7a4a5548be 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -31,10 +31,13 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.TestRetryer; +import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.terracotta.connection.Connection; import org.terracotta.connection.entity.EntityRef; @@ -49,10 +52,14 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; +import java.util.stream.Stream; +import static java.time.Duration.ofSeconds; +import static java.time.temporal.ChronoUnit.SECONDS; +import static java.util.EnumSet.of; import static org.ehcache.clustered.common.EhcacheEntityVersion.ENTITY_VERSION; -import static org.ehcache.clustered.reconnect.BasicCacheReconnectTest.RESOURCE_CONFIG; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; +import static org.ehcache.testing.TestRetryer.tryValues; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; @@ -67,15 +74,27 @@ public class ReconnectDuringDestroyTest extends ClusteredTests { private static List proxies; PersistentCacheManager cacheManager; - @ClassRule - public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + @ClassRule @Rule + public static final TestRetryer CLUSTER = tryValues( + Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(3)), + leaseLength -> newCluster().in(clusterPath()).withServiceFragment( + "" + + "" + + "64" + + "" + + "\n" + + "" + + "" + + "" + leaseLength.get(SECONDS) + "" + + "" + + "").build(), + of(OutputIs.CLASS_RULE)); @BeforeClass public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); + CLUSTER.get().getClusterControl().waitForActive(); proxies = new ArrayList<>(); - connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.getConnectionURI(), proxies); + connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getConnectionURI(), proxies); } @Before @@ -117,9 +136,13 @@ public void reconnectDuringDestroyTest() throws Exception { } } // For reconnection. - setDelay(6000, proxies); // Connection Lease time is 5 seconds so delaying for more than 5 seconds. - Thread.sleep(6000); - setDelay(0L, proxies); + long delay = CLUSTER.input().plusSeconds(1).toMillis(); + setDelay(delay, proxies); + try { + Thread.sleep(delay); + } finally { + setDelay(0L, proxies); + } client = LeasedConnectionFactory.connect(connectionURI, new Properties()); // For mimicking the cacheManager.destroy() in the reconnect path. @@ -163,12 +186,16 @@ public void reconnectAfterDestroyOneOfTheCache() throws Exception { cacheManager.destroyCache("clustered-cache-1"); // For reconnection. - setDelay(6000, proxies); // Connection Lease time is 5 seconds so delaying for more than 5 seconds. - Thread.sleep(6000); - setDelay(0L, proxies); + long delay = CLUSTER.input().plusSeconds(1L).toMillis(); + setDelay(delay, proxies); + try { + Thread.sleep(delay); + } finally { + setDelay(0L, proxies); + } Cache cache2Again = cacheManager.getCache("clustered-cache-2", Long.class, String.class); - assertThatEventually(() -> cache2Again.get(1L), equalTo("The one")).within(Duration.ofSeconds(10)); + assertThatEventually(() -> cache2Again.get(1L), equalTo("The one")).within(ofSeconds(10)); assertThat(cache2Again.get(2L), equalTo("The two")); cache2Again.put(3L, "The three"); assertThat(cache2Again.get(3L), equalTo("The three")); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java index 6045a71b97..fdfe286290 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java @@ -33,6 +33,8 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.testing.TestRetryer; +import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -58,9 +60,14 @@ import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.stream.Stream; +import static java.time.Duration.ofSeconds; +import static java.time.temporal.ChronoUnit.SECONDS; +import static java.util.EnumSet.of; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.ehcache.testing.TestRetryer.tryValues; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; /** @@ -80,18 +87,6 @@ public class TerminatedServerTest extends ClusteredTests { private static final int CLIENT_MAX_PENDING_REQUESTS = 5; - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" - + "" - + "" - + "" - + "5" - + "" - + "\n"; - private static Map OLD_PROPERTIES; @BeforeClass @@ -132,14 +127,29 @@ private ThrowableAssertAlternative assertExceptionOccur } @ClassRule @Rule - public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); + public static final TestRetryer CLUSTER = tryValues( + Stream.of(ofSeconds(2), ofSeconds(10), ofSeconds(30)), + leaseLength -> new ParallelTestCluster( + newCluster().in(clusterPath()).withServiceFragment( + "" + + "" + + "64" + + "" + + "" + + "" + + "" + + "" + leaseLength.get(SECONDS) + "" + + "" + + "\n").build()), + of(OutputIs.CLASS_RULE, OutputIs.RULE)); + @Rule public final TestName testName = new TestName(); @Before public void waitForActive() throws Exception { - CLUSTER.getClusterControl().startAllServers(); - CLUSTER.getClusterControl().waitForActive(); + CLUSTER.get().getClusterControl().startAllServers(); + CLUSTER.get().getClusterControl().waitForActive(); } /** @@ -149,14 +159,14 @@ public void waitForActive() throws Exception { public void testTerminationBeforeCacheManagerClose() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/").resolve(testName.getMethodName())) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); - CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.get().getClusterControl().terminateAllServers(); - new TimeLimitedTask(10, TimeUnit.SECONDS) { + new TimeLimitedTask(CLUSTER.input().plusSeconds(10)) { @Override Void runTask() throws Exception { cacheManager.close(); @@ -171,7 +181,7 @@ Void runTask() throws Exception { public void testTerminationBeforeCacheManagerCloseWithCaches() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/").resolve(testName.getMethodName())) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, @@ -180,7 +190,7 @@ public void testTerminationBeforeCacheManagerCloseWithCaches() throws Exception PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); - CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.get().getClusterControl().terminateAllServers(); cacheManager.close(); @@ -189,12 +199,12 @@ public void testTerminationBeforeCacheManagerCloseWithCaches() throws Exception @Test public void testTerminationBeforeCacheManagerRetrieve() throws Exception { // Close all servers - CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.get().getClusterControl().terminateAllServers(); // Try to retrieve an entity (that doesn't exist but I don't care... the server is not running anyway CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().connection(Duration.ofSeconds(1))) // Need a connection timeout shorter than the TimeLimitedTask timeout .expecting(server -> server.defaultServerResource("primary-server-resource"))); PersistentCacheManager cacheManagerExisting = clusteredCacheManagerBuilder.build(false); @@ -203,7 +213,7 @@ public void testTerminationBeforeCacheManagerRetrieve() throws Exception { long synackTimeout = TimeUnit.MILLISECONDS.toSeconds(ClientMessageTransport.TRANSPORT_HANDSHAKE_SYNACK_TIMEOUT); assertExceptionOccurred(StateTransitionException.class, - new TimeLimitedTask(3 + synackTimeout, TimeUnit.SECONDS) { + new TimeLimitedTask(ofSeconds(3 + synackTimeout)) { @Override Void runTask() { cacheManagerExisting.init(); @@ -218,7 +228,7 @@ Void runTask() { public void testTerminationBeforeCacheManagerDestroyCache() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/").resolve(testName.getMethodName())) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, @@ -234,10 +244,10 @@ public void testTerminationBeforeCacheManagerDestroyCache() throws Exception { cacheManager.removeCache("simple-cache"); - CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.get().getClusterControl().terminateAllServers(); assertExceptionOccurred(CachePersistenceException.class, - new TimeLimitedTask(10, TimeUnit.SECONDS) { + new TimeLimitedTask(ofSeconds(10)) { @Override Void runTask() throws Exception { cacheManager.destroyCache("simple-cache"); @@ -251,15 +261,15 @@ Void runTask() throws Exception { public void testTerminationBeforeCacheCreate() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/").resolve(testName.getMethodName())) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); - CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.get().getClusterControl().terminateAllServers(); assertExceptionOccurred(IllegalStateException.class, - new TimeLimitedTask>(10, TimeUnit.SECONDS) { + new TimeLimitedTask>(ofSeconds(10)) { @Override Cache runTask() throws Exception { return cacheManager.createCache("simple-cache", @@ -275,7 +285,7 @@ Cache runTask() throws Exception { public void testTerminationBeforeCacheRemove() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/").resolve(testName.getMethodName())) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, @@ -284,7 +294,7 @@ public void testTerminationBeforeCacheRemove() throws Exception { PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); cacheManager.init(); - CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.get().getClusterControl().terminateAllServers(); cacheManager.removeCache("simple-cache"); } @@ -293,7 +303,7 @@ public void testTerminationBeforeCacheRemove() throws Exception { public void testTerminationThenGet() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().read(Duration.of(1, ChronoUnit.SECONDS)).build()) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", @@ -310,9 +320,9 @@ public void testTerminationThenGet() throws Exception { assertThat(cache.get(2L)).isNotNull(); - CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.get().getClusterControl().terminateAllServers(); - String value = new TimeLimitedTask(5, TimeUnit.SECONDS) { + String value = new TimeLimitedTask(ofSeconds(5)) { @Override String runTask() throws Exception { return cache.get(2L); @@ -326,7 +336,7 @@ String runTask() throws Exception { public void testTerminationThenContainsKey() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().read(Duration.of(1, ChronoUnit.SECONDS)).build()) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", @@ -343,9 +353,9 @@ public void testTerminationThenContainsKey() throws Exception { assertThat(cache.containsKey(2L)).isTrue(); - CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.get().getClusterControl().terminateAllServers(); - boolean value = new TimeLimitedTask(5, TimeUnit.SECONDS) { + boolean value = new TimeLimitedTask(ofSeconds(5)) { @Override Boolean runTask() throws Exception { return cache.containsKey(2L); @@ -360,7 +370,7 @@ Boolean runTask() throws Exception { public void testTerminationThenIterator() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().read(Duration.of(1, ChronoUnit.SECONDS)).build()) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", @@ -375,11 +385,11 @@ public void testTerminationThenIterator() throws Exception { cache.put(2L, "deux"); cache.put(3L, "trois"); - CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.get().getClusterControl().terminateAllServers(); - Iterator> value = new TimeLimitedTask>>(5, TimeUnit.SECONDS) { + Iterator> value = new TimeLimitedTask>>(ofSeconds(5)) { @Override - Iterator> runTask() throws Exception { + Iterator> runTask() { return cache.iterator(); } }.run(); @@ -391,7 +401,7 @@ Iterator> runTask() throws Exception { public void testTerminationThenPut() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().write(Duration.of(1, ChronoUnit.SECONDS)).build()) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", @@ -406,10 +416,10 @@ public void testTerminationThenPut() throws Exception { cache.put(2L, "deux"); cache.put(3L, "trois"); - CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.get().getClusterControl().terminateAllServers(); // The resilience strategy will pick it up and not exception is thrown - new TimeLimitedTask(10, TimeUnit.SECONDS) { + new TimeLimitedTask(ofSeconds(10)) { @Override Void runTask() throws Exception { cache.put(2L, "dos"); @@ -422,7 +432,7 @@ Void runTask() throws Exception { public void testTerminationThenPutIfAbsent() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().write(Duration.of(1, ChronoUnit.SECONDS)).build()) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", @@ -437,10 +447,10 @@ public void testTerminationThenPutIfAbsent() throws Exception { cache.put(2L, "deux"); cache.put(3L, "trois"); - CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.get().getClusterControl().terminateAllServers(); // The resilience strategy will pick it up and not exception is thrown - new TimeLimitedTask(10, TimeUnit.SECONDS) { + new TimeLimitedTask(ofSeconds(10)) { @Override String runTask() throws Exception { return cache.putIfAbsent(2L, "dos"); @@ -452,7 +462,7 @@ String runTask() throws Exception { public void testTerminationThenRemove() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().write(Duration.of(1, ChronoUnit.SECONDS)).build()) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", @@ -467,9 +477,9 @@ public void testTerminationThenRemove() throws Exception { cache.put(2L, "deux"); cache.put(3L, "trois"); - CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.get().getClusterControl().terminateAllServers(); - new TimeLimitedTask(10, TimeUnit.SECONDS) { + new TimeLimitedTask(ofSeconds(10)) { @Override Void runTask() throws Exception { cache.remove(2L); @@ -484,7 +494,7 @@ public void testTerminationThenClear() throws Exception { CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .using(statisticsService) - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts().write(Duration.of(1, ChronoUnit.SECONDS)).build()) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("simple-cache", @@ -499,10 +509,10 @@ public void testTerminationThenClear() throws Exception { cache.put(2L, "deux"); cache.put(3L, "trois"); - CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.get().getClusterControl().terminateAllServers(); // The resilience strategy will pick it up and not exception is thrown - new TimeLimitedTask(10, TimeUnit.SECONDS) { + new TimeLimitedTask(ofSeconds(10)) { @Override Void runTask() { cache.clear(); @@ -523,7 +533,7 @@ public void testTerminationFreezesTheClient() throws Exception { try(PersistentCacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/").resolve(testName.getMethodName())) + .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.get().getConnectionURI().resolve("/").resolve(testName.getMethodName())) .timeouts(TimeoutsBuilder.timeouts() .read(readOperationTimeout)) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) @@ -536,7 +546,7 @@ public void testTerminationFreezesTheClient() throws Exception { Cache cache = cacheManager.getCache("simple-cache", Long.class, String.class); cache.put(1L, "un"); - CLUSTER.getClusterControl().terminateAllServers(); + CLUSTER.get().getClusterControl().terminateAllServers(); // Fill the inflight queue and check that we wait no longer than the read timeout for (int i = 0; i < CLIENT_MAX_PENDING_REQUESTS; i++) { @@ -544,7 +554,7 @@ public void testTerminationFreezesTheClient() throws Exception { } // The resilience strategy will pick it up and not exception is thrown - new TimeLimitedTask(readOperationTimeout.toMillis() * 2, TimeUnit.MILLISECONDS) { // I multiply by 2 to let some room after the expected timeout + new TimeLimitedTask(readOperationTimeout.multipliedBy(2)) { // I multiply by 2 to let some room after the expected timeout @Override Void runTask() { cache.get(1L); // the call that could block @@ -576,14 +586,12 @@ private abstract class TimeLimitedTask { * and test task completion & thread interrupt clear. */ private final byte[] lock = new byte[0]; - private final long timeLimit; - private final TimeUnit unit; + private final Duration timeLimit; private volatile boolean isDone = false; private volatile boolean isExpired = false; - private TimeLimitedTask(long timeLimit, TimeUnit unit) { + private TimeLimitedTask(Duration timeLimit) { this.timeLimit = timeLimit; - this.unit = unit; } /** @@ -596,7 +604,7 @@ private TimeLimitedTask(long timeLimit, TimeUnit unit) { /** * Invokes {@link #runTask()} under a time limit. If {@code runTask} execution exceeds the amount of - * time specified in the {@link TimeLimitedTask#TimeLimitedTask(long, TimeUnit) constructor}, the task + * time specified in the {@link TimeLimitedTask#TimeLimitedTask(Duration) constructor}, the task * {@code Thread} is first interrupted and, if the thread remains alive for another duration of the time * limit, the thread is forcefully stopped using {@link Thread#stop()}. * @@ -609,7 +617,7 @@ private TimeLimitedTask(long timeLimit, TimeUnit unit) { V run() throws Exception { V result; - Future future = interruptAfter(timeLimit, unit); + Future future = interruptAfter(timeLimit); try { result = this.runTask(); } finally { @@ -618,7 +626,7 @@ V run() throws Exception { future.cancel(true); Thread.interrupted(); // Reset interrupted status } - assertThat(isExpired).describedAs( "%s test thread exceeded its time limit of %d %s", testName.getMethodName(), timeLimit, unit).isFalse(); + assertThat(isExpired).describedAs( "%s test thread exceeded its time limit of %s", testName.getMethodName(), timeLimit).isFalse(); } return result; @@ -629,15 +637,14 @@ V run() throws Exception { * If the timeout expires, a thread dump is taken and the current thread interrupted. * * @param interval the amount of time to wait - * @param unit the unit for {@code interval} * * @return a {@code Future} that may be used to cancel the timeout. */ - private Future interruptAfter(final long interval, final TimeUnit unit) { + private Future interruptAfter(Duration interval) { final Thread targetThread = Thread.currentThread(); FutureTask killer = new FutureTask<>(() -> { try { - unit.sleep(interval); + Thread.sleep(interval.toMillis()); if (!isDone && targetThread.isAlive()) { synchronized (lock) { if (isDone) { @@ -656,7 +663,7 @@ private Future interruptAfter(final long interval, final TimeUnit unit) { * looping wait where the interrupt status is recorded but ignored until the awaited event * occurs. */ - unit.timedJoin(targetThread, interval); + targetThread.join(interval.toMillis()); if (!isDone && targetThread.isAlive()) { System.out.format("%s test thread did not respond to Thread.interrupt; forcefully stopping %s%n", testName.getMethodName(), targetThread); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java index cf0ed9b677..381c9daef3 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java @@ -38,22 +38,15 @@ public class CMClosedEventSentTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "64" - + "" - + "\n" - + "" - + "" - + "5" - + "" - + ""; - @ClassRule - public static ClusterWithManagement CLUSTER = new ClusterWithManagement(newCluster() - .in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); + public static ClusterWithManagement CLUSTER = new ClusterWithManagement( + newCluster().in(clusterPath()).withServiceFragment( + "" + + "" + + "64" + + "64" + + "" + + "").build()); @Test(timeout = 60_000) public void test_CACHE_MANAGER_CLOSED() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java index 7cc3e07ebe..6dae15cd78 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java @@ -31,6 +31,7 @@ import org.terracotta.management.model.context.ContextContainer; import org.terracotta.management.model.stats.ContextualStatistics; +import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -43,6 +44,8 @@ import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.Matchers.arrayContainingInAnyOrder; +import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ClusteringManagementServiceTest extends AbstractClusteringManagementTest { @@ -140,8 +143,13 @@ public void test_A_topology() throws Exception { @Test public void test_A_client_tags_exposed() throws Exception { - String[] tags = readTopology().getClient(ehcacheClientIdentifier).get().getTags().toArray(new String[0]); - assertThat(tags).containsOnly("server-node-1", "webapp-1"); + assertThatEventually(() -> { + try { + return readTopology().getClient(ehcacheClientIdentifier).get().getTags().toArray(new String[0]); + } catch (Exception e) { + throw new AssertionError(e); + } + }, arrayContainingInAnyOrder("server-node-1", "webapp-1")).within(Duration.ofSeconds(5)); } @Test diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index 8786af138f..5c61934511 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -26,10 +26,13 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; +import org.ehcache.testing.TestRetryer; +import org.ehcache.testing.TestRetryer.OutputIs; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.terracotta.management.model.capabilities.descriptors.Settings; @@ -38,7 +41,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Stream; +import static java.time.Duration.ofSeconds; +import static java.time.temporal.ChronoUnit.SECONDS; +import static java.util.EnumSet.of; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.clustered.management.AbstractClusteringManagementTest.waitForAllNotifications; @@ -46,6 +53,7 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.ehcache.testing.TestRetryer.tryValues; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; @@ -54,37 +62,37 @@ public class ManagementClusterConnectionTest extends ClusteredTests { - private static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "64" - + "" - + "\n" - + "" - + "" - + "5" - + "" - + ""; - protected static CacheManager cacheManager; protected static ObjectMapper mapper = new ObjectMapper(); private static final List proxies = new ArrayList<>(); - @ClassRule - public static ClusterWithManagement CLUSTER = new ClusterWithManagement(newCluster() - .in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build()); - + @ClassRule @Rule + public static TestRetryer CLUSTER = tryValues( + Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), + leaseLength -> new ClusterWithManagement( + newCluster().in(clusterPath()).withServiceFragment( + "" + + "" + + "64" + + "64" + + "" + + "\n" + + "" + + "" + + "" + leaseLength.get(SECONDS) + "" + + "" + + "").build()), + of(OutputIs.CLASS_RULE)); @BeforeClass public static void beforeClass() throws Exception { mapper.configure(SerializationFeature.INDENT_OUTPUT, true); - CLUSTER.getCluster().getClusterControl().waitForActive(); + CLUSTER.get().getCluster().getClusterControl().waitForActive(); - URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.getCluster().getConnectionURI(), proxies); + URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getCluster().getConnectionURI(), proxies); cacheManager = newCacheManagerBuilder() // cluster config @@ -111,7 +119,7 @@ public static void beforeClass() throws Exception { assertThat(cacheManager.getStatus(), equalTo(Status.AVAILABLE)); // test_notifs_sent_at_CM_init - waitForAllNotifications(CLUSTER.getNmsService(), + waitForAllNotifications(CLUSTER.get().getNmsService(), "CLIENT_CONNECTED", "CLIENT_PROPERTY_ADDED", "CLIENT_PROPERTY_ADDED", @@ -129,7 +137,7 @@ public static void beforeClass() throws Exception { @Test public void test_reconnection() throws Exception { - long count = CLUSTER.getNmsService().readTopology().clientStream() + long count = CLUSTER.get().getNmsService().readTopology().clientStream() .filter(client -> client.getName() .startsWith("Ehcache:") && client.isManageable() && client.getTags() .containsAll(Arrays.asList("webapp-1", "server-node-1"))) @@ -139,10 +147,13 @@ public void test_reconnection() throws Exception { String instanceId = getInstanceId(); - setDelay(6000, proxies); - Thread.sleep(6000); - - setDelay(0L, proxies); + long delay = CLUSTER.input().plusSeconds(1L).toMillis(); + setDelay(delay, proxies); + try { + Thread.sleep(delay); + } finally { + setDelay(0L, proxies); + } Cache cache = cacheManager.getCache("dedicated-cache-1", String.class, String.class); String initiate_reconnect = cache.get("initiate reconnect"); @@ -151,7 +162,7 @@ public void test_reconnection() throws Exception { assertThatEventually(() -> { try { - return CLUSTER.getNmsService().readTopology().clientStream() + return CLUSTER.get().getNmsService().readTopology().clientStream() .filter(client -> client.getName() .startsWith("Ehcache:") && client.isManageable() && client.getTags() .containsAll(Arrays.asList("webapp-1", "server-node-1"))) @@ -164,7 +175,7 @@ public void test_reconnection() throws Exception { } private String getInstanceId() throws Exception { - return CLUSTER.getNmsService().readTopology().clientStream() + return CLUSTER.get().getNmsService().readTopology().clientStream() .filter(client -> client.getName().startsWith("Ehcache:") && client.isManageable()) .findFirst().get() .getManagementRegistry().get() diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java index 25619a4cb1..6bfb47fa3d 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java @@ -28,20 +28,29 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.testing.TestRetryer; +import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.BeforeClass; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; import java.net.URI; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; +import static java.time.Duration.ofSeconds; +import static java.time.temporal.ChronoUnit.SECONDS; +import static java.util.EnumSet.of; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; +import static org.ehcache.testing.TestRetryer.tryValues; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; @@ -50,17 +59,6 @@ import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; public class BasicCacheReconnectTest extends ClusteredTests { - public static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" - + "\n" - + "" - + "" - + "5" - + "" - + ""; private static PersistentCacheManager cacheManager; @@ -72,15 +70,27 @@ public class BasicCacheReconnectTest extends ClusteredTests { private static final List proxies = new ArrayList<>(); - @ClassRule - public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + @ClassRule @Rule + public static final TestRetryer CLUSTER = tryValues( + Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), + leaseLength -> newCluster().in(clusterPath()).withServiceFragment( + "" + + "" + + "64" + + "" + + "\n" + + "" + + "" + + "" + leaseLength.get(SECONDS) + "" + + "" + + "").build(), + of(OutputIs.CLASS_RULE)); @BeforeClass public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); + CLUSTER.get().getClusterControl().waitForActive(); - URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.getConnectionURI(), proxies); + URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getConnectionURI(), proxies); CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() @@ -157,10 +167,13 @@ public void reconnectDuringCacheDestroy() throws Exception { } - private static void expireLease() throws InterruptedException { - setDelay(6000, proxies); - Thread.sleep(6000); - - setDelay(0L, proxies); + private void expireLease() throws InterruptedException { + long delay = CLUSTER.input().plusSeconds(1L).toMillis(); + setDelay(delay, proxies); + try { + Thread.sleep(delay); + } finally { + setDelay(0L, proxies); + } } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java index 64164e321e..00c606491e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java @@ -21,17 +21,25 @@ import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.util.TCPProxyUtil; import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.testing.TestRetryer; +import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.BeforeClass; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; import java.net.URI; +import java.time.Duration; import java.util.ArrayList; import java.util.List; +import java.util.stream.Stream; -import static org.ehcache.clustered.reconnect.BasicCacheReconnectTest.RESOURCE_CONFIG; +import static java.time.Duration.ofSeconds; +import static java.time.temporal.ChronoUnit.SECONDS; +import static java.util.EnumSet.of; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; +import static org.ehcache.testing.TestRetryer.tryValues; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; public class CacheManagerDestroyReconnectTest extends ClusteredTests { @@ -41,15 +49,27 @@ public class CacheManagerDestroyReconnectTest extends ClusteredTests { private static final List proxies = new ArrayList<>(); - @ClassRule - public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + @ClassRule @Rule + public static final TestRetryer CLUSTER = tryValues( + Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), + leaseLength -> newCluster().in(clusterPath()).withServiceFragment( + "" + + "" + + "64" + + "" + + "\n" + + "" + + "" + + "" + leaseLength.get(SECONDS) + "" + + "" + + "").build(), + of(OutputIs.CLASS_RULE)); @BeforeClass public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); + CLUSTER.get().getClusterControl().waitForActive(); - URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.getConnectionURI(), proxies); + URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getConnectionURI(), proxies); CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() @@ -62,10 +82,13 @@ public static void waitForActive() throws Exception { @Test public void testDestroyCacheManagerReconnects() throws Exception { - setDelay(6000, proxies); - Thread.sleep(6000); - - setDelay(0L, proxies); + long delay = CLUSTER.input().plusSeconds(1L).toMillis(); + setDelay(delay, proxies); + try { + Thread.sleep(delay); + } finally { + setDelay(0L, proxies); + } cacheManager.close(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index 5623dc5978..34291fe8ab 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -32,8 +32,11 @@ import org.ehcache.event.CacheEvent; import org.ehcache.event.CacheEventListener; import org.ehcache.event.EventType; +import org.ehcache.testing.TestRetryer; +import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.BeforeClass; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; @@ -49,8 +52,13 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; +import static java.time.Duration.ofSeconds; +import static java.time.temporal.ChronoUnit.SECONDS; +import static java.util.EnumSet.of; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; +import static org.ehcache.testing.TestRetryer.tryValues; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.junit.Assert.assertThat; @@ -59,18 +67,7 @@ import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; public class EventsReconnectTest extends ClusteredTests { - private static final Duration TIMEOUT = Duration.ofSeconds(5); - public static final String RESOURCE_CONFIG = - "" - + "" - + "64" - + "" - + "\n" - + "" - + "" - + "5" - + "" - + ""; + private static final Duration TIMEOUT = ofSeconds(5); private static PersistentCacheManager cacheManager; @@ -108,15 +105,27 @@ final void clear() { private static final List proxies = new ArrayList<>(); - @ClassRule - public static Cluster CLUSTER = - newCluster().in(clusterPath()).withServiceFragment(RESOURCE_CONFIG).build(); + @ClassRule @Rule + public static final TestRetryer CLUSTER = tryValues( + Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), + leaseLength -> newCluster().in(clusterPath()).withServiceFragment( + "" + + "" + + "64" + + "" + + "\n" + + "" + + "" + + "" + leaseLength.get(SECONDS) + "" + + "" + + "").build(), + of(OutputIs.CLASS_RULE)); @BeforeClass public static void waitForActive() throws Exception { - CLUSTER.getClusterControl().waitForActive(); + CLUSTER.get().getClusterControl().waitForActive(); - URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.getConnectionURI(), proxies); + URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getConnectionURI(), proxies); CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() @@ -168,11 +177,13 @@ public void eventsFlowAgainAfterReconnection() throws Exception { } } - private static void expireLease() throws InterruptedException { - setDelay(6000, proxies); - Thread.sleep(6000); - - setDelay(0L, proxies); + long delay = CLUSTER.input().plusSeconds(1L).toMillis(); + setDelay(delay, proxies); + try { + Thread.sleep(delay); + } finally { + setDelay(0L, proxies); + } } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ExecutorScheduler.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ExecutorScheduler.java index fc60a33b9a..ab75dfbb87 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ExecutorScheduler.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ExecutorScheduler.java @@ -20,25 +20,33 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; public class ExecutorScheduler implements RunnerScheduler { - public final ExecutorService executor; + public final Supplier executorSupplier; + public final AtomicReference executor = new AtomicReference<>(); - public ExecutorScheduler(ExecutorService executor) { - this.executor = executor; + public ExecutorScheduler(Supplier executorSupplier) { + this.executorSupplier = executorSupplier; } @Override public void schedule(Runnable childStatement) { - executor.execute(childStatement); + ExecutorService executorService; + while ((executorService = executor.get()) == null && !executor.compareAndSet(null, (executorService = executorSupplier.get()))) { + executorService.shutdown(); + } + executorService.execute(childStatement); } @Override public void finished() { - executor.shutdown(); + ExecutorService departing = executor.getAndSet(null); + departing.shutdown(); try { - if (!executor.awaitTermination(1, TimeUnit.DAYS)) { + if (!departing.awaitTermination(1, TimeUnit.DAYS)) { throw new AssertionError(new TimeoutException()); } } catch (InterruptedException e) { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/Parallel.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/Parallel.java index 60dd8797dd..2876eeaffd 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/Parallel.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/Parallel.java @@ -24,6 +24,6 @@ public class Parallel extends BlockJUnit4ClassRunner { public Parallel(Class klass) throws InitializationError { super(klass); - setScheduler(new ExecutorScheduler(newCachedThreadPool(r -> new Thread(r, "TestRunner-Thread-" + klass)))); + setScheduler(new ExecutorScheduler(() -> newCachedThreadPool(r -> new Thread(r, "TestRunner-Thread-" + klass)))); } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ParallelParameterized.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ParallelParameterized.java index 32364286f7..3c64e2ba32 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ParallelParameterized.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ParallelParameterized.java @@ -24,10 +24,10 @@ public class ParallelParameterized extends Parameterized { public ParallelParameterized(Class klass) throws Throwable { super(klass); - setScheduler(new ExecutorScheduler(newCachedThreadPool(r -> new Thread(r, "TestRunner-Thread-" + klass)))); + setScheduler(new ExecutorScheduler(() -> newCachedThreadPool(r -> new Thread(r, "TestRunner-Thread-" + klass)))); getChildren().forEach(child -> { if (child instanceof ParentRunner) { - ((ParentRunner) child).setScheduler(new ExecutorScheduler(newCachedThreadPool(r -> new Thread(r, "TestRunner-Thread-" + r.toString())))); + ((ParentRunner) child).setScheduler(new ExecutorScheduler(() -> newCachedThreadPool(r -> new Thread(r, "TestRunner-Thread-" + r.toString())))); } }); } diff --git a/management/build.gradle b/management/build.gradle index ffa4b3a93e..39862e432e 100644 --- a/management/build.gradle +++ b/management/build.gradle @@ -39,4 +39,5 @@ dependencies { testImplementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" testImplementation 'org.xmlunit:xmlunit-core:2.6.0' testImplementation 'org.xmlunit:xmlunit-matchers:2.6.0' + testImplementation project(':test-utilities') } diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java index 83560a2430..5c54ee2788 100755 --- a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java @@ -29,8 +29,11 @@ import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; import org.ehcache.management.registry.DefaultManagementRegistryService; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; +import org.ehcache.testing.TestRetryer; import org.junit.After; import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.terracotta.management.model.context.Context; import org.terracotta.management.model.stats.ContextualStatistics; @@ -46,23 +49,25 @@ import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; -import java.util.stream.IntStream; +import java.util.stream.Stream; +import static java.time.Duration.ofMillis; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.ehcache.core.statistics.StatsUtils.findOperationStatisticOnChildren; +import static org.ehcache.testing.TestRetryer.tryValues; public class StandardEhcacheStatisticsTest { - private static final int HISTOGRAM_WINDOW_MILLIS = 400; - private static final int NEXT_WINDOW_SLEEP_MILLIS = 500; + @ClassRule @Rule + public static final TestRetryer TIME_BASE = tryValues(Stream.of(1, 2, 4, 8, 16, 32).map(i -> ofMillis(50).multipliedBy(i))); private CacheManager cacheManager; private Cache cache; private ManagementRegistryService managementRegistry; private Context context; - private long latency; + private Duration latency = Duration.ZERO; private final Map systemOfRecords = new HashMap<>(); @Before @@ -99,7 +104,7 @@ public void delete(Long key) { LatencyHistogramConfiguration latencyHistogramConfiguration = new LatencyHistogramConfiguration( LatencyHistogramConfiguration.DEFAULT_PHI, LatencyHistogramConfiguration.DEFAULT_BUCKET_COUNT, - Duration.ofMillis(HISTOGRAM_WINDOW_MILLIS) + TIME_BASE.get().multipliedBy(8L) ); DefaultManagementRegistryConfiguration registryConfiguration = new DefaultManagementRegistryConfiguration() .setCacheManagerAlias("myCacheManager3") @@ -162,25 +167,25 @@ public void getCacheGetHitMissLatencies() { Consumer verifier = histogram -> { assertThat(histogram.count()).isEqualTo(0L); - latency = 100; + latency = TIME_BASE.get().multipliedBy(2L); cache.get(1L); - latency = 50; + latency = TIME_BASE.get().multipliedBy(1L); cache.get(2L); assertThat(histogram.count()).isEqualTo(2L); - assertThat(histogram.maximum()).isGreaterThanOrEqualTo(TimeUnit.MILLISECONDS.toNanos(100L)); + assertThat(histogram.maximum()).isGreaterThanOrEqualTo(TIME_BASE.get().multipliedBy(2L).toNanos()); - minimumSleep(NEXT_WINDOW_SLEEP_MILLIS); + minimumSleep(TIME_BASE.get().multipliedBy(10)); - latency = 50; + latency = TIME_BASE.get().multipliedBy(1L); cache.get(3L); - latency = 150; + latency = TIME_BASE.get().multipliedBy(3L); cache.get(4L); assertThat(histogram.count()).isEqualTo(2L); - assertThat(histogram.maximum()).isGreaterThanOrEqualTo(TimeUnit.MILLISECONDS.toNanos(150L)); + assertThat(histogram.maximum()).isGreaterThanOrEqualTo(TIME_BASE.get().multipliedBy(3L).toNanos()); }; verifier.accept(getHistogram(CacheOperationOutcomes.GetOutcome.MISS, "get")); @@ -217,8 +222,8 @@ private > LatencyHistogramStatistic getHistogram(T type, Strin // Using System.nanoTime (accurate to 1 micro-second or better) in lieu of System.currentTimeMillis (on Windows // accurate to ~16ms), the inaccuracy of which compounds when invoked multiple times, as in this method. - private void minimumSleep(long millis) { - long end = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(millis); + private void minimumSleep(Duration sleep) { + long end = System.nanoTime() + sleep.toNanos(); while (true) { long nanosLeft = end - System.nanoTime(); diff --git a/settings.gradle b/settings.gradle index 5af54e753a..3d89ecf10a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -27,7 +27,7 @@ pluginManagement { } } -include "api", "spi-tester", "core", "core-spi-test", "impl", "management", "transactions", "107", "xml", +include "test-utilities", "api", "spi-tester", "core", "core-spi-test", "impl", "management", "transactions", "107", "xml", "clustered", "clustered:common-api", "clustered:common", "clustered:server:service-api", "clustered:server:service", "clustered:server:entity", "clustered:client", "clustered:clustered-dist", "clustered:ops-tool", diff --git a/test-utilities/build.gradle b/test-utilities/build.gradle new file mode 100644 index 0000000000..5f022305d9 --- /dev/null +++ b/test-utilities/build.gradle @@ -0,0 +1,3 @@ +dependencies { + api "junit:junit:$junitVersion" +} diff --git a/test-utilities/config/checkstyle-suppressions.xml b/test-utilities/config/checkstyle-suppressions.xml new file mode 100644 index 0000000000..be989c924a --- /dev/null +++ b/test-utilities/config/checkstyle-suppressions.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/test-utilities/src/main/java/org/ehcache/testing/TestRetryer.java b/test-utilities/src/main/java/org/ehcache/testing/TestRetryer.java new file mode 100644 index 0000000000..a19fd833df --- /dev/null +++ b/test-utilities/src/main/java/org/ehcache/testing/TestRetryer.java @@ -0,0 +1,214 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.testing; + +import org.junit.AssumptionViolatedException; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import static java.util.Arrays.asList; +import static java.util.Collections.max; +import static java.util.Objects.requireNonNull; +import static java.util.stream.Collectors.joining; +import static org.junit.Assert.assertTrue; + +public class TestRetryer implements TestRule, Supplier { + + private static final Logger LOGGER = LoggerFactory.getLogger(TestRetryer.class); + + private final Function mapper; + private final Set outputIs; + private final Stream inputs; + + private final AtomicReference inputRef = new AtomicReference<>(); + private final AtomicReference outputRef = new AtomicReference<>(); + + private volatile boolean isClassRule = false; + private volatile boolean isRule = false; + + private volatile boolean terminalAttempt = false; + private volatile Map attemptResults = Collections.emptyMap(); + + private final Map accumulatedFailures = new ConcurrentHashMap<>(); + + @SafeVarargs @SuppressWarnings("varargs") // Creating a stream from an array is safe + public static TestRetryer tryValues(T... values) { + return tryValues(Stream.of(values)); + } + + public static TestRetryer tryValues(Stream values) { + return tryValues(values, Function.identity()); + } + + public static TestRetryer tryValues(Stream values, Function mapper) { + return tryValues(values, mapper, EnumSet.noneOf(OutputIs.class)); + } + + public static TestRetryer tryValues(Stream values, Function mapper, Set outputIs) { + return new TestRetryer<>(values, mapper, outputIs); + } + + private TestRetryer(Stream values, Function mapper, Set outputIs) { + this.inputs = values.map(Objects::requireNonNull); + this.mapper = requireNonNull(mapper); + this.outputIs = requireNonNull(outputIs); + } + + @Override + public Statement apply(Statement base, Description description) { + if (description.isTest()) { + isRule = true; + if (!isClassRule) { + throw new AssertionError(getClass().getSimpleName() + " must be annotated with both @ClassRule and @Rule"); + } + Statement target; + R output = get(); + if (output instanceof TestRule && outputIs.contains(OutputIs.RULE)) { + target = ((TestRule) output).apply(base, description); + } else { + target = base; + } + + return new Statement() { + @Override + public void evaluate() throws Throwable { + try { + target.evaluate(); + } catch (Throwable t) { + throw handleTestException(description, t); + } finally { + attemptResults.putIfAbsent(description, "PASSED"); + } + } + }; + } else { + isClassRule = true; + return new Statement() { + @Override + public void evaluate() throws Throwable { + Iterator iterator = inputs.iterator(); + while (iterator.hasNext()) { + T input = iterator.next(); + terminalAttempt = !iterator.hasNext(); + attemptResults = new ConcurrentHashMap<>(); + LOGGER.debug("{}: attempting with input value {}", description, input); + assertTrue(inputRef.compareAndSet(null, input)); + try { + R output = mapper.apply(input); + LOGGER.debug("{}: input {} maps to {}", description, input, output); + assertTrue(outputRef.compareAndSet(null, output)); + try { + if (output instanceof TestRule && outputIs.contains(OutputIs.CLASS_RULE)) { + ((TestRule) output).apply(base, description).evaluate(); + } else { + base.evaluate(); + } + } catch (Throwable t) { + throw handleTestException(description, t); + } finally { + assertTrue(outputRef.compareAndSet(output, null)); + } + } finally { + assertTrue(inputRef.compareAndSet(input, null)); + } + if (!isRule) { + throw new AssertionError(TestRetryer.this.getClass().getSimpleName() + " must be annotated with both @ClassRule and @Rule"); + } else if (attemptResults.values().stream().noneMatch(Throwable.class::isInstance)) { + LOGGER.debug("{}: successful with input value {}", description, input); + return; + } else { + LOGGER.info("{}: failed with input value {}\n{}", description, input, + attemptResults.entrySet().stream().map(e -> { + String testMethodHeader = e.getKey().getMethodName() + ": "; + return indent(testMethodHeader + e.getValue().toString(), 4, 4 + testMethodHeader.length()); + }).collect(joining("\n")) + ); + } + } + } + }; + } + } + + private Throwable handleTestException(Description description, Throwable t) { + Throwable failure = (Throwable) attemptResults.merge(description, t, (a, b) -> { + if (a instanceof Throwable) { + ((Throwable) a).addSuppressed((Throwable) b); + return a; + } else { + return b; + } + }); + Throwable merged = accumulatedFailures.merge(description, t, (a, b) -> { + b.addSuppressed(a); + return b; + }); + if (isTerminalAttempt()) { + return merged; + } else { + return new AssumptionViolatedException("Failure for input parameter: " + input(), failure); + } + } + + public T input() { + return requireNonNull(inputRef.get()); + } + + public R get() { + return requireNonNull(outputRef.get()); + } + + private boolean isTerminalAttempt() { + return terminalAttempt; + } + + public enum OutputIs { + RULE, CLASS_RULE; + } + + private static CharSequence indent(String string, Integer ... indent) { + char[] chars = new char[max(asList(indent))]; + Arrays.fill(chars, ' '); + String indentStrings = new String(chars); + String[] strings = string.split("(?m)^"); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < strings.length; i++) { + if (i < indent.length) { + sb.append(indentStrings, 0, indent[i]); + } else { + sb.append(indentStrings, 0, indent[indent.length - 1]); + } + sb.append(strings[i]); + } + return sb; + } +} diff --git a/test-utilities/src/test/java/org/ehcache/testing/TestRetryerTest.java b/test-utilities/src/test/java/org/ehcache/testing/TestRetryerTest.java new file mode 100644 index 0000000000..33e26bbc88 --- /dev/null +++ b/test-utilities/src/test/java/org/ehcache/testing/TestRetryerTest.java @@ -0,0 +1,191 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.testing; + +import org.junit.Assert; +import org.junit.ClassRule; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.JUnitCore; +import org.junit.runner.Result; +import org.junit.runners.JUnit4; +import org.junit.runners.model.InitializationError; + +import static org.hamcrest.Matchers.array; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.internal.matchers.ThrowableMessageMatcher.hasMessage; + +public class TestRetryerTest { + + @Test @SuppressWarnings("unchecked") + public void testExceptionsSuppressProperly() throws InitializationError { + Result result = new JUnitCore().run(new JUnit4(RepeatedFailure.class)); + + assertThat(result.getFailureCount(), is(1)); + + Throwable exception = result.getFailures().get(0).getException(); + assertThat(exception, hasMessage(equalTo("Failed: 4"))); + assertThat(exception.getSuppressed(), array(hasMessage(equalTo("Failed: 3")))); + assertThat(exception.getSuppressed()[0].getSuppressed(), array(hasMessage(equalTo("Failed: 2")))); + assertThat(exception.getSuppressed()[0].getSuppressed()[0].getSuppressed(), array(hasMessage(equalTo("Failed: 1")))); + } + + @Test + public void testNoRetryOnImmediateSuccess() throws InitializationError { + Result result = new JUnitCore().run(new JUnit4(ImmediateSuccess.class)); + assertTrue(result.wasSuccessful()); + assertThat(result.getFailureCount(), is(0)); + assertThat(result.getRunCount(), is(1)); + } + + @Test + public void testRetryAndPassOnEventualSuccess() throws InitializationError { + Result result = new JUnitCore().run(new JUnit4(EventualSuccess.class)); + + assertTrue(result.wasSuccessful()); + assertThat(result.getFailureCount(), is(0)); + assertThat(result.getRunCount(), is(4)); + } + + @Test + public void testMissingClassRuleAnnotationTriggersFailure() throws InitializationError { + Result result = new JUnitCore().run(new JUnit4(MissingClassRuleAnnotation.class)); + + assertFalse(result.wasSuccessful()); + assertThat(result.getRunCount(), is(0)); + assertThat(result.getFailureCount(), is(1)); + Throwable throwable = result.getFailures().get(0).getException(); + assertThat(throwable, hasMessage(is("TestRetryer must be annotated with both @ClassRule and @Rule"))); + } + + @Test + public void testMissingRuleAnnotationTriggersFailure() throws InitializationError { + Result result = new JUnitCore().run(new JUnit4(MissingRuleAnnotation.class)); + + assertFalse(result.wasSuccessful()); + assertThat(result.getRunCount(), is(1)); + assertThat(result.getFailureCount(), is(1)); + Throwable throwable = result.getFailures().get(0).getException(); + assertThat(throwable, hasMessage(is("TestRetryer must be annotated with both @ClassRule and @Rule"))); + } + + @Test + public void testEffectivelyEmptyTestIsSafe() throws InitializationError { + Result result = new JUnitCore().run(new JUnit4(EffectivelyEmptyTest.class)); + + assertTrue(result.wasSuccessful()); + assertThat(result.getIgnoreCount(), is(1)); + assertThat(result.getRunCount(), is(0)); + assertThat(result.getFailureCount(), is(0)); + } + + @Test + public void testFailingTestLogsCorrectly() throws InitializationError { + Result result = new JUnitCore().run(new JUnit4(PartiallyFailingThenPassingTest.class)); + + assertTrue(result.wasSuccessful()); + assertThat(result.getFailureCount(), is(0)); + assertThat(result.getRunCount(), is(6)); + } + + @Ignore + public static class RepeatedFailure { + + @ClassRule @Rule + public static TestRetryer RETRYER = TestRetryer.tryValues(1, 2, 3, 4); + + @Test + public void test() { + Assert.fail("Failed: " + RETRYER.get()); + } + } + + @Ignore + public static class ImmediateSuccess { + + @ClassRule @Rule + public static TestRetryer RETRYER = TestRetryer.tryValues(1, 2, 3, 4); + + @Test + public void test() {} + } + + @Ignore + public static class EventualSuccess { + + @ClassRule @Rule + public static TestRetryer RETRYER = TestRetryer.tryValues(1, 2, 3, 4); + + @Test + public void test() { + Assert.assertThat(RETRYER.get(), is(4)); + } + } + + @Ignore + public static class MissingClassRuleAnnotation { + + @Rule + public TestRetryer RETRYER = TestRetryer.tryValues(1, 2, 3, 4); + + @Test + public void test() { + } + } + + @Ignore + public static class MissingRuleAnnotation { + + @ClassRule + public static TestRetryer RETRYER = TestRetryer.tryValues(1, 2, 3, 4); + + @Test + public void test() { + } + } + + @Ignore + public static class EffectivelyEmptyTest { + + @ClassRule @Rule + public static TestRetryer RETRYER = TestRetryer.tryValues(1, 2, 3, 4); + + @Test @Ignore + public void test() { + } + } + + @Ignore + public static class PartiallyFailingThenPassingTest { + + @ClassRule @Rule + public static TestRetryer RETRYER = TestRetryer.tryValues(1, 2, 3, 4); + + @Test + public void passingTest() { + } + + @Test + public void failingTest() { + assertThat(RETRYER.get(), is(3)); + } + } +} From 66717427466e802ab27f8a576800970ac7dc9103 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Fri, 1 May 2020 09:42:21 -0700 Subject: [PATCH 248/372] Bump to the latest tc artifacts Co-authored-by: Chris Dennis --- .../org/ehcache/jsr107/StatisticsTest.java | 8 ++-- .../clustered/client/ClusteredEventsTest.java | 12 ++++-- .../service/ConnectionClosedTest.java | 4 +- .../ActivePassiveClientIdTest.java | 3 ++ .../BasicCacheOpsMultiThreadedTest.java | 4 +- .../clustered/EventsFailureBehaviorTest.java | 42 +++++++++---------- .../java/org/ehcache/clustered/LeaseTest.java | 4 +- .../clustered/ReconnectDuringDestroyTest.java | 4 +- .../ClusteringManagementServiceTest.java | 7 ++-- .../ManagementClusterConnectionTest.java | 6 +-- .../reconnect/AutoCreateOnReconnectTest.java | 7 ++-- .../reconnect/EventsReconnectTest.java | 4 +- .../clustered/sync/PassiveSyncTest.java | 4 +- .../java/org/ehcache/osgi/OsgiTestUtils.java | 17 ++++---- .../EhcacheMessageTrackerMessage.java | 1 + .../server/store/ClusterTierActiveEntity.java | 1 + .../store/ClusterTierPassiveEntity.java | 1 + gradle.properties | 10 ++--- 18 files changed, 75 insertions(+), 64 deletions(-) diff --git a/107/src/test/java/org/ehcache/jsr107/StatisticsTest.java b/107/src/test/java/org/ehcache/jsr107/StatisticsTest.java index 1bb909d7c8..5064e6a396 100644 --- a/107/src/test/java/org/ehcache/jsr107/StatisticsTest.java +++ b/107/src/test/java/org/ehcache/jsr107/StatisticsTest.java @@ -33,7 +33,7 @@ import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.lessThan; -import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; +import static org.terracotta.utilities.test.matchers.Eventually.within; /** * @author Ludovic Orban @@ -209,7 +209,7 @@ public void test_getAverageGetTime() throws Exception { heapCache.get("key"); heapCache.get("key"); - assertThatEventually(() -> heapStatistics.getAverageGetTime(), greaterThan(0.0f)).within(Duration.ofMillis(1100)); + assertThat(heapStatistics::getAverageGetTime, within(Duration.ofMillis(1100)).matches(greaterThan(0.0f))); } @Test @@ -222,7 +222,7 @@ public void test_getAveragePutTime() throws Exception { heapCache.put("key", "value"); heapCache.put("key", "value"); - assertThatEventually(() -> heapStatistics.getAveragePutTime(), greaterThan(0.0f)).within(Duration.ofMillis(1100)); + assertThat(heapStatistics::getAveragePutTime, within(Duration.ofMillis(1100)).matches(greaterThan(0.0f))); } @Test @@ -241,6 +241,6 @@ public void test_getAverageRemoveTime() throws Exception { heapCache.remove("key3"); heapCache.remove("key4"); - assertThatEventually(() -> heapStatistics.getAverageRemoveTime(), greaterThan(0.0f)).within(Duration.ofMillis(1100)); + assertThat(heapStatistics::getAverageRemoveTime, within(Duration.ofMillis(1100)).matches(greaterThan(0.0f))); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java index 167004f779..2660f0c185 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java @@ -52,7 +52,7 @@ import static org.hamcrest.collection.IsIterableContainingInOrder.contains; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertThat; -import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; +import static org.terracotta.utilities.test.matchers.Eventually.within; public class ClusteredEventsTest { @@ -112,7 +112,10 @@ public void testNonExpiringEventSequence() throws TimeoutException { updated(1L, "bat", "bag"), removed(1L, "bag")); - assertThatEventually(() -> driverEvents, expectedSequence).and(() -> observerEvents, expectedSequence).within(Duration.ofSeconds(10)); + within(Duration.ofSeconds(10)).runsCleanly(() -> { + assertThat(driverEvents, expectedSequence); + assertThat(observerEvents, expectedSequence); + }); } } } @@ -159,7 +162,10 @@ public void testExpiringEventSequence() throws TimeoutException { created(1L, "baz"), expired(1L, "baz")); - assertThatEventually(() -> driverEvents, expectedSequence).and(() -> observerEvents, expectedSequence).within(Duration.ofSeconds(10)); + within(Duration.ofSeconds(10)).runsCleanly(() -> { + assertThat(driverEvents, expectedSequence); + assertThat(observerEvents, expectedSequence); + }); } } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java index d804bab4e7..960019acc3 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java @@ -40,7 +40,7 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; -import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; +import static org.terracotta.utilities.test.matchers.Eventually.within; public class ConnectionClosedTest { @@ -99,7 +99,7 @@ public void testCacheOperationThrowsAfterConnectionClosed() throws Exception { connections.iterator().next().close(); - assertThatEventually(() -> cache.get(1L), is("value")).within(Duration.ofSeconds(60)); + assertThat(() -> cache.get(1L), within(Duration.ofSeconds(60)).is("value")); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java index c133e3fb50..2d913a3b62 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java @@ -133,6 +133,7 @@ public void tearDown() throws Exception { } @Test + @SuppressWarnings("deprecation") public void messageTrackedAndRemovedWhenClientLeaves() throws Exception { assertThat(activeMessageHandler.getTrackedClients().count()).isZero(); // no client tracked @@ -167,6 +168,7 @@ public void untrackedMessageAreNotStored() throws Exception { } @Test + @SuppressWarnings("deprecation") public void trackedMessagesReplicatedToPassive() throws Exception { clusterControl.terminateOnePassive(); @@ -186,6 +188,7 @@ public void trackedMessagesReplicatedToPassive() throws Exception { } @Test + @SuppressWarnings("deprecation") public void messageTrackedAndRemovedByPassiveWhenClientLeaves() throws Exception { assertThat(passiveMessageHandler.getTrackedClients().count()).isZero(); // nothing tracked right now diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index f8606959ed..7b9fa77d53 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -49,7 +49,7 @@ import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; +import static org.terracotta.utilities.test.matchers.Eventually.within; /** * Simulate multiple clients starting up the same cache manager simultaneously and ensure that puts and gets works just @@ -109,7 +109,7 @@ private Callable content() { assertThat(customValueCache.get(1L), is("value")); synCache.put(firstClientEndKey, true); } else { - assertThatEventually(() -> synCache.get(firstClientEndKey), notNullValue()).within(Duration.ofSeconds(30)); + assertThat(() -> synCache.get(firstClientEndKey), within(Duration.ofSeconds(30)).matches(notNullValue())); assertThat(customValueCache.get(1L), is("value")); } return null; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index 3a94aa862f..70f4a1d288 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -59,7 +59,7 @@ import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; +import static org.terracotta.utilities.test.matchers.Eventually.within; @RunWith(Parallel.class) public class EventsFailureBehaviorTest extends ClusteredTests { @@ -130,7 +130,7 @@ private void failover(Cache cache1, Cache cache2) th CLUSTER.getClusterControl().terminateActive(); // wait for clients to be back in business - assertThatEventually(() -> { + assertThat(() -> { try { cache1.replace(1L, new byte[0], new byte[0]); cache2.replace(1L, new byte[0], new byte[0]); @@ -138,7 +138,7 @@ private void failover(Cache cache1, Cache cache2) th } catch (Exception e) { return false; } - }, is(true)).within(FAILOVER_TIMEOUT); + }, within(FAILOVER_TIMEOUT).is(true)); } @Test @@ -154,10 +154,10 @@ public void testEventsFailover() throws Exception { range(0, KEYS).forEach(k -> { cache1.put(k, value); }); - assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.CREATED), hasSize(greaterThan(0))).within(TIMEOUT); - assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.EVICTED), hasSize(greaterThan(0))).within(TIMEOUT); - assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.CREATED), hasSize(greaterThan(0))).within(TIMEOUT); - assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.EVICTED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThat(() -> accountingCacheEventListener1.events.get(EventType.CREATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + assertThat(() -> accountingCacheEventListener1.events.get(EventType.EVICTED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + assertThat(() -> accountingCacheEventListener2.events.get(EventType.CREATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + assertThat(() -> accountingCacheEventListener2.events.get(EventType.EVICTED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); // failover passive -> active failover(cache1, cache2); @@ -165,20 +165,20 @@ public void testEventsFailover() throws Exception { range(0, KEYS).forEach(k -> { cache1.put(k, value); }); - assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.UPDATED), hasSize(greaterThan(0))).within(TIMEOUT); - assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.UPDATED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThat(() -> accountingCacheEventListener1.events.get(EventType.UPDATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + assertThat(() -> accountingCacheEventListener2.events.get(EventType.UPDATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); range(0, KEYS).forEach(cache1::remove); - assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.REMOVED), hasSize(greaterThan(0))).within(TIMEOUT); - assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.REMOVED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThat(() -> accountingCacheEventListener1.events.get(EventType.REMOVED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + assertThat(() -> accountingCacheEventListener2.events.get(EventType.REMOVED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); range(KEYS, KEYS * 2).forEach(k -> { cache1.put(k, value); }); - assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.CREATED), hasSize(greaterThan(0))).within(TIMEOUT); - assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.EVICTED), hasSize(greaterThan(0))).within(TIMEOUT); - assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.CREATED), hasSize(greaterThan(0))).within(TIMEOUT); - assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.EVICTED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThat(() -> accountingCacheEventListener1.events.get(EventType.CREATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + assertThat(() -> accountingCacheEventListener1.events.get(EventType.EVICTED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + assertThat(() -> accountingCacheEventListener2.events.get(EventType.CREATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + assertThat(() -> accountingCacheEventListener2.events.get(EventType.EVICTED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); } @Test @@ -194,10 +194,10 @@ public void testExpirationFailover() throws Exception { range(0, KEYS).forEach(k -> { cache1.put(k, value); }); - assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.CREATED), hasSize(greaterThan(0))).within(TIMEOUT); - assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.EVICTED), hasSize(greaterThan(0))).within(TIMEOUT); - assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.CREATED), hasSize(greaterThan(0))).within(TIMEOUT); - assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.EVICTED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThat(() -> accountingCacheEventListener1.events.get(EventType.CREATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + assertThat(() -> accountingCacheEventListener1.events.get(EventType.EVICTED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + assertThat(() -> accountingCacheEventListener2.events.get(EventType.CREATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + assertThat(() -> accountingCacheEventListener2.events.get(EventType.EVICTED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); // failover passive -> active failover(cache1, cache2); @@ -205,8 +205,8 @@ public void testExpirationFailover() throws Exception { range(0, KEYS).forEach(k -> { assertThat(cache1.get(k), is(nullValue())); }); - assertThatEventually(() -> accountingCacheEventListener1.events.get(EventType.EXPIRED), hasSize(greaterThan(0))).within(TIMEOUT); - assertThatEventually(() -> accountingCacheEventListener2.events.get(EventType.EXPIRED), hasSize(greaterThan(0))).within(TIMEOUT); + assertThat(() -> accountingCacheEventListener1.events.get(EventType.EXPIRED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + assertThat(() -> accountingCacheEventListener2.events.get(EventType.EXPIRED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java index c70c6a3d3b..83fdb9dd48 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java @@ -55,7 +55,7 @@ import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; +import static org.terracotta.utilities.test.matchers.Eventually.within; @RunWith(Parameterized.class) public class LeaseTest extends ClusteredTests { @@ -119,7 +119,7 @@ public void leaseExpiry() throws Exception { setDelay(0L, proxies); } - assertThatEventually(() -> cache.get(1L), is("The one")).within(Duration.ofSeconds(30)); + assertThat(() -> cache.get(1L), within(Duration.ofSeconds(60)).is("The one")); assertThat(cache.get(2L), equalTo("The two")); assertThat(cache.get(3L), equalTo("The three")); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java index 0e87f4b178..34be9dcc4b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -63,7 +63,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; +import static org.terracotta.utilities.test.matchers.Eventually.within; /** * ReconnectDuringDestroyTest @@ -185,7 +185,7 @@ public void reconnectAfterDestroyOneOfTheCache() throws Exception { } Cache cache2Again = cacheManager.getCache("clustered-cache-2", Long.class, String.class); - assertThatEventually(() -> cache2Again.get(1L), equalTo("The one")).within(ofSeconds(10)); + assertThat(() -> cache2Again.get(1L), within(ofSeconds(10)).is("The one")); assertThat(cache2Again.get(2L), equalTo("The two")); cache2Again.put(3L, "The three"); assertThat(cache2Again.get(3L), equalTo("The three")); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java index 6dae15cd78..f06f9671bb 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java @@ -18,6 +18,7 @@ import org.ehcache.Cache; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; +import org.hamcrest.MatcherAssert; import org.junit.FixMethodOrder; import org.junit.Ignore; import org.junit.Test; @@ -45,7 +46,7 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.hamcrest.Matchers.arrayContainingInAnyOrder; -import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; +import static org.terracotta.utilities.test.matchers.Eventually.within; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ClusteringManagementServiceTest extends AbstractClusteringManagementTest { @@ -143,13 +144,13 @@ public void test_A_topology() throws Exception { @Test public void test_A_client_tags_exposed() throws Exception { - assertThatEventually(() -> { + MatcherAssert.assertThat(() -> { try { return readTopology().getClient(ehcacheClientIdentifier).get().getTags().toArray(new String[0]); } catch (Exception e) { throw new AssertionError(e); } - }, arrayContainingInAnyOrder("server-node-1", "webapp-1")).within(Duration.ofSeconds(5)); + }, within(Duration.ofSeconds(5)).matches(arrayContainingInAnyOrder("server-node-1", "webapp-1"))); } @Test diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index 6d7a1511aa..2762d99a93 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -62,7 +62,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; +import static org.terracotta.utilities.test.matchers.Eventually.within; public class ManagementClusterConnectionTest extends ClusteredTests { @@ -161,7 +161,7 @@ public void test_reconnection() throws Exception { assertThat(initiate_reconnect, Matchers.nullValue()); - assertThatEventually(() -> { + assertThat(() -> { try { return CLUSTER.get().getNmsService().readTopology().clientStream() .filter(client -> client.getName() @@ -171,7 +171,7 @@ public void test_reconnection() throws Exception { } catch (Exception e) { throw new AssertionError(e); } - }, is(1L)).within(Duration.ofSeconds(30)); + }, within(Duration.ofSeconds(30)).is(1L)); assertThat(getInstanceId(), equalTo(instanceId)); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java index d24fd2b52c..cb63ff5766 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java @@ -31,9 +31,10 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; +import static org.terracotta.utilities.test.matchers.Eventually.within; public class AutoCreateOnReconnectTest extends ClusteredTests { @@ -60,10 +61,10 @@ public void cacheManagerCanReconnect() throws Exception { CLUSTER.getClusterControl().terminateAllServers(); CLUSTER.getClusterControl().startAllServers(); - assertThatEventually(() -> { + assertThat(() -> { cache.put(1L, "two"); return cache.get(1L); - }, is("two")).within(Duration.ofSeconds(30)); + }, within(Duration.ofSeconds(30)).is("two")); } } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index d1e09534a6..b3ddfb90e2 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -64,7 +64,7 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; +import static org.terracotta.utilities.test.matchers.Eventually.within; public class EventsReconnectTest extends ClusteredTests { private static final Duration TIMEOUT = ofSeconds(5); @@ -159,7 +159,7 @@ public void eventsFlowAgainAfterReconnection() throws Exception { getSucceededFuture.get(20000, TimeUnit.MILLISECONDS); - assertThatEventually(() -> cacheEventListener.events.get(EventType.CREATED), hasSize(beforeDisconnectionEventCounter + 1)).within(TIMEOUT); + assertThat(() -> cacheEventListener.events.get(EventType.CREATED), within(TIMEOUT).matches(hasSize(beforeDisconnectionEventCounter + 1))); } finally { cacheManager.destroyCache("clustered-cache"); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java index fcb96b6f6f..80d82fbfc4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java @@ -40,7 +40,7 @@ import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.WaitForAssert.assertThatEventually; +import static org.terracotta.utilities.test.matchers.Eventually.within; public class PassiveSyncTest extends ClusteredTests { @@ -78,7 +78,7 @@ public void testSync() throws Exception { CLUSTER.getClusterControl().terminateActive(); - assertThatEventually(() -> cache.get(0L), notNullValue()).within(Duration.ofSeconds(130)); + assertThat(() -> cache.get(0L), within(Duration.ofSeconds(130)).matches(notNullValue())); for (long i = -5; i < 5; i++) { assertThat(cache.get(i), equalTo("value" + i)); } diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java index 4762385814..ed40975a01 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -107,24 +107,21 @@ public static Cluster startServer(Path serverDirectory) throws IOException { .command(Paths.get(System.getProperty("java.home")).resolve("bin") .resolve(System.getProperty("os.name").contains("Windows") ? "java.exe" : "java").toString()); - String tcServerOptions = System.getProperty("tc-server-opts"); - if (tcServerOptions != null) { - serverProcess.command().addAll(asList(tcServerOptions.split("\\s"))); - } serverProcess.command().addAll(asList( "-Xmx128m", "-Dtc.install-root=" + serverDir, "-cp", serverDir.resolve("lib").resolve("tc.jar").toString(), "com.tc.server.TCServerMain", + "--auto-activate", "--cluster-name=foo", "--failover-priority=availability", "--client-reconnect-window=120s", - "--node-name=default-server", - "--node-hostname=localhost", - "--node-port=" + tsaPort, - "--node-group-port=" + tsaGroupPort, - "--node-log-dir=" + serverDirectory.resolve("logs"), - "--node-repository-dir=" + serverDirectory.resolve("repository"), + "--name=default-server", + "--hostname=localhost", + "--port=" + tsaPort, + "--group-port=" + tsaGroupPort, + "--log-dir=" + serverDirectory.resolve("logs"), + "--config-dir=" + serverDirectory.resolve("repository"), "--offheap-resources=main:32MB")); serverProcess.inheritIO(); diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java index c515efcca4..ec99d041e0 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java @@ -39,6 +39,7 @@ public EhcacheMessageTrackerMessage(int segmentId, Map messageHandler) { this(segmentId, messageHandler.getTrackedClients() .collect(toMap(ClientSourceId::toLong, clientSourceId -> messageHandler.getTrackedResponsesForSegment(segmentId, clientSourceId)))); diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java index a88df2224c..183f17d7d5 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java @@ -962,6 +962,7 @@ private interface DataSyncMessageHandler { boolean execute(); } + @SuppressWarnings("deprecation") private void sendMessageTrackerReplication(PassiveSynchronizationChannel syncChannel, int concurrencyKey) { Map> clientSourceIdTrackingMap = messageHandler.getTrackedClients() .collect(toMap(ClientSourceId::toLong, clientSourceId -> messageHandler.getTrackedResponsesForSegment(concurrencyKey, clientSourceId))); diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java index 80bcfff72f..2c38cdbdfe 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java @@ -191,6 +191,7 @@ private EhcacheEntityResponse invokePassiveInternal(InvokeContext context, Ehcac return success(); } + @SuppressWarnings("deprecation") private void invokeSyncOperation(InvokeContext context, EhcacheSyncMessage message) { switch (message.getMessageType()) { case DATA: diff --git a/gradle.properties b/gradle.properties index c82f4fbe50..9dab320efe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,11 +10,11 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre1 -terracottaApisVersion = 1.7.0-pre1 -terracottaCoreVersion = 5.7.0-pre25 -terracottaPassthroughTestingVersion = 1.7.0-pre12 -terracottaUtilitiesVersion = 0.0.2 +terracottaPlatformVersion = 5.8.0-pre4 +terracottaApisVersion = 1.7.0-pre2 +terracottaCoreVersion = 5.7.0-pre29 +terracottaPassthroughTestingVersion = 1.7.0-pre13 +terracottaUtilitiesVersion = 0.0.3 # Test lib versions junitVersion = 4.12 From 1ccad5d4d3929b0a26d4507fa97f0c06d15375bd Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 11 May 2020 09:51:56 -0400 Subject: [PATCH 249/372] Upgrade tc-platform to 5.8.0-pre5 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 9dab320efe..35a1b6b42d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre4 +terracottaPlatformVersion = 5.8.0-pre5 terracottaApisVersion = 1.7.0-pre2 terracottaCoreVersion = 5.7.0-pre29 terracottaPassthroughTestingVersion = 1.7.0-pre13 From d1f8b2b700923367c0e17b1d8d7d81c311df2720 Mon Sep 17 00:00:00 2001 From: Saurabh Agarwal Date: Wed, 13 May 2020 02:18:27 +0530 Subject: [PATCH 250/372] Bumped-up platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 35a1b6b42d..7e511544d9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre5 +terracottaPlatformVersion = 5.8.0-pre6 terracottaApisVersion = 1.7.0-pre2 terracottaCoreVersion = 5.7.0-pre29 terracottaPassthroughTestingVersion = 1.7.0-pre13 From 516cf7f6c7566f4e50ba99caaf7cfbb175b8cecf Mon Sep 17 00:00:00 2001 From: Saurabh Agarwal Date: Wed, 13 May 2020 12:08:28 +0530 Subject: [PATCH 251/372] Bumped-up platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7e511544d9..c12539f739 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre6 +terracottaPlatformVersion = 5.8.0-pre7 terracottaApisVersion = 1.7.0-pre2 terracottaCoreVersion = 5.7.0-pre29 terracottaPassthroughTestingVersion = 1.7.0-pre13 From 833de294d83dd41a04dd10ec54412b470c8f27bc Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 16 May 2020 08:56:56 -0400 Subject: [PATCH 252/372] Upgrade tc-platform to 5.8.0-pre9: * TDB-4990: Refactoring of json wiring in dynamic config (https://github.com/Terracotta-OSS/terracotta-platform/pull/716) * Added in dependencies so that felix can generate the right "resolution:=optional" attribute in the Import-Package manifest entry (https://github.com/Terracotta-OSS/terracotta-platform/pull/729) --- clustered/clustered-dist/build.gradle | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clustered/clustered-dist/build.gradle b/clustered/clustered-dist/build.gradle index f805b17bcd..f56cc761b0 100644 --- a/clustered/clustered-dist/build.gradle +++ b/clustered/clustered-dist/build.gradle @@ -88,7 +88,7 @@ jar { 'Bundle-SymbolicName': 'org.ehcache.clustered', 'Export-Package': '!com.tc.*, !com.terracotta.*, !org.terracotta.*, !org.ehcache.*.internal.*, !sun.misc, ' + 'org.ehcache.clustered.client.*, org.ehcache.clustered.common.*', - 'Import-Package': '!sun.misc.*, org.ehcache.xml.*;resolution:=optional, jdk.jfr.*;resolution:=optional, !com.fasterxml.jackson.annotation, *' + 'Import-Package': '!sun.misc.*, org.ehcache.xml.*;resolution:=optional, jdk.jfr.*;resolution:=optional, !com.fasterxml.jackson.annotation, !com.fasterxml.jackson.core, !com.fasterxml.jackson.databind.module, *' ) } diff --git a/gradle.properties b/gradle.properties index c12539f739..4d8173c87e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre7 +terracottaPlatformVersion = 5.8.0-pre9 terracottaApisVersion = 1.7.0-pre2 terracottaCoreVersion = 5.7.0-pre29 terracottaPassthroughTestingVersion = 1.7.0-pre13 From 10aeec64363a427b5e8be289746c9541e2655a3e Mon Sep 17 00:00:00 2001 From: Saurabh Agarwal Date: Wed, 20 May 2020 13:28:21 +0530 Subject: [PATCH 253/372] Bumped-up platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4d8173c87e..af76f691d6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre9 +terracottaPlatformVersion = 5.8.0-pre10 terracottaApisVersion = 1.7.0-pre2 terracottaCoreVersion = 5.7.0-pre29 terracottaPassthroughTestingVersion = 1.7.0-pre13 From bed949cc9da4891d1a0d84924f78569944e50ea3 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Wed, 3 Jun 2020 10:15:40 -0700 Subject: [PATCH 254/372] Bump dependencies --- gradle.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index af76f691d6..4b12850f2f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,10 +10,10 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre10 -terracottaApisVersion = 1.7.0-pre2 -terracottaCoreVersion = 5.7.0-pre29 -terracottaPassthroughTestingVersion = 1.7.0-pre13 +terracottaPlatformVersion = 5.8.0-pre11 +terracottaApisVersion = 1.7.0-pre3 +terracottaCoreVersion = 5.7.0-pre30 +terracottaPassthroughTestingVersion = 1.7.0-pre14 terracottaUtilitiesVersion = 0.0.3 # Test lib versions From 8f885ac5e8c552e39eadff5c74b4a97547b0a87c Mon Sep 17 00:00:00 2001 From: "House, James" Date: Tue, 9 Jun 2020 23:29:52 -0400 Subject: [PATCH 255/372] update to platform 5.8-pre12 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4b12850f2f..7dc780850d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre11 +terracottaPlatformVersion = 5.8.0-pre12 terracottaApisVersion = 1.7.0-pre3 terracottaCoreVersion = 5.7.0-pre30 terracottaPassthroughTestingVersion = 1.7.0-pre14 From fa1b4a4bf52119507502b85a268a3615a41f7944 Mon Sep 17 00:00:00 2001 From: "House, James" Date: Thu, 11 Jun 2020 09:49:51 -0400 Subject: [PATCH 256/372] update to terracotta-platfrom 5.8.0-pre13 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7dc780850d..3c7fd20c10 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre12 +terracottaPlatformVersion = 5.8.0-pre13 terracottaApisVersion = 1.7.0-pre3 terracottaCoreVersion = 5.7.0-pre30 terracottaPassthroughTestingVersion = 1.7.0-pre14 From 69cd395a5cdcf9b3f72ae183c8d3e0e03d864852 Mon Sep 17 00:00:00 2001 From: "House, James" Date: Fri, 12 Jun 2020 16:06:36 -0400 Subject: [PATCH 257/372] update to tc-platform 5.8.0-pre14 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 3c7fd20c10..83bb5fb2be 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre13 +terracottaPlatformVersion = 5.8.0-pre14 terracottaApisVersion = 1.7.0-pre3 terracottaCoreVersion = 5.7.0-pre30 terracottaPassthroughTestingVersion = 1.7.0-pre14 From 3951ed477cd4d24c836cd94f881c3f24629bcd08 Mon Sep 17 00:00:00 2001 From: mobasherul Date: Thu, 28 May 2020 00:24:56 +0530 Subject: [PATCH 258/372] Notifying clients about topology changes required for failover. --- clustered/client/build.gradle | 1 + .../client/internal/ConnectionSource.java | 65 ++++++++++++++++++- clustered/clustered-dist/build.gradle | 3 +- 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/clustered/client/build.gradle b/clustered/client/build.gradle index c62e6b3b5a..aa134c0eec 100644 --- a/clustered/client/build.gradle +++ b/clustered/client/build.gradle @@ -26,6 +26,7 @@ dependencies { providedImplementation "org.terracotta:entity-client-api:$terracottaApisVersion" providedImplementation "org.terracotta:runnel:$terracottaPlatformVersion" providedImplementation "org.terracotta:lease-api:$terracottaPlatformVersion" + providedImplementation "org.terracotta.dynamic-config.entities:dynamic-config-topology-entity-client:$terracottaPlatformVersion" providedImplementation "org.terracotta:connection-api:$terracottaApisVersion" compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java index ac9b882a96..0b22f5cac7 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java @@ -16,9 +16,18 @@ package org.ehcache.clustered.client.internal; import org.terracotta.connection.ConnectionException; +import org.terracotta.connection.entity.Entity; +import org.terracotta.connection.entity.EntityRef; +import org.terracotta.dynamic_config.api.model.Node; +import org.terracotta.dynamic_config.entity.topology.client.DynamicTopologyEntity; +import org.terracotta.dynamic_config.entity.topology.common.DynamicTopologyEntityConstants; +import org.terracotta.exception.EntityNotFoundException; +import org.terracotta.exception.EntityNotProvidedException; +import org.terracotta.exception.EntityVersionMismatchException; import org.terracotta.lease.connection.LeasedConnection; import org.terracotta.lease.connection.LeasedConnectionFactory; +import java.io.IOException; import java.net.InetSocketAddress; import java.net.URI; import java.net.URISyntaxException; @@ -26,6 +35,11 @@ import java.util.List; import java.util.Objects; import java.util.Properties; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.Future; +import java.util.concurrent.ExecutionException; public abstract class ConnectionSource { @@ -81,14 +95,21 @@ private static URI extractClusterUri(URI uri) { public static class ServerList extends ConnectionSource { - private final Iterable servers; + private final CopyOnWriteArraySet servers; private final String clusterTierManager; public ServerList(Iterable servers, String clusterTierManager) { - this.servers = cloneServers(Objects.requireNonNull(servers, "Servers cannot be null")); + this.servers = createServerList(servers); this.clusterTierManager = Objects.requireNonNull(clusterTierManager, "Cluster tier manager identifier cannot be null"); } + private CopyOnWriteArraySet createServerList(Iterable servers) { + Objects.requireNonNull(servers, "Servers cannot be null"); + CopyOnWriteArraySet serverList = new CopyOnWriteArraySet<>(); + servers.forEach(server -> serverList.add(server)); + return serverList; + } + @Override public String getClusterTierManager() { return clusterTierManager; @@ -96,7 +117,45 @@ public String getClusterTierManager() { @Override public LeasedConnection connect(Properties connectionProperties) throws ConnectionException { - return LeasedConnectionFactory.connect(servers, connectionProperties); + LeasedConnection connection = LeasedConnectionFactory.connect(servers, connectionProperties); + try { + EntityRef ref = connection.getEntityRef(DynamicTopologyEntity.class, 1, DynamicTopologyEntityConstants.ENTITY_NAME); + DynamicTopologyEntity dynamicTopologyEntity = ref.fetchEntity(null); + dynamicTopologyEntity.setListener(new DynamicTopologyEntity.Listener() { + @Override + public void onNodeRemoval(int stripeId, Node removedNode) { + servers.remove(removedNode.getNodeAddress()); + } + + @Override + public void onNodeAddition(int stripeId, Node addedNode) { + servers.add(addedNode.getNodeAddress()); + } + }); + return new LeasedConnection() { + @Override + public EntityRef getEntityRef(Class cls, long version, String name) throws EntityNotProvidedException { + return connection.getEntityRef(cls, version, name); + } + + @Override + public void close() throws IOException { + Future close = dynamicTopologyEntity.releaseEntity(); + try { + close.get(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (ExecutionException e) { + throw new IOException(e.getCause()); + } catch (TimeoutException e) { + } finally { + connection.close(); + } + } + }; + } catch (EntityNotProvidedException | EntityVersionMismatchException | EntityNotFoundException e) { + throw new AssertionError(e); + } } @Override diff --git a/clustered/clustered-dist/build.gradle b/clustered/clustered-dist/build.gradle index f56cc761b0..259b51f016 100644 --- a/clustered/clustered-dist/build.gradle +++ b/clustered/clustered-dist/build.gradle @@ -66,6 +66,7 @@ configurations { dependencies { compileOnly "org.terracotta.internal:client-runtime:$terracottaCoreVersion" compileOnly "org.terracotta:lease-api:$terracottaPlatformVersion" + compileOnly "org.terracotta.dynamic-config.entities:dynamic-config-topology-entity-client:$terracottaPlatformVersion" serverApis project(':clustered:server:service-api') serverLibs project(':clustered:server:entity') @@ -88,7 +89,7 @@ jar { 'Bundle-SymbolicName': 'org.ehcache.clustered', 'Export-Package': '!com.tc.*, !com.terracotta.*, !org.terracotta.*, !org.ehcache.*.internal.*, !sun.misc, ' + 'org.ehcache.clustered.client.*, org.ehcache.clustered.common.*', - 'Import-Package': '!sun.misc.*, org.ehcache.xml.*;resolution:=optional, jdk.jfr.*;resolution:=optional, !com.fasterxml.jackson.annotation, !com.fasterxml.jackson.core, !com.fasterxml.jackson.databind.module, *' + 'Import-Package': '!sun.misc.*, org.ehcache.xml.*;resolution:=optional, jdk.jfr.*;resolution:=optional, !com.fasterxml.jackson.*, !org.terracotta.json, *' ) } From eeb15406482e327ecd45a31eb96d3630012c9e92 Mon Sep 17 00:00:00 2001 From: mobasherul Date: Mon, 29 Jun 2020 17:28:58 +0530 Subject: [PATCH 259/372] Updating server startup doc --- .../test/resources/configs/docs/tc-config.xml | 12 ------- .../docs/asciidoc/user/clustered-cache.adoc | 32 ++++--------------- 2 files changed, 7 insertions(+), 37 deletions(-) delete mode 100644 clustered/client/src/test/resources/configs/docs/tc-config.xml diff --git a/clustered/client/src/test/resources/configs/docs/tc-config.xml b/clustered/client/src/test/resources/configs/docs/tc-config.xml deleted file mode 100644 index 57d1553f1c..0000000000 --- a/clustered/client/src/test/resources/configs/docs/tc-config.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - 128 - 96 - - - - diff --git a/docs/src/docs/asciidoc/user/clustered-cache.adoc b/docs/src/docs/asciidoc/user/clustered-cache.adoc index c5225aa2c9..c973b7fe09 100644 --- a/docs/src/docs/asciidoc/user/clustered-cache.adoc +++ b/docs/src/docs/asciidoc/user/clustered-cache.adoc @@ -129,37 +129,19 @@ Here is a pictorial representation of the concepts explained above: [[starting-server]] == Starting the Terracotta Server -You can start the Terracotta Server with the following configuration. -It contains the bare minimum configuration required for the samples in the rest of the document to work. +The snippet below defines two offheap resources named `primary-server-resource` and `secondary-server-resource` having +sizes `128MB` and `96MB` respectively: -[source,xml,indent=0] +[listing] ---- -include::{sourcedir38}/clustered/client/src/test/resources/configs/docs/tc-config.xml[] +offheap-resources=primary-server-resource:128MB,secondary-server-resource:96MB ---- -The above configuration defines two named server off-heap resources: - -<1> An off-heap resource of 128 MB size named `primary-server-resource`. -<2> Another off-heap resource named `secondary-server-resource` with 96 MB capacity. - -The rest of the document explains in detail how you can configure cache managers and caches to consume the server's off-heap resources. +This can either be defined in config properties file or during server startup. Assuming that you have the clustered Ehcache kit available locally, start with extracting the *ehcache-clustered* kit. -Change to your extracted directory and then execute the *start-tc-server* script as below to start the Terracotta server with the above configuration: - -On Windows: -[source,cmd] ----- -cd /server/bin -start-tc-server.bat -f /tc-config.xml ----- - -On Unix/Mac: -[source,bash] ----- -cd /server/bin -./start-tc-server.sh -f /tc-config.xml ----- +Change to your extracted directory and then execute the *start-tc-server* script located under `$KIT_DIR/server/bin` to start the Terracotta server. +You will then need to activate the cluster using `activate` command of config tool which is located under `$KIT_DIR/tools/bin`. NOTE: You will need to have `JAVA_HOME` point to a Java 8 installation while starting the Terracotta server. From ff75b47abb450d87f68730d4252eb2061ad9a561 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 8 Jul 2020 16:12:25 -0400 Subject: [PATCH 260/372] Upgrade core and platform dependencies --- gradle.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 83bb5fb2be..2eb4966590 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,10 +10,10 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre14 -terracottaApisVersion = 1.7.0-pre3 -terracottaCoreVersion = 5.7.0-pre30 -terracottaPassthroughTestingVersion = 1.7.0-pre14 +terracottaPlatformVersion = 5.8.0-pre15 +terracottaApisVersion = 1.7.0-pre5 +terracottaCoreVersion = 5.7.0-pre32 +terracottaPassthroughTestingVersion = 1.7.0-pre15 terracottaUtilitiesVersion = 0.0.3 # Test lib versions From 033ff88b7fc359a8bbef5afa57291e22b4468e1f Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 14 Jul 2020 15:54:56 -0400 Subject: [PATCH 261/372] Remove empty InternalClusterTierClientEntity interface --- ...ClusterTierManagerClientEntityFactory.java | 11 ++++----- .../store/ClusterTierClientEntityService.java | 2 +- .../InternalClusterTierClientEntity.java | 23 ------------------- .../store/SimpleClusterTierClientEntity.java | 2 +- .../DefaultClusteringServiceDestroyTest.java | 10 ++++---- .../store/ClusterTierServerEntityService.java | 2 +- 6 files changed, 13 insertions(+), 37 deletions(-) delete mode 100644 clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java index 5ccf938575..0bc2fcec9a 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java @@ -24,7 +24,6 @@ import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock.Hold; import org.ehcache.clustered.client.internal.store.ClusterTierClientEntity; import org.ehcache.clustered.client.internal.store.ClusterTierUserData; -import org.ehcache.clustered.client.internal.store.InternalClusterTierClientEntity; import org.ehcache.clustered.client.service.EntityBusyException; import org.ehcache.clustered.common.ServerSideConfiguration; import org.ehcache.clustered.common.internal.ClusterTierManagerConfiguration; @@ -278,9 +277,9 @@ private EntityRef entityRef; + EntityRef entityRef; try { - entityRef = connection.getEntityRef(InternalClusterTierClientEntity.class, ENTITY_VERSION, entityName(clusterTierManagerIdentifier, storeIdentifier)); + entityRef = connection.getEntityRef(ClusterTierClientEntity.class, ENTITY_VERSION, entityName(clusterTierManagerIdentifier, storeIdentifier)); } catch (EntityNotProvidedException e) { throw new AssertionError(e); } @@ -310,7 +309,7 @@ public ClusterTierClientEntity fetchOrCreateClusteredStoreEntity(String clusterT } private ClusterTierClientEntity fetchClusterTierClientEntity(String storeIdentifier, - EntityRef entityRef) + EntityRef entityRef) throws EntityNotFoundException { try { return entityRef.fetchEntity(new ClusterTierUserData(entityTimeouts, storeIdentifier, asyncWorker)); @@ -322,9 +321,9 @@ private ClusterTierClientEntity fetchClusterTierClientEntity(String storeIdentif } public void destroyClusteredStoreEntity(String clusterTierManagerIdentifier, String storeIdentifier) throws EntityNotFoundException, CachePersistenceException { - EntityRef entityRef; + EntityRef entityRef; try { - entityRef = connection.getEntityRef(InternalClusterTierClientEntity.class, ENTITY_VERSION, entityName(clusterTierManagerIdentifier, storeIdentifier)); + entityRef = connection.getEntityRef(ClusterTierClientEntity.class, ENTITY_VERSION, entityName(clusterTierManagerIdentifier, storeIdentifier)); if (!entityRef.destroy()) { throw new CachePersistenceException("Cannot destroy cluster tier '" + storeIdentifier + "': in use by other client(s)"); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java index 2829d1dd7f..b495bcf91b 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java @@ -39,7 +39,7 @@ public class ClusterTierClientEntityService implements EntityClientService cls) { - return InternalClusterTierClientEntity.class.isAssignableFrom(cls); + return ClusterTierClientEntity.class.isAssignableFrom(cls); } @Override diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java deleted file mode 100644 index 4841c72255..0000000000 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.ehcache.clustered.client.internal.store; - -/** - * InternalClusterTierClientEntity : Marker interface for any extensions that is used internally - */ -public interface InternalClusterTierClientEntity extends ClusterTierClientEntity { -} diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java index a2aa60dbe4..0c1522b9e6 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java @@ -60,7 +60,7 @@ /** * ClusterTierClientEntity */ -public class SimpleClusterTierClientEntity implements InternalClusterTierClientEntity { +public class SimpleClusterTierClientEntity implements ClusterTierClientEntity { private static final Logger LOGGER = LoggerFactory.getLogger(SimpleClusterTierClientEntity.class); private static final Set GET_STORE_OPS = EnumSet.of( diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java index 2e3055d231..078e3a93a8 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java @@ -19,7 +19,7 @@ import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntity; import org.ehcache.clustered.client.internal.MockConnectionService; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLockClient; -import org.ehcache.clustered.client.internal.store.InternalClusterTierClientEntity; +import org.ehcache.clustered.client.internal.store.ClusterTierClientEntity; import org.ehcache.clustered.common.internal.ClusterTierManagerConfiguration; import org.ehcache.clustered.common.internal.exceptions.DestroyInProgressException; import org.ehcache.clustered.common.internal.lock.LockMessaging; @@ -61,7 +61,7 @@ public class DefaultClusteringServiceDestroyTest { @Mock private EntityRef managerEntityRef; @Mock - private EntityRef tierEntityRef; + private EntityRef tierEntityRef; @Mock private EntityRef lockEntityRef; @@ -84,7 +84,7 @@ public void testDestroyAllFullyMocked() throws Exception { stores.add("store2"); when(managerEntity.prepareForDestroy()).thenReturn(stores); - when(getEntityRef(InternalClusterTierClientEntity.class)).thenReturn(tierEntityRef); + when(getEntityRef(ClusterTierClientEntity.class)).thenReturn(tierEntityRef); when(tierEntityRef.destroy()).thenReturn(true); when(managerEntityRef.destroy()).thenReturn(true); @@ -124,7 +124,7 @@ public void testAutoCreateOnPartialDestroyState() throws Exception { stores.add("store2"); when(managerEntity.prepareForDestroy()).thenReturn(stores); - when(getEntityRef(InternalClusterTierClientEntity.class)).thenReturn(tierEntityRef); + when(getEntityRef(ClusterTierClientEntity.class)).thenReturn(tierEntityRef); when(tierEntityRef.destroy()).thenReturn(true); when(managerEntityRef.destroy()).thenReturn(true); @@ -174,7 +174,7 @@ public void testDestroyOnPartialDestroyState() throws Exception { stores.add("store2"); when(managerEntity.prepareForDestroy()).thenReturn(stores); - when(getEntityRef(InternalClusterTierClientEntity.class)).thenReturn(tierEntityRef); + when(getEntityRef(ClusterTierClientEntity.class)).thenReturn(tierEntityRef); when(tierEntityRef.destroy()).thenReturn(true); when(managerEntityRef.destroy()).thenReturn(true); diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java index 0e6fff599c..b4b7ec0a34 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java @@ -62,7 +62,7 @@ public long getVersion() { @Override public boolean handlesEntityType(String typeName) { - return typeName.equals("org.ehcache.clustered.client.internal.store.InternalClusterTierClientEntity"); + return typeName.equals("org.ehcache.clustered.client.internal.store.ClusterTierClientEntity"); } @Override From a0e99f8963df3dca1a4b09038a28aafb5dde2570 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 15 Jul 2020 16:42:13 -0400 Subject: [PATCH 262/372] Revert "Remove empty InternalClusterTierClientEntity interface" This reverts commit 033ff88b7fc359a8bbef5afa57291e22b4468e1f. --- ...ClusterTierManagerClientEntityFactory.java | 11 +++++---- .../store/ClusterTierClientEntityService.java | 2 +- .../InternalClusterTierClientEntity.java | 23 +++++++++++++++++++ .../store/SimpleClusterTierClientEntity.java | 2 +- .../DefaultClusteringServiceDestroyTest.java | 10 ++++---- .../store/ClusterTierServerEntityService.java | 2 +- 6 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java index 0bc2fcec9a..5ccf938575 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java @@ -24,6 +24,7 @@ import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock.Hold; import org.ehcache.clustered.client.internal.store.ClusterTierClientEntity; import org.ehcache.clustered.client.internal.store.ClusterTierUserData; +import org.ehcache.clustered.client.internal.store.InternalClusterTierClientEntity; import org.ehcache.clustered.client.service.EntityBusyException; import org.ehcache.clustered.common.ServerSideConfiguration; import org.ehcache.clustered.common.internal.ClusterTierManagerConfiguration; @@ -277,9 +278,9 @@ private EntityRef entityRef; + EntityRef entityRef; try { - entityRef = connection.getEntityRef(ClusterTierClientEntity.class, ENTITY_VERSION, entityName(clusterTierManagerIdentifier, storeIdentifier)); + entityRef = connection.getEntityRef(InternalClusterTierClientEntity.class, ENTITY_VERSION, entityName(clusterTierManagerIdentifier, storeIdentifier)); } catch (EntityNotProvidedException e) { throw new AssertionError(e); } @@ -309,7 +310,7 @@ public ClusterTierClientEntity fetchOrCreateClusteredStoreEntity(String clusterT } private ClusterTierClientEntity fetchClusterTierClientEntity(String storeIdentifier, - EntityRef entityRef) + EntityRef entityRef) throws EntityNotFoundException { try { return entityRef.fetchEntity(new ClusterTierUserData(entityTimeouts, storeIdentifier, asyncWorker)); @@ -321,9 +322,9 @@ private ClusterTierClientEntity fetchClusterTierClientEntity(String storeIdentif } public void destroyClusteredStoreEntity(String clusterTierManagerIdentifier, String storeIdentifier) throws EntityNotFoundException, CachePersistenceException { - EntityRef entityRef; + EntityRef entityRef; try { - entityRef = connection.getEntityRef(ClusterTierClientEntity.class, ENTITY_VERSION, entityName(clusterTierManagerIdentifier, storeIdentifier)); + entityRef = connection.getEntityRef(InternalClusterTierClientEntity.class, ENTITY_VERSION, entityName(clusterTierManagerIdentifier, storeIdentifier)); if (!entityRef.destroy()) { throw new CachePersistenceException("Cannot destroy cluster tier '" + storeIdentifier + "': in use by other client(s)"); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java index b495bcf91b..2829d1dd7f 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java @@ -39,7 +39,7 @@ public class ClusterTierClientEntityService implements EntityClientService cls) { - return ClusterTierClientEntity.class.isAssignableFrom(cls); + return InternalClusterTierClientEntity.class.isAssignableFrom(cls); } @Override diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java new file mode 100644 index 0000000000..4841c72255 --- /dev/null +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java @@ -0,0 +1,23 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered.client.internal.store; + +/** + * InternalClusterTierClientEntity : Marker interface for any extensions that is used internally + */ +public interface InternalClusterTierClientEntity extends ClusterTierClientEntity { +} diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java index 0c1522b9e6..a2aa60dbe4 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java @@ -60,7 +60,7 @@ /** * ClusterTierClientEntity */ -public class SimpleClusterTierClientEntity implements ClusterTierClientEntity { +public class SimpleClusterTierClientEntity implements InternalClusterTierClientEntity { private static final Logger LOGGER = LoggerFactory.getLogger(SimpleClusterTierClientEntity.class); private static final Set GET_STORE_OPS = EnumSet.of( diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java index 078e3a93a8..2e3055d231 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java @@ -19,7 +19,7 @@ import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntity; import org.ehcache.clustered.client.internal.MockConnectionService; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLockClient; -import org.ehcache.clustered.client.internal.store.ClusterTierClientEntity; +import org.ehcache.clustered.client.internal.store.InternalClusterTierClientEntity; import org.ehcache.clustered.common.internal.ClusterTierManagerConfiguration; import org.ehcache.clustered.common.internal.exceptions.DestroyInProgressException; import org.ehcache.clustered.common.internal.lock.LockMessaging; @@ -61,7 +61,7 @@ public class DefaultClusteringServiceDestroyTest { @Mock private EntityRef managerEntityRef; @Mock - private EntityRef tierEntityRef; + private EntityRef tierEntityRef; @Mock private EntityRef lockEntityRef; @@ -84,7 +84,7 @@ public void testDestroyAllFullyMocked() throws Exception { stores.add("store2"); when(managerEntity.prepareForDestroy()).thenReturn(stores); - when(getEntityRef(ClusterTierClientEntity.class)).thenReturn(tierEntityRef); + when(getEntityRef(InternalClusterTierClientEntity.class)).thenReturn(tierEntityRef); when(tierEntityRef.destroy()).thenReturn(true); when(managerEntityRef.destroy()).thenReturn(true); @@ -124,7 +124,7 @@ public void testAutoCreateOnPartialDestroyState() throws Exception { stores.add("store2"); when(managerEntity.prepareForDestroy()).thenReturn(stores); - when(getEntityRef(ClusterTierClientEntity.class)).thenReturn(tierEntityRef); + when(getEntityRef(InternalClusterTierClientEntity.class)).thenReturn(tierEntityRef); when(tierEntityRef.destroy()).thenReturn(true); when(managerEntityRef.destroy()).thenReturn(true); @@ -174,7 +174,7 @@ public void testDestroyOnPartialDestroyState() throws Exception { stores.add("store2"); when(managerEntity.prepareForDestroy()).thenReturn(stores); - when(getEntityRef(ClusterTierClientEntity.class)).thenReturn(tierEntityRef); + when(getEntityRef(InternalClusterTierClientEntity.class)).thenReturn(tierEntityRef); when(tierEntityRef.destroy()).thenReturn(true); when(managerEntityRef.destroy()).thenReturn(true); diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java index b4b7ec0a34..0e6fff599c 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java @@ -62,7 +62,7 @@ public long getVersion() { @Override public boolean handlesEntityType(String typeName) { - return typeName.equals("org.ehcache.clustered.client.internal.store.ClusterTierClientEntity"); + return typeName.equals("org.ehcache.clustered.client.internal.store.InternalClusterTierClientEntity"); } @Override From c675b968fc5bbd2559830bbaf24edd78ed50850b Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 15 Jul 2020 16:45:31 -0400 Subject: [PATCH 263/372] Document the jusitification for keeping `InternalClusterTierClientEntity' --- .../internal/store/InternalClusterTierClientEntity.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java index 4841c72255..6ffd28401c 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java @@ -16,8 +16,12 @@ package org.ehcache.clustered.client.internal.store; -/** - * InternalClusterTierClientEntity : Marker interface for any extensions that is used internally +/* + * Since this interface has been used historically as the client-side interface that + * identifies a cluster-tier entity it must remain as **the** interface even though + * it is empty. We could remove it and hack up the server entity service to accept + * both variants but this seems like a cleaner and more future proof decision. This + * way if we need to introduce any 'internal' methods we can. */ public interface InternalClusterTierClientEntity extends ClusterTierClientEntity { } From c3c29f34b43cc66fc5bfea448fa132f209066978 Mon Sep 17 00:00:00 2001 From: Saurabh Agarwal Date: Sat, 18 Jul 2020 16:04:45 +0530 Subject: [PATCH 264/372] Bumped-up versions --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 2eb4966590..3d1d7b79ae 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre15 +terracottaPlatformVersion = 5.8.0-pre16 terracottaApisVersion = 1.7.0-pre5 -terracottaCoreVersion = 5.7.0-pre32 +terracottaCoreVersion = 5.7.0-pre33 terracottaPassthroughTestingVersion = 1.7.0-pre15 terracottaUtilitiesVersion = 0.0.3 From 7eefa15fd12134571ab05c2dc4cc6cbdc0dc74d5 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 17 Jul 2020 13:59:00 -0400 Subject: [PATCH 265/372] Standardize async testing timeouts --- .../BasicCacheOpsMultiThreadedTest.java | 5 +- .../clustered/EventsFailureBehaviorTest.java | 52 ++++++++++++------- .../java/org/ehcache/clustered/LeaseTest.java | 14 +++-- .../clustered/ReconnectDuringDestroyTest.java | 9 ++-- .../ClusteringManagementServiceTest.java | 5 +- .../ManagementClusterConnectionTest.java | 7 +-- .../reconnect/AutoCreateOnReconnectTest.java | 6 +-- .../reconnect/EventsReconnectTest.java | 11 ++-- .../clustered/replication/DuplicateTest.java | 22 ++++---- .../clustered/sync/PassiveSyncTest.java | 5 +- .../org/ehcache/testing/StandardTimeouts.java | 27 ++++++++++ 11 files changed, 94 insertions(+), 69 deletions(-) create mode 100644 clustered/integration-test/src/test/java/org/ehcache/testing/StandardTimeouts.java diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index 7b9fa77d53..8e673a2ccb 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -22,7 +22,6 @@ import org.ehcache.clustered.common.Consistency; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.units.MemoryUnit; -import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; @@ -45,11 +44,11 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.matchers.Eventually.within; /** * Simulate multiple clients starting up the same cache manager simultaneously and ensure that puts and gets works just @@ -109,7 +108,7 @@ private Callable content() { assertThat(customValueCache.get(1L), is("value")); synCache.put(firstClientEndKey, true); } else { - assertThat(() -> synCache.get(firstClientEndKey), within(Duration.ofSeconds(30)).matches(notNullValue())); + assertThat(() -> synCache.get(firstClientEndKey), eventually().matches(notNullValue())); assertThat(customValueCache.get(1L), is("value")); } return null; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index 70f4a1d288..37a1a09426 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -53,13 +53,13 @@ import static java.util.stream.LongStream.range; import static org.ehcache.clustered.client.config.builders.TimeoutsBuilder.timeouts; +import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.matchers.Eventually.within; @RunWith(Parallel.class) public class EventsFailureBehaviorTest extends ClusteredTests { @@ -138,7 +138,7 @@ private void failover(Cache cache1, Cache cache2) th } catch (Exception e) { return false; } - }, within(FAILOVER_TIMEOUT).is(true)); + }, eventually().is(true)); } @Test @@ -154,10 +154,12 @@ public void testEventsFailover() throws Exception { range(0, KEYS).forEach(k -> { cache1.put(k, value); }); - assertThat(() -> accountingCacheEventListener1.events.get(EventType.CREATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); - assertThat(() -> accountingCacheEventListener1.events.get(EventType.EVICTED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); - assertThat(() -> accountingCacheEventListener2.events.get(EventType.CREATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); - assertThat(() -> accountingCacheEventListener2.events.get(EventType.EVICTED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + eventually().runsCleanly(() -> { + assertThat(accountingCacheEventListener1.events.get(EventType.CREATED), hasSize(greaterThan(0))); + assertThat(accountingCacheEventListener1.events.get(EventType.EVICTED), hasSize(greaterThan(0))); + assertThat(accountingCacheEventListener2.events.get(EventType.CREATED), hasSize(greaterThan(0))); + assertThat(accountingCacheEventListener2.events.get(EventType.EVICTED), hasSize(greaterThan(0))); + }); // failover passive -> active failover(cache1, cache2); @@ -165,20 +167,26 @@ public void testEventsFailover() throws Exception { range(0, KEYS).forEach(k -> { cache1.put(k, value); }); - assertThat(() -> accountingCacheEventListener1.events.get(EventType.UPDATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); - assertThat(() -> accountingCacheEventListener2.events.get(EventType.UPDATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + eventually().runsCleanly(() -> { + assertThat(accountingCacheEventListener1.events.get(EventType.UPDATED), hasSize(greaterThan(0))); + assertThat(accountingCacheEventListener2.events.get(EventType.UPDATED), hasSize(greaterThan(0))); + }); range(0, KEYS).forEach(cache1::remove); - assertThat(() -> accountingCacheEventListener1.events.get(EventType.REMOVED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); - assertThat(() -> accountingCacheEventListener2.events.get(EventType.REMOVED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + eventually().runsCleanly(() -> { + assertThat(accountingCacheEventListener1.events.get(EventType.REMOVED), hasSize(greaterThan(0))); + assertThat(accountingCacheEventListener2.events.get(EventType.REMOVED), hasSize(greaterThan(0))); + }); range(KEYS, KEYS * 2).forEach(k -> { cache1.put(k, value); }); - assertThat(() -> accountingCacheEventListener1.events.get(EventType.CREATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); - assertThat(() -> accountingCacheEventListener1.events.get(EventType.EVICTED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); - assertThat(() -> accountingCacheEventListener2.events.get(EventType.CREATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); - assertThat(() -> accountingCacheEventListener2.events.get(EventType.EVICTED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + eventually().runsCleanly(() -> { + assertThat(accountingCacheEventListener1.events.get(EventType.CREATED), hasSize(greaterThan(0))); + assertThat(accountingCacheEventListener1.events.get(EventType.EVICTED), hasSize(greaterThan(0))); + assertThat(accountingCacheEventListener2.events.get(EventType.CREATED), hasSize(greaterThan(0))); + assertThat(accountingCacheEventListener2.events.get(EventType.EVICTED), hasSize(greaterThan(0))); + }); } @Test @@ -194,10 +202,12 @@ public void testExpirationFailover() throws Exception { range(0, KEYS).forEach(k -> { cache1.put(k, value); }); - assertThat(() -> accountingCacheEventListener1.events.get(EventType.CREATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); - assertThat(() -> accountingCacheEventListener1.events.get(EventType.EVICTED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); - assertThat(() -> accountingCacheEventListener2.events.get(EventType.CREATED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); - assertThat(() -> accountingCacheEventListener2.events.get(EventType.EVICTED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + eventually().runsCleanly(() -> { + assertThat(accountingCacheEventListener1.events.get(EventType.CREATED), hasSize(greaterThan(0))); + assertThat(accountingCacheEventListener1.events.get(EventType.EVICTED), hasSize(greaterThan(0))); + assertThat(accountingCacheEventListener2.events.get(EventType.CREATED), hasSize(greaterThan(0))); + assertThat(accountingCacheEventListener2.events.get(EventType.EVICTED), hasSize(greaterThan(0))); + }); // failover passive -> active failover(cache1, cache2); @@ -205,8 +215,10 @@ public void testExpirationFailover() throws Exception { range(0, KEYS).forEach(k -> { assertThat(cache1.get(k), is(nullValue())); }); - assertThat(() -> accountingCacheEventListener1.events.get(EventType.EXPIRED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); - assertThat(() -> accountingCacheEventListener2.events.get(EventType.EXPIRED), within(TIMEOUT).matches(hasSize(greaterThan(0)))); + eventually().runsCleanly(() -> { + assertThat(accountingCacheEventListener1.events.get(EventType.EXPIRED), hasSize(greaterThan(0))); + assertThat(accountingCacheEventListener2.events.get(EventType.EXPIRED), hasSize(greaterThan(0))); + }); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java index 83fdb9dd48..fee4d7b536 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java @@ -30,7 +30,6 @@ import org.ehcache.testing.TestRetryer; import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.After; -import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; @@ -45,17 +44,15 @@ import java.util.stream.Stream; import static java.time.Duration.ofSeconds; -import static java.time.temporal.ChronoUnit.SECONDS; import static java.util.EnumSet.of; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; +import static org.ehcache.testing.StandardTimeouts.eventually; import static org.ehcache.testing.TestRetryer.tryValues; import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.matchers.Eventually.within; @RunWith(Parameterized.class) public class LeaseTest extends ClusteredTests { @@ -119,10 +116,11 @@ public void leaseExpiry() throws Exception { setDelay(0L, proxies); } - assertThat(() -> cache.get(1L), within(Duration.ofSeconds(60)).is("The one")); - assertThat(cache.get(2L), equalTo("The two")); - assertThat(cache.get(3L), equalTo("The three")); - + eventually().runsCleanly(() -> { + assertThat(cache.get(1L), equalTo("The one")); + assertThat(cache.get(2L), equalTo("The two")); + assertThat(cache.get(3L), equalTo("The three")); + }); } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java index 34be9dcc4b..9a9215bb7c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -55,15 +55,14 @@ import java.util.stream.Stream; import static java.time.Duration.ofSeconds; -import static java.time.temporal.ChronoUnit.SECONDS; import static java.util.EnumSet.of; import static org.ehcache.clustered.common.EhcacheEntityVersion.ENTITY_VERSION; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; +import static org.ehcache.testing.StandardTimeouts.eventually; import static org.ehcache.testing.TestRetryer.tryValues; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.matchers.Eventually.within; /** * ReconnectDuringDestroyTest @@ -185,8 +184,10 @@ public void reconnectAfterDestroyOneOfTheCache() throws Exception { } Cache cache2Again = cacheManager.getCache("clustered-cache-2", Long.class, String.class); - assertThat(() -> cache2Again.get(1L), within(ofSeconds(10)).is("The one")); - assertThat(cache2Again.get(2L), equalTo("The two")); + eventually().runsCleanly(() -> { + assertThat(cache2Again.get(1L), equalTo("The one")); + assertThat(cache2Again.get(2L), equalTo("The two")); + }); cache2Again.put(3L, "The three"); assertThat(cache2Again.get(3L), equalTo("The three")); } finally { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java index f06f9671bb..50f6c20edc 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java @@ -32,7 +32,6 @@ import org.terracotta.management.model.context.ContextContainer; import org.terracotta.management.model.stats.ContextualStatistics; -import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -45,8 +44,8 @@ import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.Matchers.arrayContainingInAnyOrder; -import static org.terracotta.utilities.test.matchers.Eventually.within; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ClusteringManagementServiceTest extends AbstractClusteringManagementTest { @@ -150,7 +149,7 @@ public void test_A_client_tags_exposed() throws Exception { } catch (Exception e) { throw new AssertionError(e); } - }, within(Duration.ofSeconds(5)).matches(arrayContainingInAnyOrder("server-node-1", "webapp-1"))); + }, eventually().matches(arrayContainingInAnyOrder("server-node-1", "webapp-1"))); } @Test diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index 2762d99a93..3e8e460573 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -40,14 +40,12 @@ import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Stream; import static java.time.Duration.ofSeconds; -import static java.time.temporal.ChronoUnit.SECONDS; import static java.util.Collections.unmodifiableMap; import static java.util.EnumSet.of; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; @@ -57,12 +55,11 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.ehcache.testing.StandardTimeouts.eventually; import static org.ehcache.testing.TestRetryer.tryValues; import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.matchers.Eventually.within; public class ManagementClusterConnectionTest extends ClusteredTests { @@ -171,7 +168,7 @@ public void test_reconnection() throws Exception { } catch (Exception e) { throw new AssertionError(e); } - }, within(Duration.ofSeconds(30)).is(1L)); + }, eventually().is(1L)); assertThat(getInstanceId(), equalTo(instanceId)); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java index cb63ff5766..c6802cb6de 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java @@ -24,17 +24,15 @@ import org.terracotta.testing.rules.Cluster; import java.net.URI; -import java.time.Duration; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.matchers.Eventually.within; public class AutoCreateOnReconnectTest extends ClusteredTests { @@ -64,7 +62,7 @@ public void cacheManagerCanReconnect() throws Exception { assertThat(() -> { cache.put(1L, "two"); return cache.get(1L); - }, within(Duration.ofSeconds(30)).is("two")); + }, eventually().is("two")); } } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index b3ddfb90e2..96700845d0 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -55,19 +55,17 @@ import java.util.stream.Stream; import static java.time.Duration.ofSeconds; -import static java.time.temporal.ChronoUnit.SECONDS; import static java.util.EnumSet.of; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; +import static org.ehcache.testing.StandardTimeouts.eventually; import static org.ehcache.testing.TestRetryer.tryValues; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.matchers.Eventually.within; public class EventsReconnectTest extends ClusteredTests { - private static final Duration TIMEOUT = ofSeconds(5); private static PersistentCacheManager cacheManager; @@ -157,10 +155,9 @@ public void eventsFlowAgainAfterReconnection() throws Exception { } }); - getSucceededFuture.get(20000, TimeUnit.MILLISECONDS); - - assertThat(() -> cacheEventListener.events.get(EventType.CREATED), within(TIMEOUT).matches(hasSize(beforeDisconnectionEventCounter + 1))); - + assertThat(getSucceededFuture::isDone, eventually().is(true)); + getSucceededFuture.getNow(null); + assertThat(() -> cacheEventListener.events.get(EventType.CREATED), eventually().matches(hasSize(beforeDisconnectionEventCounter + 1))); } finally { cacheManager.destroyCache("clustered-cache"); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java index 39a2c8f297..cb113a3b43 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java @@ -41,11 +41,11 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; +import static org.ehcache.testing.StandardTimeouts.eventually; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; public class DuplicateTest extends ClusteredTests { @@ -107,11 +107,12 @@ public void duplicateAfterFailoverAreReturningTheCorrectResponse() throws Except CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); CLUSTER.getClusterControl().terminateActive(); - puts.get(30, TimeUnit.SECONDS); + assertThat(puts::isDone, eventually().is(true)); + puts.get(); //Verify cache entries on mirror for (int i = 0; i < numEntries; i++) { - assertThat(cache.get(i)).isEqualTo("value:" + i); + assertThat(cache.get(i), is("value:" + i)); } } finally { executorService.shutdownNow(); @@ -120,14 +121,13 @@ public void duplicateAfterFailoverAreReturningTheCorrectResponse() throws Except } @SuppressWarnings("unchecked") - private ResilienceStrategy failingResilienceStrategy() throws Exception { + private ResilienceStrategy failingResilienceStrategy() { return (ResilienceStrategy) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { ResilienceStrategy.class}, (proxy, method, args) -> { if(method.getName().endsWith("Failure")) { - fail("Failure on " + method.getName(), findStoreAccessException(args)); // one param is always a SAE - return null; + throw new AssertionError("Failure on " + method.getName(), findStoreAccessException(args)); // one param is always a SAE } switch(method.getName()) { @@ -136,8 +136,7 @@ private ResilienceStrategy failingResilienceStrategy() throws E case "equals": return proxy == args[0]; default: - fail("Unexpected method call: " + method.getName()); - return null; + throw new AssertionError("Unexpected method call: " + method.getName()); } }); } @@ -148,7 +147,6 @@ private StoreAccessException findStoreAccessException(Object[] objects) { return (StoreAccessException) o; } } - fail("There should be an exception somewhere in " + Arrays.toString(objects)); - return null; + throw new AssertionError("There should be an exception somewhere in " + Arrays.toString(objects)); } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java index 80d82fbfc4..42c76f5a23 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java @@ -32,15 +32,14 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import java.time.Duration; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; +import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -import static org.terracotta.utilities.test.matchers.Eventually.within; public class PassiveSyncTest extends ClusteredTests { @@ -78,7 +77,7 @@ public void testSync() throws Exception { CLUSTER.getClusterControl().terminateActive(); - assertThat(() -> cache.get(0L), within(Duration.ofSeconds(130)).matches(notNullValue())); + assertThat(() -> cache.get(0L), eventually().matches(notNullValue())); for (long i = -5; i < 5; i++) { assertThat(cache.get(i), equalTo("value" + i)); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/testing/StandardTimeouts.java b/clustered/integration-test/src/test/java/org/ehcache/testing/StandardTimeouts.java new file mode 100644 index 0000000000..1ac947b4d5 --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/testing/StandardTimeouts.java @@ -0,0 +1,27 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.testing; + +import org.terracotta.utilities.test.matchers.Eventually; + +import java.time.Duration; + +public interface StandardTimeouts { + + static Eventually.Timeout eventually() { + return Eventually.within(Duration.ofMinutes(1L)); + } +} From c5710f09c17843a2c24af9ec20d46d158ab5c420 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 20 Jul 2020 14:59:46 -0400 Subject: [PATCH 266/372] Support extension of entity configurations --- .../internal/messages/EntityConfigurationCodec.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EntityConfigurationCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EntityConfigurationCodec.java index b5e6f970d3..e9edfc9478 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EntityConfigurationCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EntityConfigurationCodec.java @@ -25,6 +25,8 @@ import org.terracotta.runnel.decoding.StructDecoder; import org.terracotta.runnel.encoding.StructEncoder; +import java.nio.ByteBuffer; + import static java.nio.ByteBuffer.wrap; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.SERVER_STORE_NAME_FIELD; import static org.terracotta.runnel.StructBuilder.newStructBuilder; @@ -68,7 +70,11 @@ public byte[] encode(ClusterTierEntityConfiguration configuration) { } public ClusterTierEntityConfiguration decodeClusteredStoreConfiguration(byte[] configuration) { - StructDecoder decoder = clusteredStoreConfigurationStruct.decoder(wrap(configuration)); + return decodeClusteredStoreConfiguration(wrap(configuration)); + } + + public ClusterTierEntityConfiguration decodeClusteredStoreConfiguration(ByteBuffer buffer) { + StructDecoder decoder = clusteredStoreConfigurationStruct.decoder(buffer); String managerIdentifier = decoder.string(IDENTIFIER); if (managerIdentifier == null) { throw new IllegalArgumentException("Payload is an invalid content"); From 4ea573a94767de44c875980dea16e551754e9a1d Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 22 Jul 2020 17:32:47 -0400 Subject: [PATCH 267/372] Upgrade to new tc-platform version --- .../ehcache/clustered/client/internal/ConnectionSource.java | 4 ++-- .../clustered/management/ClusteringManagementServiceTest.java | 2 +- gradle.properties | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java index 0b22f5cac7..5145cbba15 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java @@ -124,12 +124,12 @@ public LeasedConnection connect(Properties connectionProperties) throws Connecti dynamicTopologyEntity.setListener(new DynamicTopologyEntity.Listener() { @Override public void onNodeRemoval(int stripeId, Node removedNode) { - servers.remove(removedNode.getNodeAddress()); + servers.remove(removedNode.getAddress()); } @Override public void onNodeAddition(int stripeId, Node addedNode) { - servers.add(addedNode.getNodeAddress()); + servers.add(addedNode.getAddress()); } }); return new LeasedConnection() { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java index 50f6c20edc..a0318cf903 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java @@ -383,7 +383,7 @@ public void test_G_stats_collection() throws Exception { .map(ContextualStatistics::getCapability) .collect(Collectors.toCollection(TreeSet::new)); - assertThat(capabilities).containsOnly("PoolStatistics", "ServerStoreStatistics", "OffHeapResourceStatistics"); + assertThat(capabilities).contains("PoolStatistics", "ServerStoreStatistics", "OffHeapResourceStatistics"); // ensure we collect stats from all registered objects (pools and stores) diff --git a/gradle.properties b/gradle.properties index 3d1d7b79ae..963cddf371 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre16 +terracottaPlatformVersion = 5.8.0-pre17 terracottaApisVersion = 1.7.0-pre5 terracottaCoreVersion = 5.7.0-pre33 terracottaPassthroughTestingVersion = 1.7.0-pre15 From ba51ffd5d854d4109e87e7c351f67008275fb619 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 29 Jul 2020 18:01:19 -0400 Subject: [PATCH 268/372] Upgrade to new tc-platform version --- .../ClusteringManagementServiceTest.java | 14 ++++++-------- gradle.properties | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java index a0318cf903..5a3e7b5999 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java @@ -271,17 +271,15 @@ public void test_D_server_capabilities_exposed() throws Exception { // tms entity managerCapabilities = readTopology().activeServerEntityStream().filter(serverEntity -> serverEntity.is(CLUSTER.getTmsServerEntityIdentifier())).findFirst().get().getManagementRegistry().get().getCapabilities().toArray(new Capability[0]); - assertThat(managerCapabilities.length).isEqualTo(5); + assertThat(managerCapabilities.length).isEqualTo(3); - assertThat(managerCapabilities[0].getName()).isEqualTo("DataRootSettings"); - assertThat(managerCapabilities[1].getName()).isEqualTo("DataRootStatistics"); - assertThat(managerCapabilities[2].getName()).isEqualTo("OffHeapResourceSettings"); - assertThat(managerCapabilities[3].getName()).isEqualTo("OffHeapResourceStatistics"); - assertThat(managerCapabilities[4].getName()).isEqualTo("StatisticCollectorCapability"); + assertThat(managerCapabilities[0].getName()).isEqualTo("OffHeapResourceSettings"); + assertThat(managerCapabilities[1].getName()).isEqualTo("OffHeapResourceStatistics"); + assertThat(managerCapabilities[2].getName()).isEqualTo("StatisticCollectorCapability"); - assertThat(managerCapabilities[2].getDescriptors()).hasSize(3); // time + 2 resources + assertThat(managerCapabilities[0].getDescriptors()).hasSize(3); // time + 2 resources - assertThat(managerCapabilities[3].getDescriptors()).containsOnlyElementsOf(OFFHEAP_RES_DESCRIPTORS); + assertThat(managerCapabilities[1].getDescriptors()).containsOnlyElementsOf(OFFHEAP_RES_DESCRIPTORS); } @Test diff --git a/gradle.properties b/gradle.properties index 963cddf371..2909bb0c7e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre17 +terracottaPlatformVersion = 5.8.0-pre19 terracottaApisVersion = 1.7.0-pre5 terracottaCoreVersion = 5.7.0-pre33 terracottaPassthroughTestingVersion = 1.7.0-pre15 From 7a771868afc583034a03004f73f1d80402386609 Mon Sep 17 00:00:00 2001 From: Prasanta Kumar Date: Fri, 7 Aug 2020 12:13:00 +0530 Subject: [PATCH 269/372] version bump of terracotta platform --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 2909bb0c7e..40587290aa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre19 +terracottaPlatformVersion = 5.8.0-pre20 terracottaApisVersion = 1.7.0-pre5 terracottaCoreVersion = 5.7.0-pre33 terracottaPassthroughTestingVersion = 1.7.0-pre15 From a3f1df8654344fa421ad78001df61088b9626348 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 11 Aug 2020 10:04:40 -0400 Subject: [PATCH 270/372] Upgrade to new tc-platform version (stripe name support in DC and M&M plus DC fixes) --- .../src/assemble/server/conf/cluster.properties | 1 + gradle.properties | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/clustered/clustered-dist/src/assemble/server/conf/cluster.properties b/clustered/clustered-dist/src/assemble/server/conf/cluster.properties index 221ec16d0c..55f37ac5bf 100644 --- a/clustered/clustered-dist/src/assemble/server/conf/cluster.properties +++ b/clustered/clustered-dist/src/assemble/server/conf/cluster.properties @@ -14,3 +14,4 @@ stripe.1.node.1.node-port=9410 stripe.1.node.1.node-public-hostname= stripe.1.node.1.node-public-port= stripe.1.node.1.tc-properties= +stripe.1.stripe-name=default-stripe diff --git a/gradle.properties b/gradle.properties index 40587290aa..f71c6dd3cb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,11 +10,11 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre20 +terracottaPlatformVersion = 5.8.0-pre21 terracottaApisVersion = 1.7.0-pre5 terracottaCoreVersion = 5.7.0-pre33 terracottaPassthroughTestingVersion = 1.7.0-pre15 -terracottaUtilitiesVersion = 0.0.3 +terracottaUtilitiesVersion = 0.0.5 # Test lib versions junitVersion = 4.12 From 826491ca67477a86f880c5df88428d72cfb0ac2f Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 11 Aug 2020 21:24:00 -0400 Subject: [PATCH 271/372] Upgrade to new tc-platform version (stripe name support in DC and M&M) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index f71c6dd3cb..8b02587289 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre21 +terracottaPlatformVersion = 5.8.0-pre22 terracottaApisVersion = 1.7.0-pre5 terracottaCoreVersion = 5.7.0-pre33 terracottaPassthroughTestingVersion = 1.7.0-pre15 From d19af9520230f8b535114d9a1a7c815e1a014320 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 12 Aug 2020 16:51:27 -0400 Subject: [PATCH 272/372] Fixes #2815 Use a thread-safe set for tracking hash invalidations --- .../clustered/server/store/ClusterTierActiveEntity.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java b/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java index bc14273c4c..3eccfbc420 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java @@ -473,7 +473,9 @@ private void clientInvalidated(ClientDescriptor clientDescriptor, int invalidati private void invalidateHashForClient(ClientDescriptor originatingClientDescriptor, long key) { int invalidationId = invalidationIdGenerator.getAndIncrement(); - Set clientsToInvalidate = new HashSet<>(getConnectedClients()); + Set connectedClients = getConnectedClients(); + Set clientsToInvalidate = ConcurrentHashMap.newKeySet(connectedClients.size()); + clientsToInvalidate.addAll(connectedClients); if (originatingClientDescriptor != null) { clientsToInvalidate.remove(originatingClientDescriptor); } From d47f4003546c5c6ab9bb75e1aa4a03a3ac07d138 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 13 Aug 2020 12:46:49 -0400 Subject: [PATCH 273/372] Make DuplicateTest more reliable under extreme-timing scenarios --- .../clustered/replication/DuplicateTest.java | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java index cb113a3b43..7e0a39d64e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java @@ -41,11 +41,14 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.Semaphore; +import static java.util.concurrent.TimeUnit.MINUTES; import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; +import static org.junit.Assume.assumeThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; public class DuplicateTest extends ClusteredTests { @@ -73,7 +76,7 @@ public void tearDown() throws Exception { public void duplicateAfterFailoverAreReturningTheCorrectResponse() throws Exception { CacheManagerBuilder builder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI()) - .timeouts(TimeoutsBuilder.timeouts().write(Duration.ofSeconds(30))) + .timeouts(TimeoutsBuilder.timeouts().write(Duration.ofSeconds(60))) .autoCreate(server -> server.defaultServerResource("primary-server-resource"))) .withCache("cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Integer.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() @@ -86,30 +89,40 @@ public void duplicateAfterFailoverAreReturningTheCorrectResponse() throws Except Cache cache = cacheManager.getCache("cache", Integer.class, String.class); int numEntries = 3000; - AtomicInteger currentEntry = new AtomicInteger(); //Perform put operations in another thread ExecutorService executorService = Executors.newSingleThreadExecutor(); try { + Semaphore failoverAllowed = new Semaphore(0); + Semaphore failoverComplete = new Semaphore(0); Future puts = executorService.submit(() -> { - while (true) { - int i = currentEntry.getAndIncrement(); - if (i >= numEntries) { - break; + try { + for (int i = 0; i < numEntries; i++) { + if (i == 100) { + failoverAllowed.release(); + } + if (i == (numEntries - 100)) { + failoverComplete.acquire(); + } + cache.put(i, "value:" + i); } - cache.put(i, "value:" + i); + } catch (InterruptedException e) { + throw new AssertionError(e); } }); - while (currentEntry.get() < 100); // wait to make sure some entries are added before shutdown - // Failover to mirror when put & replication are in progress CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); + assertThat(failoverAllowed.tryAcquire(1, MINUTES), is(true)); CLUSTER.getClusterControl().terminateActive(); + failoverComplete.release(); assertThat(puts::isDone, eventually().is(true)); puts.get(); + //if failover didn't interrupt puts then the test is 'moot' + assumeThat(cache.get(0), is(notNullValue())); + //Verify cache entries on mirror for (int i = 0; i < numEntries; i++) { assertThat(cache.get(i), is("value:" + i)); From 1dcb7bb10f6718626f7379ae9b7bee1ddc1ffccc Mon Sep 17 00:00:00 2001 From: Saurabh Agarwal Date: Wed, 12 Aug 2020 15:28:00 +0530 Subject: [PATCH 274/372] Bumped-up versions --- gradle.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 8b02587289..d19d663191 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,10 +10,10 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre22 -terracottaApisVersion = 1.7.0-pre5 -terracottaCoreVersion = 5.7.0-pre33 -terracottaPassthroughTestingVersion = 1.7.0-pre15 +terracottaPlatformVersion = 5.8.0-pre23 +terracottaApisVersion = 1.7.0-pre6 +terracottaCoreVersion = 5.7.0-pre35 +terracottaPassthroughTestingVersion = 1.7.0-pre16 terracottaUtilitiesVersion = 0.0.5 # Test lib versions From affb502abba4a2feb4b0e53b367b6bdccf9978fd Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 12 Aug 2020 11:28:16 -0400 Subject: [PATCH 275/372] Update gradle.properties terracottaPassthroughTestingVersion = 1.7.0-pre17 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d19d663191..d72a95dabc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ jaxbVersion = 2.3.1 terracottaPlatformVersion = 5.8.0-pre23 terracottaApisVersion = 1.7.0-pre6 terracottaCoreVersion = 5.7.0-pre35 -terracottaPassthroughTestingVersion = 1.7.0-pre16 +terracottaPassthroughTestingVersion = 1.7.0-pre17 terracottaUtilitiesVersion = 0.0.5 # Test lib versions From 4815754ef3f092531327d2f5c79433be8b265998 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 14 Aug 2020 13:43:43 -0400 Subject: [PATCH 276/372] Upgrade to new tc-platform version (DC config versioning and backward compat) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d72a95dabc..fe5ba2c501 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre23 +terracottaPlatformVersion = 5.8.0-pre24 terracottaApisVersion = 1.7.0-pre6 terracottaCoreVersion = 5.7.0-pre35 terracottaPassthroughTestingVersion = 1.7.0-pre17 From e2fb537f1fe866ac4b4db37d1cb2f7ec2bf55e62 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 14 Aug 2020 14:49:06 -0400 Subject: [PATCH 277/372] Upgrade to new tc-platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index fe5ba2c501..fb5325c365 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre24 +terracottaPlatformVersion = 5.8.0-pre25 terracottaApisVersion = 1.7.0-pre6 terracottaCoreVersion = 5.7.0-pre35 terracottaPassthroughTestingVersion = 1.7.0-pre17 From 4f1f58328f0492b3fc23c728f47c47f97702aede Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 17 Aug 2020 12:17:02 -0400 Subject: [PATCH 278/372] Upgrade to new tc-platform version --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index fb5325c365..70a048cc5b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre25 +terracottaPlatformVersion = 5.8.0-pre26 terracottaApisVersion = 1.7.0-pre6 -terracottaCoreVersion = 5.7.0-pre35 +terracottaCoreVersion = 5.7.0-pre36 terracottaPassthroughTestingVersion = 1.7.0-pre17 terracottaUtilitiesVersion = 0.0.5 From 61d1ecc20068c090f41c87a526662cd085cd1dc6 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 19 Aug 2020 09:02:56 -0400 Subject: [PATCH 279/372] Upgrade to new tc-platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 70a048cc5b..f3b1c8fbda 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre26 +terracottaPlatformVersion = 5.8.0-pre27 terracottaApisVersion = 1.7.0-pre6 terracottaCoreVersion = 5.7.0-pre36 terracottaPassthroughTestingVersion = 1.7.0-pre17 From 1a3f57860882f8a5d9c454f51effed6b3902d305 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 19 Aug 2020 16:43:09 -0400 Subject: [PATCH 280/372] Upgrade to new tc-platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index f3b1c8fbda..197422e602 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre27 +terracottaPlatformVersion = 5.8.0-pre28 terracottaApisVersion = 1.7.0-pre6 terracottaCoreVersion = 5.7.0-pre36 terracottaPassthroughTestingVersion = 1.7.0-pre17 From 8e3414e823b15dc53aeff0bf1ec7118718943393 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 19 Aug 2020 13:56:57 -0400 Subject: [PATCH 281/372] Clustered events are broken: * across failover due to uncoordinated eviction (disable tests) * expired events are getting dropped on eviction --- .../client/internal/store/ClusteredStore.java | 11 +- .../store/operations/ChainResolver.java | 16 ++- .../operations/EternalChainResolver.java | 9 +- .../store/operations/ExpiryChainResolver.java | 20 ++- .../clustered/EventsFailureBehaviorTest.java | 118 ++++++++++++------ 5 files changed, 121 insertions(+), 53 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index 0da2ae3234..e24a8ffe4d 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -822,11 +822,16 @@ public void onInvalidateHash(long hash, Chain evictedChain) { } if (evictedChain != null) { StoreEventSink sink = clusteredStore.storeEventDispatcher.eventSink(); - Map> operationMap = clusteredStore.resolver.resolveAll(evictedChain, clusteredStore.timeSource.getTimeMillis()); + Map> operationMap = clusteredStore.resolver.resolveAll(evictedChain); + long now = clusteredStore.timeSource.getTimeMillis(); for (Map.Entry> entry : operationMap.entrySet()) { K key = entry.getKey(); - V value = entry.getValue() == null ? null : entry.getValue().get(); - sink.evicted(key, () -> value); + ValueHolder valueHolder = entry.getValue(); + if (valueHolder.isExpired(now)) { + sink.expired(key, valueHolder); + } else { + sink.evicted(key, valueHolder); + } } clusteredStore.storeEventDispatcher.releaseEventSink(sink); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java index b0d77e6b9d..a5245c5507 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java @@ -77,7 +77,7 @@ public ValueHolder resolve(ServerStoreProxy.ChainEntry entry, K key, long now } /** - * Resolves all keys within the given chain to their current values. + * Resolves all keys within the given chain to their current values while removing expired values. * * @param chain target chain * @param now current time @@ -85,6 +85,14 @@ public ValueHolder resolve(ServerStoreProxy.ChainEntry entry, K key, long now */ public abstract Map> resolveAll(Chain chain, long now); + /** + * Resolves all keys within the given chain to their current values while retaining expired values. + * + * @param chain target chain + * @return a map of current values + */ + public abstract Map> resolveAll(Chain chain); + /** * Compacts the given chain entry by resolving every key within. * @@ -92,7 +100,7 @@ public ValueHolder resolve(ServerStoreProxy.ChainEntry entry, K key, long now */ public void compact(ServerStoreProxy.ChainEntry entry) { ChainBuilder builder = new ChainBuilder(); - for (PutOperation operation : resolveAll(entry).values()) { + for (PutOperation operation : resolveToSimplePuts(entry).values()) { builder = builder.add(codec.encode(operation)); } Chain compacted = builder.build(); @@ -142,7 +150,7 @@ protected PutOperation resolve(ServerStoreProxy.ChainEntry entry, K key, i * @param chain target chain * @return a map of equivalent put operations */ - protected Map> resolveAll(Chain chain) { + public Map> resolveToSimplePuts(Chain chain) { //absent hash-collisions this should always be a 1 entry map Map> compacted = new HashMap<>(2); for (Element element : chain) { @@ -161,7 +169,7 @@ protected Map> resolveAll(Chain chain) { * @return the equivalent put operation */ public PutOperation resolve(Chain chain, K key) { - return resolveAll(chain).get(key); + return resolveToSimplePuts(chain).get(key); } /** diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/EternalChainResolver.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/EternalChainResolver.java index da73db546a..0fe81f3a25 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/EternalChainResolver.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/EternalChainResolver.java @@ -51,8 +51,8 @@ public ValueHolder resolve(ServerStoreProxy.ChainEntry entry, K key, long now } @Override - public Map> resolveAll(Chain chain, long now) { - Map> resolved = resolveAll(chain); + public Map> resolveAll(Chain chain) { + Map> resolved = resolveToSimplePuts(chain); Map> values = new HashMap<>(resolved.size()); for (Map.Entry> e : resolved.entrySet()) { @@ -61,6 +61,11 @@ public Map> resolveAll(Chain chain, long now) { return unmodifiableMap(values); } + @Override + public Map> resolveAll(Chain chain, long now) { + return resolveAll(chain); + } + /** * Applies the given operation returning a result that never expires. * diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java index 8683edbcc3..70d9df31d9 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java @@ -82,17 +82,28 @@ public ValueHolder resolve(ServerStoreProxy.ChainEntry entry, K key, long now @Override public Map> resolveAll(Chain chain, long now) { - Map> resolved = resolveAll(chain); + Map> resolved = resolveAll(chain); Map> values = new HashMap<>(resolved.size()); - for (Map.Entry> e : resolved.entrySet()) { - if (now < e.getValue().expirationTime()) { - values.put(e.getKey(), new ClusteredValueHolder<>(e.getValue().getValue(), e.getValue().expirationTime())); + for (Map.Entry> e : resolved.entrySet()) { + if (!e.getValue().isExpired(now)) { + values.put(e.getKey(), e.getValue()); } } return unmodifiableMap(values); } + @Override + public Map> resolveAll(Chain chain) { + Map> resolved = resolveToSimplePuts(chain); + + Map> values = new HashMap<>(resolved.size()); + for (Map.Entry> e : resolved.entrySet()) { + values.put(e.getKey(), new ClusteredValueHolder<>(e.getValue().getValue(), e.getValue().expirationTime())); + } + return unmodifiableMap(values); + } + /** * Applies the given operation returning a result with an expiry time determined by this resolvers expiry policy. *

@@ -101,7 +112,6 @@ public Map> resolveAll(Chain chain, long now) { * @param key cache key * @param existing current state * @param operation operation to apply - * @param now current time * @return the equivalent put operation */ @Override diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index b27e1d2850..4668c3dc5c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -33,6 +33,7 @@ import org.ehcache.expiry.ExpiryPolicy; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; @@ -40,19 +41,33 @@ import java.io.File; import java.time.Duration; import java.util.EnumSet; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import static java.util.stream.LongStream.range; import static org.awaitility.Awaitility.await; -import static org.hamcrest.Matchers.greaterThan; +import static org.ehcache.event.EventType.CREATED; +import static org.ehcache.event.EventType.EVICTED; +import static org.ehcache.event.EventType.EXPIRED; +import static org.ehcache.event.EventType.REMOVED; +import static org.ehcache.event.EventType.UPDATED; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.either; +import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isOneOf; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +/* + * Eventing behavior is broken across a failover due to actives and passives + * evicting independently. Until this behavior is fixed or at least detectable + * this test cannot reliably assert anything. + */ +@Ignore("Eventing is broken across failover") public class EventsFailureBehaviorTest extends ClusteredTests { private static final int KEYS = 500; @@ -125,7 +140,7 @@ private void failover(Cache cache1, Cache cache2) th }); } - @Test + @Test @SuppressWarnings("unchecked") public void testEventsFailover() throws Exception { AccountingCacheEventListener accountingCacheEventListener1 = new AccountingCacheEventListener<>(); Cache cache1 = createCache(cacheManager1, accountingCacheEventListener1, ExpiryPolicyBuilder.noExpiration()); @@ -138,10 +153,16 @@ public void testEventsFailover() throws Exception { range(0, KEYS).forEach(k -> { cache1.put(k, value); }); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.CREATED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.EVICTED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.CREATED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.EVICTED).size(), greaterThan(0)); + + await().atMost(TIMEOUT).untilAsserted(() -> range(0, KEYS).forEach(k -> { + if (cache1.containsKey(k)) { + assertThat(accountingCacheEventListener1.events, hasEntry(is(k), containsInAnyOrder(CREATED))); + assertThat(accountingCacheEventListener2.events, hasEntry(is(k), containsInAnyOrder(accountingCacheEventListener1.events.get(k).toArray()))); + } else { + assertThat(accountingCacheEventListener1.events, hasEntry(is(k), containsInAnyOrder(CREATED, EVICTED))); + assertThat(accountingCacheEventListener2.events, hasEntry(is(k), containsInAnyOrder(accountingCacheEventListener1.events.get(k).toArray()))); + } + })); // failover passive -> active failover(cache1, cache2); @@ -149,23 +170,45 @@ public void testEventsFailover() throws Exception { range(0, KEYS).forEach(k -> { cache1.put(k, value); }); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.UPDATED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.UPDATED).size(), greaterThan(0)); + await().atMost(TIMEOUT).untilAsserted(() -> range(0, KEYS).forEach(k -> { + if (cache1.containsKey(k)) { + assertThat(accountingCacheEventListener1.events, hasEntry(is(k), + either(containsInAnyOrder(CREATED, UPDATED)) + .or(containsInAnyOrder(CREATED, EVICTED, CREATED)))); + assertThat(accountingCacheEventListener2.events, hasEntry(is(k), containsInAnyOrder(accountingCacheEventListener1.events.get(k).toArray()))); + } else { + assertThat(accountingCacheEventListener1.events, hasEntry(is(k), + either(containsInAnyOrder(CREATED, UPDATED, EVICTED)) + .or(containsInAnyOrder(CREATED, EVICTED, CREATED, EVICTED)))); + assertThat(accountingCacheEventListener2.events, hasEntry(is(k), containsInAnyOrder(accountingCacheEventListener1.events.get(k).toArray()))); + } + })); range(0, KEYS).forEach(cache1::remove); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.REMOVED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.REMOVED).size(), greaterThan(0)); + await().atMost(TIMEOUT).untilAsserted(() -> range(0, KEYS).forEach(k -> { + assertThat(accountingCacheEventListener1.events, hasEntry(is(k), + either(containsInAnyOrder(CREATED, UPDATED, REMOVED)) + .or(containsInAnyOrder(CREATED, EVICTED, CREATED, REMOVED)) + .or(containsInAnyOrder(CREATED, UPDATED, EVICTED)) + .or(containsInAnyOrder(CREATED, EVICTED, CREATED, EVICTED)))); + assertThat(accountingCacheEventListener2.events, hasEntry(is(k), containsInAnyOrder(accountingCacheEventListener1.events.get(k).toArray()))); + })); range(KEYS, KEYS * 2).forEach(k -> { cache1.put(k, value); }); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.CREATED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.EVICTED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.CREATED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.EVICTED).size(), greaterThan(0)); + await().atMost(TIMEOUT).untilAsserted(() -> range(KEYS, KEYS * 2).forEach(k -> { + if (cache1.containsKey(k)) { + assertThat(accountingCacheEventListener1.events, hasEntry(is(k), containsInAnyOrder(CREATED))); + assertThat(accountingCacheEventListener2.events, hasEntry(is(k), containsInAnyOrder(accountingCacheEventListener1.events.get(k).toArray()))); + } else { + assertThat(accountingCacheEventListener1.events, hasEntry(is(k), containsInAnyOrder(CREATED, EVICTED))); + assertThat(accountingCacheEventListener2.events, hasEntry(is(k), containsInAnyOrder(accountingCacheEventListener1.events.get(k).toArray()))); + } + })); } - @Test + @Test @SuppressWarnings("unchecked") public void testExpirationFailover() throws Exception { AccountingCacheEventListener accountingCacheEventListener1 = new AccountingCacheEventListener<>(); Cache cache1 = createCache(cacheManager1, accountingCacheEventListener1, ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(1))); @@ -175,13 +218,18 @@ public void testExpirationFailover() throws Exception { byte[] value = new byte[10 * 1024]; - range(0, KEYS).forEach(k -> { - cache1.put(k, value); - }); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.CREATED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.EVICTED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.CREATED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.EVICTED).size(), greaterThan(0)); + range(0, KEYS).forEach(k -> cache1.put(k, value)); + + await().atMost(TIMEOUT).untilAsserted(() -> range(0, KEYS).forEach(k -> { + if (cache1.containsKey(k)) { + assertThat(accountingCacheEventListener1.events, hasEntry(is(k), containsInAnyOrder(CREATED))); + assertThat(accountingCacheEventListener2.events, hasEntry(is(k), containsInAnyOrder(accountingCacheEventListener1.events.get(k).toArray()))); + } else { + assertThat(accountingCacheEventListener1.events, hasEntry(is(k), containsInAnyOrder(is(CREATED), isOneOf(EVICTED, EXPIRED)))); + //assertThat(accountingCacheEventListener2.events, hasEntry(is(k), containsInAnyOrder(accountingCacheEventListener1.events.get(k).toArray()))); + assertThat(accountingCacheEventListener2.events, hasEntry(is(k), containsInAnyOrder(is(CREATED), isOneOf(EVICTED, EXPIRED)))); + } + })); // failover passive -> active failover(cache1, cache2); @@ -189,30 +237,22 @@ public void testExpirationFailover() throws Exception { range(0, KEYS).forEach(k -> { assertThat(cache1.get(k), is(nullValue())); }); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener1.events.get(EventType.EXPIRED).size(), greaterThan(0)); - await().atMost(TIMEOUT).until(() -> accountingCacheEventListener2.events.get(EventType.EXPIRED).size(), greaterThan(0)); + + await().atMost(TIMEOUT).untilAsserted(() -> range(0, KEYS).forEach(k -> { + assertThat(accountingCacheEventListener1.events, hasEntry(is(k), containsInAnyOrder(is(CREATED), isOneOf(EVICTED, EXPIRED)))); + //assertThat(accountingCacheEventListener2.events, hasEntry(is(k), containsInAnyOrder(accountingCacheEventListener1.events.get(k).toArray()))); + assertThat(accountingCacheEventListener2.events, hasEntry(is(k), containsInAnyOrder(is(CREATED), isOneOf(EVICTED, EXPIRED)))); + })); } static class AccountingCacheEventListener implements CacheEventListener { - private final Map>> events; - - AccountingCacheEventListener() { - events = new HashMap<>(); - clear(); - } + private final Map> events = new ConcurrentHashMap<>(); @Override public void onEvent(CacheEvent event) { - events.get(event.getType()).add(event); + events.computeIfAbsent(event.getKey(), key -> new CopyOnWriteArrayList<>()).add(event.getType()); } - - final void clear() { - for (EventType value : EventType.values()) { - events.put(value, new CopyOnWriteArrayList<>()); - } - } - } } From c6193ceeac6c5b13efdf7831cb07fe1276e25277 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 21 Aug 2020 16:42:09 -0400 Subject: [PATCH 282/372] Upgrade to new tc-platform version --- .../client/internal/ConnectionSource.java | 15 ++++++++------- gradle.properties | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java index 5145cbba15..b14e05d7b1 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java @@ -19,6 +19,7 @@ import org.terracotta.connection.entity.Entity; import org.terracotta.connection.entity.EntityRef; import org.terracotta.dynamic_config.api.model.Node; +import org.terracotta.dynamic_config.api.model.UID; import org.terracotta.dynamic_config.entity.topology.client.DynamicTopologyEntity; import org.terracotta.dynamic_config.entity.topology.common.DynamicTopologyEntityConstants; import org.terracotta.exception.EntityNotFoundException; @@ -35,11 +36,11 @@ import java.util.List; import java.util.Objects; import java.util.Properties; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.Future; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; public abstract class ConnectionSource { @@ -123,13 +124,13 @@ public LeasedConnection connect(Properties connectionProperties) throws Connecti DynamicTopologyEntity dynamicTopologyEntity = ref.fetchEntity(null); dynamicTopologyEntity.setListener(new DynamicTopologyEntity.Listener() { @Override - public void onNodeRemoval(int stripeId, Node removedNode) { - servers.remove(removedNode.getAddress()); + public void onNodeRemoval(UID stripeUID, Node removedNode) { + servers.remove(removedNode.getEndpoint(null).getAddress()); } @Override - public void onNodeAddition(int stripeId, Node addedNode) { - servers.add(addedNode.getAddress()); + public void onNodeAddition(UID stripeUID, Node addedNode) { + servers.add(addedNode.getEndpoint(null).getAddress()); } }); return new LeasedConnection() { diff --git a/gradle.properties b/gradle.properties index 197422e602..fdd3cdab71 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre28 +terracottaPlatformVersion = 5.8.0-pre29 terracottaApisVersion = 1.7.0-pre6 -terracottaCoreVersion = 5.7.0-pre36 +terracottaCoreVersion = 5.7.0-pre37 terracottaPassthroughTestingVersion = 1.7.0-pre17 terracottaUtilitiesVersion = 0.0.5 From 6dd5110a1335c2323d37d8a72863eb06b95522bf Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 24 Aug 2020 22:36:12 -0400 Subject: [PATCH 283/372] Upgrade to new tc-platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index fdd3cdab71..8e365157b5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre29 +terracottaPlatformVersion = 5.8.0-pre30 terracottaApisVersion = 1.7.0-pre6 terracottaCoreVersion = 5.7.0-pre37 terracottaPassthroughTestingVersion = 1.7.0-pre17 From e92cfcd2b22b96a0756f8be74d7f17edc6a88405 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 25 Aug 2020 17:50:06 -0400 Subject: [PATCH 284/372] Upgrade to final release TC versions --- gradle.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 8e365157b5..0ed5f53de4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,10 +10,10 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0-pre30 -terracottaApisVersion = 1.7.0-pre6 -terracottaCoreVersion = 5.7.0-pre37 -terracottaPassthroughTestingVersion = 1.7.0-pre17 +terracottaPlatformVersion = 5.8.0 +terracottaApisVersion = 1.7.0 +terracottaCoreVersion = 5.7.0 +terracottaPassthroughTestingVersion = 1.7.0 terracottaUtilitiesVersion = 0.0.5 # Test lib versions From 5aaa86b30fd216404c8adb4085022e348cdc4d0a Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 26 Aug 2020 21:42:42 -0400 Subject: [PATCH 285/372] Correctly remove and add addresses based on user input --- .../client/internal/ConnectionSource.java | 14 ++++++++++---- gradle.properties | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java index b14e05d7b1..ffb5f8a00a 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java @@ -18,6 +18,7 @@ import org.terracotta.connection.ConnectionException; import org.terracotta.connection.entity.Entity; import org.terracotta.connection.entity.EntityRef; +import org.terracotta.dynamic_config.api.model.Cluster; import org.terracotta.dynamic_config.api.model.Node; import org.terracotta.dynamic_config.api.model.UID; import org.terracotta.dynamic_config.entity.topology.client.DynamicTopologyEntity; @@ -124,13 +125,18 @@ public LeasedConnection connect(Properties connectionProperties) throws Connecti DynamicTopologyEntity dynamicTopologyEntity = ref.fetchEntity(null); dynamicTopologyEntity.setListener(new DynamicTopologyEntity.Listener() { @Override - public void onNodeRemoval(UID stripeUID, Node removedNode) { - servers.remove(removedNode.getEndpoint(null).getAddress()); + public void onNodeRemoval(Cluster cluster, UID stripeUID, Node removedNode) { + servers.remove(removedNode.getInternalAddress()); + removedNode.getPublicAddress().ifPresent(servers::remove); } @Override - public void onNodeAddition(UID stripeUID, Node addedNode) { - servers.add(addedNode.getEndpoint(null).getAddress()); + public void onNodeAddition(Cluster cluster, UID addedNodeUID) { + InetSocketAddress anAddress = servers.iterator().next(); // a random address from the user provided URI + cluster.getEndpoints(anAddress).stream() // get the cluster node endpoints for this user address + .filter(endpoint -> endpoint.getNodeUID().equals(addedNodeUID)) + .map(Node.Endpoint::getAddress) + .forEach(servers::add); } }); return new LeasedConnection() { diff --git a/gradle.properties b/gradle.properties index 0ed5f53de4..a66889b31d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.0 +terracottaPlatformVersion = 5.8.1-pre1 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.0 terracottaPassthroughTestingVersion = 1.7.0 From 398bb07c9fe50098a4a65fbb1f52fb67c98697fa Mon Sep 17 00:00:00 2001 From: mobasherul Date: Tue, 1 Sep 2020 12:16:26 +0530 Subject: [PATCH 286/372] Bump up platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index a66889b31d..1abc22eb07 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre1 +terracottaPlatformVersion = 5.8.1-pre2 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.0 terracottaPassthroughTestingVersion = 1.7.0 From 759ff89571cd88bc684a8c710c1c3bdd3c70bb96 Mon Sep 17 00:00:00 2001 From: "Venkata Sairam, Madduri" Date: Tue, 1 Sep 2020 23:12:52 +0530 Subject: [PATCH 287/372] Remove client directory exclusion from platform kit --- clustered/clustered-dist/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clustered/clustered-dist/build.gradle b/clustered/clustered-dist/build.gradle index 259b51f016..7ae071ad64 100644 --- a/clustered/clustered-dist/build.gradle +++ b/clustered/clustered-dist/build.gradle @@ -109,8 +109,8 @@ distributions { f.path = f.path.replace("platform-kit-$terracottaPlatformVersion/", "") } exclude { f -> - // Exclude tc's client subdir and README.txt - Issue 1273 - f.path.contains('client/') || f.path.contains('README.txt') || f.path.contains('server/conf') + // Exclude tc's README.txt - Issue 1273 + f.path.contains('README.txt') || f.path.contains('server/conf') } includeEmptyDirs = false } From f5285f6c7171896979c9fb9581b98ada71e5a5e1 Mon Sep 17 00:00:00 2001 From: Saurabh Agarwal Date: Wed, 9 Sep 2020 10:28:12 +0530 Subject: [PATCH 288/372] Bumped-up versions --- gradle.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 1abc22eb07..04e9218e56 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,11 +10,11 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre2 +terracottaPlatformVersion = 5.8.1-pre4 terracottaApisVersion = 1.7.0 -terracottaCoreVersion = 5.7.0 +terracottaCoreVersion = 5.7.1-pre1 terracottaPassthroughTestingVersion = 1.7.0 -terracottaUtilitiesVersion = 0.0.5 +terracottaUtilitiesVersion = 0.0.6 # Test lib versions junitVersion = 4.12 From 127f050ff45c343fdb084468b7fe74782a76e55d Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 9 Sep 2020 15:19:05 -0400 Subject: [PATCH 289/372] Adopt tc utils version of TestRetryer --- clustered/integration-test/build.gradle | 1 - .../IterationFailureBehaviorTest.java | 17 +- .../java/org/ehcache/clustered/LeaseTest.java | 17 +- .../clustered/ReconnectDuringDestroyTest.java | 17 +- .../clustered/TerminatedServerTest.java | 19 +- .../ManagementClusterConnectionTest.java | 17 +- .../reconnect/BasicCacheReconnectTest.java | 18 +- .../CacheManagerDestroyReconnectTest.java | 18 +- .../reconnect/EventsReconnectTest.java | 17 +- management/build.gradle | 1 - .../StandardEhcacheStatisticsTest.java | 7 +- settings.gradle | 2 +- test-utilities/build.gradle | 3 - .../config/checkstyle-suppressions.xml | 9 - .../java/org/ehcache/testing/TestRetryer.java | 214 ------------------ .../org/ehcache/testing/TestRetryerTest.java | 191 ---------------- 16 files changed, 60 insertions(+), 508 deletions(-) delete mode 100644 test-utilities/build.gradle delete mode 100644 test-utilities/config/checkstyle-suppressions.xml delete mode 100644 test-utilities/src/main/java/org/ehcache/testing/TestRetryer.java delete mode 100644 test-utilities/src/test/java/org/ehcache/testing/TestRetryerTest.java diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index ee58f478b9..b8b8276bdb 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -44,7 +44,6 @@ dependencies { testImplementation (group:'org.terracotta', name:'galvan-platform-support', version: terracottaPlatformVersion) testImplementation group: 'javax.cache', name: 'cache-api', version: jcacheVersion - testImplementation project(':test-utilities') } task unzipKit(type: Copy) { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java index 1535db5e3b..5c018c8b1a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java @@ -28,25 +28,20 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.spi.resilience.StoreAccessException; -import org.ehcache.testing.TestRetryer; -import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.terracotta.exception.ConnectionClosedException; import org.terracotta.testing.rules.Cluster; +import org.terracotta.utilities.test.rules.TestRetryer; import java.time.Duration; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import java.util.stream.Stream; import static java.time.Duration.ofSeconds; -import static java.time.temporal.ChronoUnit.SECONDS; -import static java.util.EnumSet.of; import static java.util.function.Function.identity; import static java.util.stream.Collectors.toMap; import static java.util.stream.LongStream.range; @@ -58,17 +53,17 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; public class IterationFailureBehaviorTest extends ClusteredTests { private static final int KEYS = 100; @ClassRule @Rule - public static final TestRetryer CLUSTER = TestRetryer.tryValues( - Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), - leaseLength -> newCluster(2).in(clusterPath()).withServiceFragment( - offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build(), - of(OutputIs.CLASS_RULE)); + public static final TestRetryer CLUSTER = TestRetryer.tryValues(ofSeconds(1), ofSeconds(10), ofSeconds(30)) + .map(leaseLength -> newCluster(2).in(clusterPath()).withServiceFragment( + offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build()) + .outputIs(CLASS_RULE); @Before public void startAllServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java index fee4d7b536..1cde819531 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java @@ -27,8 +27,6 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.TestRetryer; -import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.After; import org.junit.ClassRule; import org.junit.Rule; @@ -36,34 +34,33 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.terracotta.testing.rules.Cluster; +import org.terracotta.utilities.test.rules.TestRetryer; import java.net.URI; import java.time.Duration; import java.util.ArrayList; import java.util.List; -import java.util.stream.Stream; import static java.time.Duration.ofSeconds; -import static java.util.EnumSet.of; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.testing.StandardTimeouts.eventually; -import static org.ehcache.testing.TestRetryer.tryValues; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; +import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; @RunWith(Parameterized.class) public class LeaseTest extends ClusteredTests { @ClassRule @Rule - public static final TestRetryer CLUSTER = tryValues( - Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), - leaseLength -> newCluster().in(clusterPath()).withServiceFragment( - offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build(), - of(OutputIs.CLASS_RULE)); + public static final TestRetryer CLUSTER = tryValues(ofSeconds(1), ofSeconds(10), ofSeconds(30)) + .map(leaseLength -> newCluster().in(clusterPath()).withServiceFragment( + offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build()) + .outputIs(CLASS_RULE); private final List proxies = new ArrayList<>(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java index 9a9215bb7c..6b226ce0bd 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -31,8 +31,6 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.TestRetryer; -import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; @@ -46,23 +44,23 @@ import org.terracotta.testing.rules.Cluster; import com.tc.net.proxy.TCPProxy; +import org.terracotta.utilities.test.rules.TestRetryer; import java.net.URI; import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Properties; -import java.util.stream.Stream; import static java.time.Duration.ofSeconds; -import static java.util.EnumSet.of; import static org.ehcache.clustered.common.EhcacheEntityVersion.ENTITY_VERSION; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; import static org.ehcache.testing.StandardTimeouts.eventually; -import static org.ehcache.testing.TestRetryer.tryValues; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; +import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; /** * ReconnectDuringDestroyTest @@ -74,11 +72,10 @@ public class ReconnectDuringDestroyTest extends ClusteredTests { PersistentCacheManager cacheManager; @ClassRule @Rule - public static final TestRetryer CLUSTER = tryValues( - Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(3)), - leaseLength -> newCluster().in(clusterPath()).withServiceFragment( - offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build(), - of(OutputIs.CLASS_RULE)); + public static final TestRetryer CLUSTER = tryValues(ofSeconds(1), ofSeconds(10), ofSeconds(3)) + .map(leaseLength -> newCluster().in(clusterPath()).withServiceFragment( + offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build()) + .outputIs(CLASS_RULE); @BeforeClass public static void initializeProxy() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java index 9c4d80bddd..a67b1abb3c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java @@ -33,8 +33,6 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.statistics.DefaultStatisticsService; -import org.ehcache.testing.TestRetryer; -import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -50,6 +48,7 @@ import com.tc.properties.TCProperties; import com.tc.properties.TCPropertiesConsts; import com.tc.properties.TCPropertiesImpl; +import org.terracotta.utilities.test.rules.TestRetryer; import java.time.Duration; import java.time.temporal.ChronoUnit; @@ -60,15 +59,14 @@ import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.stream.Stream; import static java.time.Duration.ofSeconds; -import static java.time.temporal.ChronoUnit.SECONDS; -import static java.util.EnumSet.of; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.ehcache.testing.TestRetryer.tryValues; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; +import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.RULE; +import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; /** * Provides integration tests in which the server is terminated before the Ehcache operation completes. @@ -127,12 +125,11 @@ private ThrowableAssertAlternative assertExceptionOccur } @ClassRule @Rule - public static final TestRetryer CLUSTER = tryValues( - Stream.of(ofSeconds(2), ofSeconds(10), ofSeconds(30)), - leaseLength -> new ParallelTestCluster( + public static final TestRetryer CLUSTER = tryValues(ofSeconds(2), ofSeconds(10), ofSeconds(30)) + .map(leaseLength -> new ParallelTestCluster( newCluster().in(clusterPath()).withServiceFragment( - offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build()), - of(OutputIs.CLASS_RULE, OutputIs.RULE)); + offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build())) + .outputIs(CLASS_RULE, RULE); @Rule public final TestName testName = new TestName(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index 3e8e460573..ecd45dfc11 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -26,8 +26,6 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; -import org.ehcache.testing.TestRetryer; -import org.ehcache.testing.TestRetryer.OutputIs; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.BeforeClass; @@ -35,6 +33,7 @@ import org.junit.Rule; import org.junit.Test; import org.terracotta.management.model.capabilities.descriptors.Settings; +import org.terracotta.utilities.test.rules.TestRetryer; import java.net.URI; import java.time.Duration; @@ -43,11 +42,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.stream.Stream; import static java.time.Duration.ofSeconds; import static java.util.Collections.unmodifiableMap; -import static java.util.EnumSet.of; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.clustered.management.AbstractClusteringManagementTest.waitForAllNotifications; @@ -56,10 +53,11 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.testing.StandardTimeouts.eventually; -import static org.ehcache.testing.TestRetryer.tryValues; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; +import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; public class ManagementClusterConnectionTest extends ClusteredTests { @@ -76,12 +74,11 @@ public class ManagementClusterConnectionTest extends ClusteredTests { } @ClassRule @Rule - public static TestRetryer CLUSTER = tryValues( - Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), - leaseLength -> new ClusterWithManagement( + public static TestRetryer CLUSTER = tryValues(ofSeconds(1), ofSeconds(10), ofSeconds(30)) + .map(leaseLength -> new ClusterWithManagement( newCluster().in(clusterPath()).withServiceFragment( - offheapResources(resources) + leaseLength(leaseLength)).build()), - of(OutputIs.CLASS_RULE)); + offheapResources(resources) + leaseLength(leaseLength)).build())) + .outputIs(CLASS_RULE); @BeforeClass public static void beforeClass() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java index 4a6c2a7a02..4afcdf6bd9 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java @@ -28,13 +28,12 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.testing.TestRetryer; -import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; +import org.terracotta.utilities.test.rules.TestRetryer; import java.net.URI; import java.time.Duration; @@ -44,19 +43,17 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; -import java.util.stream.Stream; import static java.time.Duration.ofSeconds; -import static java.time.temporal.ChronoUnit.SECONDS; -import static java.util.EnumSet.of; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; -import static org.ehcache.testing.TestRetryer.tryValues; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; +import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; public class BasicCacheReconnectTest extends ClusteredTests { @@ -71,11 +68,10 @@ public class BasicCacheReconnectTest extends ClusteredTests { private static final List proxies = new ArrayList<>(); @ClassRule @Rule - public static final TestRetryer CLUSTER = tryValues( - Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), - leaseLength -> newCluster().in(clusterPath()).withServiceFragment( - offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build(), - of(OutputIs.CLASS_RULE)); + public static final TestRetryer CLUSTER = tryValues(ofSeconds(1), ofSeconds(10), ofSeconds(30)) + .map(leaseLength -> newCluster().in(clusterPath()).withServiceFragment( + offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build()) + .outputIs(CLASS_RULE); @BeforeClass public static void initializeCacheManager() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java index 1d87a60904..d0f48679f5 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java @@ -21,26 +21,23 @@ import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.util.TCPProxyUtil; import org.ehcache.config.builders.CacheManagerBuilder; -import org.ehcache.testing.TestRetryer; -import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; +import org.terracotta.utilities.test.rules.TestRetryer; import java.net.URI; import java.time.Duration; import java.util.ArrayList; import java.util.List; -import java.util.stream.Stream; import static java.time.Duration.ofSeconds; -import static java.time.temporal.ChronoUnit.SECONDS; -import static java.util.EnumSet.of; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; -import static org.ehcache.testing.TestRetryer.tryValues; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; +import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; public class CacheManagerDestroyReconnectTest extends ClusteredTests { @@ -50,11 +47,10 @@ public class CacheManagerDestroyReconnectTest extends ClusteredTests { private static final List proxies = new ArrayList<>(); @ClassRule @Rule - public static final TestRetryer CLUSTER = tryValues( - Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), - leaseLength -> newCluster().in(clusterPath()).withServiceFragment( - offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build(), - of(OutputIs.CLASS_RULE)); + public static final TestRetryer CLUSTER = tryValues(ofSeconds(1), ofSeconds(10), ofSeconds(30)) + .map(leaseLength -> newCluster().in(clusterPath()).withServiceFragment( + offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build()) + .outputIs(CLASS_RULE); @BeforeClass public static void initializeCacheManager() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index 96700845d0..1430731e3d 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -32,13 +32,12 @@ import org.ehcache.event.CacheEvent; import org.ehcache.event.CacheEventListener; import org.ehcache.event.EventType; -import org.ehcache.testing.TestRetryer; -import org.ehcache.testing.TestRetryer.OutputIs; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; +import org.terracotta.utilities.test.rules.TestRetryer; import java.net.URI; import java.time.Duration; @@ -52,18 +51,17 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; -import java.util.stream.Stream; import static java.time.Duration.ofSeconds; -import static java.util.EnumSet.of; import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; import static org.ehcache.testing.StandardTimeouts.eventually; -import static org.ehcache.testing.TestRetryer.tryValues; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; +import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; +import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; public class EventsReconnectTest extends ClusteredTests { @@ -104,11 +102,10 @@ final void clear() { private static final List proxies = new ArrayList<>(); @ClassRule @Rule - public static final TestRetryer CLUSTER = tryValues( - Stream.of(ofSeconds(1), ofSeconds(10), ofSeconds(30)), - leaseLength -> newCluster().in(clusterPath()).withServiceFragment( - offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build(), - of(OutputIs.CLASS_RULE)); + public static final TestRetryer CLUSTER = tryValues(ofSeconds(1), ofSeconds(10), ofSeconds(30)) + .map(leaseLength -> newCluster().in(clusterPath()).withServiceFragment( + offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build()) + .outputIs(CLASS_RULE); @BeforeClass public static void initializeCacheManager() throws Exception { diff --git a/management/build.gradle b/management/build.gradle index 39862e432e..ffa4b3a93e 100644 --- a/management/build.gradle +++ b/management/build.gradle @@ -39,5 +39,4 @@ dependencies { testImplementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" testImplementation 'org.xmlunit:xmlunit-core:2.6.0' testImplementation 'org.xmlunit:xmlunit-matchers:2.6.0' - testImplementation project(':test-utilities') } diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java index 5c54ee2788..989d38415a 100755 --- a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java @@ -29,7 +29,6 @@ import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; import org.ehcache.management.registry.DefaultManagementRegistryService; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; -import org.ehcache.testing.TestRetryer; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -41,6 +40,7 @@ import org.terracotta.statistics.derived.OperationResultFilter; import org.terracotta.statistics.derived.latency.LatencyHistogramStatistic; import org.terracotta.statistics.observer.ChainedOperationObserver; +import org.terracotta.utilities.test.rules.TestRetryer; import java.time.Duration; import java.util.Collection; @@ -49,18 +49,17 @@ import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; -import java.util.stream.Stream; import static java.time.Duration.ofMillis; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.ehcache.core.statistics.StatsUtils.findOperationStatisticOnChildren; -import static org.ehcache.testing.TestRetryer.tryValues; +import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; public class StandardEhcacheStatisticsTest { @ClassRule @Rule - public static final TestRetryer TIME_BASE = tryValues(Stream.of(1, 2, 4, 8, 16, 32).map(i -> ofMillis(50).multipliedBy(i))); + public static final TestRetryer TIME_BASE = tryValues(1, 2, 4, 8, 16, 32).map(i -> ofMillis(50).multipliedBy(i)); private CacheManager cacheManager; private Cache cache; diff --git a/settings.gradle b/settings.gradle index 3d89ecf10a..5af54e753a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -27,7 +27,7 @@ pluginManagement { } } -include "test-utilities", "api", "spi-tester", "core", "core-spi-test", "impl", "management", "transactions", "107", "xml", +include "api", "spi-tester", "core", "core-spi-test", "impl", "management", "transactions", "107", "xml", "clustered", "clustered:common-api", "clustered:common", "clustered:server:service-api", "clustered:server:service", "clustered:server:entity", "clustered:client", "clustered:clustered-dist", "clustered:ops-tool", diff --git a/test-utilities/build.gradle b/test-utilities/build.gradle deleted file mode 100644 index 5f022305d9..0000000000 --- a/test-utilities/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -dependencies { - api "junit:junit:$junitVersion" -} diff --git a/test-utilities/config/checkstyle-suppressions.xml b/test-utilities/config/checkstyle-suppressions.xml deleted file mode 100644 index be989c924a..0000000000 --- a/test-utilities/config/checkstyle-suppressions.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/test-utilities/src/main/java/org/ehcache/testing/TestRetryer.java b/test-utilities/src/main/java/org/ehcache/testing/TestRetryer.java deleted file mode 100644 index a19fd833df..0000000000 --- a/test-utilities/src/main/java/org/ehcache/testing/TestRetryer.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.ehcache.testing; - -import org.junit.AssumptionViolatedException; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Stream; - -import static java.util.Arrays.asList; -import static java.util.Collections.max; -import static java.util.Objects.requireNonNull; -import static java.util.stream.Collectors.joining; -import static org.junit.Assert.assertTrue; - -public class TestRetryer implements TestRule, Supplier { - - private static final Logger LOGGER = LoggerFactory.getLogger(TestRetryer.class); - - private final Function mapper; - private final Set outputIs; - private final Stream inputs; - - private final AtomicReference inputRef = new AtomicReference<>(); - private final AtomicReference outputRef = new AtomicReference<>(); - - private volatile boolean isClassRule = false; - private volatile boolean isRule = false; - - private volatile boolean terminalAttempt = false; - private volatile Map attemptResults = Collections.emptyMap(); - - private final Map accumulatedFailures = new ConcurrentHashMap<>(); - - @SafeVarargs @SuppressWarnings("varargs") // Creating a stream from an array is safe - public static TestRetryer tryValues(T... values) { - return tryValues(Stream.of(values)); - } - - public static TestRetryer tryValues(Stream values) { - return tryValues(values, Function.identity()); - } - - public static TestRetryer tryValues(Stream values, Function mapper) { - return tryValues(values, mapper, EnumSet.noneOf(OutputIs.class)); - } - - public static TestRetryer tryValues(Stream values, Function mapper, Set outputIs) { - return new TestRetryer<>(values, mapper, outputIs); - } - - private TestRetryer(Stream values, Function mapper, Set outputIs) { - this.inputs = values.map(Objects::requireNonNull); - this.mapper = requireNonNull(mapper); - this.outputIs = requireNonNull(outputIs); - } - - @Override - public Statement apply(Statement base, Description description) { - if (description.isTest()) { - isRule = true; - if (!isClassRule) { - throw new AssertionError(getClass().getSimpleName() + " must be annotated with both @ClassRule and @Rule"); - } - Statement target; - R output = get(); - if (output instanceof TestRule && outputIs.contains(OutputIs.RULE)) { - target = ((TestRule) output).apply(base, description); - } else { - target = base; - } - - return new Statement() { - @Override - public void evaluate() throws Throwable { - try { - target.evaluate(); - } catch (Throwable t) { - throw handleTestException(description, t); - } finally { - attemptResults.putIfAbsent(description, "PASSED"); - } - } - }; - } else { - isClassRule = true; - return new Statement() { - @Override - public void evaluate() throws Throwable { - Iterator iterator = inputs.iterator(); - while (iterator.hasNext()) { - T input = iterator.next(); - terminalAttempt = !iterator.hasNext(); - attemptResults = new ConcurrentHashMap<>(); - LOGGER.debug("{}: attempting with input value {}", description, input); - assertTrue(inputRef.compareAndSet(null, input)); - try { - R output = mapper.apply(input); - LOGGER.debug("{}: input {} maps to {}", description, input, output); - assertTrue(outputRef.compareAndSet(null, output)); - try { - if (output instanceof TestRule && outputIs.contains(OutputIs.CLASS_RULE)) { - ((TestRule) output).apply(base, description).evaluate(); - } else { - base.evaluate(); - } - } catch (Throwable t) { - throw handleTestException(description, t); - } finally { - assertTrue(outputRef.compareAndSet(output, null)); - } - } finally { - assertTrue(inputRef.compareAndSet(input, null)); - } - if (!isRule) { - throw new AssertionError(TestRetryer.this.getClass().getSimpleName() + " must be annotated with both @ClassRule and @Rule"); - } else if (attemptResults.values().stream().noneMatch(Throwable.class::isInstance)) { - LOGGER.debug("{}: successful with input value {}", description, input); - return; - } else { - LOGGER.info("{}: failed with input value {}\n{}", description, input, - attemptResults.entrySet().stream().map(e -> { - String testMethodHeader = e.getKey().getMethodName() + ": "; - return indent(testMethodHeader + e.getValue().toString(), 4, 4 + testMethodHeader.length()); - }).collect(joining("\n")) - ); - } - } - } - }; - } - } - - private Throwable handleTestException(Description description, Throwable t) { - Throwable failure = (Throwable) attemptResults.merge(description, t, (a, b) -> { - if (a instanceof Throwable) { - ((Throwable) a).addSuppressed((Throwable) b); - return a; - } else { - return b; - } - }); - Throwable merged = accumulatedFailures.merge(description, t, (a, b) -> { - b.addSuppressed(a); - return b; - }); - if (isTerminalAttempt()) { - return merged; - } else { - return new AssumptionViolatedException("Failure for input parameter: " + input(), failure); - } - } - - public T input() { - return requireNonNull(inputRef.get()); - } - - public R get() { - return requireNonNull(outputRef.get()); - } - - private boolean isTerminalAttempt() { - return terminalAttempt; - } - - public enum OutputIs { - RULE, CLASS_RULE; - } - - private static CharSequence indent(String string, Integer ... indent) { - char[] chars = new char[max(asList(indent))]; - Arrays.fill(chars, ' '); - String indentStrings = new String(chars); - String[] strings = string.split("(?m)^"); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < strings.length; i++) { - if (i < indent.length) { - sb.append(indentStrings, 0, indent[i]); - } else { - sb.append(indentStrings, 0, indent[indent.length - 1]); - } - sb.append(strings[i]); - } - return sb; - } -} diff --git a/test-utilities/src/test/java/org/ehcache/testing/TestRetryerTest.java b/test-utilities/src/test/java/org/ehcache/testing/TestRetryerTest.java deleted file mode 100644 index 33e26bbc88..0000000000 --- a/test-utilities/src/test/java/org/ehcache/testing/TestRetryerTest.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.ehcache.testing; - -import org.junit.Assert; -import org.junit.ClassRule; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.JUnitCore; -import org.junit.runner.Result; -import org.junit.runners.JUnit4; -import org.junit.runners.model.InitializationError; - -import static org.hamcrest.Matchers.array; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.internal.matchers.ThrowableMessageMatcher.hasMessage; - -public class TestRetryerTest { - - @Test @SuppressWarnings("unchecked") - public void testExceptionsSuppressProperly() throws InitializationError { - Result result = new JUnitCore().run(new JUnit4(RepeatedFailure.class)); - - assertThat(result.getFailureCount(), is(1)); - - Throwable exception = result.getFailures().get(0).getException(); - assertThat(exception, hasMessage(equalTo("Failed: 4"))); - assertThat(exception.getSuppressed(), array(hasMessage(equalTo("Failed: 3")))); - assertThat(exception.getSuppressed()[0].getSuppressed(), array(hasMessage(equalTo("Failed: 2")))); - assertThat(exception.getSuppressed()[0].getSuppressed()[0].getSuppressed(), array(hasMessage(equalTo("Failed: 1")))); - } - - @Test - public void testNoRetryOnImmediateSuccess() throws InitializationError { - Result result = new JUnitCore().run(new JUnit4(ImmediateSuccess.class)); - assertTrue(result.wasSuccessful()); - assertThat(result.getFailureCount(), is(0)); - assertThat(result.getRunCount(), is(1)); - } - - @Test - public void testRetryAndPassOnEventualSuccess() throws InitializationError { - Result result = new JUnitCore().run(new JUnit4(EventualSuccess.class)); - - assertTrue(result.wasSuccessful()); - assertThat(result.getFailureCount(), is(0)); - assertThat(result.getRunCount(), is(4)); - } - - @Test - public void testMissingClassRuleAnnotationTriggersFailure() throws InitializationError { - Result result = new JUnitCore().run(new JUnit4(MissingClassRuleAnnotation.class)); - - assertFalse(result.wasSuccessful()); - assertThat(result.getRunCount(), is(0)); - assertThat(result.getFailureCount(), is(1)); - Throwable throwable = result.getFailures().get(0).getException(); - assertThat(throwable, hasMessage(is("TestRetryer must be annotated with both @ClassRule and @Rule"))); - } - - @Test - public void testMissingRuleAnnotationTriggersFailure() throws InitializationError { - Result result = new JUnitCore().run(new JUnit4(MissingRuleAnnotation.class)); - - assertFalse(result.wasSuccessful()); - assertThat(result.getRunCount(), is(1)); - assertThat(result.getFailureCount(), is(1)); - Throwable throwable = result.getFailures().get(0).getException(); - assertThat(throwable, hasMessage(is("TestRetryer must be annotated with both @ClassRule and @Rule"))); - } - - @Test - public void testEffectivelyEmptyTestIsSafe() throws InitializationError { - Result result = new JUnitCore().run(new JUnit4(EffectivelyEmptyTest.class)); - - assertTrue(result.wasSuccessful()); - assertThat(result.getIgnoreCount(), is(1)); - assertThat(result.getRunCount(), is(0)); - assertThat(result.getFailureCount(), is(0)); - } - - @Test - public void testFailingTestLogsCorrectly() throws InitializationError { - Result result = new JUnitCore().run(new JUnit4(PartiallyFailingThenPassingTest.class)); - - assertTrue(result.wasSuccessful()); - assertThat(result.getFailureCount(), is(0)); - assertThat(result.getRunCount(), is(6)); - } - - @Ignore - public static class RepeatedFailure { - - @ClassRule @Rule - public static TestRetryer RETRYER = TestRetryer.tryValues(1, 2, 3, 4); - - @Test - public void test() { - Assert.fail("Failed: " + RETRYER.get()); - } - } - - @Ignore - public static class ImmediateSuccess { - - @ClassRule @Rule - public static TestRetryer RETRYER = TestRetryer.tryValues(1, 2, 3, 4); - - @Test - public void test() {} - } - - @Ignore - public static class EventualSuccess { - - @ClassRule @Rule - public static TestRetryer RETRYER = TestRetryer.tryValues(1, 2, 3, 4); - - @Test - public void test() { - Assert.assertThat(RETRYER.get(), is(4)); - } - } - - @Ignore - public static class MissingClassRuleAnnotation { - - @Rule - public TestRetryer RETRYER = TestRetryer.tryValues(1, 2, 3, 4); - - @Test - public void test() { - } - } - - @Ignore - public static class MissingRuleAnnotation { - - @ClassRule - public static TestRetryer RETRYER = TestRetryer.tryValues(1, 2, 3, 4); - - @Test - public void test() { - } - } - - @Ignore - public static class EffectivelyEmptyTest { - - @ClassRule @Rule - public static TestRetryer RETRYER = TestRetryer.tryValues(1, 2, 3, 4); - - @Test @Ignore - public void test() { - } - } - - @Ignore - public static class PartiallyFailingThenPassingTest { - - @ClassRule @Rule - public static TestRetryer RETRYER = TestRetryer.tryValues(1, 2, 3, 4); - - @Test - public void passingTest() { - } - - @Test - public void failingTest() { - assertThat(RETRYER.get(), is(3)); - } - } -} From e1e99a78edac02ecea6577838bdb68eedadc324d Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 9 Sep 2020 21:57:07 -0400 Subject: [PATCH 290/372] Upgrade to terracotta-platform 5.8.1-pre5 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 04e9218e56..0a4be1f826 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre4 +terracottaPlatformVersion = 5.8.1-pre5 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.1-pre1 terracottaPassthroughTestingVersion = 1.7.0 From 5748a3057c169f437d9aab88850f8cf1fcf97747 Mon Sep 17 00:00:00 2001 From: Tom Mesic <59479956+tmesic99@users.noreply.github.com> Date: Thu, 17 Sep 2020 14:28:03 -0400 Subject: [PATCH 291/372] Upgrade to terracotta-platform 5.8.1-pre6 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 0a4be1f826..4872c48fa0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre5 +terracottaPlatformVersion = 5.8.1-pre6 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.1-pre1 terracottaPassthroughTestingVersion = 1.7.0 From d20ed0da1c5532e6401cb0499d4063ff164e6a21 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 22 Sep 2020 14:21:34 -0400 Subject: [PATCH 292/372] Upgrade to new tc-platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4872c48fa0..196b7699e7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre6 +terracottaPlatformVersion = 5.8.1-pre8 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.1-pre1 terracottaPassthroughTestingVersion = 1.7.0 From 2c985a05d721c10f7d68468b95a7c885ac305080 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 25 Sep 2020 10:48:36 -0400 Subject: [PATCH 293/372] Improve TestClientDescriptor and associated classes to better represent real client behaviors --- .../ClusterTierManagerActiveEntityTest.java | 83 ++-- .../server/TestClientDescriptor.java | 22 +- .../clustered/server/TestInvokeContext.java | 20 +- .../store/ClusterTierActiveEntityTest.java | 426 +++++++++--------- .../store/ClusterTierPassiveEntityTest.java | 24 +- .../server/store/LockManagerImplTest.java | 25 +- 6 files changed, 291 insertions(+), 309 deletions(-) diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java index 0b188d6023..aa8f959f69 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java @@ -80,7 +80,7 @@ public void testDisconnectedNotConnected() throws Exception { EhcacheStateService ehcacheStateService = registry.getService(new EhcacheStateServiceConfig(blankConfiguration, registry, DEFAULT_MAPPER)); final ClusterTierManagerActiveEntity activeEntity = new ClusterTierManagerActiveEntity(blankConfiguration, ehcacheStateService, management); - ClientDescriptor client = new TestClientDescriptor(); + ClientDescriptor client = TestClientDescriptor.newClient(); activeEntity.disconnected(client); // Not expected to fail ... } @@ -103,7 +103,7 @@ public void testConfigure() throws Exception { ClusterTierManagerConfiguration configuration = new ClusterTierManagerConfiguration("identifier", serverSideConfiguration); EhcacheStateService ehcacheStateService = registry.getService(new EhcacheStateServiceConfig(configuration, registry, DEFAULT_MAPPER)); final ClusterTierManagerActiveEntity activeEntity = new ClusterTierManagerActiveEntity(configuration, ehcacheStateService, management); - ClientDescriptor client = new TestClientDescriptor(); + ClientDescriptor client = TestClientDescriptor.newClient(); activeEntity.connected(client); assertThat(registry.getStoreManagerService().getSharedResourcePoolIds(), containsInAnyOrder("primary", "secondary")); @@ -225,15 +225,16 @@ public void testValidate2Clients() throws Exception { EhcacheStateService ehcacheStateService = registry.getService(new EhcacheStateServiceConfig(configuration, registry, DEFAULT_MAPPER)); final ClusterTierManagerActiveEntity activeEntity = new ClusterTierManagerActiveEntity(configuration, ehcacheStateService, management); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); - assertSuccess(activeEntity.invokeActive(context, MESSAGE_FACTORY.validateStoreManager(serverSideConfig))); + TestClientDescriptor client1 = TestClientDescriptor.newClient(); + activeEntity.connected(client1); - TestInvokeContext context2 = new TestInvokeContext(); - activeEntity.connected(context2.getClientDescriptor()); + assertSuccess(activeEntity.invokeActive(client1.invokeContext(), MESSAGE_FACTORY.validateStoreManager(serverSideConfig))); - assertSuccess(activeEntity.invokeActive(context2, MESSAGE_FACTORY.validateStoreManager(serverSideConfig))); + TestClientDescriptor client2 = TestClientDescriptor.newClient(); + activeEntity.connected(client2); + + assertSuccess(activeEntity.invokeActive(client2.invokeContext(), MESSAGE_FACTORY.validateStoreManager(serverSideConfig))); } @Test @@ -251,9 +252,9 @@ public void testValidateAfterConfigure() throws Exception { EhcacheStateService ehcacheStateService = registry.getService(new EhcacheStateServiceConfig(configuration, registry, DEFAULT_MAPPER)); final ClusterTierManagerActiveEntity activeEntity = new ClusterTierManagerActiveEntity(configuration, ehcacheStateService, management); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); - assertSuccess(activeEntity.invokeActive(context, MESSAGE_FACTORY.validateStoreManager(serverSideConfig))); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); + assertSuccess(activeEntity.invokeActive(client.invokeContext(), MESSAGE_FACTORY.validateStoreManager(serverSideConfig))); } @Test @@ -271,10 +272,10 @@ public void testValidateExtraResource() throws Exception { ClusterTierManagerConfiguration configuration = new ClusterTierManagerConfiguration("identifier", serverSideConfiguration); EhcacheStateService ehcacheStateService = registry.getService(new EhcacheStateServiceConfig(configuration, registry, DEFAULT_MAPPER)); final ClusterTierManagerActiveEntity activeEntity = new ClusterTierManagerActiveEntity(configuration, ehcacheStateService, management); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertFailure(activeEntity.invokeActive(context, + assertFailure(activeEntity.invokeActive(client.invokeContext(), MESSAGE_FACTORY.validateStoreManager(new ServerSideConfigBuilder() .defaultResource("defaultServerResource") .sharedPool("primary", "serverResource1", 4, MemoryUnit.MEGABYTES) @@ -297,10 +298,10 @@ public void testValidateNoDefaultResource() throws Exception { ClusterTierManagerConfiguration configuration = new ClusterTierManagerConfiguration("identifier", serverSideConfiguration); EhcacheStateService ehcacheStateService = registry.getService(new EhcacheStateServiceConfig(configuration, registry, DEFAULT_MAPPER)); final ClusterTierManagerActiveEntity activeEntity = new ClusterTierManagerActiveEntity(configuration, ehcacheStateService, management); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertFailure(activeEntity.invokeActive(context, + assertFailure(activeEntity.invokeActive(client.invokeContext(), MESSAGE_FACTORY.validateStoreManager(new ServerSideConfigBuilder() .defaultResource("defaultServerResource") .sharedPool("primary", "serverResource1", 4, MemoryUnit.MEGABYTES) @@ -340,10 +341,10 @@ public void testValidateIdenticalConfiguration() throws Exception { EhcacheStateService ehcacheStateService = registry.getService(new EhcacheStateServiceConfig(configuration, registry, DEFAULT_MAPPER)); final ClusterTierManagerActiveEntity activeEntity = new ClusterTierManagerActiveEntity(configuration, ehcacheStateService, management); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertThat(activeEntity.invokeActive(context, MESSAGE_FACTORY.validateStoreManager(validateConfig)).getResponseType(), is(EhcacheResponseType.SUCCESS)); + assertThat(activeEntity.invokeActive(client.invokeContext(), MESSAGE_FACTORY.validateStoreManager(validateConfig)).getResponseType(), is(EhcacheResponseType.SUCCESS)); } @Test @@ -362,14 +363,14 @@ public void testValidateSharedPoolNamesDifferent() throws Exception { EhcacheStateService ehcacheStateService = registry.getService(new EhcacheStateServiceConfig(configuration, registry, DEFAULT_MAPPER)); ClusterTierManagerActiveEntity activeEntity = new ClusterTierManagerActiveEntity(configuration, ehcacheStateService, management); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); ServerSideConfiguration validate = new ServerSideConfigBuilder() .defaultResource("defaultServerResource") .sharedPool("primary", "serverResource1", 4, MemoryUnit.MEGABYTES) .sharedPool("ternary", "serverResource2", 8, MemoryUnit.MEGABYTES) .build(); - assertFailure(activeEntity.invokeActive(context, MESSAGE_FACTORY.validateStoreManager(validate)), InvalidServerSideConfigurationException.class, "Pool names not equal."); + assertFailure(activeEntity.invokeActive(client.invokeContext(), MESSAGE_FACTORY.validateStoreManager(validate)), InvalidServerSideConfigurationException.class, "Pool names not equal."); } @Test @@ -388,14 +389,14 @@ public void testValidateDefaultResourceNameDifferent() throws Exception { EhcacheStateService ehcacheStateService = registry.getService(new EhcacheStateServiceConfig(configuration, registry, DEFAULT_MAPPER)); ClusterTierManagerActiveEntity activeEntity = new ClusterTierManagerActiveEntity(configuration, ehcacheStateService, management); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); ServerSideConfiguration validate = new ServerSideConfigBuilder() .defaultResource("defaultServerResource2") .sharedPool("primary", "serverResource1", 4, MemoryUnit.MEGABYTES) .sharedPool("secondary", "serverResource2", 8, MemoryUnit.MEGABYTES) .build(); - assertFailure(activeEntity.invokeActive(context, MESSAGE_FACTORY.validateStoreManager(validate)), InvalidServerSideConfigurationException.class, "Default resource not aligned."); + assertFailure(activeEntity.invokeActive(client.invokeContext(), MESSAGE_FACTORY.validateStoreManager(validate)), InvalidServerSideConfigurationException.class, "Default resource not aligned."); } @Test @@ -414,14 +415,14 @@ public void testValidateClientSharedPoolSizeTooBig() throws Exception { EhcacheStateService ehcacheStateService = registry.getService(new EhcacheStateServiceConfig(configuration, registry, DEFAULT_MAPPER)); ClusterTierManagerActiveEntity activeEntity = new ClusterTierManagerActiveEntity(configuration, ehcacheStateService, management); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); ServerSideConfiguration validate = new ServerSideConfigBuilder() .defaultResource("defaultServerResource1") .sharedPool("primary", "serverResource1", 4, MemoryUnit.MEGABYTES) .sharedPool("secondary", "serverResource2", 36, MemoryUnit.MEGABYTES) .build(); - assertFailure(activeEntity.invokeActive(context, MESSAGE_FACTORY.validateStoreManager(validate)),InvalidServerSideConfigurationException.class, "Pool 'secondary' not equal."); + assertFailure(activeEntity.invokeActive(client.invokeContext(), MESSAGE_FACTORY.validateStoreManager(validate)),InvalidServerSideConfigurationException.class, "Pool 'secondary' not equal."); } @Test @@ -440,9 +441,9 @@ public void testValidateSecondClientInheritsFirstClientConfig() throws Exception EhcacheStateService ehcacheStateService = registry.getService(new EhcacheStateServiceConfig(configuration, registry, DEFAULT_MAPPER)); ClusterTierManagerActiveEntity activeEntity = new ClusterTierManagerActiveEntity(configuration, ehcacheStateService, management); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); - assertSuccess(activeEntity.invokeActive(context, MESSAGE_FACTORY.validateStoreManager(null))); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); + assertSuccess(activeEntity.invokeActive(client.invokeContext(), MESSAGE_FACTORY.validateStoreManager(null))); } @Test @@ -453,11 +454,11 @@ public void testInvalidMessageThrowsError() throws Exception { EhcacheStateService ehcacheStateService = registry.getService(new EhcacheStateServiceConfig(blankConfiguration, registry, DEFAULT_MAPPER)); final ClusterTierManagerActiveEntity activeEntity = new ClusterTierManagerActiveEntity(blankConfiguration, ehcacheStateService, management); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); try { - activeEntity.invokeActive(context, new InvalidMessage()); + activeEntity.invokeActive(client.invokeContext(), new InvalidMessage()); fail("Invalid message should result in AssertionError"); } catch (AssertionError e) { assertThat(e.getMessage(), containsString("Unsupported")); @@ -472,10 +473,10 @@ public void testPrepareForDestroy() throws Exception { EhcacheStateService ehcacheStateService = registry.getService(new EhcacheStateServiceConfig(blankConfiguration, registry, DEFAULT_MAPPER)); final ClusterTierManagerActiveEntity activeEntity = new ClusterTierManagerActiveEntity(blankConfiguration, ehcacheStateService, management); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - activeEntity.invokeActive(context, MESSAGE_FACTORY.prepareForDestroy()); + activeEntity.invokeActive(client.invokeContext(), MESSAGE_FACTORY.prepareForDestroy()); try { ehcacheStateService.validate(null); @@ -495,10 +496,10 @@ public void testPrepareForDestroyInProgress() throws Exception { final ClusterTierManagerActiveEntity activeEntity = new ClusterTierManagerActiveEntity(blankConfiguration, ehcacheStateService, management); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertFailure(activeEntity.invokeActive(context, MESSAGE_FACTORY.validateStoreManager(null)), DestroyInProgressException.class, "in progress for destroy"); + assertFailure(activeEntity.invokeActive(client.invokeContext(), MESSAGE_FACTORY.validateStoreManager(null)), DestroyInProgressException.class, "in progress for destroy"); } diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java index 26b2f20923..bbe1e12bb1 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java @@ -16,20 +16,30 @@ package org.ehcache.clustered.server; +import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse; +import org.terracotta.entity.ActiveInvokeContext; import org.terracotta.entity.ClientDescriptor; import org.terracotta.entity.ClientSourceId; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; public final class TestClientDescriptor implements ClientDescriptor { - private static final AtomicInteger counter = new AtomicInteger(0); + private static final AtomicLong counter = new AtomicLong(1L); - private final int clientId = counter.incrementAndGet(); + private final long clientId; + private final AtomicLong transactionId = new AtomicLong(1L); - public static ClientDescriptor create() { - return new TestClientDescriptor(); + public static TestClientDescriptor newClient() { + return new TestClientDescriptor(counter.getAndIncrement()); } + private TestClientDescriptor(long clientId) { + this.clientId = clientId; + } + + public ActiveInvokeContext invokeContext() { + return new TestInvokeContext(this, transactionId.getAndIncrement()); + } @Override public ClientSourceId getSourceId() { return new TestClientSourceId(clientId); @@ -56,6 +66,6 @@ public boolean equals(Object o) { @Override public int hashCode() { - return clientId; + return Long.hashCode(clientId); } } diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestInvokeContext.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestInvokeContext.java index 91f54ff049..e1d000868d 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestInvokeContext.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestInvokeContext.java @@ -23,16 +23,14 @@ import org.terracotta.entity.ClientDescriptor; import org.terracotta.entity.ClientSourceId; -import java.util.concurrent.atomic.AtomicLong; +final class TestInvokeContext implements ActiveInvokeContext { -public final class TestInvokeContext implements ActiveInvokeContext { + private final ClientDescriptor clientDescriptor; + private final long txnId; - private final AtomicLong currentTransactionId = new AtomicLong(); - - private final ClientDescriptor clientDescriptor = new TestClientDescriptor(); - - public void incrementCurrentTransactionId() { - currentTransactionId.incrementAndGet(); + TestInvokeContext(ClientDescriptor clientDescriptor, long txnId) { + this.clientDescriptor = clientDescriptor; + this.txnId = txnId; } @Override @@ -42,7 +40,7 @@ public ClientDescriptor getClientDescriptor() { @Override public ActiveInvokeChannel openInvokeChannel() { - return null; + throw new UnsupportedOperationException(); } @Override @@ -52,12 +50,12 @@ public ClientSourceId getClientSource() { @Override public long getCurrentTransactionId() { - return currentTransactionId.get(); + return txnId; } @Override public long getOldestTransactionId() { - return 1; + return 0; } @Override diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index 0f6422ec36..c3d04bd407 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -38,7 +38,6 @@ import org.ehcache.clustered.server.ServerSideServerStore; import org.ehcache.clustered.server.ServerStoreEventListener; import org.ehcache.clustered.server.TestClientDescriptor; -import org.ehcache.clustered.server.TestInvokeContext; import org.ehcache.clustered.server.internal.messages.EhcacheDataSyncMessage; import org.ehcache.clustered.server.internal.messages.PassiveReplicationMessage; import org.ehcache.clustered.server.state.EhcacheStateService; @@ -56,6 +55,7 @@ import org.terracotta.client.message.tracker.OOOMessageHandler; import org.terracotta.client.message.tracker.OOOMessageHandlerConfiguration; import org.terracotta.client.message.tracker.OOOMessageHandlerImpl; +import org.terracotta.entity.ActiveInvokeContext; import org.terracotta.entity.ClientCommunicator; import org.terracotta.entity.ClientDescriptor; import org.terracotta.entity.ConfigurationException; @@ -139,7 +139,7 @@ public void testConfigNull() throws Exception { public void testConnected() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); - ClientDescriptor client = new TestClientDescriptor(); + ClientDescriptor client = TestClientDescriptor.newClient(); activeEntity.connected(client); Set connectedClients = activeEntity.getConnectedClients(); @@ -151,7 +151,7 @@ public void testConnected() throws Exception { public void testConnectedAgain() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); - ClientDescriptor client = new TestClientDescriptor(); + ClientDescriptor client = TestClientDescriptor.newClient(); activeEntity.connected(client); activeEntity.connected(client); @@ -164,10 +164,10 @@ public void testConnectedAgain() throws Exception { public void testConnectedSecond() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); - ClientDescriptor client1 = new TestClientDescriptor(); + ClientDescriptor client1 = TestClientDescriptor.newClient(); activeEntity.connected(client1); - ClientDescriptor client2 = new TestClientDescriptor(); + ClientDescriptor client2 = TestClientDescriptor.newClient(); activeEntity.connected(client2); Set connectedClients = activeEntity.getConnectedClients(); @@ -179,7 +179,7 @@ public void testConnectedSecond() throws Exception { public void testDisconnectedNotConnected() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); - ClientDescriptor client1 = new TestClientDescriptor(); + ClientDescriptor client1 = TestClientDescriptor.newClient(); activeEntity.disconnected(client1); // Not expected to fail ... } @@ -191,7 +191,7 @@ public void testDisconnectedNotConnected() throws Exception { public void testDisconnected() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); - ClientDescriptor client1 = new TestClientDescriptor(); + ClientDescriptor client1 = TestClientDescriptor.newClient(); activeEntity.connected(client1); activeEntity.disconnected(client1); @@ -203,29 +203,27 @@ public void testEventListenerEnabledTracking() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext ctx1 = new TestInvokeContext(); - ClientDescriptor client1 = ctx1.getClientDescriptor(); - TestInvokeContext ctx2 = new TestInvokeContext(); - ClientDescriptor client2 = ctx2.getClientDescriptor(); + TestClientDescriptor client1 = TestClientDescriptor.newClient(); + TestClientDescriptor client2 = TestClientDescriptor.newClient(); // check that connecting clients does not enable listeners by default activeEntity.connected(client1); activeEntity.connected(client2); assertThat(activeEntity.getEventListeners().size(), is(0)); - assertThat(activeEntity.invokeActive(ctx1, new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); + assertThat(activeEntity.invokeActive(client1.invokeContext(), new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); assertThat(activeEntity.getEventListeners().size(), is(1)); // a client can register as many times as it wants, it's considered a single listener - assertThat(activeEntity.invokeActive(ctx1, new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); + assertThat(activeEntity.invokeActive(client1.invokeContext(), new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); assertThat(activeEntity.getEventListeners().size(), is(1)); - assertThat(activeEntity.invokeActive(ctx2, new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); + assertThat(activeEntity.invokeActive(client2.invokeContext(), new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); assertThat(activeEntity.getEventListeners().size(), is(2)); // check that disabling events is accounted for - assertThat(activeEntity.invokeActive(ctx2, new ServerStoreOpMessage.EnableEventListenerMessage(false)), succeeds()); + assertThat(activeEntity.invokeActive(client2.invokeContext(), new ServerStoreOpMessage.EnableEventListenerMessage(false)), succeeds()); assertThat(activeEntity.getEventListeners().size(), is(1)); // check that disabling events from a client that does not have events enabled is a noop - assertThat(activeEntity.invokeActive(ctx2, new ServerStoreOpMessage.EnableEventListenerMessage(false)), succeeds()); + assertThat(activeEntity.invokeActive(client2.invokeContext(), new ServerStoreOpMessage.EnableEventListenerMessage(false)), succeeds()); assertThat(activeEntity.getEventListeners().size(), is(1)); // check that disconnected clients are accounted for @@ -240,10 +238,10 @@ public void testEventListenerEnabledTracking() throws Exception { public void testDisconnectedSecond() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); - ClientDescriptor client1 = new TestClientDescriptor(); + ClientDescriptor client1 = TestClientDescriptor.newClient(); activeEntity.connected(client1); - ClientDescriptor client2 = new TestClientDescriptor(); + ClientDescriptor client2 = TestClientDescriptor.newClient(); activeEntity.connected(client2); assertThat(activeEntity.getConnectedClients(), hasSize(2)); @@ -283,15 +281,14 @@ public void testEnableEventListenerMessageEnablesOrDisablesEventsOnStore() throw ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(registry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext ctx1 = new TestInvokeContext(); - ClientDescriptor client1 = ctx1.getClientDescriptor(); + TestClientDescriptor client = TestClientDescriptor.newClient(); - activeEntity.connected(client1); + activeEntity.connected(client); // also check that duplicating enable/disable calls has no effect - assertThat(activeEntity.invokeActive(ctx1, new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); - assertThat(activeEntity.invokeActive(ctx1, new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); - assertThat(activeEntity.invokeActive(ctx1, new ServerStoreOpMessage.EnableEventListenerMessage(false)), succeeds()); - assertThat(activeEntity.invokeActive(ctx1, new ServerStoreOpMessage.EnableEventListenerMessage(false)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.EnableEventListenerMessage(true)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.EnableEventListenerMessage(false)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.EnableEventListenerMessage(false)), succeeds()); storeOrderVerifier.verify(store).enableEvents(eq(true)); storeOrderVerifier.verify(store).enableEvents(eq(false)); @@ -302,41 +299,41 @@ public void testAppendInvalidationAcksTakenIntoAccount() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context1 = new TestInvokeContext(); - TestInvokeContext context2 = new TestInvokeContext(); - TestInvokeContext context3 = new TestInvokeContext(); - activeEntity.connected(context1.getClientDescriptor()); - activeEntity.connected(context2.getClientDescriptor()); - activeEntity.connected(context3.getClientDescriptor()); + TestClientDescriptor client1 = TestClientDescriptor.newClient(); + TestClientDescriptor client2 = TestClientDescriptor.newClient(); + TestClientDescriptor client3 = TestClientDescriptor.newClient(); + activeEntity.connected(client1); + activeEntity.connected(client2); + activeEntity.connected(client3); // attach to the store - assertThat(activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - assertThat(activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - assertThat(activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client1.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client2.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client3.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); // perform an append - assertThat(activeEntity.invokeActive(context1, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))), succeeds()); + assertThat(activeEntity.invokeActive(client1.invokeContext(), new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))), succeeds()); // assert that an invalidation request is pending assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(1)); InvalidationHolder invalidationHolder = activeEntity.getClientsWaitingForInvalidation().values().iterator().next(); - assertThat(invalidationHolder.clientDescriptorWaitingForInvalidation, is(context1.getClientDescriptor())); + assertThat(invalidationHolder.clientDescriptorWaitingForInvalidation, is(client1)); assertThat(invalidationHolder.clientsHavingToInvalidate.size(), is(2)); - assertThat(invalidationHolder.clientsHavingToInvalidate, containsInAnyOrder(context2.getClientDescriptor(), context3.getClientDescriptor())); + assertThat(invalidationHolder.clientsHavingToInvalidate, containsInAnyOrder(client2, client3)); // client 2 acks - assertThat(activeEntity.invokeActive(context2, new ServerStoreOpMessage.ClientInvalidationAck(1L, activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())), succeeds()); + assertThat(activeEntity.invokeActive(client2.invokeContext(), new ServerStoreOpMessage.ClientInvalidationAck(1L, activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())), succeeds()); // assert that client 2 is not waited for anymore assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(1)); invalidationHolder = activeEntity.getClientsWaitingForInvalidation().values().iterator().next(); - assertThat(invalidationHolder.clientDescriptorWaitingForInvalidation, is(context1.getClientDescriptor())); + assertThat(invalidationHolder.clientDescriptorWaitingForInvalidation, is(client1)); assertThat(invalidationHolder.clientsHavingToInvalidate.size(), is(1)); - assertThat(invalidationHolder.clientsHavingToInvalidate, contains(context3.getClientDescriptor())); + assertThat(invalidationHolder.clientsHavingToInvalidate, contains(client3)); // client 3 acks - assertThat(activeEntity.invokeActive(context3, new ServerStoreOpMessage.ClientInvalidationAck(1L, activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())), succeeds()); + assertThat(activeEntity.invokeActive(client3.invokeContext(), new ServerStoreOpMessage.ClientInvalidationAck(1L, activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())), succeeds()); // assert that the invalidation request is done since all clients disconnected assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(0)); @@ -347,40 +344,40 @@ public void testClearInvalidationAcksTakenIntoAccount() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context1 = new TestInvokeContext(); - TestInvokeContext context2 = new TestInvokeContext(); - TestInvokeContext context3 = new TestInvokeContext(); - activeEntity.connected(context1.getClientDescriptor()); - activeEntity.connected(context2.getClientDescriptor()); - activeEntity.connected(context3.getClientDescriptor()); + TestClientDescriptor client1 = TestClientDescriptor.newClient(); + TestClientDescriptor client2 = TestClientDescriptor.newClient(); + TestClientDescriptor client3 = TestClientDescriptor.newClient(); + activeEntity.connected(client1); + activeEntity.connected(client2); + activeEntity.connected(client3); // attach to the store - assertThat(activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - assertThat(activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - assertThat(activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client1.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client2.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client3.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); // perform a clear - assertThat(activeEntity.invokeActive(context1, new ServerStoreOpMessage.ClearMessage()), succeeds()); + assertThat(activeEntity.invokeActive(client1.invokeContext(), new ServerStoreOpMessage.ClearMessage()), succeeds()); // assert that an invalidation request is pending assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(1)); InvalidationHolder invalidationHolder = activeEntity.getClientsWaitingForInvalidation().values().iterator().next(); - assertThat(invalidationHolder.clientDescriptorWaitingForInvalidation, is(context1.getClientDescriptor())); + assertThat(invalidationHolder.clientDescriptorWaitingForInvalidation, is(client1)); assertThat(invalidationHolder.clientsHavingToInvalidate.size(), is(2)); - assertThat(invalidationHolder.clientsHavingToInvalidate, containsInAnyOrder(context2.getClientDescriptor(), context3.getClientDescriptor())); + assertThat(invalidationHolder.clientsHavingToInvalidate, containsInAnyOrder(client2, client3)); // client 2 acks - assertThat(activeEntity.invokeActive(context2, new ServerStoreOpMessage.ClientInvalidationAllAck(activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())), succeeds()); + assertThat(activeEntity.invokeActive(client2.invokeContext(), new ServerStoreOpMessage.ClientInvalidationAllAck(activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())), succeeds()); // assert that client 2 is not waited for anymore assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(1)); invalidationHolder = activeEntity.getClientsWaitingForInvalidation().values().iterator().next(); - assertThat(invalidationHolder.clientDescriptorWaitingForInvalidation, is(context1.getClientDescriptor())); + assertThat(invalidationHolder.clientDescriptorWaitingForInvalidation, is(client1)); assertThat(invalidationHolder.clientsHavingToInvalidate.size(), is(1)); - assertThat(invalidationHolder.clientsHavingToInvalidate, contains(context3.getClientDescriptor())); + assertThat(invalidationHolder.clientsHavingToInvalidate, contains(client3)); // client 3 acks - assertThat(activeEntity.invokeActive(context3, new ServerStoreOpMessage.ClientInvalidationAllAck(activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())), succeeds()); + assertThat(activeEntity.invokeActive(client3.invokeContext(), new ServerStoreOpMessage.ClientInvalidationAllAck(activeEntity.getClientsWaitingForInvalidation().keySet().iterator().next())), succeeds()); // assert that the invalidation request is done since all clients disconnected assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(0)); @@ -391,33 +388,33 @@ public void testAppendInvalidationDisconnectionOfInvalidatingClientsTakenIntoAcc ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context1 = new TestInvokeContext(); - TestInvokeContext context2 = new TestInvokeContext(); - TestInvokeContext context3 = new TestInvokeContext(); - activeEntity.connected(context1.getClientDescriptor()); - activeEntity.connected(context2.getClientDescriptor()); - activeEntity.connected(context3.getClientDescriptor()); + TestClientDescriptor client1 = TestClientDescriptor.newClient(); + TestClientDescriptor client2 = TestClientDescriptor.newClient(); + TestClientDescriptor client3 = TestClientDescriptor.newClient(); + activeEntity.connected(client1); + activeEntity.connected(client2); + activeEntity.connected(client3); // attach to the store - assertThat(activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - assertThat(activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - assertThat(activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client1.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client2.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client3.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); // perform an append - assertThat(activeEntity.invokeActive(context1, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))), succeeds()); + assertThat(activeEntity.invokeActive(client1.invokeContext(), new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))), succeeds()); // disconnect client2 - activeEntity.disconnected(context2.getClientDescriptor()); + activeEntity.disconnected(client2); // assert that client 2 is not waited for anymore assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(1)); InvalidationHolder invalidationHolder = activeEntity.getClientsWaitingForInvalidation().values().iterator().next(); - assertThat(invalidationHolder.clientDescriptorWaitingForInvalidation, is(context1.getClientDescriptor())); + assertThat(invalidationHolder.clientDescriptorWaitingForInvalidation, is(client1)); assertThat(invalidationHolder.clientsHavingToInvalidate.size(), is(1)); - assertThat(invalidationHolder.clientsHavingToInvalidate, contains(context3.getClientDescriptor())); + assertThat(invalidationHolder.clientsHavingToInvalidate, contains(client3)); // disconnect client3 - activeEntity.disconnected(context3.getClientDescriptor()); + activeEntity.disconnected(client3); // assert that the invalidation request is done since all clients disconnected assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(0)); @@ -428,33 +425,33 @@ public void testClearInvalidationDisconnectionOfInvalidatingClientsTakenIntoAcco ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context1 = new TestInvokeContext(); - TestInvokeContext context2 = new TestInvokeContext(); - TestInvokeContext context3 = new TestInvokeContext(); - activeEntity.connected(context1.getClientDescriptor()); - activeEntity.connected(context2.getClientDescriptor()); - activeEntity.connected(context3.getClientDescriptor()); + TestClientDescriptor client1 = TestClientDescriptor.newClient(); + TestClientDescriptor client2 = TestClientDescriptor.newClient(); + TestClientDescriptor client3 = TestClientDescriptor.newClient(); + activeEntity.connected(client1); + activeEntity.connected(client2); + activeEntity.connected(client3); // attach to the store - assertThat(activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - assertThat(activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - assertThat(activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client1.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client2.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client3.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); // perform an append - assertThat(activeEntity.invokeActive(context1, new ServerStoreOpMessage.ClearMessage()), succeeds()); + assertThat(activeEntity.invokeActive(client1.invokeContext(), new ServerStoreOpMessage.ClearMessage()), succeeds()); // disconnect client2 - activeEntity.disconnected(context2.getClientDescriptor()); + activeEntity.disconnected(client2); // assert that client 2 is not waited for anymore assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(1)); InvalidationHolder invalidationHolder = activeEntity.getClientsWaitingForInvalidation().values().iterator().next(); - assertThat(invalidationHolder.clientDescriptorWaitingForInvalidation, is(context1.getClientDescriptor())); + assertThat(invalidationHolder.clientDescriptorWaitingForInvalidation, is(client1)); assertThat(invalidationHolder.clientsHavingToInvalidate.size(), is(1)); - assertThat(invalidationHolder.clientsHavingToInvalidate, contains(context3.getClientDescriptor())); + assertThat(invalidationHolder.clientsHavingToInvalidate, contains(client3)); // disconnect client3 - activeEntity.disconnected(context3.getClientDescriptor()); + activeEntity.disconnected(client3); // assert that the invalidation request is done since all clients disconnected assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(0)); @@ -470,23 +467,23 @@ public void testAppendInvalidationDisconnectionOfBlockingClientTakenIntoAccount( new ClusterTierEntityConfiguration(identifier, defaultStoreName, serverStoreConfiguration), DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context1 = new TestInvokeContext(); - TestInvokeContext context2 = new TestInvokeContext(); - TestInvokeContext context3 = new TestInvokeContext(); - activeEntity.connected(context1.getClientDescriptor()); - activeEntity.connected(context2.getClientDescriptor()); - activeEntity.connected(context3.getClientDescriptor()); + TestClientDescriptor client1 = TestClientDescriptor.newClient(); + TestClientDescriptor client2 = TestClientDescriptor.newClient(); + TestClientDescriptor client3 = TestClientDescriptor.newClient(); + activeEntity.connected(client1); + activeEntity.connected(client2); + activeEntity.connected(client3); // attach to the store - assertThat(activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); - assertThat(activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); - assertThat(activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client1.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client2.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client3.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); // perform an append - assertThat(activeEntity.invokeActive(context1, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))), succeeds()); + assertThat(activeEntity.invokeActive(client1.invokeContext(), new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))), succeeds()); // disconnect client1 - activeEntity.disconnected(context1.getClientDescriptor()); + activeEntity.disconnected(client1); // assert that the invalidation request is done since the originating client disconnected assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(0)); @@ -502,23 +499,23 @@ public void testClearInvalidationDisconnectionOfBlockingClientTakenIntoAccount() new ClusterTierEntityConfiguration(identifier, defaultStoreName, serverStoreConfiguration), DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context1 = new TestInvokeContext(); - TestInvokeContext context2 = new TestInvokeContext(); - TestInvokeContext context3 = new TestInvokeContext(); - activeEntity.connected(context1.getClientDescriptor()); - activeEntity.connected(context2.getClientDescriptor()); - activeEntity.connected(context3.getClientDescriptor()); + TestClientDescriptor client1 = TestClientDescriptor.newClient(); + TestClientDescriptor client2 = TestClientDescriptor.newClient(); + TestClientDescriptor client3 = TestClientDescriptor.newClient(); + activeEntity.connected(client1); + activeEntity.connected(client2); + activeEntity.connected(client3); // attach to the store - assertThat(activeEntity.invokeActive(context1, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); - assertThat(activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); - assertThat(activeEntity.invokeActive(context3, new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client1.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client2.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client3.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, serverStoreConfiguration)), succeeds()); // perform an append - assertThat(activeEntity.invokeActive(context1, new ServerStoreOpMessage.ClearMessage()), succeeds()); + assertThat(activeEntity.invokeActive(client1.invokeContext(), new ServerStoreOpMessage.ClearMessage()), succeeds()); // disconnect client1 - activeEntity.disconnected(context1.getClientDescriptor()); + activeEntity.disconnected(client1); // assert that the invalidation request is done since the originating client disconnected assertThat(activeEntity.getClientsWaitingForInvalidation().size(), is(0)); @@ -529,15 +526,15 @@ public void testWithAttachmentSucceedsInvokingServerStoreOperation() throws Exce ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); // attach to the store - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))), succeeds()); - EhcacheEntityResponse response = activeEntity.invokeActive(context, new ServerStoreOpMessage.GetMessage(1L)); + EhcacheEntityResponse response = activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.GetMessage(1L)); assertThat(response, instanceOf(EhcacheEntityResponse.GetResponse.class)); EhcacheEntityResponse.GetResponse getResponse = (EhcacheEntityResponse.GetResponse) response; assertThat(getResponse.getChain().isEmpty(), is(false)); @@ -555,17 +552,17 @@ public void testCreateDedicatedServerStore() throws Exception { assertThat(activeEntity.getConnectedClients(), empty()); assertThat(defaultRegistry.getStoreManagerService().getStores(), containsInAnyOrder(defaultStoreName)); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - assertThat(activeEntity.getConnectedClients(), contains(context.getClientDescriptor())); + assertThat(activeEntity.getConnectedClients(), contains(client)); /* * Ensure the dedicated resource pool remains after client disconnect. */ - activeEntity.disconnected(context.getClientDescriptor()); + activeEntity.disconnected(client); assertThat(defaultRegistry.getStoreManagerService().getDedicatedResourcePoolIds(), containsInAnyOrder(defaultStoreName)); @@ -592,20 +589,20 @@ public void testValidateDedicatedServerStore() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client1 = TestClientDescriptor.newClient(); + activeEntity.connected(client1); - TestInvokeContext context2 = new TestInvokeContext(); - activeEntity.connected(context2.getClientDescriptor()); + TestClientDescriptor client2 = TestClientDescriptor.newClient(); + activeEntity.connected(client2); - assertThat(activeEntity.invokeActive(context2, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client2.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); assertThat(defaultRegistry.getStoreManagerService().getDedicatedResourcePoolIds(), containsInAnyOrder(defaultStoreName)); assertThat(defaultRegistry.getResource(defaultResource).getUsed(), is(MemoryUnit.MEGABYTES.toBytes(1L))); assertThat(activeEntity.getConnectedClients(), hasSize(2)); - assertThat(activeEntity.getConnectedClients(), containsInAnyOrder(context.getClientDescriptor(), context2.getClientDescriptor())); + assertThat(activeEntity.getConnectedClients(), containsInAnyOrder(client1, client2)); assertThat(defaultRegistry.getStoreManagerService().getStores(), contains(defaultStoreName)); } @@ -614,10 +611,10 @@ public void testValidateDedicatedServerStoreBad() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertThat(activeEntity.invokeActive(context, + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, new ServerStoreConfigBuilder() .dedicated(defaultResource, 8, MemoryUnit.MEGABYTES) @@ -630,10 +627,10 @@ public void testValidateUnknown() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, new ServerStoreConfigBuilder().unknown().build())), succeeds()); } @@ -687,12 +684,12 @@ public void testValidateSharedServerStore() throws Exception { new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, storeConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, storeConfiguration)), succeeds()); - assertThat(activeEntity.getConnectedClients(), contains(context.getClientDescriptor())); + assertThat(activeEntity.getConnectedClients(), contains(client)); } @Test @@ -700,8 +697,8 @@ public void testValidateServerStore_DedicatedStoresDifferentSizes() throws Excep ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); ServerStoreConfiguration storeConfiguration = new ServerStoreConfigBuilder() .dedicated(defaultResource, 2, MemoryUnit.MEGABYTES) @@ -714,7 +711,7 @@ public void testValidateServerStore_DedicatedStoresDifferentSizes() throws Excep ", desired: " + storeConfiguration.getPoolAllocation(); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, storeConfiguration)), + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, storeConfiguration)), failsWith(both(IsInstanceOf.any(InvalidServerStoreConfigurationException.class)).and(withMessage(containsString(expectedMessageContent))))); } @@ -723,8 +720,8 @@ public void testValidateServerStore_DedicatedStoreResourceNamesDifferent() throw ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); ServerStoreConfiguration storeConfiguration = new ServerStoreConfigBuilder() .dedicated("otherResource", 1, MemoryUnit.MEGABYTES) @@ -737,7 +734,7 @@ public void testValidateServerStore_DedicatedStoreResourceNamesDifferent() throw ", desired: " + storeConfiguration.getPoolAllocation(); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, storeConfiguration)), + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, storeConfiguration)), failsWith(both(IsInstanceOf.any(InvalidServerStoreConfigurationException.class)).and(withMessage(containsString(expectedMessageContent))))); } @@ -751,8 +748,8 @@ public void testValidateServerStore_DifferentSharedPools() throws Exception { new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); ServerStoreConfiguration otherConfiguration = new ServerStoreConfigBuilder() .shared("other") @@ -765,7 +762,7 @@ public void testValidateServerStore_DifferentSharedPools() throws Exception { ", desired: " + otherConfiguration.getPoolAllocation(); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, otherConfiguration)), + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, otherConfiguration)), failsWith(both(IsInstanceOf.any(InvalidServerStoreConfigurationException.class)).and(withMessage(containsString(expectedMessageContent))))); } @@ -835,11 +832,11 @@ public void testSyncToPassiveNoData() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); @SuppressWarnings("unchecked") PassiveSynchronizationChannel syncChannel = mock(PassiveSynchronizationChannel.class); @@ -853,17 +850,17 @@ public void testSyncToPassiveBatchedByDefault() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); ByteBuffer payload = ByteBuffer.allocate(512); // Put keys that maps to the same concurrency key - assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, payload)), succeeds()); - assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(-2L, payload)), succeeds()); - assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(17L, payload)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(1L, payload)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(-2L, payload)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(17L, payload)), succeeds()); @SuppressWarnings("unchecked") PassiveSynchronizationChannel syncChannel = mock(PassiveSynchronizationChannel.class); @@ -947,14 +944,14 @@ public void testReplicationMessageAndOriginalServerStoreOpMessageHasSameConcurre IEntityMessenger entityMessenger = defaultRegistry.getEntityMessenger(); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); reset(entityMessenger); EhcacheEntityMessage getAndAppend = new ServerStoreOpMessage.GetAndAppendMessage(1L, createPayload(1L)); - activeEntity.invokeActive(context, getAndAppend); + activeEntity.invokeActive(client.invokeContext(), getAndAppend); ArgumentCaptor captor = ArgumentCaptor.forClass(PassiveReplicationMessage.ChainReplicationMessage.class); verify(entityMessenger).messageSelfAndDeferRetirement(isNotNull(), captor.capture()); @@ -967,60 +964,39 @@ public void testReplicationMessageAndOriginalServerStoreOpMessageHasSameConcurre public void testInvalidMessageThrowsError() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); try { - activeEntity.invokeActive(context, new InvalidMessage()); + activeEntity.invokeActive(client.invokeContext(), new InvalidMessage()); fail("Invalid message should result in AssertionError"); } catch (AssertionError e) { assertThat(e.getMessage(), containsString("Unsupported")); } } - @Test - public void testActiveTracksMessageDuplication() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); - activeEntity.createNew(); - - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - - ServerStoreOpMessage.AppendMessage message = new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L)); - activeEntity.invokeActive(context, message); - - // create another message that has the same message ID - message = new ServerStoreOpMessage.AppendMessage(2L, createPayload(1L)); - - activeEntity.invokeActive(context, message); // this invoke should be rejected due to duplicate message id - - ServerStoreOpMessage.GetMessage getMessage = new ServerStoreOpMessage.GetMessage(2L); - EhcacheEntityResponse.GetResponse response = (EhcacheEntityResponse.GetResponse) activeEntity.invokeActive(context, getMessage); - assertThat(response.getChain().isEmpty(), is(false)); - } - @Test public void testActiveMessageTracking() throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); EhcacheStateServiceImpl ehcacheStateService = defaultRegistry.getStoreManagerService(); ehcacheStateService.createStore(defaultStoreName, defaultStoreConfiguration, false); //hack to enable message tracking on active - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - context.incrementCurrentTransactionId(); + ActiveInvokeContext context = client.invokeContext(); - ServerStoreOpMessage.AppendMessage message = new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L)); - EhcacheEntityResponse expected = activeEntity.invokeActive(context, message); + EhcacheEntityResponse expected = activeEntity.invokeActive(context, new ServerStoreOpMessage.GetAndAppendMessage(1L, createPayload(1L))); - // create another message that has the same message ID - message = new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L)); + // this invoke should be rejected due to duplicate message id + EhcacheEntityResponse actual = activeEntity.invokeActive(context, new ServerStoreOpMessage.GetAndAppendMessage(1L, createPayload(2L))); - EhcacheEntityResponse actual = activeEntity.invokeActive(context, message); // this invoke should be rejected due to duplicate message id assertThat(actual, sameInstance(expected)); + + EhcacheEntityResponse.GetResponse response = (EhcacheEntityResponse.GetResponse) activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.GetMessage(1L)); + assertThat(response.getChain(), hasPayloads(1L)); } @Test @SuppressWarnings("unchecked") @@ -1029,22 +1005,22 @@ public void testShortIterationIsNotTracked() throws Exception { EhcacheStateServiceImpl ehcacheStateService = defaultRegistry.getStoreManagerService(); ehcacheStateService.createStore(defaultStoreName, defaultStoreConfiguration, false); //hack to enable message tracking on active - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(2L))); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(2L, createPayload(3L))); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(2L, createPayload(4L))); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(1L, createPayload(2L))); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(2L, createPayload(3L))); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(2L, createPayload(4L))); - EhcacheEntityResponse.IteratorBatch iteratorBatch = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorOpenMessage(Integer.MAX_VALUE)); + EhcacheEntityResponse.IteratorBatch iteratorBatch = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.IteratorOpenMessage(Integer.MAX_VALUE)); assertThat(iteratorBatch.isLast(), is(true)); assertThat(iteratorBatch.getChains(), containsInAnyOrder(hasPayloads(1L, 2L), hasPayloads(3L, 4L))); - assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorAdvanceMessage(iteratorBatch.getIdentity(), Integer.MAX_VALUE)), failsWith(instanceOf(InvalidOperationException.class))); + assertThat(activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.IteratorAdvanceMessage(iteratorBatch.getIdentity(), Integer.MAX_VALUE)), failsWith(instanceOf(InvalidOperationException.class))); } @Test @@ -1053,17 +1029,17 @@ public void testLongIteration() throws Exception { EhcacheStateServiceImpl ehcacheStateService = defaultRegistry.getStoreManagerService(); ehcacheStateService.createStore(defaultStoreName, defaultStoreConfiguration, false); //hack to enable message tracking on active - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(2L))); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(2L, createPayload(3L))); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(2L, createPayload(4L))); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(1L, createPayload(2L))); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(2L, createPayload(3L))); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(2L, createPayload(4L))); - EhcacheEntityResponse.IteratorBatch batchOne = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorOpenMessage(1)); + EhcacheEntityResponse.IteratorBatch batchOne = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.IteratorOpenMessage(1)); Matcher chainOne = hasPayloads(1L, 2L); Matcher chainTwo = hasPayloads(3L, 4L); @@ -1071,7 +1047,7 @@ public void testLongIteration() throws Exception { assertThat(batchOne.isLast(), is(false)); assertThat(batchOne.getChains(), either(contains(chainOne)).or(contains(chainTwo))); - EhcacheEntityResponse.IteratorBatch batchTwo = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorAdvanceMessage(batchOne.getIdentity(), Integer.MAX_VALUE)); + EhcacheEntityResponse.IteratorBatch batchTwo = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.IteratorAdvanceMessage(batchOne.getIdentity(), Integer.MAX_VALUE)); assertThat(batchTwo.isLast(), is(true)); if (contains(chainOne).matches(batchOne.getChains())) { assertThat(batchTwo.getChains(), contains(chainTwo)); @@ -1079,7 +1055,7 @@ public void testLongIteration() throws Exception { assertThat(batchTwo.getChains(), contains(chainOne)); } - assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorAdvanceMessage(batchOne.getIdentity(), Integer.MAX_VALUE)), failsWith(instanceOf(InvalidOperationException.class))); + assertThat(activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.IteratorAdvanceMessage(batchOne.getIdentity(), Integer.MAX_VALUE)), failsWith(instanceOf(InvalidOperationException.class))); } @Test @@ -1088,17 +1064,17 @@ public void testExplicitIteratorClose() throws Exception { EhcacheStateServiceImpl ehcacheStateService = defaultRegistry.getStoreManagerService(); ehcacheStateService.createStore(defaultStoreName, defaultStoreConfiguration, false); //hack to enable message tracking on active - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(1L, createPayload(2L))); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(2L, createPayload(3L))); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(2L, createPayload(4L))); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(1L, createPayload(1L))); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(1L, createPayload(2L))); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(2L, createPayload(3L))); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(2L, createPayload(4L))); - EhcacheEntityResponse.IteratorBatch batchOne = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorOpenMessage(1)); + EhcacheEntityResponse.IteratorBatch batchOne = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.IteratorOpenMessage(1)); Matcher chainOne = hasPayloads(1L, 2L); Matcher chainTwo = hasPayloads(3L, 4L); @@ -1106,27 +1082,27 @@ public void testExplicitIteratorClose() throws Exception { assertThat(batchOne.isLast(), is(false)); assertThat(batchOne.getChains(), either(contains(chainOne)).or(contains(chainTwo))); - assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorCloseMessage(batchOne.getIdentity())), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.IteratorCloseMessage(batchOne.getIdentity())), succeeds()); - assertThat(activeEntity.invokeActive(context, new ServerStoreOpMessage.IteratorAdvanceMessage(batchOne.getIdentity(), Integer.MAX_VALUE)), failsWith(instanceOf(InvalidOperationException.class))); + assertThat(activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.IteratorAdvanceMessage(batchOne.getIdentity(), Integer.MAX_VALUE)), failsWith(instanceOf(InvalidOperationException.class))); } private void prepareAndRunActiveEntityForPassiveSync(BiConsumer testConsumer) throws Exception { ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); activeEntity.createNew(); - TestInvokeContext context = new TestInvokeContext(); - activeEntity.connected(context.getClientDescriptor()); + TestClientDescriptor client = TestClientDescriptor.newClient(); + activeEntity.connected(client); - assertThat(activeEntity.invokeActive(context, new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); + assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, defaultStoreConfiguration)), succeeds()); ByteBuffer payload = ByteBuffer.allocate(512); // Put keys that maps to the same concurrency key ServerStoreOpMessage.AppendMessage testMessage = new ServerStoreOpMessage.AppendMessage(1L, payload); - activeEntity.invokeActive(context, testMessage); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(-2L, payload)); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(17L, payload)); - activeEntity.invokeActive(context, new ServerStoreOpMessage.AppendMessage(33L, payload)); + activeEntity.invokeActive(client.invokeContext(), testMessage); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(-2L, payload)); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(17L, payload)); + activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.AppendMessage(33L, payload)); ConcurrencyStrategies.DefaultConcurrencyStrategy concurrencyStrategy = new ConcurrencyStrategies.DefaultConcurrencyStrategy(DEFAULT_MAPPER); int concurrencyKey = concurrencyStrategy.concurrencyKey(testMessage); diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java index ed2b2916b5..0ebcec649b 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java @@ -25,7 +25,7 @@ import org.ehcache.clustered.common.internal.store.ClusterTierEntityConfiguration; import org.ehcache.clustered.server.EhcacheStateServiceImpl; import org.ehcache.clustered.server.KeySegmentMapper; -import org.ehcache.clustered.server.TestInvokeContext; +import org.ehcache.clustered.server.TestClientDescriptor; import org.ehcache.clustered.server.internal.messages.PassiveReplicationMessage; import org.ehcache.clustered.server.state.EhcacheStateService; import org.junit.Before; @@ -130,9 +130,9 @@ public void testDestroyServerStore() throws Exception { @Test public void testInvalidMessageThrowsError() throws Exception { ClusterTierPassiveEntity passiveEntity = new ClusterTierPassiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); - TestInvokeContext context = new TestInvokeContext(); + TestClientDescriptor client = TestClientDescriptor.newClient(); try { - passiveEntity.invokePassive(context, new InvalidMessage()); + passiveEntity.invokePassive(client.invokeContext(), new InvalidMessage()); fail("Invalid message should result in AssertionError"); } catch (AssertionError e) { assertThat(e.getMessage(), containsString("Unsupported")); @@ -145,25 +145,25 @@ public void testPassiveTracksMessageDuplication() throws Exception { passiveEntity.createNew(); Chain chain = sequencedChainOf(createPayload(1L)); - TestInvokeContext context = new TestInvokeContext(); + TestClientDescriptor client = TestClientDescriptor.newClient(); long clientId = 3; PassiveReplicationMessage message1 = new PassiveReplicationMessage.ChainReplicationMessage(2, chain, 2L, 1L, clientId); - passiveEntity.invokePassive(context, message1); + passiveEntity.invokePassive(client.invokeContext(), message1); // Should be added assertThat(passiveEntity.getStateService().getStore(passiveEntity.getStoreIdentifier()).get(2).isEmpty(), is(false)); Chain emptyChain = sequencedChainOf(); PassiveReplicationMessage message2 = new PassiveReplicationMessage.ChainReplicationMessage(2, emptyChain, 2L, 1L, clientId); - passiveEntity.invokePassive(context, message2); + passiveEntity.invokePassive(client.invokeContext(), message2); // Should not be cleared, message is a duplicate assertThat(passiveEntity.getStateService().getStore(passiveEntity.getStoreIdentifier()).get(2).isEmpty(), is(false)); PassiveReplicationMessage message3 = new PassiveReplicationMessage.ChainReplicationMessage(2, chain, 3L, 1L, clientId); - passiveEntity.invokePassive(context, message3); + passiveEntity.invokePassive(client.invokeContext(), message3); // Should be added as well, different message id assertThat(passiveEntity.getStateService().getStore(passiveEntity.getStoreIdentifier()).get(2).isEmpty(), is(false)); @@ -173,17 +173,17 @@ public void testPassiveTracksMessageDuplication() throws Exception { public void testOversizeReplaceAtHeadMessage() throws Exception { ClusterTierPassiveEntity passiveEntity = new ClusterTierPassiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); passiveEntity.createNew(); - TestInvokeContext context = new TestInvokeContext(); + TestClientDescriptor client = TestClientDescriptor.newClient(); int key = 2; Chain chain = sequencedChainOf(createPayload(1L)); PassiveReplicationMessage message = new PassiveReplicationMessage.ChainReplicationMessage(key, chain, 2L, 1L, 3L); - passiveEntity.invokePassive(context, message); + passiveEntity.invokePassive(client.invokeContext(), message); Chain oversizeChain = sequencedChainOf(createPayload(2L, 1024 * 1024)); ServerStoreOpMessage.ReplaceAtHeadMessage oversizeMsg = new ServerStoreOpMessage.ReplaceAtHeadMessage(key, chain, oversizeChain); - passiveEntity.invokePassive(context, oversizeMsg); + passiveEntity.invokePassive(client.invokeContext(), oversizeMsg); // Should be evicted, the value is oversize. assertThat(passiveEntity.getStateService().getStore(passiveEntity.getStoreIdentifier()).get(key).isEmpty(), is(true)); } @@ -192,12 +192,12 @@ public void testOversizeReplaceAtHeadMessage() throws Exception { public void testOversizeChainReplicationMessage() throws Exception { ClusterTierPassiveEntity passiveEntity = new ClusterTierPassiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); passiveEntity.createNew(); - TestInvokeContext context = new TestInvokeContext(); + TestClientDescriptor client = TestClientDescriptor.newClient(); long key = 2L; Chain oversizeChain = sequencedChainOf(createPayload(key, 1024 * 1024)); PassiveReplicationMessage oversizeMsg = new PassiveReplicationMessage.ChainReplicationMessage(key, oversizeChain, 2L, 1L, (long) 3); - passiveEntity.invokePassive(context, oversizeMsg); + passiveEntity.invokePassive(client.invokeContext(), oversizeMsg); // Should be cleared, the value is oversize. assertThat(passiveEntity.getStateService().getStore(passiveEntity.getStoreIdentifier()).get(key).isEmpty(), is(true)); } diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java index 13569cacc4..ce4165126b 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java @@ -18,21 +18,17 @@ import org.ehcache.clustered.server.TestClientDescriptor; import org.junit.Test; import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; import org.terracotta.entity.ClientDescriptor; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; -import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; @@ -41,7 +37,7 @@ public class LockManagerImplTest { @Test public void testLock() { LockManagerImpl lockManager = new LockManagerImpl(); - ClientDescriptor clientDescriptor = new TestClientDescriptor(); + ClientDescriptor clientDescriptor = TestClientDescriptor.newClient(); assertThat(lockManager.lock(1L, clientDescriptor), is(true)); assertThat(lockManager.lock(1L, clientDescriptor), is(false)); assertThat(lockManager.lock(2L, clientDescriptor), is(true)); @@ -50,7 +46,7 @@ public void testLock() { @Test public void testUnlock() { LockManagerImpl lockManager = new LockManagerImpl(); - ClientDescriptor clientDescriptor = new TestClientDescriptor(); + ClientDescriptor clientDescriptor = TestClientDescriptor.newClient(); assertThat(lockManager.lock(1L, clientDescriptor), is(true)); lockManager.unlock(1L); assertThat(lockManager.lock(1L, clientDescriptor), is(true)); @@ -60,8 +56,8 @@ public void testUnlock() { @SuppressWarnings("unchecked") public void testSweepLocksForClient() { LockManagerImpl lockManager = new LockManagerImpl(); - ClientDescriptor clientDescriptor1 = new TestClientDescriptor(); - ClientDescriptor clientDescriptor2 = new TestClientDescriptor(); + ClientDescriptor clientDescriptor1 = TestClientDescriptor.newClient(); + ClientDescriptor clientDescriptor2 = TestClientDescriptor.newClient(); assertThat(lockManager.lock(1L, clientDescriptor1), is(true)); assertThat(lockManager.lock(2L, clientDescriptor1), is(true)); @@ -98,20 +94,21 @@ public void testSweepLocksForClient() { public void testCreateLockStateAfterFailover() { LockManagerImpl lockManager = new LockManagerImpl(); - ClientDescriptor clientDescriptor = new TestClientDescriptor(); + ClientDescriptor clientDescriptor1 = TestClientDescriptor.newClient(); Set locks = new HashSet<>(); locks.add(1L); locks.add(100L); locks.add(1000L); - lockManager.createLockStateAfterFailover(clientDescriptor, locks); + lockManager.createLockStateAfterFailover(clientDescriptor1, locks); - ClientDescriptor clientDescriptor1 = new TestClientDescriptor(); + ClientDescriptor clientDescriptor2 = TestClientDescriptor.newClient(); - assertThat(lockManager.lock(100L, clientDescriptor1), is(false)); - assertThat(lockManager.lock(1000L, clientDescriptor1), is(false)); - assertThat(lockManager.lock(1L, clientDescriptor1), is(false)); + + assertThat(lockManager.lock(100L, clientDescriptor2), is(false)); + assertThat(lockManager.lock(1000L, clientDescriptor2), is(false)); + assertThat(lockManager.lock(1L, clientDescriptor2), is(false)); } From 2dc8a9f88a58b1394b55ae7bb2036b0f4c356f68 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Fri, 25 Sep 2020 07:44:10 -0700 Subject: [PATCH 294/372] sync message tracker changes. send catchup when failing over --- .../ActivePassiveClientIdTest.java | 13 ++- .../internal/messages/EhcacheMessageType.java | 3 +- .../common/internal/messages/BaseCodec.java | 3 + .../server/ConcurrencyStrategies.java | 5 + .../server/EhcacheExecutionStrategy.java | 3 + .../EhcacheMessageTrackerCatchup.java | 40 +++++++ .../EhcacheMessageTrackerMessage.java | 19 +--- .../internal/messages/EhcacheServerCodec.java | 100 +++++++++++++++++- .../messages/EhcacheSyncMessageCodec.java | 7 +- .../server/store/ClusterTierActiveEntity.java | 22 ++-- .../store/ClusterTierPassiveEntity.java | 77 +++++++++++++- .../EhcacheMessageTrackerMessageTest.java | 2 +- .../messages/EhcacheSyncMessageCodecTest.java | 6 +- .../store/ClusterTierActiveEntityTest.java | 5 +- .../store/ClusterTierPassiveEntityTest.java | 3 +- gradle.properties | 4 +- 16 files changed, 254 insertions(+), 58 deletions(-) create mode 100644 clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerCatchup.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java index 2d913a3b62..4094626ddd 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java @@ -47,6 +47,7 @@ import java.net.URI; import java.util.Map; import java.util.function.Predicate; +import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; @@ -133,14 +134,12 @@ public void tearDown() throws Exception { } @Test - @SuppressWarnings("deprecation") public void messageTrackedAndRemovedWhenClientLeaves() throws Exception { assertThat(activeMessageHandler.getTrackedClients().count()).isZero(); // no client tracked storeProxy.getAndAppend(42L, createPayload(42L)); - Map responses = activeMessageHandler.getTrackedResponsesForSegment(KEY_ENDS_UP_IN_SEGMENT_11, activeMessageHandler.getTrackedClients().findFirst().get()); - assertThat(responses).hasSize(1); // should now track one message + assertThat(activeMessageHandler.getRecordedMessages().collect(Collectors.toList())).hasSize(1); // should now track one message assertThat(activeEntity.getConnectedClients()).hasSize(1); // make sure we currently have one client attached @@ -168,7 +167,6 @@ public void untrackedMessageAreNotStored() throws Exception { } @Test - @SuppressWarnings("deprecation") public void trackedMessagesReplicatedToPassive() throws Exception { clusterControl.terminateOnePassive(); @@ -183,18 +181,19 @@ public void trackedMessagesReplicatedToPassive() throws Exception { assertThat(passiveMessageHandler.getTrackedClients().count()).isEqualTo(1L); // one client tracked - Map responses = passiveMessageHandler.getTrackedResponsesForSegment(KEY_ENDS_UP_IN_SEGMENT_11, passiveMessageHandler.getTrackedClients().findFirst().get()); + Map responses = activeMessageHandler.getRecordedMessages().filter(r->r.getClientSourceId().toLong() == activeMessageHandler.getTrackedClients().findFirst().get().toLong()) + .collect(Collectors.toMap(r->r.getTransactionId(), r->r.getResponse())); assertThat(responses).hasSize(1); // one message should have sync } @Test - @SuppressWarnings("deprecation") public void messageTrackedAndRemovedByPassiveWhenClientLeaves() throws Exception { assertThat(passiveMessageHandler.getTrackedClients().count()).isZero(); // nothing tracked right now storeProxy.getAndAppend(42L, createPayload(42L)); - Map responses = passiveMessageHandler.getTrackedResponsesForSegment(KEY_ENDS_UP_IN_SEGMENT_11, passiveMessageHandler.getTrackedClients().findFirst().get()); + Map responses = activeMessageHandler.getRecordedMessages().filter(r->r.getClientSourceId().toLong() == activeMessageHandler.getTrackedClients().findFirst().get().toLong()) + .collect(Collectors.toMap(r->r.getTransactionId(), r->r.getResponse())); assertThat(responses).hasSize(1); // should now track one message service.stop(); // stop the service. It will remove the client diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java index ab1b47ef26..06963dd68b 100644 --- a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java +++ b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java @@ -54,7 +54,8 @@ public enum EhcacheMessageType { // Passive replication messages CHAIN_REPLICATION_OP, CLEAR_INVALIDATION_COMPLETE, - INVALIDATION_COMPLETE; + INVALIDATION_COMPLETE, + MESSAGE_CATCHUP; public static final EnumSet LIFECYCLE_MESSAGES = of(VALIDATE, VALIDATE_SERVER_STORE, PREPARE_FOR_DESTROY); public static boolean isLifecycleMessage(EhcacheMessageType value) { diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/BaseCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/BaseCodec.java index d7f8affffe..b85360cb2e 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/BaseCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/BaseCodec.java @@ -34,6 +34,7 @@ import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.ITERATOR_CLOSE; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.ITERATOR_OPEN; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.LOCK; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_CATCHUP; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.PUT_IF_ABSENT; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.REPLACE; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.UNLOCK; @@ -85,6 +86,8 @@ public class BaseCodec { .mapping(CHAIN_REPLICATION_OP, 61) .mapping(CLEAR_INVALIDATION_COMPLETE, 63) .mapping(INVALIDATION_COMPLETE, 64) + + .mapping(MESSAGE_CATCHUP, 71) .build(); public static final String RESPONSE_TYPE_FIELD_NAME = "opCode"; diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ConcurrencyStrategies.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ConcurrencyStrategies.java index 5cd2ef105a..5ac47d1b79 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ConcurrencyStrategies.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ConcurrencyStrategies.java @@ -23,6 +23,7 @@ import org.ehcache.clustered.common.internal.messages.EhcacheEntityMessage; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage; import org.terracotta.entity.ConcurrencyStrategy; +import org.ehcache.clustered.server.internal.messages.EhcacheMessageTrackerCatchup; import static java.util.Collections.singleton; @@ -55,6 +56,7 @@ public Set getKeysForSynchronization() { public static class DefaultConcurrencyStrategy implements ConcurrencyStrategy { public static final int DATA_CONCURRENCY_KEY_OFFSET = DEFAULT_KEY + 1; + public static final int TRACKER_SYNC_KEY = Integer.MAX_VALUE - 1; private final KeySegmentMapper mapper; @@ -69,6 +71,8 @@ public int concurrencyKey(EhcacheEntityMessage entityMessage) { } else if (entityMessage instanceof ConcurrentEntityMessage) { ConcurrentEntityMessage concurrentEntityMessage = (ConcurrentEntityMessage) entityMessage; return DATA_CONCURRENCY_KEY_OFFSET + mapper.getSegmentForKey(concurrentEntityMessage.concurrencyKey()); + } else if (entityMessage instanceof EhcacheMessageTrackerCatchup) { + return MANAGEMENT_KEY; } else { return DEFAULT_KEY; } @@ -80,6 +84,7 @@ public Set getKeysForSynchronization() { for (int i = 0; i <= mapper.getSegments(); i++) { result.add(DEFAULT_KEY + i); } + result.add(TRACKER_SYNC_KEY); return Collections.unmodifiableSet(result); } } diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/EhcacheExecutionStrategy.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/EhcacheExecutionStrategy.java index c5cba5f45c..d24ce6da60 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/EhcacheExecutionStrategy.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/EhcacheExecutionStrategy.java @@ -21,6 +21,7 @@ import org.ehcache.clustered.server.internal.messages.PassiveReplicationMessage; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage; import org.ehcache.clustered.common.internal.messages.StateRepositoryOpMessage; +import org.ehcache.clustered.server.internal.messages.EhcacheMessageTrackerCatchup; import org.ehcache.clustered.server.internal.messages.EhcacheSyncMessage; import org.terracotta.entity.ExecutionStrategy; @@ -50,6 +51,8 @@ public Location getExecutionLocation(EhcacheEntityMessage message) { return Location.ACTIVE; } else if (message instanceof PassiveReplicationMessage) { return Location.PASSIVE; + } else if (message instanceof EhcacheMessageTrackerCatchup) { + return Location.PASSIVE; } else if (message instanceof EhcacheSyncMessage) { throw new AssertionError("Unexpected use of ExecutionStrategy for sync messages"); } diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerCatchup.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerCatchup.java new file mode 100644 index 0000000000..afae8434a0 --- /dev/null +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerCatchup.java @@ -0,0 +1,40 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered.server.internal.messages; + +import java.util.Collection; +import org.ehcache.clustered.common.internal.messages.EhcacheEntityMessage; +import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse; + +import org.terracotta.client.message.tracker.RecordedMessage; + +/** + * Message sending messages that are tracked for duplication. If a passive becoming active receives + * a duplicate, it needs to discard it. + */ +public class EhcacheMessageTrackerCatchup extends EhcacheEntityMessage { + + private final Collection> trackedMessages; + + public EhcacheMessageTrackerCatchup(Collection> trackedMessages) { + this.trackedMessages = trackedMessages; + } + + public Collection> getTrackedMessages() { + return trackedMessages; + } +} diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java index ec99d041e0..ca6c6fdf1c 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java @@ -16,35 +16,22 @@ package org.ehcache.clustered.server.internal.messages; -import org.ehcache.clustered.common.internal.messages.EhcacheEntityMessage; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse; -import org.terracotta.client.message.tracker.OOOMessageHandler; -import org.terracotta.entity.ClientSourceId; import java.util.Map; -import static java.util.stream.Collectors.toMap; - /** * Message sending messages that are tracked for duplication. If a passive becoming active receives * a duplicate, it needs to discard it. */ public class EhcacheMessageTrackerMessage extends EhcacheSyncMessage { - private final int segmentId; private final Map> trackedMessages; - public EhcacheMessageTrackerMessage(int segmentId, Map> trackedMessages) { - this.segmentId = segmentId; + public EhcacheMessageTrackerMessage(Map> trackedMessages) { this.trackedMessages = trackedMessages; } - @SuppressWarnings("deprecation") - public EhcacheMessageTrackerMessage(int segmentId, OOOMessageHandler messageHandler) { - this(segmentId, messageHandler.getTrackedClients() - .collect(toMap(ClientSourceId::toLong, clientSourceId -> messageHandler.getTrackedResponsesForSegment(segmentId, clientSourceId)))); - } - @Override public SyncMessageType getMessageType() { return SyncMessageType.MESSAGE_TRACKER; @@ -53,8 +40,4 @@ public SyncMessageType getMessageType() { public Map> getTrackedMessages() { return trackedMessages; } - - public int getSegmentId() { - return segmentId; - } } diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java index 46ce38330b..42001e7fc1 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java @@ -27,10 +27,22 @@ import org.terracotta.runnel.decoding.Enm; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; -import static java.nio.ByteBuffer.wrap; -import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.isPassiveReplicationMessage; +import org.terracotta.client.message.tracker.RecordedMessage; +import org.terracotta.entity.ClientDescriptor; +import org.terracotta.entity.ClientSourceId; +import org.terracotta.runnel.Struct; +import org.terracotta.runnel.decoding.StructArrayDecoder; +import org.terracotta.runnel.decoding.StructDecoder; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.EHCACHE_MESSAGE_TYPES_ENUM_MAPPING; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.MESSAGE_TYPE_FIELD_INDEX; +import static org.ehcache.clustered.common.internal.messages.BaseCodec.MESSAGE_TYPE_FIELD_NAME; +import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.isPassiveReplicationMessage; +import static org.terracotta.runnel.StructBuilder.newStructBuilder; /** * EhcacheServerCodec */ @@ -41,6 +53,22 @@ public class EhcacheServerCodec implements MessageCodec { + encoder.int64(CLIENT_ID, value.getClientSourceId().toLong()); + encoder.int64(TRANSACTION_ID, value.getTransactionId()); + encoder.byteBuffer(MESSAGE, ByteBuffer.wrap(encodeMessage(value.getRequest()))); + }).encode().array(); + } + @Override public EhcacheEntityMessage decodeMessage(byte[] payload) { - ByteBuffer byteBuffer = wrap(payload); - Enm opCodeEnm = EhcacheCodec.OP_CODE_DECODER.decoder(byteBuffer).enm("opCode"); + ByteBuffer byteBuffer = ByteBuffer.wrap(payload); + Enm opCodeEnm = EhcacheCodec.OP_CODE_DECODER.decoder(byteBuffer).enm(MESSAGE_TYPE_FIELD_NAME); if (!opCodeEnm.isFound()) { throw new AssertionError("Got a message without an opCode"); } @@ -69,7 +109,9 @@ public EhcacheEntityMessage decodeMessage(byte[] payload) { byteBuffer.rewind(); EhcacheMessageType messageType = opCodeEnm.get(); - if (isPassiveReplicationMessage(messageType)) { + if (messageType == EhcacheMessageType.MESSAGE_CATCHUP) { + return decodeCatchup(payload); + } else if (isPassiveReplicationMessage(messageType)) { return replicationCodec.decode(messageType, byteBuffer); } return clientCodec.decodeMessage(byteBuffer, messageType); @@ -84,4 +126,52 @@ public byte[] encodeResponse(EhcacheEntityResponse response) throws MessageCodec public EhcacheEntityResponse decodeResponse(byte[] payload) throws MessageCodecException { return clientCodec.decodeResponse(payload); } + + private EhcacheMessageTrackerCatchup decodeCatchup(byte[] payload) { + StructArrayDecoder> array = MESSAGE_HISTORY.decoder(ByteBuffer.wrap(payload)).structs(MESSAGE_SEQUENCE); + if (array == null) { + return new EhcacheMessageTrackerCatchup(Collections.emptyList()); + } + List> list = new ArrayList<>(array.length()); + while (array.hasNext()) { + StructDecoder>> decoder = array.next(); + long cid = decoder.int64(CLIENT_ID); + long transaction = decoder.int64(TRANSACTION_ID); + ByteBuffer buff = decoder.byteBuffer(MESSAGE); + EhcacheEntityMessage msg = decodeMessage(buff.array()); + + list.add(new RecordedMessage() { + @Override + public ClientSourceId getClientSourceId() { + return new ClientSourceId() { + @Override + public long toLong() { + return cid; + } + + @Override + public boolean matches(ClientDescriptor cd) { + return cd.getSourceId().toLong() == cid; + } + }; + } + + @Override + public long getTransactionId() { + return transaction; + } + + @Override + public EhcacheEntityMessage getRequest() { + return msg; + } + + @Override + public EhcacheEntityResponse getResponse() { + return null; + } + }); + } + return new EhcacheMessageTrackerCatchup(list); + } } diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java index 1618f84cd5..efdaa00555 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java @@ -153,8 +153,8 @@ private byte[] encodeMessageTrackerSync(EhcacheMessageTrackerMessage syncMessage responseEncoder.byteBuffer(MESSAGE_TRACKER_RESPONSE_FIELD, encodeResponse(response.getValue())); }); } - }) - .int32(MESSAGE_TRACKER_SEGMENT_FIELD, syncMessage.getSegmentId()); + }); + return encoder.encode().array(); } @@ -237,8 +237,7 @@ private EhcacheSyncMessage decodeMessageTracker(ByteBuffer message) { } } } - Integer segmentId = decoder.int32(MESSAGE_TRACKER_SEGMENT_FIELD); - return new EhcacheMessageTrackerMessage(segmentId, trackedMessages); + return new EhcacheMessageTrackerMessage(trackedMessages); } private EhcacheSyncMessage decodeStateRepoSync(ByteBuffer message) { diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java index 2eb5a85eee..97d19f8746 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java @@ -26,6 +26,7 @@ import org.ehcache.clustered.common.internal.messages.EhcacheEntityMessage; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse; import org.ehcache.clustered.common.internal.messages.EhcacheMessageType; +import org.ehcache.clustered.server.internal.messages.EhcacheMessageTrackerCatchup; import org.ehcache.clustered.common.internal.messages.EhcacheOperationMessage; import org.ehcache.clustered.common.internal.messages.LifecycleMessage; import org.ehcache.clustered.common.internal.messages.LifecycleMessage.ValidateServerStore; @@ -105,6 +106,7 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; import static java.util.Collections.emptyMap; import static java.util.stream.Collectors.toMap; @@ -126,7 +128,7 @@ import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.isStateRepoOperationMessage; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.isStoreOperationMessage; import static org.ehcache.clustered.server.ConcurrencyStrategies.DEFAULT_KEY; -import static org.ehcache.clustered.server.ConcurrencyStrategies.clusterTierConcurrency; +import static org.ehcache.clustered.server.ConcurrencyStrategies.DefaultConcurrencyStrategy.TRACKER_SYNC_KEY; /** * ClusterTierActiveEntity @@ -187,7 +189,7 @@ public ClusterTierActiveEntity(ServiceRegistry registry, ClusterTierEntityConfig stateService = registry.getService(new EhcacheStoreStateServiceConfig(entityConfiguration.getManagerIdentifier(), defaultMapper)); entityMessenger = registry.getService(new BasicServiceConfiguration<>(IEntityMessenger.class)); messageHandler = registry.getService(new OOOMessageHandlerConfiguration<>(managerIdentifier + "###" + storeIdentifier, - ClusterTierActiveEntity::isTrackedMessage, defaultMapper.getSegments() + 1, new MessageToTrackerSegmentFunction(clusterTierConcurrency(defaultMapper)))); + ClusterTierActiveEntity::isTrackedMessage)); } catch (ServiceException e) { throw new ConfigurationException("Unable to retrieve service: " + e.getMessage()); } @@ -763,6 +765,11 @@ public void notifyDestroyed(ClientSourceId sourceId) { @Override public ReconnectHandler startReconnect() { + try { + this.entityMessenger.messageSelf(new EhcacheMessageTrackerCatchup(this.messageHandler.getRecordedMessages().filter(m->m.getRequest() != null).collect(Collectors.toList()))); + } catch (MessageCodecException mce) { + throw new AssertionError("Codec error", mce); + } return (clientDescriptor, bytes) -> { if (inflightInvalidations == null) { throw new AssertionError("Load existing was not invoked before handleReconnect"); @@ -796,6 +803,8 @@ public void synchronizeKeyToPassive(PassiveSynchronizationChannel messageQ = new SynchronousQueue<>(); @@ -822,8 +831,6 @@ public void synchronizeKeyToPassive(PassiveSynchronizationChannel syncChannel, int concurrencyKey) { + private void sendMessageTrackerReplication(PassiveSynchronizationChannel syncChannel) { Map> clientSourceIdTrackingMap = messageHandler.getTrackedClients() - .collect(toMap(ClientSourceId::toLong, clientSourceId -> messageHandler.getTrackedResponsesForSegment(concurrencyKey, clientSourceId))); + .collect(toMap(ClientSourceId::toLong, clientSourceId -> messageHandler.getRecordedMessages().filter(r->r.getClientSourceId().toLong() == clientSourceId.toLong()).collect(Collectors.toMap(rm->rm.getTransactionId(), rm->rm.getResponse())))); if (!clientSourceIdTrackingMap.isEmpty()) { - syncChannel.synchronizeToPassive(new EhcacheMessageTrackerMessage(concurrencyKey, clientSourceIdTrackingMap)); + syncChannel.synchronizeToPassive(new EhcacheMessageTrackerMessage(clientSourceIdTrackingMap)); } } diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java index 2c38cdbdfe..c865aa4fe8 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java @@ -36,6 +36,7 @@ import org.ehcache.clustered.server.internal.messages.PassiveReplicationMessage; import org.ehcache.clustered.server.internal.messages.PassiveReplicationMessage.InvalidationCompleteMessage; import org.ehcache.clustered.server.internal.messages.PassiveReplicationMessage.ChainReplicationMessage; +import org.ehcache.clustered.server.internal.messages.EhcacheMessageTrackerCatchup; import org.ehcache.clustered.server.management.ClusterTierManagement; import org.ehcache.clustered.server.state.EhcacheStateContext; import org.ehcache.clustered.server.state.EhcacheStateService; @@ -44,6 +45,7 @@ import org.slf4j.LoggerFactory; import org.terracotta.client.message.tracker.OOOMessageHandler; import org.terracotta.client.message.tracker.OOOMessageHandlerConfiguration; +import org.terracotta.client.message.tracker.RecordedMessage; import org.terracotta.entity.ClientSourceId; import org.terracotta.entity.ConfigurationException; import org.terracotta.entity.EntityUserException; @@ -55,13 +57,14 @@ import org.terracotta.offheapstore.exceptions.OversizeMappingException; import java.util.concurrent.TimeoutException; +import java.util.stream.Stream; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.getResponse; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.success; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.isPassiveReplicationMessage; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.isStateRepoOperationMessage; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.isStoreOperationMessage; -import static org.ehcache.clustered.server.ConcurrencyStrategies.clusterTierConcurrency; + /** * ClusterTierPassiveEntity @@ -87,7 +90,7 @@ public ClusterTierPassiveEntity(ServiceRegistry registry, ClusterTierEntityConfi try { stateService = registry.getService(new EhcacheStoreStateServiceConfig(config.getManagerIdentifier(), defaultMapper)); messageHandler = registry.getService(new OOOMessageHandlerConfiguration<>(managerIdentifier + "###" + storeIdentifier, - ClusterTierActiveEntity::isTrackedMessage, defaultMapper.getSegments() + 1, new MessageToTrackerSegmentFunction(clusterTierConcurrency(defaultMapper)))); + ClusterTierActiveEntity::isTrackedMessage)); } catch (ServiceException e) { throw new ConfigurationException("Unable to retrieve service: " + e.getMessage()); } @@ -183,6 +186,8 @@ private EhcacheEntityResponse invokePassiveInternal(InvokeContext context, Ehcac } } else if (message instanceof EhcacheSyncMessage) { invokeSyncOperation(context, (EhcacheSyncMessage) message); + } else if (message instanceof EhcacheMessageTrackerCatchup) { + invokeCatchup(context, (EhcacheMessageTrackerCatchup) message); } else { throw new AssertionError("Unsupported EhcacheEntityMessage: " + message.getClass()); } @@ -191,6 +196,47 @@ private EhcacheEntityResponse invokePassiveInternal(InvokeContext context, Ehcac return success(); } + private void invokeCatchup(InvokeContext context, EhcacheMessageTrackerCatchup catchup) { + catchup.getTrackedMessages().forEach(r -> { + InvokeContext replay = new InvokeContext() { + @Override + public ClientSourceId getClientSource() { + return context.makeClientSourceId(r.getClientSourceId().toLong()); + } + + @Override + public long getCurrentTransactionId() { + return r.getTransactionId(); + } + + @Override + public long getOldestTransactionId() { + return context.getOldestTransactionId(); + } + + @Override + public boolean isValidClientInformation() { + return true; + } + + @Override + public ClientSourceId makeClientSourceId(long l) { + return context.makeClientSourceId(l); + } + + @Override + public int getConcurrencyKey() { + return 0; + } + }; + try { + messageHandler.invoke(replay, r.getRequest(), this::invokePassiveInternal); + } catch (EntityUserException use) { + // swallow any user exceptions here + } + }); + } + @SuppressWarnings("deprecation") private void invokeSyncOperation(InvokeContext context, EhcacheSyncMessage message) { switch (message.getMessageType()) { @@ -205,8 +251,31 @@ private void invokeSyncOperation(InvokeContext context, EhcacheSyncMessage messa break; case MESSAGE_TRACKER: EhcacheMessageTrackerMessage messageTrackerMessage = (EhcacheMessageTrackerMessage) message; - messageTrackerMessage.getTrackedMessages().forEach((key, value) -> - messageHandler.loadTrackedResponsesForSegment(messageTrackerMessage.getSegmentId(), context.makeClientSourceId(key), value)); + Stream> converted = + messageTrackerMessage.getTrackedMessages().entrySet().stream().flatMap(e -> e.getValue().entrySet().stream().map(v -> { + return new RecordedMessage() { + @Override + public ClientSourceId getClientSourceId() { + return context.makeClientSourceId(e.getKey()); + } + + @Override + public long getTransactionId() { + return v.getKey(); + } + + @Override + public EhcacheEntityMessage getRequest() { + return null; + } + + @Override + public EhcacheEntityResponse getResponse() { + return v.getValue(); + } + }; + })); + messageHandler.loadRecordedMessages(converted); break; default: throw new AssertionError("Unsupported Sync operation " + message.getMessageType()); diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessageTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessageTest.java index b9e294e85b..a0cee7625b 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessageTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessageTest.java @@ -57,7 +57,7 @@ public void before() { trackingMap.put(id1.toLong(), res1); trackingMap.put(id2.toLong(), res2); - message = new EhcacheMessageTrackerMessage(2, trackingMap); + message = new EhcacheMessageTrackerMessage(trackingMap); } @Test diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java index db772f427d..414125bd9a 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java @@ -58,7 +58,7 @@ public void testDataSyncMessageEncodeDecode() throws Exception { @Test public void testMessageTrackerSyncEncodeDecode_emptyMessage() throws Exception { - EhcacheMessageTrackerMessage message = new EhcacheMessageTrackerMessage(1, new HashMap<>()); + EhcacheMessageTrackerMessage message = new EhcacheMessageTrackerMessage(new HashMap<>()); byte[] encodedMessage = codec.encode(0, message); EhcacheMessageTrackerMessage decoded = (EhcacheMessageTrackerMessage) codec.decode(0, encodedMessage); assertThat(decoded.getTrackedMessages()).isEmpty(); @@ -69,7 +69,7 @@ public void testMessageTrackerSyncEncodeDecode_clientWithoutMessage() throws Exc HashMap> trackerMap = new HashMap<>(); trackerMap.put(1L, new HashMap<>()); - EhcacheMessageTrackerMessage message = new EhcacheMessageTrackerMessage(1, trackerMap); + EhcacheMessageTrackerMessage message = new EhcacheMessageTrackerMessage(trackerMap); byte[] encodedMessage = codec.encode(0, message); EhcacheMessageTrackerMessage decoded = (EhcacheMessageTrackerMessage) codec.decode(0, encodedMessage); assertThat(decoded.getTrackedMessages()).isEmpty(); @@ -104,7 +104,7 @@ public void testMessageTrackerSyncEncodeDecode_messages() throws Exception { responses2.put(5L, r5); trackerMap.put(2L, responses2); - EhcacheMessageTrackerMessage message = new EhcacheMessageTrackerMessage(1, trackerMap); + EhcacheMessageTrackerMessage message = new EhcacheMessageTrackerMessage(trackerMap); byte[] encodedMessage = codec.encode(0, message); EhcacheMessageTrackerMessage decoded = (EhcacheMessageTrackerMessage) codec.decode(0, encodedMessage); diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index c3d04bd407..6bae4a1f30 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -1174,7 +1174,7 @@ public T getService(final ServiceConfiguration configuration) { } else if (serviceType.isAssignableFrom(EntityManagementRegistry.class)) { return (T) entityManagementRegistry; } else if (serviceType.isAssignableFrom(OOOMessageHandler.class)) { - return (T) new OOOMessageHandlerImpl<>(message -> true, 1, message -> 0, () -> {}); + return (T) new OOOMessageHandlerImpl<>(message -> true, () -> {}); } throw new AssertionError("Unknown service configuration of type: " + serviceType); } @@ -1354,8 +1354,7 @@ public boolean addOffHeapResource(OffHeapResourceIdentifier identifier, long cap return null; } else if(serviceConfiguration instanceof OOOMessageHandlerConfiguration) { OOOMessageHandlerConfiguration oooMessageHandlerConfiguration = (OOOMessageHandlerConfiguration) serviceConfiguration; - return (T) new OOOMessageHandlerImpl<>(oooMessageHandlerConfiguration.getTrackerPolicy(), - oooMessageHandlerConfiguration.getSegments(), oooMessageHandlerConfiguration.getSegmentationStrategy(), () -> {}); + return (T) new OOOMessageHandlerImpl<>(oooMessageHandlerConfiguration.getTrackerPolicy(), () -> {}); } throw new UnsupportedOperationException("Registry.getService does not support " + serviceConfiguration.getClass().getName()); diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java index 0ebcec649b..ee18650c0b 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java @@ -362,8 +362,7 @@ public boolean addOffHeapResource(OffHeapResourceIdentifier identifier, long cap return null; } else if(serviceConfiguration instanceof OOOMessageHandlerConfiguration) { OOOMessageHandlerConfiguration oooMessageHandlerConfiguration = (OOOMessageHandlerConfiguration) serviceConfiguration; - return (T) new OOOMessageHandlerImpl<>(oooMessageHandlerConfiguration.getTrackerPolicy(), - oooMessageHandlerConfiguration.getSegments(), oooMessageHandlerConfiguration.getSegmentationStrategy(), () -> {}); + return (T) new OOOMessageHandlerImpl<>(oooMessageHandlerConfiguration.getTrackerPolicy(), () -> {}); } throw new UnsupportedOperationException("Registry.getService does not support " + serviceConfiguration.getClass().getName()); diff --git a/gradle.properties b/gradle.properties index 196b7699e7..c44a0e9ce5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.3.0 jaxbVersion = 2.3.1 # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre8 +terracottaPlatformVersion = 5.8.1-pre10 terracottaApisVersion = 1.7.0 -terracottaCoreVersion = 5.7.1-pre1 +terracottaCoreVersion = 5.7.1-pre5 terracottaPassthroughTestingVersion = 1.7.0 terracottaUtilitiesVersion = 0.0.6 From 308a24f1b553519b3d7d709dd851a5fdb978f523 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Wed, 30 Sep 2020 07:28:20 -0700 Subject: [PATCH 295/372] update tests to accomdate increased memory requirements on windows --- azure-pipelines.yml | 3 ++- .../BasicClusteredCacheOpsReplicationMultiThreadedTest.java | 1 + .../replication/BasicClusteredCacheOpsReplicationTest.java | 1 + ...icClusteredCacheOpsReplicationWithMultipleClientsTest.java | 1 + .../BasicClusteredCacheOpsReplicationWithServersApiTest.java | 1 + .../replication/BasicLifeCyclePassiveReplicationTest.java | 1 + .../java/org/ehcache/clustered/replication/DuplicateTest.java | 4 +++- .../clustered/replication/OversizedCacheOpsPassiveTest.java | 3 ++- .../test/java/org/ehcache/clustered/sync/PassiveSyncTest.java | 4 +++- 9 files changed, 15 insertions(+), 4 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 590980b08b..3d05a082e6 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -40,10 +40,11 @@ jobs: vmImage: 'windows-latest' jdkVersion: '1.8' jobName: 'WindowsJava8' + options: '--max-workers=1' - template: build-templates/gradle-common.yml@templates parameters: vmImage: 'windows-latest' jdkVersion: '1.8' - options: '-PtestVM=java11Home' + options: '-PtestVM=java11Home --max-workers=1' jobName: 'WindowsJava11' diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index f6f137eb12..26a57e29ac 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -98,6 +98,7 @@ public static Consistency[] data() { @ClassRule @Rule public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()) + .withServerHeap(512) .withServiceFragment(offheapResource("primary-server-resource", 16)).build()); @Rule diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java index cf76ef8983..2a2e5792d3 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java @@ -72,6 +72,7 @@ public static Consistency[] data() { @ClassRule @Rule public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()) + .withServerHeap(512) .withServiceFragment(offheapResource("primary-server-resource", 32)).build()); @Rule diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java index 32f2f8c481..ad6b72c90c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java @@ -81,6 +81,7 @@ public static Consistency[] data() { @ClassRule @Rule public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()) + .withServerHeap(512) .withServiceFragment(offheapResource("primary-server-resource", 16)).build()); @Rule diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java index 0108cbc55e..6bd054bbc4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java @@ -52,6 +52,7 @@ public class BasicClusteredCacheOpsReplicationWithServersApiTest extends Cluster @ClassRule public static Cluster CLUSTER = newCluster(2).in(clusterPath()) + .withServerHeap(512) .withServiceFragment(offheapResource("primary-server-resource", 16)).build(); @Before diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java index cd4cd3f519..a61ea78543 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java @@ -45,6 +45,7 @@ public class BasicLifeCyclePassiveReplicationTest extends ClusteredTests { @ClassRule @Rule public static final ParallelTestCluster CLUSTER = new ParallelTestCluster(newCluster(2).in(clusterPath()) + .withServerHeap(512) .withServiceFragment(offheapResource("primary-server-resource", 16)).build()); @Before diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java index 7e0a39d64e..0efb52e800 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java @@ -57,7 +57,9 @@ public class DuplicateTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = - newCluster(2).in(clusterPath()).withServiceFragment(offheapResource("primary-server-resource", 512)).build(); + newCluster(2).in(clusterPath()) + .withServerHeap(512) + .withServiceFragment(offheapResource("primary-server-resource", 512)).build(); @Before public void startServers() throws Exception { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java index 9f53d8f867..d3411d9ffe 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java @@ -52,6 +52,7 @@ public class OversizedCacheOpsPassiveTest extends ClusteredTests { newCluster(2).in(clusterPath()) .withSystemProperty("ehcache.sync.data.gets.threshold", "2") .withServiceFragment(offheapResource("primary-server-resource", 2)) + .withSystemProperty("JAVA_OPTS", "-Xms1024m -Xmx8192m") .build(); @Test @@ -84,7 +85,7 @@ private void doPuts(CacheManagerBuilder clusteredCacheMa CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", CACHE_SIZE_IN_MB, MemoryUnit.MB))) - .build(); + .build(); syncLatch.countDown(); Cache cache = cacheManager.createCache("clustered-cache", config); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java index 42c76f5a23..feba1e4e0d 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java @@ -45,7 +45,9 @@ public class PassiveSyncTest extends ClusteredTests { @ClassRule public static Cluster CLUSTER = newCluster(2).in(clusterPath()) - .withServiceFragment(offheapResource("primary-server-resource", 16)).build(); + .withServiceFragment(offheapResource("primary-server-resource", 16)) + .withServerHeap(512) + .build(); @Before public void startServers() throws Exception { From 4485219b500ac9365744da5f7af431dbdfc69bf0 Mon Sep 17 00:00:00 2001 From: Clifford W Johnson Date: Wed, 11 Nov 2020 15:24:11 -0500 Subject: [PATCH 296/372] Replace TCPProxyUtil with TCPProxyManager This commit replaces TCPProxyUtil, which relied on PortChooser, with TCPProxyManager, which makes use of PortManager. --- .../java/org/ehcache/clustered/LeaseTest.java | 77 +++++------- .../clustered/ReconnectDuringDestroyTest.java | 37 +++--- .../ManagementClusterConnectionTest.java | 23 ++-- .../reconnect/BasicCacheReconnectTest.java | 22 ++-- .../CacheManagerDestroyReconnectTest.java | 24 ++-- .../reconnect/EventsReconnectTest.java | 21 ++-- .../clustered/util/TCPProxyManager.java | 117 ++++++++++++++++++ .../ehcache/clustered/util/TCPProxyUtil.java | 92 -------------- 8 files changed, 219 insertions(+), 194 deletions(-) create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/util/TCPProxyManager.java delete mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/util/TCPProxyUtil.java diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java index 1cde819531..102d53a1b2 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java @@ -15,19 +15,17 @@ */ package org.ehcache.clustered; -import com.tc.net.proxy.TCPProxy; import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; -import org.ehcache.clustered.util.TCPProxyUtil; +import org.ehcache.clustered.util.TCPProxyManager; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.junit.After; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; @@ -38,12 +36,9 @@ import java.net.URI; import java.time.Duration; -import java.util.ArrayList; -import java.util.List; import static java.time.Duration.ofSeconds; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; -import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.Matchers.equalTo; @@ -62,13 +57,6 @@ public class LeaseTest extends ClusteredTests { offheapResource("primary-server-resource", 64) + leaseLength(leaseLength)).build()) .outputIs(CLASS_RULE); - private final List proxies = new ArrayList<>(); - - @After - public void after() { - proxies.forEach(TCPProxy::stop); - } - @Parameterized.Parameters public static ResourcePoolsBuilder[] data() { return new ResourcePoolsBuilder[]{ @@ -85,39 +73,40 @@ public static ResourcePoolsBuilder[] data() { @Test public void leaseExpiry() throws Exception { - URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getConnectionURI(), proxies); - - CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() - .with(ClusteringServiceConfigurationBuilder.cluster(connectionURI.resolve("/crud-cm")) - .timeouts(TimeoutsBuilder.timeouts().connection(Duration.ofSeconds(20))) - .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); - PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); - cacheManager.init(); - - CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, - resourcePoolsBuilder).build(); - - Cache cache = cacheManager.createCache("clustered-cache", config); - cache.put(1L, "The one"); - cache.put(2L, "The two"); - cache.put(3L, "The three"); - assertThat(cache.get(1L), equalTo("The one")); - assertThat(cache.get(2L), equalTo("The two")); - assertThat(cache.get(3L), equalTo("The three")); - - long delay = CLUSTER.input().plusSeconds(1L).toMillis(); - setDelay(delay, proxies); - try { - Thread.sleep(delay); - } finally { - setDelay(0L, proxies); - } - - eventually().runsCleanly(() -> { + try (TCPProxyManager proxyManager = TCPProxyManager.create(CLUSTER.get().getConnectionURI())) { + URI connectionURI = proxyManager.getURI(); + + CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() + .with(ClusteringServiceConfigurationBuilder.cluster(connectionURI.resolve("/crud-cm")) + .timeouts(TimeoutsBuilder.timeouts().connection(Duration.ofSeconds(20))) + .autoCreate(server -> server.defaultServerResource("primary-server-resource"))); + PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(false); + cacheManager.init(); + + CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, + resourcePoolsBuilder).build(); + + Cache cache = cacheManager.createCache("clustered-cache", config); + cache.put(1L, "The one"); + cache.put(2L, "The two"); + cache.put(3L, "The three"); assertThat(cache.get(1L), equalTo("The one")); assertThat(cache.get(2L), equalTo("The two")); assertThat(cache.get(3L), equalTo("The three")); - }); - } + long delay = CLUSTER.input().plusSeconds(1L).toMillis(); + proxyManager.setDelay(delay); + try { + Thread.sleep(delay); + } finally { + proxyManager.setDelay(0); + } + + eventually().runsCleanly(() -> { + assertThat(cache.get(1L), equalTo("The one")); + assertThat(cache.get(2L), equalTo("The two")); + assertThat(cache.get(3L), equalTo("The three")); + }); + } + } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java index 6b226ce0bd..427240e26b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -25,12 +25,13 @@ import org.ehcache.clustered.client.service.EntityBusyException; import org.ehcache.clustered.common.internal.ClusterTierManagerConfiguration; import org.ehcache.clustered.reconnect.ThrowingResiliencyStrategy; -import org.ehcache.clustered.util.TCPProxyUtil; +import org.ehcache.clustered.util.TCPProxyManager; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; @@ -43,18 +44,13 @@ import org.terracotta.lease.connection.LeasedConnectionFactory; import org.terracotta.testing.rules.Cluster; -import com.tc.net.proxy.TCPProxy; import org.terracotta.utilities.test.rules.TestRetryer; -import java.net.URI; import java.time.Duration; -import java.util.ArrayList; -import java.util.List; import java.util.Properties; import static java.time.Duration.ofSeconds; import static org.ehcache.clustered.common.EhcacheEntityVersion.ENTITY_VERSION; -import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; @@ -67,8 +63,7 @@ */ public class ReconnectDuringDestroyTest extends ClusteredTests { - private static URI connectionURI; - private static List proxies; + private static TCPProxyManager proxyManager; PersistentCacheManager cacheManager; @ClassRule @Rule @@ -79,14 +74,18 @@ public class ReconnectDuringDestroyTest extends ClusteredTests { @BeforeClass public static void initializeProxy() throws Exception { - proxies = new ArrayList<>(); - connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getConnectionURI(), proxies); + proxyManager = TCPProxyManager.create(CLUSTER.get().getConnectionURI()); + } + + @AfterClass + public static void closeProxy() { + proxyManager.close(); } @Before public void initializeCacheManager() { ClusteringServiceConfiguration clusteringConfiguration = - ClusteringServiceConfigurationBuilder.cluster(connectionURI.resolve("/crud-cm")) + ClusteringServiceConfigurationBuilder.cluster(proxyManager.getURI().resolve("/crud-cm")) .autoCreate(server -> server.defaultServerResource("primary-server-resource")).build(); CacheManagerBuilder clusteredCacheManagerBuilder @@ -106,7 +105,7 @@ public void reconnectDuringDestroyTest() throws Exception { cacheManager.close(); Connection client = null; try { - client = LeasedConnectionFactory.connect(connectionURI, new Properties()); + client = LeasedConnectionFactory.connect(proxyManager.getURI(), new Properties()); VoltronReadWriteLock voltronReadWriteLock = new VoltronReadWriteLock(client, "crud-cm"); try (VoltronReadWriteLock.Hold localMaintenance = voltronReadWriteLock.tryWriteLock()) { if (localMaintenance == null) { @@ -123,13 +122,13 @@ public void reconnectDuringDestroyTest() throws Exception { } // For reconnection. long delay = CLUSTER.input().plusSeconds(1).toMillis(); - setDelay(delay, proxies); + proxyManager.setDelay(delay); try { Thread.sleep(delay); } finally { - setDelay(0L, proxies); + proxyManager.setDelay(0); } - client = LeasedConnectionFactory.connect(connectionURI, new Properties()); + client = LeasedConnectionFactory.connect(proxyManager.getURI(), new Properties()); // For mimicking the cacheManager.destroy() in the reconnect path. voltronReadWriteLock = new VoltronReadWriteLock(client, "crud-cm"); @@ -150,7 +149,9 @@ public void reconnectDuringDestroyTest() throws Exception { } } } finally { - client.close(); + if (client != null) { + client.close(); + } } } @@ -173,11 +174,11 @@ public void reconnectAfterDestroyOneOfTheCache() throws Exception { // For reconnection. long delay = CLUSTER.input().plusSeconds(1L).toMillis(); - setDelay(delay, proxies); + proxyManager.setDelay(delay); try { Thread.sleep(delay); } finally { - setDelay(0L, proxies); + proxyManager.setDelay(0); } Cache cache2Again = cacheManager.getCache("clustered-cache-2", Long.class, String.class); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index ecd45dfc11..d4f01ed585 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -17,16 +17,16 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; -import com.tc.net.proxy.TCPProxy; import org.ehcache.Cache; import org.ehcache.CacheManager; import org.ehcache.Status; import org.ehcache.clustered.ClusteredTests; -import org.ehcache.clustered.util.TCPProxyUtil; +import org.ehcache.clustered.util.TCPProxyManager; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; import org.hamcrest.Matchers; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -37,10 +37,8 @@ import java.net.URI; import java.time.Duration; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; import static java.time.Duration.ofSeconds; @@ -48,7 +46,6 @@ import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.clustered.management.AbstractClusteringManagementTest.waitForAllNotifications; -import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; @@ -64,7 +61,7 @@ public class ManagementClusterConnectionTest extends ClusteredTests { protected static CacheManager cacheManager; protected static ObjectMapper mapper = new ObjectMapper(); - private static final List proxies = new ArrayList<>(); + private static TCPProxyManager proxyManager; private static final Map resources; static { HashMap map = new HashMap<>(); @@ -87,7 +84,8 @@ public static void beforeClass() throws Exception { CLUSTER.get().getCluster().getClusterControl().waitForActive(); - URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getCluster().getConnectionURI(), proxies); + proxyManager = TCPProxyManager.create(CLUSTER.get().getCluster().getConnectionURI()); + URI connectionURI = proxyManager.getURI(); cacheManager = newCacheManagerBuilder() // cluster config @@ -130,6 +128,13 @@ public static void beforeClass() throws Exception { ); } + @AfterClass + public static void afterClass() { + if (proxyManager != null) { + proxyManager.close(); + } + } + @Test public void test_reconnection() throws Exception { long count = CLUSTER.get().getNmsService().readTopology().clientStream() @@ -143,11 +148,11 @@ public void test_reconnection() throws Exception { String instanceId = getInstanceId(); long delay = CLUSTER.input().plusSeconds(1L).toMillis(); - setDelay(delay, proxies); + proxyManager.setDelay(delay); try { Thread.sleep(delay); } finally { - setDelay(0L, proxies); + proxyManager.setDelay(0); } Cache cache = cacheManager.getCache("dedicated-cache-1", String.class, String.class); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java index 4afcdf6bd9..8080911f67 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java @@ -15,19 +15,19 @@ */ package org.ehcache.clustered.reconnect; -import com.tc.net.proxy.TCPProxy; import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.internal.store.ReconnectInProgressException; -import org.ehcache.clustered.util.TCPProxyUtil; +import org.ehcache.clustered.util.TCPProxyManager; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; @@ -37,15 +37,12 @@ import java.net.URI; import java.time.Duration; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import static java.time.Duration.ofSeconds; -import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; @@ -57,6 +54,7 @@ public class BasicCacheReconnectTest extends ClusteredTests { + private static TCPProxyManager proxyManager; private static PersistentCacheManager cacheManager; private static CacheConfiguration config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, @@ -65,8 +63,6 @@ public class BasicCacheReconnectTest extends ClusteredTests { .withResilienceStrategy(new ThrowingResiliencyStrategy<>()) .build(); - private static final List proxies = new ArrayList<>(); - @ClassRule @Rule public static final TestRetryer CLUSTER = tryValues(ofSeconds(1), ofSeconds(10), ofSeconds(30)) .map(leaseLength -> newCluster().in(clusterPath()).withServiceFragment( @@ -75,7 +71,8 @@ public class BasicCacheReconnectTest extends ClusteredTests { @BeforeClass public static void initializeCacheManager() throws Exception { - URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getConnectionURI(), proxies); + proxyManager = TCPProxyManager.create(CLUSTER.get().getConnectionURI()); + URI connectionURI = proxyManager.getURI(); CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() @@ -85,6 +82,11 @@ public static void initializeCacheManager() throws Exception { cacheManager.init(); } + @AfterClass + public static void stopProxies() { + proxyManager.close(); + } + @Test public void cacheOpsDuringReconnection() throws Exception { @@ -154,11 +156,11 @@ public void reconnectDuringCacheDestroy() throws Exception { private void expireLease() throws InterruptedException { long delay = CLUSTER.input().plusSeconds(1L).toMillis(); - setDelay(delay, proxies); + proxyManager.setDelay(delay); try { Thread.sleep(delay); } finally { - setDelay(0L, proxies); + proxyManager.setDelay(0); } } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java index d0f48679f5..7e838b7dd5 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java @@ -15,12 +15,12 @@ */ package org.ehcache.clustered.reconnect; -import com.tc.net.proxy.TCPProxy; import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; -import org.ehcache.clustered.util.TCPProxyUtil; +import org.ehcache.clustered.util.TCPProxyManager; import org.ehcache.config.builders.CacheManagerBuilder; +import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; @@ -30,22 +30,17 @@ import java.net.URI; import java.time.Duration; -import java.util.ArrayList; -import java.util.List; import static java.time.Duration.ofSeconds; -import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; public class CacheManagerDestroyReconnectTest extends ClusteredTests { - + private static TCPProxyManager proxyManager; private static PersistentCacheManager cacheManager; - private static final List proxies = new ArrayList<>(); - @ClassRule @Rule public static final TestRetryer CLUSTER = tryValues(ofSeconds(1), ofSeconds(10), ofSeconds(30)) .map(leaseLength -> newCluster().in(clusterPath()).withServiceFragment( @@ -54,7 +49,8 @@ public class CacheManagerDestroyReconnectTest extends ClusteredTests { @BeforeClass public static void initializeCacheManager() throws Exception { - URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getConnectionURI(), proxies); + proxyManager = TCPProxyManager.create(CLUSTER.get().getConnectionURI()); + URI connectionURI = proxyManager.getURI(); CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() @@ -64,15 +60,20 @@ public static void initializeCacheManager() throws Exception { cacheManager.init(); } + @AfterClass + public static void stopProxies() { + proxyManager.close(); + } + @Test public void testDestroyCacheManagerReconnects() throws Exception { long delay = CLUSTER.input().plusSeconds(1L).toMillis(); - setDelay(delay, proxies); + proxyManager.setDelay(delay); try { Thread.sleep(delay); } finally { - setDelay(0L, proxies); + proxyManager.setDelay(0); } cacheManager.close(); @@ -80,7 +81,6 @@ public void testDestroyCacheManagerReconnects() throws Exception { cacheManager.destroy(); System.out.println(cacheManager.getStatus()); - } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index 1430731e3d..b69c86c8fd 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -15,14 +15,13 @@ */ package org.ehcache.clustered.reconnect; -import com.tc.net.proxy.TCPProxy; import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.internal.store.ReconnectInProgressException; -import org.ehcache.clustered.util.TCPProxyUtil; +import org.ehcache.clustered.util.TCPProxyManager; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheEventListenerConfigurationBuilder; @@ -32,6 +31,7 @@ import org.ehcache.event.CacheEvent; import org.ehcache.event.CacheEventListener; import org.ehcache.event.EventType; +import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; @@ -41,7 +41,6 @@ import java.net.URI; import java.time.Duration; -import java.util.ArrayList; import java.util.EnumSet; import java.util.HashMap; import java.util.List; @@ -53,7 +52,6 @@ import java.util.concurrent.TimeUnit; import static java.time.Duration.ofSeconds; -import static org.ehcache.clustered.util.TCPProxyUtil.setDelay; import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; @@ -65,6 +63,7 @@ public class EventsReconnectTest extends ClusteredTests { + private static TCPProxyManager proxyManager; private static PersistentCacheManager cacheManager; private static class AccountingCacheEventListener implements CacheEventListener { @@ -99,8 +98,6 @@ final void clear() { .withResilienceStrategy(new ThrowingResiliencyStrategy<>()) .build(); - private static final List proxies = new ArrayList<>(); - @ClassRule @Rule public static final TestRetryer CLUSTER = tryValues(ofSeconds(1), ofSeconds(10), ofSeconds(30)) .map(leaseLength -> newCluster().in(clusterPath()).withServiceFragment( @@ -109,7 +106,8 @@ final void clear() { @BeforeClass public static void initializeCacheManager() throws Exception { - URI connectionURI = TCPProxyUtil.getProxyURI(CLUSTER.get().getConnectionURI(), proxies); + proxyManager = TCPProxyManager.create(CLUSTER.get().getConnectionURI()); + URI connectionURI = proxyManager.getURI(); CacheManagerBuilder clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() @@ -119,6 +117,11 @@ public static void initializeCacheManager() throws Exception { cacheManager.init(); } + @AfterClass + public static void stopProxies() { + proxyManager.close(); + } + @Test public void eventsFlowAgainAfterReconnection() throws Exception { try { @@ -162,11 +165,11 @@ public void eventsFlowAgainAfterReconnection() throws Exception { private static void expireLease() throws InterruptedException { long delay = CLUSTER.input().plusSeconds(1L).toMillis(); - setDelay(delay, proxies); + proxyManager.setDelay(delay); try { Thread.sleep(delay); } finally { - setDelay(0L, proxies); + proxyManager.setDelay(0); } } } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/TCPProxyManager.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/TCPProxyManager.java new file mode 100644 index 0000000000..66bdea9571 --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/TCPProxyManager.java @@ -0,0 +1,117 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.clustered.util; + +import com.tc.net.proxy.TCPProxy; + +import org.terracotta.utilities.test.net.PortManager; + +import java.net.InetAddress; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static java.util.Collections.unmodifiableList; + +/** + * Manages creation and use of {@link TCPProxy} instances for a collection of Terracotta servers. + */ +public class TCPProxyManager implements AutoCloseable { + private static final String STRIPE_SEPARATOR = ","; + + private final List proxyPorts; + private final List proxies; + + private TCPProxyManager(List proxyPorts, List proxies) { + this.proxyPorts = unmodifiableList(proxyPorts); + this.proxies = unmodifiableList(proxies); + } + + /** + * Creates a new {@code TCPProxyManager} instance holding {@link TCPProxy} instances for + * the endpoints represented in the specified connection URI. + *

+ * This method creates {@code TCPProxy} instances for servers on {@code localhost}. + *

+ * A reference to the returned {@code TCPProxyManager} must be maintained for the duration + * of the use of the {@code TCPProxy} instances contained therein -- allowing the + * {@code TCPProxyManager} to become weakly-referenced while the proxies are in + * active use could result in random connection-related failures. + * + * @param connectionURI the {@code terracotta} connection URI + * @return a new {@code TCPProxyManager} instance with a {@code TCPProxy} for each endpoint + * @throws Exception if + */ + public static TCPProxyManager create(URI connectionURI) throws Exception { + List primaryPorts = parsePorts(connectionURI); + List proxyPorts = PortManager.getInstance().reservePorts(primaryPorts.size()); + + List proxies = new ArrayList<>(primaryPorts.size()); + InetAddress host = InetAddress.getByName("localhost"); + try { + for (int i = 0; i < primaryPorts.size(); i++) { + TCPProxy proxy = new TCPProxy(proxyPorts.get(i).port(), host, primaryPorts.get(i), 0L, false, null); + proxies.add(proxy); + proxy.start(); + } + } catch (Exception e) { + proxyPorts.forEach(PortManager.PortRef::close); + throw e; + } + + return new TCPProxyManager(proxyPorts, proxies); + } + + /** + * Returns the URI to use for the proxy connection to the Terracotta cluster. + * @return the URI for connection to the Terracotta cluster via the allocated {@link TCPProxy} instances + */ + public URI getURI() { + String uri = proxyPorts.stream() + .map(portRef -> "localhost:" + portRef.port()) + .collect(Collectors.joining(STRIPE_SEPARATOR, "terracotta://", "")); + + return URI.create(uri); + } + + /** + * Sets the delay for each allocated {@link TCPProxy} instance. + * @param delay the non-negative delay + */ + public void setDelay(long delay) { + proxies.forEach(p -> p.setDelay(delay)); + } + + /** + * Stops each allocated {@link TCPProxy} instance and releases the allocated proxy ports. + */ + @Override + public void close() { + proxies.forEach(TCPProxy::stop); + proxyPorts.forEach(PortManager.PortRef::close); + } + + private static List parsePorts(URI connectionURI) { + String withoutProtocol = connectionURI.toString().substring(13); + return Arrays.stream(withoutProtocol.split(STRIPE_SEPARATOR)) + .map(stripe -> stripe.substring(stripe.indexOf(":") + 1)) + .mapToInt(Integer::parseInt) + .boxed() + .collect(Collectors.toList()); + } +} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/TCPProxyUtil.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/TCPProxyUtil.java deleted file mode 100644 index 8ba910117f..0000000000 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/TCPProxyUtil.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.ehcache.clustered.util; - -import com.tc.net.proxy.TCPProxy; -import org.terracotta.testing.common.PortChooser; - -import java.net.InetAddress; -import java.net.URI; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -public final class TCPProxyUtil { - - private static final String STRIPE_SEPARATOR = ","; - - private TCPProxyUtil() { - - } - - public static URI getProxyURI(URI connectionURI, List proxies) throws Exception { - - List ports = parsePorts(connectionURI); - List proxyPorts = createProxyPorts(ports.size()); - - for (int i = 0; i < ports.size(); i++) { - int port = ports.get(i); - int proxyPort = proxyPorts.get(i); - - InetAddress host = InetAddress.getByName("localhost"); - TCPProxy proxy = new TCPProxy(proxyPort, host, port, 0L, false, null); - proxies.add(proxy); - proxy.start(); - } - - return createURI(proxyPorts); - } - - private static List parsePorts(URI connectionURI) { - String uriString = connectionURI.toString(); - String withoutProtocol = uriString.substring(13); - String[] stripes = withoutProtocol.split(STRIPE_SEPARATOR); - - return Arrays.stream(stripes) - .map(stripe -> stripe.substring(stripe.indexOf(":") + 1)) - .mapToInt(Integer::parseInt) - .boxed() - .collect(Collectors.toList()); - } - - private static List createProxyPorts(int portCount) { - PortChooser portChooser = new PortChooser(); - int firstProxyPort = portChooser.chooseRandomPorts(portCount); - - return IntStream - .range(0, portCount) - .map(i -> firstProxyPort + i) - .boxed() - .collect(Collectors.toList()); - } - - private static URI createURI(List proxyPorts) { - - String uri = proxyPorts.stream() - .map(port -> "localhost:" + port) - .collect(Collectors.joining(",", "terracotta://", "")); - - return URI.create(uri); - } - - public static void setDelay(long delay, List proxies) { - for (TCPProxy proxy : proxies) { - proxy.setDelay(delay); - } - } -} From 8c90b48eff47b0a041a5bc2540c8efc571f0acdb Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 18 Sep 2020 15:46:10 -0400 Subject: [PATCH 297/372] Upgrade to sizeof 0.4.0 --- gradle.properties | 2 +- impl/build.gradle | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index c44a0e9ce5..0752f37f88 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ offheapVersion = 2.5.1 statisticVersion = 2.1 jcacheVersion = 1.1.0 slf4jVersion = 1.7.25 -sizeofVersion = 0.3.0 +sizeofVersion = 0.4.0 jaxbVersion = 2.3.1 # Terracotta clustered diff --git a/impl/build.gradle b/impl/build.gradle index b393167fd0..303d31c72e 100644 --- a/impl/build.gradle +++ b/impl/build.gradle @@ -31,9 +31,7 @@ sourceSets { dependencies { api project(':core') implementation group: 'org.terracotta', name: 'offheap-store', version: parent.offheapVersion - implementation (group: 'org.ehcache', name: 'sizeof', version: parent.sizeofVersion) { - exclude group:'org.slf4j', module:'slf4j-api' - } + implementation group: 'org.ehcache', name: 'sizeof', version: parent.sizeofVersion implementation group: 'org.terracotta', name: 'terracotta-utilities-tools', version: parent.terracottaUtilitiesVersion compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':core-spi-test') From bcc5b9b256984d5eb479e490e145774a3e8f5846 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 14 Aug 2020 12:13:45 -0400 Subject: [PATCH 298/372] UnitTestConnection service should be thread-safe --- .../internal/UnitTestConnectionService.java | 65 ++++++++++--------- .../internal/service/ConnectionStateTest.java | 13 ++-- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java index 643d8cad8b..c6b66f3f6d 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java @@ -35,6 +35,7 @@ import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.stream.Collectors; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLockEntityClientService; import org.ehcache.clustered.client.internal.store.ClusterTierClientEntityService; @@ -42,6 +43,7 @@ import org.ehcache.clustered.server.ClusterTierManagerServerEntityService; import org.ehcache.clustered.server.store.ClusterTierServerEntityService; +import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.terracotta.connection.Connection; @@ -68,6 +70,8 @@ import org.terracotta.passthrough.PassthroughServer; import org.terracotta.passthrough.PassthroughServerRegistry; +import static java.util.stream.Collectors.toCollection; +import static java.util.stream.Collectors.toList; import static org.mockito.Mockito.mock; @@ -127,8 +131,8 @@ public class UnitTestConnectionService implements ConnectionService { private static final Logger LOGGER = LoggerFactory.getLogger(UnitTestConnectionService.class); - private static final Map STRIPES = new HashMap<>(); - private static final Map SERVERS = new HashMap<>(); + private static final Map STRIPES = new ConcurrentHashMap<>(); + private static final Map SERVERS = new ConcurrentHashMap<>(); private static final String PASSTHROUGH = "passthrough"; @@ -141,26 +145,20 @@ public class UnitTestConnectionService implements ConnectionService { * @param server the {@code PassthroughServer} instance to use for connections to {@code uri} */ public static void add(URI uri, PassthroughServer server) { - URI keyURI = createKey(uri); - if (SERVERS.containsKey(keyURI)) { - throw new AssertionError("Server at " + uri + " already provided; use remove() to remove"); - } - - SERVERS.put(keyURI, new ServerDescriptor(server)); - // TODO rework that better - server.registerAsynchronousServerCrasher(mock(IAsynchronousServerCrasher.class)); - server.start(true, false); - LOGGER.info("Started PassthroughServer at {}", keyURI); + SERVERS.compute(createKey(uri), (u, existing) -> { + if (existing == null) { + server.registerAsynchronousServerCrasher(mock(IAsynchronousServerCrasher.class)); + server.start(true, false); + LOGGER.info("Started PassthroughServer at {}", u); + return new ServerDescriptor(server); + } else { + throw new AssertionError("Server at " + u + " already provided; use remove() to remove"); + } + }); } public static void addServerToStripe(String stripeName, PassthroughServer server) { - - if (STRIPES.get(stripeName) == null) { - StripeDescriptor stripeDescriptor = new StripeDescriptor(); - STRIPES.put(stripeName, stripeDescriptor); - } - - STRIPES.get(stripeName).addServer(server); + STRIPES.computeIfAbsent(stripeName, k -> new StripeDescriptor()).addServer(server); } public static void removeStripe(String stripeName) { @@ -376,25 +374,25 @@ public PassthroughServer build() { public static Collection getConnectionProperties(URI uri) { ServerDescriptor serverDescriptor = SERVERS.get(createKey(uri)); - if (serverDescriptor != null) { - return serverDescriptor.getConnections().values(); - } else { + if (serverDescriptor == null) { return Collections.emptyList(); + } else { + return serverDescriptor.getConnections().values(); } } public static Collection getConnections(URI uri) { ServerDescriptor serverDescriptor = SERVERS.get(createKey(uri)); - return serverDescriptor.getConnections().keySet(); + return serverDescriptor.getConnections().keySet().stream().map(c -> proxyConnection(serverDescriptor, c)).collect(toList()); } @Override public boolean handlesURI(URI uri) { if (PASSTHROUGH.equals(uri.getScheme())) { return STRIPES.containsKey(uri.getAuthority()); + } else { + return SERVERS.containsKey(checkURI(uri)); } - checkURI(uri); - return SERVERS.containsKey(uri); } @Override @@ -406,7 +404,10 @@ public boolean handlesConnectionType(String s) { public Connection connect(URI uri, Properties properties) throws ConnectionException { if (PASSTHROUGH.equals(uri.getScheme())) { - if(STRIPES.containsKey(uri.getAuthority())) { + StripeDescriptor stripeDescriptor = STRIPES.get(uri.getAuthority()); + if (stripeDescriptor == null) { + throw new IllegalArgumentException("UnitTestConnectionService failed to find stripe" + uri.getAuthority()); + } else { String serverName = uri.getHost(); PassthroughServer server = PassthroughServerRegistry.getSharedInstance().getServerForName(serverName); if(null != server) { @@ -419,8 +420,6 @@ public Connection connect(URI uri, Properties properties) throws ConnectionExcep STRIPES.get(uri.getAuthority()).add(connection); return connection; } - } else { - throw new IllegalArgumentException("UnitTestConnectionService failed to find stripe" + uri.getAuthority()); } } @@ -443,6 +442,10 @@ public Connection connect(URI uri, Properties properties) throws ConnectionExcep /* * Uses a Proxy around Connection so closed connections can be removed from the ServerDescriptor. */ + return proxyConnection(serverDescriptor, connection); + } + + private static Connection proxyConnection(ServerDescriptor serverDescriptor, Connection connection) { return (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), new Class[] { Connection.class }, new ConnectionInvocationHandler(serverDescriptor, connection)); @@ -463,8 +466,10 @@ public Connection connect(Iterable iterable, Properties prope * * @see #checkURI(URI) */ - private static void checkURI(URI requestURI) throws IllegalArgumentException { - if (!requestURI.equals(createKey(requestURI))) { + private static URI checkURI(URI requestURI) throws IllegalArgumentException { + if (requestURI.equals(createKey(requestURI))) { + return requestURI; + } else { throw new IllegalArgumentException("Connection URI contains user-info, path, query, and/or fragment"); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java index f6e27fcf25..16bb0c215f 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java @@ -32,28 +32,28 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.terracotta.connection.Connection; +import org.terracotta.utilities.test.matchers.ThrowsMatcher; import java.io.IOException; import java.net.URI; import java.util.Collection; import java.util.Properties; +import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; +import static org.terracotta.utilities.test.matchers.ThrowsMatcher.threw; public class ConnectionStateTest { - private static URI CLUSTER_URI = URI.create("terracotta://localhost:9510"); + private static final URI CLUSTER_URI = URI.create("terracotta://localhost:9510"); private final ClusteringServiceConfiguration serviceConfiguration = ClusteringServiceConfigurationBuilder .cluster(CLUSTER_URI) .autoCreate(c -> c) .build(); - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Before public void definePassthroughServer() { UnitTestConnectionService.add(CLUSTER_URI, @@ -65,7 +65,6 @@ public void definePassthroughServer() { @After public void removePassthrough() { - expectedException.expect(IllegalStateException.class); UnitTestConnectionService.remove(CLUSTER_URI); } @@ -77,8 +76,8 @@ public void testInitializeStateAfterConnectionCloses() throws Exception { closeConnection(); - expectedException.expect(IllegalStateException.class); - connectionState.getConnection().close(); + Connection connection = connectionState.getConnection(); + assertThat(connection::close, threw(instanceOf(IllegalStateException.class))); connectionState.initializeState(); From b119b4561a6e4efff2f209a61998278780061183 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 14 Aug 2020 12:17:46 -0400 Subject: [PATCH 299/372] ConnectionClosedTest should not be using a resilience strategy that removes keys --- .../client/internal/service/ConnectionClosedTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java index 960019acc3..7a8a4b811d 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java @@ -23,6 +23,7 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; +import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -47,7 +48,7 @@ public class ConnectionClosedTest { private static final URI CLUSTER_URI = URI.create("terracotta://connection.com:9540/timeout"); @Before - public void definePassthroughServer() throws Exception { + public void definePassthroughServer() { UnitTestConnectionService.add(CLUSTER_URI, new UnitTestConnectionService.PassthroughServerBuilder() .resource("primary-server-resource", 64, MemoryUnit.MB) @@ -55,7 +56,7 @@ public void definePassthroughServer() throws Exception { } @After - public void removePassthroughServer() throws Exception { + public void removePassthroughServer() { try { UnitTestConnectionService.remove(CLUSTER_URI); } catch (IllegalStateException e) { @@ -78,7 +79,7 @@ public void testCacheOperationThrowsAfterConnectionClosed() throws Exception { .build()) .autoCreate(c -> c)) .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, - resourcePoolsBuilder)); + resourcePoolsBuilder).withResilienceStrategy(new ThrowingResilienceStrategy<>())); try (PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true)) { Cache cache = cacheManager.getCache("clustered-cache", Long.class, String.class); From 7db3faca98e7b66d0b217b6e3a886d415ac81ac7 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 25 Aug 2020 18:58:18 -0400 Subject: [PATCH 300/372] Fix up missing pieces from the 3.8->3.9 move --- README.adoc | 8 ++--- deploy.sh | 2 +- docs/src/docs/asciidoc/user/107.adoc | 24 +++++++-------- .../asciidoc/user/cache-event-listeners.adoc | 10 +++---- .../docs/asciidoc/user/caching-concepts.adoc | 4 +-- .../docs/asciidoc/user/caching-patterns.adoc | 4 +-- .../src/docs/asciidoc/user/caching-terms.adoc | 4 +-- .../src/docs/asciidoc/user/class-loading.adoc | 4 +-- .../docs/asciidoc/user/clustered-cache.adoc | 20 ++++++------- docs/src/docs/asciidoc/user/common.adoc | 8 ++--- .../src/docs/asciidoc/user/config-derive.adoc | 24 +++++++-------- .../docs/asciidoc/user/eviction-advisor.adoc | 6 ++-- docs/src/docs/asciidoc/user/examples.adoc | 6 ++-- docs/src/docs/asciidoc/user/expiry.adoc | 14 ++++----- .../docs/asciidoc/user/getting-started.adoc | 18 +++++------ docs/src/docs/asciidoc/user/index.adoc | 6 ++-- docs/src/docs/asciidoc/user/management.adoc | 12 ++++---- .../docs/asciidoc/user/migration-guide.adoc | 6 ++-- docs/src/docs/asciidoc/user/osgi.adoc | 4 +-- docs/src/docs/asciidoc/user/performance.adoc | 6 ++-- docs/src/docs/asciidoc/user/resilience.adoc | 6 ++-- .../asciidoc/user/serializers-copiers.adoc | 8 ++--- docs/src/docs/asciidoc/user/thread-pools.adoc | 12 ++++---- docs/src/docs/asciidoc/user/tiering.adoc | 28 ++++++++--------- docs/src/docs/asciidoc/user/usermanaged.adoc | 14 ++++----- docs/src/docs/asciidoc/user/writers.adoc | 8 ++--- docs/src/docs/asciidoc/user/xa.adoc | 18 +++++------ docs/src/docs/asciidoc/user/xml.adoc | 30 +++++++++---------- docs/src/docs/asciidoc/user/xsds.adoc | 16 ++++++---- 29 files changed, 167 insertions(+), 163 deletions(-) diff --git a/README.adoc b/README.adoc index 2780a27eaf..5ece1c5e00 100644 --- a/README.adoc +++ b/README.adoc @@ -1,6 +1,6 @@ = The Ehcache 3.x line is currently the development line. -Status of the build: +Status of the build: [link="https://dev.azure.com/TerracottaCI/ehcache/_build/latest?definitionId=14"] image::https://dev.azure.com/TerracottaCI/ehcache/_apis/build/status/ehcache3[Build Status] @@ -12,11 +12,11 @@ For samples, documentation, and usage information, please see http://ehcache.org == Current release -We released 3.8.1 on September 4th 2019. +We released 3.9.0 on August 25th 2020. -The https://github.com/ehcache/ehcache3/releases/tag/v3.8.1[release notes] contain the links to the artifacts and the documentation to help you get started. +The https://github.com/ehcache/ehcache3/releases/tag/v3.9.0[release notes] contain the links to the artifacts and the documentation to help you get started. -You should consider upgrading to 3.8.x as it does all previous 3.x do and more with a fully compatible API. +You should consider upgrading to 3.9.x as it does all previous 3.x do and more with a fully compatible API. == Current development & next release diff --git a/deploy.sh b/deploy.sh index 89d52e1347..5c5c03ca6c 100755 --- a/deploy.sh +++ b/deploy.sh @@ -208,7 +208,7 @@ if [ $is_major ]; then echo " layout: \"docs35_page\"" >> _config.yml echo " ehc_version: \"${major_version}\"" >> _config.yml echo " ehc_javadoc_version: \"${version}\"" >> _config.yml - echo " ehc_checkout_dir_var: \"sourcedir38\"" >> _config.yml + echo " ehc_checkout_dir_var: \"sourcedir39\"" >> _config.yml sed -i '' "s/#needle\_for\_sourcedir/ - sourcedir${short_major_version}=\/_eh${short_major_version}\\ #needle_for_sourcedir/" _config.yml diff --git a/docs/src/docs/asciidoc/user/107.adoc b/docs/src/docs/asciidoc/user/107.adoc index 037c931643..b419af0cb4 100644 --- a/docs/src/docs/asciidoc/user/107.adoc +++ b/docs/src/docs/asciidoc/user/107.adoc @@ -1,9 +1,9 @@ --- --- = The Ehcache 3.x JSR-107 Provider -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -59,7 +59,7 @@ Here is a code sample that demonstrates the usage of the basic JCache configurat [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=basicConfigurationExample] +include::{sourcedir39}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=basicConfigurationExample] ---- <1> Retrieves the default CachingProvider implementation from the application's classpath. @@ -91,7 +91,7 @@ you can still get to the underlying Ehcache `CacheRuntimeConfiguration`: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=mutableConfigurationExample] +include::{sourcedir39}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=mutableConfigurationExample] ---- <1> Create a JCache cache using the `MutableConfiguration` interface from the JCache specification. @@ -109,7 +109,7 @@ The way you do this is as follows: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheCacheManagerConfigurationExample] +include::{sourcedir39}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheCacheManagerConfigurationExample] ---- <1> Cast the `CachingProvider` into the Ehcache specific implementation `org.ehcache.jsr107.EhcacheCachingProvider`, <2> Create a configuration using the specific Ehcache `DefaultConfiguration` and pass it some `CacheManager` level configurations, @@ -122,7 +122,7 @@ When using this mechanism, no JCache `CompleteConfiguration` is used and so you [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheBasedConfigurationExample] +include::{sourcedir39}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheBasedConfigurationExample] ---- <1> Create an Ehcache `CacheConfiguration`. @@ -142,14 +142,14 @@ The following is an example of an XML configuration: [source%nowrap,xml,indent=0] ---- -include::{sourcedir38}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml[] +include::{sourcedir39}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml[] ---- Here is an example of how to access the XML configuration using JCache: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107UsingXMLConfigExample] +include::{sourcedir39}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107UsingXMLConfigExample] ---- <1> Invoke `javax.cache.spi.CachingProvider.getCacheManager(java.net.URI, java.lang.ClassLoader)` @@ -179,7 +179,7 @@ You can do this at two different levels: [source%nowrap,xml,indent=0] ---- -include::{sourcedir38}/107/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml[lines=17..-1] +include::{sourcedir39}/107/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml[lines=17..-1] ---- <1> Using the JCache service extension, you can enable MBeans by default. @@ -201,7 +201,7 @@ To do this, add a `jsr107` service in your XML configuration file: [source%nowrap,xml,indent=0] ---- -include::{sourcedir38}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml[] +include::{sourcedir39}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml[] ---- <1> First, declare a namespace for the JCache extension, e.g. `jsr107`. @@ -218,7 +218,7 @@ Using the above configuration, you can not only supplement but also override the [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107SupplementWithTemplatesExample] +include::{sourcedir39}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107SupplementWithTemplatesExample] ---- <1> Assume existing JCache configuration code, which is store-by-value by default @@ -283,5 +283,5 @@ If you need _Ehcache through JCache_ behaviour, the following shows the relevant [source%nowrap,xml,indent=0] ---- -include::{sourcedir38}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml[tag=cacheThroughCAS] +include::{sourcedir39}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml[tag=cacheThroughCAS] ---- diff --git a/docs/src/docs/asciidoc/user/cache-event-listeners.adoc b/docs/src/docs/asciidoc/user/cache-event-listeners.adoc index f23e76d6d4..684d473e82 100644 --- a/docs/src/docs/asciidoc/user/cache-event-listeners.adoc +++ b/docs/src/docs/asciidoc/user/cache-event-listeners.adoc @@ -1,9 +1,9 @@ --- --- = Cache Event Listeners -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -18,7 +18,7 @@ Listeners are registered at the cache level - and therefore only receive events [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEventListener] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEventListener] ---- <1> Create a `CacheEventListenerConfiguration` using the builder indicating the listener and the events to receive (in this case create and update events) @@ -57,7 +57,7 @@ Cache event listeners may also be added and removed while the cache is being use [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=registerListenerAtRuntime] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=registerListenerAtRuntime] ---- <1> Create a `CacheEventListener` implementation instance. @@ -73,7 +73,7 @@ Advanced users may want to tune the level of concurrency which may be used for d [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=configuringEventProcessingQueues] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=configuringEventProcessingQueues] ---- <1> Indicate the level of concurrency desired diff --git a/docs/src/docs/asciidoc/user/caching-concepts.adoc b/docs/src/docs/asciidoc/user/caching-concepts.adoc index 1ea1c185ae..1cd3192ebc 100644 --- a/docs/src/docs/asciidoc/user/caching-concepts.adoc +++ b/docs/src/docs/asciidoc/user/caching-concepts.adoc @@ -1,9 +1,9 @@ --- --- = Concepts Related to Caching -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/caching-patterns.adoc b/docs/src/docs/asciidoc/user/caching-patterns.adoc index 26f2505e1c..b640647156 100644 --- a/docs/src/docs/asciidoc/user/caching-patterns.adoc +++ b/docs/src/docs/asciidoc/user/caching-patterns.adoc @@ -1,9 +1,9 @@ --- --- = Cache Usage Patterns -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/caching-terms.adoc b/docs/src/docs/asciidoc/user/caching-terms.adoc index 2b2754db5b..d1581a042a 100644 --- a/docs/src/docs/asciidoc/user/caching-terms.adoc +++ b/docs/src/docs/asciidoc/user/caching-terms.adoc @@ -1,9 +1,9 @@ --- --- = Terms Related to Caching -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/class-loading.adoc b/docs/src/docs/asciidoc/user/class-loading.adoc index b3b8f6f6f0..f5a6a1b768 100644 --- a/docs/src/docs/asciidoc/user/class-loading.adoc +++ b/docs/src/docs/asciidoc/user/class-loading.adoc @@ -1,9 +1,9 @@ --- --- = Class loading -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/clustered-cache.adoc b/docs/src/docs/asciidoc/user/clustered-cache.adoc index c973b7fe09..d491a2fde0 100644 --- a/docs/src/docs/asciidoc/user/clustered-cache.adoc +++ b/docs/src/docs/asciidoc/user/clustered-cache.adoc @@ -1,9 +1,9 @@ --- --- = Clustered Cache -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -157,7 +157,7 @@ Here is a code sample that shows how to configure a cache manager with clusterin [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] +include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] ---- <1> Returns the `org.ehcache.config.builders.CacheManagerBuilder` instance. @@ -174,7 +174,7 @@ This code sample demonstrates the usage of the concepts explained in the previou [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerWithServerSideConfigExample] +include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerWithServerSideConfigExample] ---- <1> `defaultServerResource(String)` on `ClusteringServiceConfigurationBuilder` instance sets the default server off-heap resource for the cache manager. @@ -201,7 +201,7 @@ When configuring a cache manager to connect to a cluster tier manager there are [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerLifecycle] +include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerLifecycle] ---- <1> In auto create mode if no cluster tier manager exists then one is created with the supplied configuration. If it exists and its configuration matches the supplied configuration then a connection is established. @@ -220,7 +220,7 @@ If it does not exist then the cache manager will fail to initialize. [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheTieredExample] +include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheTieredExample] ---- <1> Configuring the heap tier for cache. @@ -230,7 +230,7 @@ The equivalent XML configuration is as follows: [source%nowrap,xml,indent=0] ---- -include::{sourcedir38}/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=tieringSample] +include::{sourcedir39}/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=tieringSample] ---- <1> Specify the heap tier for cache. @@ -253,7 +253,7 @@ This comes with a latency penalty on the write operation required to give this g [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheConsistency] +include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheConsistency] ---- <1> Specify the consistency level through the use of additional service configuration, using _strong_ consistency here. @@ -263,7 +263,7 @@ The equivalent XML configuration is as follows: [source%nowrap,xml,indent=0] ---- -include::{sourcedir38}/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=consistencySample] +include::{sourcedir39}/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=consistencySample] ---- <1> Specify the consistency level through a custom service configuration from the `clustered` namespace. @@ -293,7 +293,7 @@ The example code below shows how this can be implemented. [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=unspecifiedClusteredCacheExample] +include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=unspecifiedClusteredCacheExample] ---- <1> Configure the first cache manager with auto create on reconnect diff --git a/docs/src/docs/asciidoc/user/common.adoc b/docs/src/docs/asciidoc/user/common.adoc index 3735b716df..54d2e69a7b 100644 --- a/docs/src/docs/asciidoc/user/common.adoc +++ b/docs/src/docs/asciidoc/user/common.adoc @@ -1,7 +1,7 @@ --- --- -ifndef::sourcedir38[] -:version: 3.8 +ifndef::sourcedir39[] +:version: 3.9 :notBuildingForSite: true ifdef::basebackend-html[:outfilesuffix: .html] :source-highlighter: coderay @@ -11,9 +11,9 @@ ifdef::basebackend-html[:outfilesuffix: .html] :icons: font :iconfont-remote!: :iconfont-name: font-awesome.min -:sourcedir38: {gradle-rootdir} +:sourcedir39: {gradle-rootdir} :imagesdir: images :sectanchors: :idprefix: :idseparator: - -endif::sourcedir38[] +endif::sourcedir39[] diff --git a/docs/src/docs/asciidoc/user/config-derive.adoc b/docs/src/docs/asciidoc/user/config-derive.adoc index 07ea68dd36..d53e12547c 100644 --- a/docs/src/docs/asciidoc/user/config-derive.adoc +++ b/docs/src/docs/asciidoc/user/config-derive.adoc @@ -1,9 +1,9 @@ --- --- = Configuration Derivation -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -22,7 +22,7 @@ with the configurations values [source,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=deriveContract] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=deriveContract] ---- <1> Creates a builder seeded with the configuration's state. <2> Configurations built using the builder are then functionally identical to the original configuration. @@ -34,13 +34,13 @@ The configuration builder returned by the derive method provide direct methods f .setting a custom classloader: [source,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=customClassLoader] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=customClassLoader] ---- .adding a cache: [source,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withCache] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withCache] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -65,7 +65,7 @@ include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivati .removing a cache: [source,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withoutCache] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withoutCache] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -93,7 +93,7 @@ builder seeded using the existing cache configuration. .updating a cache, by adding a resource: [source,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=updateCache] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=updateCache] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -131,7 +131,7 @@ creation configurations and service configurations: .adding a service creation configuration (constraining the default thread pool) [source,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withServiceCreation] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withServiceCreation] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -155,7 +155,7 @@ include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivati .updating a service creation configuration (changing the persistence path) [source,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=updateServiceCreation] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=updateServiceCreation] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -177,7 +177,7 @@ include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivati .adding a service configuration (setting a resilience strategy) [source,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withService] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withService] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -210,7 +210,7 @@ include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivati .updating a service configuration (changing a clustered cache's consistency) [source,java,indent=0] ---- -include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java[tag=updateService] +include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java[tag=updateService] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -258,7 +258,7 @@ instance its configuration are usually strongly coupled: .removing a service (making a cache manager non-clustered) [source,java,indent=0] ---- -include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java[tag=removeService] +include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java[tag=removeService] ---- <1> From all cache configurations... <2> remove any existing `ClusteredStoreConfiguration` instances. diff --git a/docs/src/docs/asciidoc/user/eviction-advisor.adoc b/docs/src/docs/asciidoc/user/eviction-advisor.adoc index 5c9941ee3a..48a7a342b8 100644 --- a/docs/src/docs/asciidoc/user/eviction-advisor.adoc +++ b/docs/src/docs/asciidoc/user/eviction-advisor.adoc @@ -1,9 +1,9 @@ --- --- = Eviction Advisor -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -29,7 +29,7 @@ If the eviction is advised against, Ehcache will try to honor the preference of [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEvictionAdvisor] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEvictionAdvisor] ---- <1> Configure a constrained heap, as the eviction advisor is only relevant when mappings get evicted from the cache. diff --git a/docs/src/docs/asciidoc/user/examples.adoc b/docs/src/docs/asciidoc/user/examples.adoc index fdb6ace920..41cd3af73a 100644 --- a/docs/src/docs/asciidoc/user/examples.adoc +++ b/docs/src/docs/asciidoc/user/examples.adoc @@ -1,9 +1,9 @@ --- --- = Examples -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -102,5 +102,5 @@ Note the presence of the +Filling cache with peeps+, +Clearing peeps cache+, and [source,xml,indent=0] ---- -include::{sourcedir38}/107/src/test/resources/ehcache-example.xml[] +include::{sourcedir39}/107/src/test/resources/ehcache-example.xml[] ---- diff --git a/docs/src/docs/asciidoc/user/expiry.adoc b/docs/src/docs/asciidoc/user/expiry.adoc index 8a3a6706e4..e25bb9a40f 100644 --- a/docs/src/docs/asciidoc/user/expiry.adoc +++ b/docs/src/docs/asciidoc/user/expiry.adoc @@ -1,9 +1,9 @@ --- --- = Expiry -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -20,7 +20,7 @@ Expiry is configured at the cache level, in Java or in XML: [source,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] ---- <1> Expiry policy is configured at the cache level, so start by defining a cache configuration, @@ -28,7 +28,7 @@ include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[t [source,xml,indent=0] ---- -include::{sourcedir38}/xml/src/test/resources/configs/docs/expiry.xml[tags=expiry] +include::{sourcedir39}/xml/src/test/resources/configs/docs/expiry.xml[tags=expiry] ---- <1> At the cache level, using the predefined _time-to-live_ again. @@ -50,7 +50,7 @@ Supporting your own expiration scheme simply means implementing the `ExpiryPolic [source,java,indent=0] ---- -include::{sourcedir38}/api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java[lines=21..-1] +include::{sourcedir39}/api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java[lines=21..-1] ---- The main points to remember on the return value from these methods: @@ -71,7 +71,7 @@ In Java: [source,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=customExpiry] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=customExpiry] ---- <1> Simply pass your custom expiry instance into the cache builder. @@ -80,7 +80,7 @@ In XML: [source,xml,indent=0] ---- -include::{sourcedir38}/xml/src/test/resources/configs/docs/expiry.xml[tags=customExpiry] +include::{sourcedir39}/xml/src/test/resources/configs/docs/expiry.xml[tags=customExpiry] ---- <1> Simply pass the fully qualified class name of your custom expiry. diff --git a/docs/src/docs/asciidoc/user/getting-started.adoc b/docs/src/docs/asciidoc/user/getting-started.adoc index af9774bb9c..98c4b32e17 100644 --- a/docs/src/docs/asciidoc/user/getting-started.adoc +++ b/docs/src/docs/asciidoc/user/getting-started.adoc @@ -1,7 +1,7 @@ -= Ehcache 3.8 Documentation -ifndef::sourcedir38[] += Ehcache 3.9 Documentation +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] We feel that the Ehcache 3.x API is a great improvement over the Ehcache 2.x API that has been used by millions of developers. We hope you enjoy this new generation of Ehcache! ifdef::notBuildingForSite[] @@ -25,7 +25,7 @@ As with the previous versions of Ehcache, the canonical way of dealing with `Cac [source,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cachemanagerExample] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cachemanagerExample] ---- <1> The static method `org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder` returns a new `org.ehcache.config.builders.CacheManagerBuilder` instance. @@ -60,7 +60,7 @@ Here is a shorter version featuring 3 important things: [source,java,indent=0] ---- -include::{sourcedir38}/integration-test/src/test/java/org/ehcache/docs/GettingStartedWithStaticImports.java[tag=java7Example] +include::{sourcedir39}/integration-test/src/test/java/org/ehcache/docs/GettingStartedWithStaticImports.java[tag=java7Example] ---- <1> A `CacheManager` implements `Closeable` so can be closed automatically by a try-with-resources. A `CacheManager` must be closed cleanly. In a `finally` block, with a `try-with-resources` or (more frequent for normal applications) in some shutdown hook. @@ -74,7 +74,7 @@ You can create an XML file to configure a `CacheManager`. [source,xml,indent=0] ---- -include::{sourcedir38}/xml/src/test/resources/configs/docs/getting-started.xml[tags=gettingStarted] +include::{sourcedir39}/xml/src/test/resources/configs/docs/getting-started.xml[tags=gettingStarted] ---- <1> Declares a `Cache` aliased to `foo`. @@ -108,7 +108,7 @@ In addition, for creating the cache manager with clustering support, you will ne [source,java,indent=0] ---- -include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] +include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] ---- <1> Returns the `org.ehcache.config.builders.CacheManagerBuilder` instance; @@ -137,7 +137,7 @@ A classical example would be using 3 tiers with a persistent disk storage. [source,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=threeTiersCacheManager] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=threeTiersCacheManager] ---- <1> If you wish to use disk storage (like for persistent `Cache` instances), you'll have to provide a @@ -156,7 +156,7 @@ The following illustrates how to configure a _time-to-live_ expiry. [source,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] ---- <1> Expiry is configured at the cache level, so start by defining a cache configuration, diff --git a/docs/src/docs/asciidoc/user/index.adoc b/docs/src/docs/asciidoc/user/index.adoc index ea45700041..62f1869de4 100644 --- a/docs/src/docs/asciidoc/user/index.adoc +++ b/docs/src/docs/asciidoc/user/index.adoc @@ -1,7 +1,7 @@ = Ehcache {version} Documentation Overview -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -9,7 +9,7 @@ endif::notBuildingForSite[] == Table of Contents -The Table of Contents provides an overview of the Ehcache 3.8 documentation on this site. +The Table of Contents provides an overview of the Ehcache 3.9 documentation on this site. Each topic below corresponds to a menu item at the left. === Basic Topics diff --git a/docs/src/docs/asciidoc/user/management.adoc b/docs/src/docs/asciidoc/user/management.adoc index 3850c4662a..87323351c6 100644 --- a/docs/src/docs/asciidoc/user/management.adoc +++ b/docs/src/docs/asciidoc/user/management.adoc @@ -1,9 +1,9 @@ --- --- = Management and Monitoring -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -30,7 +30,7 @@ cache manager builder as a service: [source,java,indent=0] ---- -include::{sourcedir38}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=usingManagementRegistry] +include::{sourcedir39}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=usingManagementRegistry] ---- <1> Optional: give a name to your cache manager by using a custom configuration <2> Create an instance of `org.ehcache.management.registry.DefaultManagementRegistryService`. This is only required because the service is used below. @@ -50,7 +50,7 @@ and a cache name to uniquely identify the cache on which you want to query stats [source,java,indent=0] ---- -include::{sourcedir38}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=capabilitiesAndContexts] +include::{sourcedir39}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=capabilitiesAndContexts] ---- <1> Query the `ManagementRegistry` for the registered managed objects' capabilities. <2> Each capability has a unique name you will need to refer to it. @@ -74,7 +74,7 @@ a managed object. Examples of actions could be: clear caches, get their configur [source,java,indent=0] ---- -include::{sourcedir38}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=actionCall] +include::{sourcedir39}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=actionCall] ---- <1> Put something in a cache. <2> Call the 'clear' action on the managed cache. Refer to the descriptors of the provider to get the exact list of @@ -92,7 +92,7 @@ manager by default, but sometimes you may want one `ManagementRegistry` to manag [source,java,indent=0] ---- -include::{sourcedir38}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=managingMultipleCacheManagers] +include::{sourcedir39}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=managingMultipleCacheManagers] ---- <1> Create an instance of `org.ehcache.management.SharedManagementService` <2> Pass it as a service to the first cache manager diff --git a/docs/src/docs/asciidoc/user/migration-guide.adoc b/docs/src/docs/asciidoc/user/migration-guide.adoc index 601b7d727c..11dd00aa43 100644 --- a/docs/src/docs/asciidoc/user/migration-guide.adoc +++ b/docs/src/docs/asciidoc/user/migration-guide.adoc @@ -1,9 +1,9 @@ --- --- = Migration Guide -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -65,7 +65,7 @@ having dedicated logic in the methods called during the lifecycle of added and u [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Ehcache3.java[tag=CustomExpiryEhcache3] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Ehcache3.java[tag=CustomExpiryEhcache3] ---- <1> Defining custom expiry to be called during the lifecycle of added mappings. diff --git a/docs/src/docs/asciidoc/user/osgi.adoc b/docs/src/docs/asciidoc/user/osgi.adoc index 4173bc0344..f80b3a8a4b 100644 --- a/docs/src/docs/asciidoc/user/osgi.adoc +++ b/docs/src/docs/asciidoc/user/osgi.adoc @@ -1,9 +1,9 @@ --- --- = OSGi Deployment -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] diff --git a/docs/src/docs/asciidoc/user/performance.adoc b/docs/src/docs/asciidoc/user/performance.adoc index 240747e906..f92b36d0ea 100644 --- a/docs/src/docs/asciidoc/user/performance.adoc +++ b/docs/src/docs/asciidoc/user/performance.adoc @@ -1,9 +1,9 @@ --- --- = Performance Tuning -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -120,7 +120,7 @@ For instance, let's say you define an expiry policy like this. [source,java,indent=0] ---- -include::{sourcedir38}/integration-test/src/test/java/org/ehcache/docs/Performance.java[tag=expiryAllocation] +include::{sourcedir39}/integration-test/src/test/java/org/ehcache/docs/Performance.java[tag=expiryAllocation] ---- <1> Will instantiate a `Duration` every time an entry is accessed diff --git a/docs/src/docs/asciidoc/user/resilience.adoc b/docs/src/docs/asciidoc/user/resilience.adoc index 131398f03e..bbe653443f 100644 --- a/docs/src/docs/asciidoc/user/resilience.adoc +++ b/docs/src/docs/asciidoc/user/resilience.adoc @@ -1,9 +1,9 @@ --- --- = Resilience -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -64,7 +64,7 @@ Timeouts can be configured using a dedicated builder or in XML. [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java[tag=timeoutsExample] +include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java[tag=timeoutsExample] ---- <1> Start setting timeouts using the build diff --git a/docs/src/docs/asciidoc/user/serializers-copiers.adoc b/docs/src/docs/asciidoc/user/serializers-copiers.adoc index 959488c4b2..a59231cddd 100644 --- a/docs/src/docs/asciidoc/user/serializers-copiers.adoc +++ b/docs/src/docs/asciidoc/user/serializers-copiers.adoc @@ -1,9 +1,9 @@ --- --- = Serializers and Copiers -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -119,7 +119,7 @@ Implement the following interface, from package `org.ehcache.spi.serialization`: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/api/src/main/java/org/ehcache/spi/serialization/Serializer.java[lines=20..-1] +include::{sourcedir39}/api/src/main/java/org/ehcache/spi/serialization/Serializer.java[lines=20..-1] ---- As the Javadoc states, there are some constructor rules, see the section <> for that. @@ -256,7 +256,7 @@ Implement the following interface: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/api/src/main/java/org/ehcache/spi/copy/Copier.java[lines=19..-1] +include::{sourcedir39}/api/src/main/java/org/ehcache/spi/copy/Copier.java[lines=19..-1] ---- * `T copyForRead(T obj)` is invoked when a copy must be made upon a read operation (like a cache `get()`), diff --git a/docs/src/docs/asciidoc/user/thread-pools.adoc b/docs/src/docs/asciidoc/user/thread-pools.adoc index 8ad9ecfc9b..446880013f 100644 --- a/docs/src/docs/asciidoc/user/thread-pools.adoc +++ b/docs/src/docs/asciidoc/user/thread-pools.adoc @@ -1,9 +1,9 @@ --- --- = Thread Pools -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -88,7 +88,7 @@ Following are examples of describing how to configure the thread pools the diffe [source%nowrap,java] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=diskStore] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=diskStore] ---- <1> Configure the thread pools. Note that the default one (`dflt`) is required for the events even when no event listener is configured. @@ -99,7 +99,7 @@ include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag= [source%nowrap,java] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=writeBehind] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=writeBehind] ---- <1> Configure the thread pools. Note that the default one (`dflt`) is required for the events even when no event listener is configured. @@ -110,7 +110,7 @@ include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag= [source%nowrap,java] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=events] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=events] ---- <1> Configure the thread pools. Note that there is no default one so all thread-using services must be configured with explicit defaults. @@ -124,7 +124,7 @@ Following is an example describing how to configure the thread pools the differe [source%nowrap,xml] ---- -include::{sourcedir38}/xml/src/test/resources/configs/docs/thread-pools.xml[tags=threadPools] +include::{sourcedir39}/xml/src/test/resources/configs/docs/thread-pools.xml[tags=threadPools] ---- <1> Configure the thread pools. Note that there is no default one. diff --git a/docs/src/docs/asciidoc/user/tiering.adoc b/docs/src/docs/asciidoc/user/tiering.adoc index ec88015acf..e62706b29a 100644 --- a/docs/src/docs/asciidoc/user/tiering.adoc +++ b/docs/src/docs/asciidoc/user/tiering.adoc @@ -1,9 +1,9 @@ --- --- = Ehcache Tiering Options -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] >>>>>>> Upgrade to Asciidoctor Gradle Plugin 2.0.0 ifdef::notBuildingForSite[] @@ -49,7 +49,7 @@ For this, simply define the single resource in the cache configuration: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheapOnly] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheapOnly] ---- <1> Start with defining the key and value type in the configuration builder. @@ -66,7 +66,7 @@ A heap tier can be sized by entries or by size. [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=heap] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=heap] ---- <1> Only 10 entries allowed on heap. Eviction will occur when full. @@ -84,7 +84,7 @@ NOTE: Byte sizing has a runtime performance impact that depends on the size and [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=byteSizedTieredCache] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=byteSizedTieredCache] ---- <1> This will limit the amount of memory used by the heap tier for storing key-value pairs. @@ -104,7 +104,7 @@ If you wish to use off-heap, you'll have to define a resource pool, giving the m [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheap] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheap] ---- <1> Only 10 MB allowed off-heap. @@ -127,7 +127,7 @@ The faster and more dedicated the disk is, the faster accessing the data will be [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=persistentCacheManager] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=persistentCacheManager] ---- <1> To obtain a `PersistentCacheManager` which is a normal `CacheManager` but with the ability to @@ -167,7 +167,7 @@ In some cases, you might want to reduce the concurrency and save resources by re [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=diskSegments] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=diskSegments] ---- <1> Define an `OffHeapDiskStoreConfiguration` instance specifying the required number of segments. @@ -235,7 +235,7 @@ Here is an example using heap, offheap and clustered. [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java[tag=threeTiersCacheManager] +include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java[tag=threeTiersCacheManager] ---- <1> Clustered specific information telling how to connect to the Terracotta cluster @@ -254,7 +254,7 @@ Let's revisit an example used earlier: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=threeTiersCacheManager] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=threeTiersCacheManager] ---- This is a cache using 3 tiers (heap, offheap, disk). @@ -268,7 +268,7 @@ Consider for instance this code: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=notShared] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=notShared] ---- You will end up with two caches that can contain 10 entries each. @@ -285,7 +285,7 @@ Thus you can't change the sizing of off-heap or disk tiers. [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=updateResourcesAtRuntime] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=updateResourcesAtRuntime] ---- <1> You will need to create a new `ResourcePools` object with resources of the required size, using `ResourcePoolsBuilder`. @@ -317,12 +317,12 @@ This method destroys a given cache. The cache shouldn't be in use by another cac .Multiple tiers using Put [plantuml] .... -include::{sourcedir38}/docs/src/docs/uml/put.puml[] +include::{sourcedir39}/docs/src/docs/uml/put.puml[] .... .Multiple tiers using Get [plantuml] .... -include::{sourcedir38}/docs/src/docs/uml/get.puml[] +include::{sourcedir39}/docs/src/docs/uml/get.puml[] .... -- In order to understand what happens for different cache operations when using multiple tiers, here are examples of _Put_ and _Get_ operations. diff --git a/docs/src/docs/asciidoc/user/usermanaged.adoc b/docs/src/docs/asciidoc/user/usermanaged.adoc index c16dcea2d1..9f78d5c165 100644 --- a/docs/src/docs/asciidoc/user/usermanaged.adoc +++ b/docs/src/docs/asciidoc/user/usermanaged.adoc @@ -1,9 +1,9 @@ --- --- = User managed caches -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -44,7 +44,7 @@ The interface definition is shown in this code: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/api/src/main/java/org/ehcache/UserManagedCache.java[lines=17..-1] +include::{sourcedir39}/api/src/main/java/org/ehcache/UserManagedCache.java[lines=17..-1] ---- === User Managed Persistent Cache @@ -63,7 +63,7 @@ The interface definition is shown in this code: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/api/src/main/java/org/ehcache/PersistentUserManagedCache.java[lines=17..-1] +include::{sourcedir39}/api/src/main/java/org/ehcache/PersistentUserManagedCache.java[lines=17..-1] ---- [[code-examples]] @@ -75,7 +75,7 @@ Here is a simple example showing a basic lifecycle of a user managed cache: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=userManagedCacheExample] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=userManagedCacheExample] ---- <1> Create a `UserManagedCache` instance. You can either pass `true` to have the builder `init()` it for you, @@ -102,7 +102,7 @@ If you want to use disk persistent cache, you will need to create and lifecycle [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=persistentUserManagedCache] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=persistentUserManagedCache] ---- <1> Create the persistence service to be used by the cache for storing data on disk. @@ -125,7 +125,7 @@ For more information on cache event listeners, see the section < Provide the `ExecutorService` for ordered and unordered event delivery. diff --git a/docs/src/docs/asciidoc/user/writers.adoc b/docs/src/docs/asciidoc/user/writers.adoc index a4e2d2217f..28b56dcfad 100644 --- a/docs/src/docs/asciidoc/user/writers.adoc +++ b/docs/src/docs/asciidoc/user/writers.adoc @@ -1,9 +1,9 @@ --- --- = Cache Loaders and Writers -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -74,7 +74,7 @@ After this time has elapsed, the batch is processed even if incomplete. [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeThroughCache] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeThroughCache] ---- <1> We register a sample `CacheLoaderWriter` that knows about the mapping ("41L" maps to "zero"). @@ -86,7 +86,7 @@ The returned mapping will populate the cache and be returned to the caller. [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeBehindCache] +include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeBehindCache] ---- <1> For write-behind you need a configured `CacheLoaderWriter`. diff --git a/docs/src/docs/asciidoc/user/xa.adoc b/docs/src/docs/asciidoc/user/xa.adoc index 606b84b518..0271d02928 100644 --- a/docs/src/docs/asciidoc/user/xa.adoc +++ b/docs/src/docs/asciidoc/user/xa.adoc @@ -1,9 +1,9 @@ --- --- = XA transactional caches -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -65,7 +65,7 @@ Here is an example: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testSimpleXACache] +include::{sourcedir39}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testSimpleXACache] ---- <1> First start the Bitronix transaction manager. By default, Ehcache will auto-detect it but will throw an exception during the cache manager initialization if BTM isn't started. @@ -96,7 +96,7 @@ Nothing special needs to be configured for this to happen, just ensure that the [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithWriteThrough] +include::{sourcedir39}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithWriteThrough] ---- <1> First start the Bitronix transaction manager. @@ -122,7 +122,7 @@ Any attempt to access one outside of such context will result in `XACacheExcepti [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testNonTransactionalAccess] +include::{sourcedir39}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testNonTransactionalAccess] ---- <1> First start the Bitronix transaction manager. @@ -151,7 +151,7 @@ Here is an example: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithThreeTiers] +include::{sourcedir39}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithThreeTiers] ---- <1> First start the Bitronix transaction manager. @@ -174,7 +174,7 @@ You can create a XML file to configure a `CacheManager`, lookup a specific trans [source%nowrap,xml,indent=0] ---- -include::{sourcedir38}/transactions/src/test/resources/docs/configs/xa-getting-started.xml[tags=gettingStarted] +include::{sourcedir39}/transactions/src/test/resources/docs/configs/xa-getting-started.xml[tags=gettingStarted] ---- <1> Declare a `TransactionManagerLookup` that will lookup your transaction manager. @@ -185,7 +185,7 @@ In order to parse an XML configuration, you can use the XmlConfiguration type: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithXMLConfig] +include::{sourcedir39}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithXMLConfig] ---- <1> The Bitronix transaction manager must be started before the cache manager is initialized. @@ -198,7 +198,7 @@ And here is what the BitronixTransactionManagerLookup implementation looks like: [source%nowrap,java,indent=0] ---- -include::{sourcedir38}/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixTransactionManagerLookup.java[tag=BitronixLookup] +include::{sourcedir39}/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixTransactionManagerLookup.java[tag=BitronixLookup] ---- <1> The `TransactionManagerLookup` interface must be implemented and the offer a `no-arg` constructor. diff --git a/docs/src/docs/asciidoc/user/xml.adoc b/docs/src/docs/asciidoc/user/xml.adoc index e49480c28c..b16a16ba58 100644 --- a/docs/src/docs/asciidoc/user/xml.adoc +++ b/docs/src/docs/asciidoc/user/xml.adoc @@ -1,9 +1,9 @@ --- --- = XML Configuration -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -108,7 +108,7 @@ NOTE: If you are obtaining your `CacheManager` through the JSR-107 API, what fol [source,java,indent=0] ---- -include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlConfig] +include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlConfig] ---- <1> Obtain a `URL` to your XML file's location <2> Instantiate an `XmlConfiguration` passing the XML file's URL to it @@ -121,14 +121,14 @@ to use a `` element from an XML file, e.g. the `/my-config.xml` [source,xml,indent=0] ---- -include::{sourcedir38}/xml/src/test/resources/configs/docs/template-sample.xml[tag=templateSample] +include::{sourcedir39}/xml/src/test/resources/configs/docs/template-sample.xml[tag=templateSample] ---- Creating a `CacheConfigurationBuilder` of that `example` `` element, would be done as follows: [source,java,indent=0] ---- -include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] +include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] ---- <1> Creates a builder, inheriting the capacity constraint of 200 entries <2> The inherent properties can be overridden by simply providing a different value prior to building the `CacheConfiguration` @@ -141,14 +141,14 @@ and the string representation of that object will give you the XML equivalent of [source,java,indent=0] ---- -include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] +include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] ---- <1> Creates a builder, inheriting the capacity constraint of 200 entries <2> The inherent properties can be overridden by simply providing a different value prior to building the `CacheConfiguration` [source,java,indent=0] ---- -include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTranslation] +include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTranslation] ---- <1> Instantiate an `XmlConfiguration` passing the cache manager `Configuration` <2> Retrieve the XML representation using the `toString` method. @@ -176,7 +176,7 @@ The simplest use of the multi-configuration features is to embed multiple cache file: [source,xml,indent=0] ---- -include::{sourcedir38}/xml/src/test/resources/configs/docs/multi/multiple-managers.xml[] +include::{sourcedir39}/xml/src/test/resources/configs/docs/multi/multiple-managers.xml[] ---- <1> A top-level `` container with namespace declarations for the `multi` and core schemas <2> Each Ehcache configuration is embedded inside a `configuration` tag with a required (unique) `identity` attribute @@ -184,7 +184,7 @@ include::{sourcedir38}/xml/src/test/resources/configs/docs/multi/multiple-manage These embedded configurations can then be retrieved via an `XmlMultiConfiguration` instance built from the XML document. [source,java,indent=0] ---- -include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleManagers] +include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleManagers] ---- <1> The `XmlMultiConfiguration` is assembled from the XML resource. <2> Once assembled the configuration is built. @@ -196,13 +196,13 @@ Multiple variant configurations for a given manager can be provided by including with a required `type` attribute: [source,xml,indent=0] ---- -include::{sourcedir38}/xml/src/test/resources/configs/docs/multi/multiple-variants.xml[tag=variants] +include::{sourcedir39}/xml/src/test/resources/configs/docs/multi/multiple-variants.xml[tag=variants] ---- A specific cache configuration can then be retrieved by choosing both a variant and an identity explicitly on retrieval. [source,java,indent=0] ---- -include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleVariants] +include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleVariants] ---- The samples above are just samples, variant types can be used to represent any kind of variation: development vs production, clustered vs unclustered, red vs blue, etc. @@ -218,7 +218,7 @@ Multiple cache managers can be retrieved from an `XmlMultiConfiguration` by iter `identities()`: [source,java,indent=0] ---- -include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleRetrieval] +include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleRetrieval] ---- <1> From a stream over the set of identities in a mult-configuration. <2> Map each identity to it's unique (non-varianted) configuration. @@ -232,7 +232,7 @@ of parsing XML multi-configuration documents are all just simple invocations of Configurations can be built from scratch as show below: [source,java,indent=0] ---- -include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=building] +include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=building] ---- <1> Starting with an initially empty set of configurations. <2> Add a configuration without variants. @@ -242,7 +242,7 @@ include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.ja They can also be built from existing configurations: [source,java,indent=0] ---- -include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=modifying] +include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=modifying] ---- <1> Starting with an existing `XmlMultiConfiguration`. <2> Remove the configuration with identity `"foo"`. @@ -250,7 +250,7 @@ include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.ja Once built a multi-configuration can be retrieved in XML form: [source,java,indent=0] ---- -include::{sourcedir38}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=rendering] +include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=rendering] ---- <1> Retrieving the XML as a rendered string. <2> Retrieving the XML as a DOM (`org.w3c.Document`). diff --git a/docs/src/docs/asciidoc/user/xsds.adoc b/docs/src/docs/asciidoc/user/xsds.adoc index 335a4c0fbb..75efb3acb4 100644 --- a/docs/src/docs/asciidoc/user/xsds.adoc +++ b/docs/src/docs/asciidoc/user/xsds.adoc @@ -1,9 +1,9 @@ --- --- = Ehcache XSDs -ifndef::sourcedir38[] +ifndef::sourcedir39[] include::{includedir}/common.adoc[] -endif::sourcedir38[] +endif::sourcedir39[] ifdef::notBuildingForSite[] include::{includedir}/menu.adoc[] @@ -21,6 +21,7 @@ endif::notBuildingForSite[] ** Location for 3.6: `http://www.ehcache.org/schema/ehcache-core-3.6.xsd` ** Location for 3.7: `http://www.ehcache.org/schema/ehcache-core-3.7.xsd` ** Location for 3.8: `http://www.ehcache.org/schema/ehcache-core-3.8.xsd` +** Location for 3.9: `http://www.ehcache.org/schema/ehcache-core-3.9.xsd` // needle_for_core_xsd * JSR-107 namespace: `http://www.ehcache.org/v3/jsr107` ** Location for 3.0: `http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd` @@ -32,6 +33,7 @@ endif::notBuildingForSite[] ** Location for 3.6: `http://www.ehcache.org/schema/ehcache-107-ext-3.6.xsd` ** Location for 3.7: `http://www.ehcache.org/schema/ehcache-107-ext-3.7.xsd` ** Location for 3.8: `http://www.ehcache.org/schema/ehcache-107-ext-3.8.xsd` +** Location for 3.9: `http://www.ehcache.org/schema/ehcache-107-ext-3.9.xsd` // needle_for_107_xsd * Transactions namespace: `http://www.ehcache.org/v3/tx` ** Location for 3.0: `http://www.ehcache.org/schema/ehcache-tx-ext-3.0.xsd` @@ -43,6 +45,7 @@ endif::notBuildingForSite[] ** Location for 3.6: `http://www.ehcache.org/schema/ehcache-tx-ext-3.6.xsd` ** Location for 3.7: `http://www.ehcache.org/schema/ehcache-tx-ext-3.7.xsd` ** Location for 3.8: `http://www.ehcache.org/schema/ehcache-tx-ext-3.8.xsd` +** Location for 3.9: `http://www.ehcache.org/schema/ehcache-tx-ext-3.9.xsd` // needle_for_transactions_xsd * Clustering namespace: `http://www.ehcache.org/v3/clustered` ** Location for 3.1: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.1.xsd` @@ -53,13 +56,14 @@ endif::notBuildingForSite[] ** Location for 3.6: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.6.xsd` ** Location for 3.7: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.7.xsd` ** Location for 3.8: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.8.xsd` +** Location for 3.9: `http://www.ehcache.org/schema/ehcache-clustered-ext-3.9.xsd` // needle_for_clustered_xsd === Usage example [source,xml,indent=0] ---- -include::{sourcedir38}/107/src/test/resources/org/ehcache/docs/public-xsds-location.xml[tag=xsdLocations] +include::{sourcedir39}/107/src/test/resources/org/ehcache/docs/public-xsds-location.xml[tag=xsdLocations] ---- [[core]] @@ -67,7 +71,7 @@ include::{sourcedir38}/107/src/test/resources/org/ehcache/docs/public-xsds-locat [source,xsd,indent=0] ---- -include::{sourcedir38}/xml/src/main/resources/ehcache-core.xsd[lines=18..-1] +include::{sourcedir39}/xml/src/main/resources/ehcache-core.xsd[lines=18..-1] ---- [[jsr-107-extension]] @@ -75,12 +79,12 @@ include::{sourcedir38}/xml/src/main/resources/ehcache-core.xsd[lines=18..-1] [source,xsd,indent=0] ---- -include::{sourcedir38}/107/src/main/resources/ehcache-107-ext.xsd[lines=18..-1] +include::{sourcedir39}/107/src/main/resources/ehcache-107-ext.xsd[lines=18..-1] ---- == XA transactions extension [source,xsd,indent=0] ---- -include::{sourcedir38}/transactions/src/main/resources/ehcache-tx-ext.xsd[lines=18..-1] +include::{sourcedir39}/transactions/src/main/resources/ehcache-tx-ext.xsd[lines=18..-1] ---- From bbeb751a965da55132f51ce7139f806e06158095 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 16 Nov 2020 16:40:20 -0500 Subject: [PATCH 301/372] Upgrade to JUnit 4.13.1 --- 107/build.gradle | 10 +++ ...che107ConfigurationIntegrationDocTest.java | 2 +- .../ConfigStatsManagementActivationTest.java | 2 +- .../jsr107/ConfigurationMergerTest.java | 2 +- .../jsr107/LoadAtomicsWith107Test.java | 2 +- .../org/ehcache/jsr107/LoaderWriterTest.java | 2 +- .../jsr107/ResourceCombinationsTest.java | 2 +- .../org/ehcache/jsr107/SerializerTest.java | 2 +- .../ehcache/jsr107/SimpleEh107ConfigTest.java | 3 +- .../java/org/ehcache/jsr107/UnwrapTest.java | 2 +- .../ClusteredResourcePoolUpdationTest.java | 39 +++++---- .../client/BasicClusteredCacheExpiryTest.java | 2 +- .../client/BasicClusteredCacheTest.java | 2 +- .../client/CacheManagerDestroyTest.java | 2 +- .../client/ClusteredCacheDestroyTest.java | 14 ++- .../clustered/client/ClusteredEventsTest.java | 2 +- .../clustered/client/EntityServiceTest.java | 2 +- .../client/NonClusteredCacheTest.java | 2 +- .../client/SimpleClusteredCacheByXmlTest.java | 2 +- .../client/TerracottaUriXmlTest.java | 2 +- ...tedCombinationsWithClusteredCacheTest.java | 2 +- .../clustered/client/XmlConsistencyTest.java | 2 +- .../clustered/client/XmlUnknownCacheTest.java | 10 +-- .../ClusteredConfigurationDerivationTest.java | 2 +- .../ClusteredStoreConfigurationTest.java | 2 +- .../ClusteredResourcePoolBuilderTest.java | 3 +- .../client/docs/ConfigurationDerivation.java | 9 +- ...terTierManagerClientEntityFactoryTest.java | 2 +- .../ClusteredCacheConfigurationParserIT.java | 2 +- ...steredResourceConfigurationParserTest.java | 2 +- ...ManagerServiceConfigurationParserTest.java | 2 +- ...ngCacheServiceConfigurationParserTest.java | 2 +- ...lusteredLoaderWriterStoreProviderTest.java | 2 +- .../ClusteredLoaderWriterStoreTest.java | 2 +- ...ClusteredWriteBehindStoreProviderTest.java | 2 +- .../writebehind/ClusteredWriteBehindTest.java | 2 +- .../lock/VoltronReadWriteLockClientTest.java | 2 +- .../lock/VoltronReadWriteLockTest.java | 2 +- ...ClusterStateRepositoryReplicationTest.java | 2 +- ...rTierManagerClientEntityExceptionTest.java | 3 +- .../service/ClusteringServiceFactoryTest.java | 2 +- .../service/ConnectionClosedTest.java | 2 +- .../internal/service/ConnectionStateTest.java | 5 +- .../DefaultClusteringServiceDestroyTest.java | 2 +- .../service/DefaultClusteringServiceTest.java | 33 +++---- .../internal/service/ReconnectTest.java | 7 +- .../StateRepositoryWhitelistingTest.java | 2 +- .../internal/store/ChainBuilderTest.java | 2 +- .../store/ClusteredStoreProviderTest.java | 3 +- .../internal/store/ClusteredStoreTest.java | 3 +- .../store/CommonServerStoreProxyTest.java | 17 ++-- .../ReconnectingServerStoreProxyTest.java | 19 ++-- .../internal/store/lock/LockManagerTest.java | 2 +- .../lock/LockRetentionDuringFailoverTest.java | 2 +- .../operations/AbstractChainResolverTest.java | 2 +- .../ConditionalReplaceOperationTest.java | 6 +- .../operations/ExpiryChainResolverTest.java | 2 +- .../store/operations/LazyValueHolderTest.java | 2 +- .../operations/TimestampOperationTest.java | 3 +- .../BasicClusteredLoaderWriterTest.java | 2 +- ...icClusteredWriteBehindPassthroughTest.java | 2 +- .../clustered/util/StatisticsTestUtils.java | 9 +- .../Store/WhitelistedUnmarshallingTest.java | 4 +- .../Store/operations/OperationCodeTest.java | 2 +- .../BaseClusteredEhcacheExceptionTest.java | 2 +- .../internal/messages/ChainCodecTest.java | 2 +- .../messages/CommonConfigCodecTest.java | 2 +- .../messages/LifeCycleMessageCodecTest.java | 2 +- .../messages/ReconnectMessageCodecTest.java | 2 +- .../internal/messages/ResponseCodecTest.java | 2 +- .../messages/ServerStoreOpCodecTest.java | 2 +- clustered/integration-test/build.gradle | 9 ++ .../BasicCacheOpsMultiThreadedTest.java | 2 +- .../clustered/BasicClusteredCacheOpsTest.java | 2 +- .../clustered/BasicEntityInteractionTest.java | 2 +- ...anagerLifecycleEhcacheIntegrationTest.java | 2 +- ...gerClientEntityFactoryIntegrationTest.java | 2 +- .../clustered/ClusteredIterationTest.java | 2 +- .../clustered/ClusteredLoaderWriterTest.java | 2 +- .../ehcache/clustered/DestroyLoopTest.java | 2 +- .../clustered/EventsFailureBehaviorTest.java | 2 +- .../IterationFailureBehaviorTest.java | 2 +- .../java/org/ehcache/clustered/LeaseTest.java | 2 +- .../clustered/OversizedCacheOpsTest.java | 2 +- .../clustered/ReconnectDuringDestroyTest.java | 2 +- .../ResourcePoolAllocationFailureTest.java | 2 +- .../VoltronReadWriteLockIntegrationTest.java | 2 +- .../AbstractClusteringManagementTest.java | 2 +- .../management/CMClosedEventSentTest.java | 2 +- .../ClusteredStatisticsCountTest.java | 10 +-- .../EhcacheManagerToStringTest.java | 2 +- .../ManagementClusterConnectionTest.java | 5 +- .../reconnect/BasicCacheReconnectTest.java | 2 +- .../reconnect/EventsReconnectTest.java | 2 +- ...dCacheOpsReplicationMultiThreadedTest.java | 2 +- ...BasicClusteredCacheOpsReplicationTest.java | 2 +- ...OpsReplicationWithMultipleClientsTest.java | 2 +- ...CacheOpsReplicationWithServersApiTest.java | 2 +- .../BasicLifeCyclePassiveReplicationTest.java | 2 +- .../clustered/replication/DuplicateTest.java | 2 +- .../clustered/sync/PassiveSyncTest.java | 2 +- .../BasicClusteredWriteBehindTest.java | 2 +- .../writebehind/WriteBehindTestBase.java | 2 +- .../operations/OperationsToolTest.java | 3 +- clustered/osgi-test/build.gradle | 4 + .../org/ehcache/osgi/ClusteredOsgiTest.java | 2 +- .../VoltronReadWriteLockActiveEntityTest.java | 2 +- .../ClusterTierManagerActiveEntityTest.java | 2 +- .../ClusterTierManagerPassiveEntityTest.java | 2 +- .../server/ServerStoreCompatibilityTest.java | 2 +- .../messages/EhcacheSyncMessageCodecTest.java | 8 +- .../PassiveReplicationMessageCodecTest.java | 3 +- .../store/ClusterTierActiveEntityTest.java | 2 +- .../store/ClusterTierPassiveEntityTest.java | 2 +- .../server/store/LockManagerImplTest.java | 2 +- .../repo/ServerStateRepositoryTest.java | 2 +- .../repo/StateRepositoryManagerTest.java | 2 +- .../server/EhcacheStateServiceImplTest.java | 2 +- .../server/offheap/ChainMapExtensionTest.java | 2 +- .../server/offheap/ChainMapTest.java | 2 +- .../offheap/OffHeapServerStoreTest.java | 21 +++-- .../offheap/PinningOffHeapChainMapTest.java | 2 +- .../EhcacheStateServiceProviderTest.java | 2 +- .../server/store/ServerStoreTest.java | 2 +- config/checkstyle.xml | 2 +- config/owasp-supressions.xml | 6 ++ .../store/StoreExpiryEventListenerTest.java | 2 +- .../internal/tier/CachingTierInvalidate.java | 2 +- .../test/java/org/ehcache/core/CacheTest.java | 2 +- .../ehcache/core/EhcacheBasicClearTest.java | 2 +- .../core/EhcacheBasicContainsKeyTest.java | 2 +- .../ehcache/core/EhcacheBasicCrudBase.java | 2 +- .../ehcache/core/EhcacheBasicGetAllTest.java | 2 +- .../org/ehcache/core/EhcacheBasicGetTest.java | 2 +- .../core/EhcacheBasicIteratorTest.java | 2 +- .../ehcache/core/EhcacheBasicPutAllTest.java | 2 +- .../core/EhcacheBasicPutIfAbsentTest.java | 2 +- .../org/ehcache/core/EhcacheBasicPutTest.java | 2 +- .../core/EhcacheBasicRemoveAllTest.java | 2 +- .../ehcache/core/EhcacheBasicRemoveTest.java | 2 +- .../core/EhcacheBasicRemoveValueTest.java | 2 +- .../ehcache/core/EhcacheBasicReplaceTest.java | 2 +- .../core/EhcacheBasicReplaceValueTest.java | 2 +- .../ehcache/core/EhcacheBulkMethodsTest.java | 2 +- .../org/ehcache/core/EhcacheManagerTest.java | 21 ++--- .../ehcache/core/StatusTransitionerTest.java | 2 +- .../ehcache/core/UserManagedCacheTest.java | 2 +- .../ConcurrentWeakIdentityHashMapTest.java | 2 +- .../config/CoreConfigurationBuilderTest.java | 2 +- .../StoreStatisticsConfigurationTest.java | 2 +- .../core/spi/ServiceLocatorPluralTest.java | 2 +- .../ehcache/core/spi/ServiceLocatorTest.java | 2 +- .../ehcache/core/store/StoreSupportTest.java | 3 +- .../ehcache/core/util/ClassLoadingTest.java | 5 +- gradle.properties | 2 +- .../concurrent/ConcurrentHashMapITest.java | 2 +- .../EhcacheRuntimeConfigurationTest.java | 2 +- .../CacheConfigurationBuilderTest.java | 2 +- .../builders/CacheManagerBuilderTest.java | 5 -- .../builders/PersistentCacheManagerTest.java | 14 ++- .../builders/ResourcePoolsBuilderTest.java | 3 +- .../WriteBehindConfigurationBuilderTest.java | 2 +- .../CacheManagerListenerInteractionsTest.java | 2 +- .../core/events/CacheManagerListenerTest.java | 4 - .../ehcache/core/spi/ServiceProviderTest.java | 2 +- .../ehcache/docs/ConfigurationDerivation.java | 37 ++++---- .../java/org/ehcache/docs/GettingStarted.java | 2 +- .../test/java/org/ehcache/docs/Tiering.java | 2 +- .../org/ehcache/docs/UserManagedCaches.java | 2 +- .../config/BaseCacheConfigurationTest.java | 35 ++++---- .../impl/config/ResourcePoolsImplTest.java | 2 +- .../DefaultCopyProviderConfigurationTest.java | 2 +- ...entDispatcherFactoryConfigurationTest.java | 2 +- ...CacheEventDispatcherConfigurationTest.java | 2 +- .../DefaultEventSourceConfigurationTest.java | 2 +- ...oledExecutionServiceConfigurationTest.java | 2 +- ...ultCacheLoaderWriterConfigurationTest.java | 2 +- ...LoaderWriterProviderConfigurationTest.java | 2 +- .../WriteBehindProviderConfigurationTest.java | 2 +- .../DefaultPersistenceConfigurationTest.java | 2 +- ...ltResilienceStrategyConfigurationTest.java | 2 +- ...enceStrategyProviderConfigurationTest.java | 2 +- ...erializationProviderConfigurationTest.java | 32 +++---- .../serializer/SerializerCountingTest.java | 2 +- .../OffHeapDiskStoreConfigurationTest.java | 2 +- ...eapDiskStoreProviderConfigurationTest.java | 2 +- .../DefaultTimeSourceServiceTest.java | 2 +- .../internal/TimeSourceConfigurationTest.java | 2 +- .../concurrent/ConcurrentHashMapTest.java | 2 +- .../otherPackage/V8FeaturesTest.java | 2 +- .../CacheEventDispatcherFactoryImplTest.java | 2 +- .../PartitionedOrderedExecutorTest.java | 3 +- .../PartitionedScheduledExecutorTest.java | 2 +- .../PartitionedUnorderedExecutorTest.java | 2 +- .../executor/PooledExecutionServiceTest.java | 86 +++++++++---------- .../AbstractWriteBehindTestBase.java | 2 +- .../WriteBehindProviderFactoryTest.java | 16 ++-- .../spi/copy/DefaultCopyProviderTest.java | 2 +- ...DefaultCacheEventListenerProviderTest.java | 2 +- .../DefaultCacheLoaderWriterProviderTest.java | 2 +- ...ResilienceStrategyProviderFactoryTest.java | 3 +- ...DefaultResilienceStrategyProviderTest.java | 2 +- .../DefaultSerializationProviderTest.java | 50 ++++------- .../DefaultStatisticsServiceTest.java | 9 +- .../internal/statistics/StatsUtilsTest.java | 12 +-- .../disk/OffHeapDiskStoreProviderTest.java | 2 +- .../store/disk/OffHeapDiskStoreTest.java | 2 +- .../EhcachePersistentSegmentTest.java | 2 +- .../heap/OnHeapStoreBulkMethodsTest.java | 2 +- .../store/heap/OnHeapStoreKeyCopierTest.java | 2 +- .../heap/OnHeapStoreValueCopierTest.java | 2 +- .../bytesized/OnHeapStoreBulkMethodsTest.java | 2 +- .../heap/holders/CopiedOnHeapKeyTest.java | 2 +- .../SerializedOnHeapValueHolderTest.java | 2 +- .../AbstractEhcacheOffHeapBackingMapTest.java | 2 +- .../offheap/AbstractOffHeapStoreTest.java | 2 +- .../offheap/AssertingOffHeapValueHolder.java | 2 +- .../offheap/BasicOffHeapValueHolderTest.java | 2 +- .../offheap/BinaryOffHeapValueHolderTest.java | 2 +- .../offheap/LazyOffHeapValueHolderTest.java | 2 +- .../store/offheap/OffHeapStoreTest.java | 2 +- .../OffHeapValueHolderPortabilityTest.java | 2 +- .../offheap/factories/EhcacheSegmentTest.java | 2 +- .../tiering/CompoundCachingTierTest.java | 2 +- .../TieredStoreFlushWhileShutdownTest.java | 2 +- .../store/tiering/TieredStoreMutatorTest.java | 2 +- .../store/tiering/TieredStoreTest.java | 4 +- .../util/ByteBufferInputStreamTest.java | 19 ++-- .../util/FileExistenceMatchersTest.java | 2 +- .../internal/util/StatisticsTestUtils.java | 9 +- .../internal/util/ThreadFactoryUtilTest.java | 2 +- .../DefaultDiskResourceServiceTest.java | 21 ++--- .../DefaultLocalPersistenceServiceTest.java | 10 +-- .../FileBasedStateRepositoryTest.java | 2 +- .../impl/serialization/AddedFieldTest.java | 6 +- .../serialization/BasicSerializationTest.java | 10 ++- .../ByteArraySerializerTest.java | 4 +- .../serialization/CharSerializerTest.java | 4 +- .../CompactJavaSerializerTest.java | 2 +- .../serialization/DoubleSerializerTest.java | 4 +- .../ehcache/impl/serialization/EnumTest.java | 18 ++-- .../serialization/FloatSerializerTest.java | 4 +- .../serialization/IntegerSerializerTest.java | 4 +- .../serialization/LongSerializerTest.java | 4 +- .../SerializeAfterEvolutionTest.java | 7 +- .../serialization/StringSerializerTest.java | 4 +- .../TransientStateRepositoryTest.java | 2 +- .../DefaultStoreEventDispatcherTest.java | 2 +- .../org/ehcache/impl/store/HashUtilsTest.java | 2 +- .../ehcache/integration/CacheCopierTest.java | 2 +- .../integration/EhcacheBulkMethodsITest.java | 2 +- .../integration/EventNotificationTest.java | 2 +- .../integration/EvictionEhcacheTest.java | 2 +- .../integration/ExpiryEhcacheTestBase.java | 2 +- .../LoaderWriterErrorEhcacheTest.java | 2 +- .../LoaderWriterSimpleEhcacheTest.java | 2 +- .../ehcache/integration/OsgiSafetyTest.java | 2 +- .../PersistentUserManagedCacheTest.java | 2 +- .../ehcache/integration/SerializersTest.java | 5 +- .../integration/SimpleEhcacheTest.java | 2 +- ...efulSerializerWithStateRepositoryTest.java | 2 +- .../integration/StoreStatisticsTest.java | 2 +- .../org/ehcache/integration/TieringTest.java | 2 +- .../UserManagedCacheEvictionTest.java | 2 +- .../UserManagedCacheLoaderWriterTest.java | 4 +- .../transactions/xa/XACacheTest.java | 2 +- .../java/org/ehcache/docs/ManagementTest.java | 31 +++---- ...tRegistryServiceConfigurationParserIT.java | 2 +- .../StandardEhCacheStatisticsQueryTest.java | 5 +- .../providers/statistics/StatsUtil.java | 2 +- .../registry/DefaultCollectorServiceTest.java | 2 +- .../DefaultManagementRegistryServiceTest.java | 8 +- .../DefaultSharedManagementServiceTest.java | 2 +- ...egistryServiceConfigurationParserTest.java | 2 +- .../management/registry/XmlConfigTest.java | 2 +- osgi-test/build.gradle | 4 + .../java/org/ehcache/osgi/Jsr107OsgiTest.java | 2 +- .../java/org/ehcache/osgi/SimpleOsgiTest.java | 2 +- .../transactions/xa/XAGettingStarted.java | 2 +- .../ehcache/transactions/NonXACacheTest.java | 2 +- .../TransactionalCacheParserIT.java | 2 +- .../ehcache/transactions/XmlConfigTest.java | 2 +- .../XAStoreConfigurationTest.java | 2 +- .../xa/internal/EhcacheXAResourceTest.java | 2 +- .../transactions/xa/internal/XAStoreTest.java | 2 +- .../xa/internal/XATransactionContextTest.java | 5 +- .../xa/internal/XAValueHolderTest.java | 2 +- .../internal/journal/AbstractJournalTest.java | 2 +- .../journal/PersistentJournalTest.java | 2 +- ...ManagerServiceConfigurationParserTest.java | 2 +- ...TxCacheServiceConfigurationParserTest.java | 2 +- ...ctionManagerProviderConfigurationTest.java | 2 +- .../org/ehcache/docs/MultiGettingStarted.java | 13 +-- .../xml/ConfigurationParserTestHelper.java | 1 - .../xml/CoreCacheConfigurationParserTest.java | 2 +- ...eCacheConfigurationBuilderDefaultTest.java | 2 +- .../xml/IntegrationConfigurationTest.java | 2 +- .../org/ehcache/xml/XmlConfigurationTest.java | 24 ++---- .../xml/multi/XmlMultiConfigurationTest.java | 2 +- 299 files changed, 619 insertions(+), 676 deletions(-) diff --git a/107/build.gradle b/107/build.gradle index 207519abde..a710808ce7 100644 --- a/107/build.gradle +++ b/107/build.gradle @@ -22,6 +22,16 @@ plugins { configurations { tckTestClasses + + all { + resolutionStrategy { + dependencySubstitution { + substitute(module('junit:junit:4.11')) + .because('CVE-2020-15250') + .with(module('junit:junit:4.13.1')) + } + } + } } sourceSets { diff --git a/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java b/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java index e46b2af60d..da71667b2e 100644 --- a/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java +++ b/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java @@ -51,6 +51,7 @@ import javax.cache.expiry.ExpiryPolicy; import javax.cache.spi.CachingProvider; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; @@ -58,7 +59,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; /** diff --git a/107/src/test/java/org/ehcache/jsr107/ConfigStatsManagementActivationTest.java b/107/src/test/java/org/ehcache/jsr107/ConfigStatsManagementActivationTest.java index 8be0438d08..cf56e09d7f 100644 --- a/107/src/test/java/org/ehcache/jsr107/ConfigStatsManagementActivationTest.java +++ b/107/src/test/java/org/ehcache/jsr107/ConfigStatsManagementActivationTest.java @@ -36,8 +36,8 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * ConfigStatsManagementActivationTest diff --git a/107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java b/107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java index 750b005cfe..d4783cb90e 100644 --- a/107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java +++ b/107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java @@ -51,12 +51,12 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; diff --git a/107/src/test/java/org/ehcache/jsr107/LoadAtomicsWith107Test.java b/107/src/test/java/org/ehcache/jsr107/LoadAtomicsWith107Test.java index 8ad6714e49..27043ea2af 100644 --- a/107/src/test/java/org/ehcache/jsr107/LoadAtomicsWith107Test.java +++ b/107/src/test/java/org/ehcache/jsr107/LoadAtomicsWith107Test.java @@ -32,8 +32,8 @@ import javax.cache.integration.CacheWriter; import javax.cache.spi.CachingProvider; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; diff --git a/107/src/test/java/org/ehcache/jsr107/LoaderWriterTest.java b/107/src/test/java/org/ehcache/jsr107/LoaderWriterTest.java index 906cf61f44..bd7265e365 100644 --- a/107/src/test/java/org/ehcache/jsr107/LoaderWriterTest.java +++ b/107/src/test/java/org/ehcache/jsr107/LoaderWriterTest.java @@ -35,8 +35,8 @@ import javax.cache.integration.CacheWriter; import javax.cache.spi.CachingProvider; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; diff --git a/107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java b/107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java index 5bb6f8bb57..6232144fa4 100644 --- a/107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java +++ b/107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java @@ -41,8 +41,8 @@ import static org.ehcache.config.units.EntryUnit.ENTRIES; import static org.ehcache.config.units.MemoryUnit.MB; import static org.ehcache.jsr107.Eh107Configuration.fromEhcacheCacheConfiguration; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; @RunWith(Parameterized.class) public class ResourceCombinationsTest { diff --git a/107/src/test/java/org/ehcache/jsr107/SerializerTest.java b/107/src/test/java/org/ehcache/jsr107/SerializerTest.java index 10bc298ac0..d638dc5097 100644 --- a/107/src/test/java/org/ehcache/jsr107/SerializerTest.java +++ b/107/src/test/java/org/ehcache/jsr107/SerializerTest.java @@ -27,7 +27,7 @@ import javax.cache.spi.CachingProvider; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; /** * @author rism diff --git a/107/src/test/java/org/ehcache/jsr107/SimpleEh107ConfigTest.java b/107/src/test/java/org/ehcache/jsr107/SimpleEh107ConfigTest.java index b37a89040a..09a8058b2e 100644 --- a/107/src/test/java/org/ehcache/jsr107/SimpleEh107ConfigTest.java +++ b/107/src/test/java/org/ehcache/jsr107/SimpleEh107ConfigTest.java @@ -24,7 +24,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicBoolean; import javax.cache.Cache; @@ -40,9 +39,9 @@ import javax.cache.integration.CompletionListenerFuture; import javax.cache.spi.CachingProvider; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * SimpleEh107ConfigTest diff --git a/107/src/test/java/org/ehcache/jsr107/UnwrapTest.java b/107/src/test/java/org/ehcache/jsr107/UnwrapTest.java index e89a692516..a3233c0fe4 100644 --- a/107/src/test/java/org/ehcache/jsr107/UnwrapTest.java +++ b/107/src/test/java/org/ehcache/jsr107/UnwrapTest.java @@ -28,9 +28,9 @@ import javax.cache.event.EventType; import javax.cache.spi.CachingProvider; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsInstanceOf.instanceOf; -import static org.junit.Assert.assertThat; /** * @author rism diff --git a/clustered/client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java index 5f2ce743b0..78273ff50a 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java @@ -21,18 +21,26 @@ import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.internal.UnitTestConnectionService; +import org.ehcache.config.CacheRuntimeConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import java.net.URI; +import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; +import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredShared; +import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.ehcache.config.units.MemoryUnit.MB; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThrows; + public class ClusteredResourcePoolUpdationTest { private static final URI CLUSTER_URI = URI.create("terracotta://example.com:9540/my-application"); @@ -41,9 +49,6 @@ public class ClusteredResourcePoolUpdationTest { private static Cache dedicatedCache; private static Cache sharedCache; - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @BeforeClass public static void setUp() throws Exception { UnitTestConnectionService.add(CLUSTER_URI, @@ -84,23 +89,23 @@ public static void tearDown() throws Exception { @Test public void testClusteredDedicatedResourcePoolUpdation() throws Exception { - expectedException.expect(UnsupportedOperationException.class); - expectedException.expectMessage("Updating CLUSTERED resource is not supported"); - dedicatedCache.getRuntimeConfiguration().updateResourcePools( - ResourcePoolsBuilder.newResourcePoolsBuilder() - .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB)) + CacheRuntimeConfiguration runtimeConfiguration = dedicatedCache.getRuntimeConfiguration(); + UnsupportedOperationException thrown = assertThrows(UnsupportedOperationException.class, () -> + runtimeConfiguration.updateResourcePools(newResourcePoolsBuilder() + .with(clusteredDedicated("primary-server-resource", 8, MB)) .build() - ); + )); + assertThat(thrown, hasProperty("message", is("Updating CLUSTERED resource is not supported"))); } @Test public void testClusteredSharedResourcePoolUpdation() throws Exception { - expectedException.expect(UnsupportedOperationException.class); - expectedException.expectMessage("Updating CLUSTERED resource is not supported"); - sharedCache.getRuntimeConfiguration().updateResourcePools( - ResourcePoolsBuilder.newResourcePoolsBuilder() - .with(ClusteredResourcePoolBuilder.clusteredShared("resource-pool-a")) + CacheRuntimeConfiguration runtimeConfiguration = sharedCache.getRuntimeConfiguration(); + UnsupportedOperationException thrown = assertThrows(UnsupportedOperationException.class, () -> + runtimeConfiguration.updateResourcePools(newResourcePoolsBuilder() + .with(clusteredShared("resource-pool-a")) .build() - ); + )); + assertThat(thrown, hasProperty("message", is("Updating CLUSTERED resource is not supported"))); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java index a883387e98..ae0e3623f1 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java @@ -37,9 +37,9 @@ import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; /** * diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java index f51c75ca8d..60988f2363 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java @@ -42,9 +42,9 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; /** * Provides basic tests for creation of a cache using a {@link org.ehcache.clustered.client.internal.store.ClusteredStore ClusteredStore}. diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java index a46bb39da2..36b91c7d94 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java @@ -36,8 +36,8 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; public class CacheManagerDestroyTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java index 224db1b73a..587f315eae 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java @@ -30,9 +30,7 @@ import org.ehcache.config.units.MemoryUnit; import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import java.net.URI; @@ -41,10 +39,12 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; public class ClusteredCacheDestroyTest { @@ -52,9 +52,6 @@ public class ClusteredCacheDestroyTest { private static final URI CLUSTER_URI = URI.create("terracotta://example.com:9540/my-application"); private static final String CLUSTERED_CACHE = "clustered-cache"; - @Rule - public ExpectedException expectedException = ExpectedException.none(); - private static final CacheManagerBuilder clusteredCacheManagerBuilder = newCacheManagerBuilder() .with(cluster(CLUSTER_URI).autoCreate(c -> c)) @@ -203,9 +200,8 @@ public void testDestroyCacheOnNonExistentCacheManager() throws CachePersistenceE public void testDestroyCacheWithTwoCacheManagerOnSameCache_forbiddenWhenInUse() throws CachePersistenceException { try (PersistentCacheManager persistentCacheManager1 = clusteredCacheManagerBuilder.build(true)) { try (PersistentCacheManager persistentCacheManager2 = clusteredCacheManagerBuilder.build(true)) { - expectedException.expect(CachePersistenceException.class); - expectedException.expectMessage("Cannot destroy cluster tier 'clustered-cache': in use by other client(s)"); - persistentCacheManager1.destroyCache(CLUSTERED_CACHE); + CachePersistenceException thrown = assertThrows(CachePersistenceException.class, () -> persistentCacheManager1.destroyCache(CLUSTERED_CACHE)); + assertThat(thrown, hasProperty("message", is("Cannot destroy cluster tier 'clustered-cache': in use by other client(s)"))); } } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java index 2660f0c185..34f75b4518 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java @@ -49,9 +49,9 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ExpiryPolicyBuilder.timeToLiveExpiration; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; import static org.hamcrest.core.IsNull.nullValue; -import static org.junit.Assert.assertThat; import static org.terracotta.utilities.test.matchers.Eventually.within; public class ClusteredEventsTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java index f52553467b..1d9b027970 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java @@ -38,7 +38,7 @@ import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; public class EntityServiceTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java index b57236f2ae..21653b939a 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java @@ -33,8 +33,8 @@ import static java.util.Spliterators.spliterator; import static java.util.stream.StreamSupport.stream; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsCollectionContaining.hasItems; -import static org.junit.Assert.assertThat; /** * Ensures that a non-clustered {@code CacheManager} can be created when clustered classes are diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/SimpleClusteredCacheByXmlTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/SimpleClusteredCacheByXmlTest.java index ddc50e979b..bfd5bf1102 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/SimpleClusteredCacheByXmlTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/SimpleClusteredCacheByXmlTest.java @@ -27,11 +27,11 @@ import org.junit.After; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import org.junit.Before; /** diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/TerracottaUriXmlTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/TerracottaUriXmlTest.java index b360c25ee6..8d132d0790 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/TerracottaUriXmlTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/TerracottaUriXmlTest.java @@ -22,8 +22,8 @@ import org.ehcache.xml.exceptions.XmlConfigurationException; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertThat; /** * TerracottaUriXmlTest diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java index e6071c57a2..b4a5460c1d 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java @@ -44,8 +44,8 @@ import java.net.URI; import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; /** diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/XmlConsistencyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/XmlConsistencyTest.java index 10bdf14cea..fdcd802b9c 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/XmlConsistencyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/XmlConsistencyTest.java @@ -25,9 +25,9 @@ import org.junit.Before; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; /** * XmlConsistencyTest diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/XmlUnknownCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/XmlUnknownCacheTest.java index 4c90d5496a..89bd750366 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/XmlUnknownCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/XmlUnknownCacheTest.java @@ -16,16 +16,14 @@ package org.ehcache.clustered.client; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.endsWith; import static org.junit.Assert.fail; import org.ehcache.xml.XmlConfiguration; import org.ehcache.xml.exceptions.XmlConfigurationException; -import org.junit.Assert; import org.junit.Test; -import static org.hamcrest.Matchers.contains; -import static org.junit.Assert.fail; /** * @@ -36,7 +34,7 @@ public class XmlUnknownCacheTest { @Test public void testGetUnknownCache() { XmlConfiguration xmlConfiguration = new XmlConfiguration(this.getClass().getResource("/configs/unknown-cluster-cache.xml")); - Assert.assertThat(xmlConfiguration.getCacheConfigurations().keySet(),contains("unknownCache")); + assertThat(xmlConfiguration.getCacheConfigurations().keySet(),contains("unknownCache")); } @Test @@ -45,7 +43,7 @@ public void testGetUnknownCacheInvalidAttribute() { new XmlConfiguration(this.getClass().getResource("/configs/unknown-cluster-cache-invalid-attribute.xml")); fail("Expected XmlConfigurationException"); } catch(XmlConfigurationException xce) { - Assert.assertThat(xce.getCause().getMessage(), endsWith("Attribute 'unit' is not allowed to appear in element 'tc:clustered'.")); + assertThat(xce.getCause().getMessage(), endsWith("Attribute 'unit' is not allowed to appear in element 'tc:clustered'.")); } } @@ -55,7 +53,7 @@ public void testGetUnknownCacheInvalidElement() { new XmlConfiguration(this.getClass().getResource("/configs/unknown-cluster-cache-invalid-element.xml")); fail("Expected XmlConfigurationException"); } catch(XmlConfigurationException xce) { - Assert.assertThat(xce.getCause().getMessage(), endsWith("Element 'tc:clustered' must have no character or element information item [children], because the type's content type is empty.")); + assertThat(xce.getCause().getMessage(), endsWith("Element 'tc:clustered' must have no character or element information item [children], because the type's content type is empty.")); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredConfigurationDerivationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredConfigurationDerivationTest.java index 5c98d54751..4dbf576386 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredConfigurationDerivationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredConfigurationDerivationTest.java @@ -23,8 +23,8 @@ import java.net.URI; import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; public class ClusteredConfigurationDerivationTest { private static final String SIMPLE_CLUSTER_XML = "/configs/simple-cluster.xml"; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredStoreConfigurationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredStoreConfigurationTest.java index 408533807f..fdb39f8f40 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredStoreConfigurationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredStoreConfigurationTest.java @@ -19,10 +19,10 @@ import org.ehcache.clustered.common.Consistency; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; public class ClusteredStoreConfigurationTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/config/builders/ClusteredResourcePoolBuilderTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/config/builders/ClusteredResourcePoolBuilderTest.java index 84b4715f0b..5c0fd438fd 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/config/builders/ClusteredResourcePoolBuilderTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/config/builders/ClusteredResourcePoolBuilderTest.java @@ -23,11 +23,10 @@ import org.hamcrest.Matchers; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; - import org.ehcache.clustered.client.config.DedicatedClusteredResourcePool; public class ClusteredResourcePoolBuilderTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java index 621b27eac0..44a23f9d3b 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java @@ -36,13 +36,14 @@ import org.hamcrest.core.IsCollectionContaining; import org.hamcrest.core.IsInstanceOf; import org.hamcrest.core.IsNot; -import org.junit.Assert; import org.junit.Test; import java.net.URI; import java.util.List; import java.util.stream.Collectors; +import static org.hamcrest.MatcherAssert.assertThat; + public class ConfigurationDerivation { @Test @@ -71,7 +72,7 @@ public void removingServices() { .build(); //end::removeService[] - Assert.assertThat(withoutClustering.getServiceCreationConfigurations(), IsNot.not(IsCollectionContaining.hasItem( + assertThat(withoutClustering.getServiceCreationConfigurations(), IsNot.not(IsCollectionContaining.hasItem( IsInstanceOf.instanceOf(ClusteringServiceConfiguration.class)))); } @@ -91,10 +92,10 @@ public void updateService() { .build(); //end::updateService[] - Assert.assertThat(ServiceUtils.findSingletonAmongst(ClusteredStoreConfiguration.class, + assertThat(ServiceUtils.findSingletonAmongst(ClusteredStoreConfiguration.class, configuration.getCacheConfigurations().get("cache").getServiceConfigurations()).getConsistency(), Is.is(Consistency.STRONG)); - Assert.assertThat(ServiceUtils.findSingletonAmongst(ClusteredStoreConfiguration.class, + assertThat(ServiceUtils.findSingletonAmongst(ClusteredStoreConfiguration.class, changedConsistency.getCacheConfigurations().get("cache").getServiceConfigurations()).getConsistency(), Is.is(Consistency.EVENTUAL)); } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java index f2cc7ee340..d82db588d0 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java @@ -25,8 +25,8 @@ import org.mockito.MockitoAnnotations; import org.terracotta.connection.Connection; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.isNull; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java index 04e4123caa..f8f5880ce4 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java @@ -23,7 +23,7 @@ import java.net.URL; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java index 8f3b782ac0..d8de0c7cdc 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java @@ -24,7 +24,7 @@ import org.xmlunit.diff.DefaultNodeMatcher; import org.xmlunit.diff.ElementSelectors; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java index 213dfee054..6012172727 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java @@ -64,6 +64,7 @@ import static java.util.stream.StreamSupport.stream; import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; import static org.ehcache.xml.XmlModel.convertToJavaTimeUnit; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; @@ -71,7 +72,6 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.IsCollectionContaining.hasItem; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java index 9604112616..ae1694471d 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java @@ -22,7 +22,7 @@ import org.xmlunit.diff.DefaultNodeMatcher; import org.xmlunit.diff.ElementSelectors; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; public class ClusteringCacheServiceConfigurationParserTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java index 477b364301..163cbfd8fd 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java @@ -31,8 +31,8 @@ import java.util.HashSet; import static org.ehcache.core.spi.ServiceLocator.dependencySet; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; public class ClusteredLoaderWriterStoreProviderTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java index 49c39c6b3b..477d6dcb9a 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java @@ -37,10 +37,10 @@ import java.util.concurrent.TimeoutException; import static org.ehcache.clustered.ChainUtils.chainOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java index 97478a704e..673381fd61 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java @@ -33,8 +33,8 @@ import java.util.HashSet; import static org.ehcache.core.spi.ServiceLocator.dependencySet; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; public class ClusteredWriteBehindStoreProviderTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java index 18656fb1a8..ff0563bf6e 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java @@ -49,8 +49,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.mock; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockClientTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockClientTest.java index 86ee2b9724..f3af9e3595 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockClientTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockClientTest.java @@ -36,8 +36,8 @@ import static org.ehcache.clustered.common.internal.lock.LockMessaging.HoldType.READ; import static org.ehcache.clustered.common.internal.lock.LockMessaging.HoldType.WRITE; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import org.junit.Before; import org.terracotta.exception.EntityNotProvidedException; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockTest.java index a7f2f56a06..41de1e0c4f 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockTest.java @@ -26,9 +26,9 @@ import static org.ehcache.clustered.common.internal.lock.LockMessaging.HoldType.READ; import static org.ehcache.clustered.common.internal.lock.LockMessaging.HoldType.WRITE; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsNull.notNullValue; import static org.hamcrest.core.IsNull.nullValue; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doThrow; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java index a8bc384c3d..86429fd73f 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java @@ -50,9 +50,9 @@ import static org.ehcache.config.Eviction.noAdvice; import static org.ehcache.config.builders.ExpiryPolicyBuilder.noExpiration; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; public class ClusterStateRepositoryReplicationTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java index 50024caddd..7c5901aed4 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java @@ -39,9 +39,10 @@ import java.net.URI; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.*; +import static org.junit.Assert.fail; /** * This class includes tests to ensure server-side exceptions returned as responses to diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java index 0f6f5a2dc7..25ba158741 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java @@ -24,8 +24,8 @@ import static java.util.Spliterators.spliterator; import static java.util.stream.StreamSupport.stream; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsCollectionContaining.hasItem; -import static org.junit.Assert.assertThat; /** * @author Clifford W. Johnson diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java index 7a8a4b811d..03dadd4f10 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java @@ -39,8 +39,8 @@ import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.terracotta.utilities.test.matchers.Eventually.within; public class ConnectionClosedTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java index 16bb0c215f..78896259d4 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java @@ -28,21 +28,18 @@ import org.ehcache.impl.serialization.StringSerializer; import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.terracotta.connection.Connection; -import org.terracotta.utilities.test.matchers.ThrowsMatcher; import java.io.IOException; import java.net.URI; import java.util.Collection; import java.util.Properties; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; import static org.terracotta.utilities.test.matchers.ThrowsMatcher.threw; public class ConnectionStateTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java index 2e3055d231..157f7cbdb5 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java @@ -39,8 +39,8 @@ import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.clustered.common.EhcacheEntityVersion.ENTITY_VERSION; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java index cb094b6559..5a6be4db87 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java @@ -60,9 +60,7 @@ import org.hamcrest.Matchers; import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.terracotta.connection.ConnectionPropertyNames; import org.terracotta.exception.EntityNotFoundException; @@ -85,17 +83,20 @@ import static org.ehcache.config.ResourceType.Core.DISK; import static org.ehcache.config.ResourceType.Core.HEAP; import static org.ehcache.config.ResourceType.Core.OFFHEAP; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; +import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; @@ -108,9 +109,6 @@ public class DefaultClusteringServiceTest { private ObservableEhcacheServerEntityService observableEhcacheServerEntityService; private ObservableClusterTierServerEntityService observableClusterTierServerEntityService; - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Before public void definePassthroughServer() throws Exception { observableEhcacheServerEntityService = new ObservableEhcacheServerEntityService(); @@ -1260,10 +1258,8 @@ public void testDestroyCantBeCalledIfStopped() throws Exception { .build(); DefaultClusteringService creationService = new DefaultClusteringService(configuration); - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(endsWith(" should be started to call destroy")); - - creationService.destroy(cacheAlias); + IllegalStateException thrown = assertThrows(IllegalStateException.class, () -> creationService.destroy(cacheAlias)); + assertThat(thrown, hasProperty("message", endsWith(" should be started to call destroy"))); } @Test @@ -2023,8 +2019,6 @@ public void testGetStateRepositoryWithinTwiceWithSameNameDifferentPersistenceSpa @Test public void testGetStateRepositoryWithinWithNonExistentPersistenceSpaceIdentifier() throws Exception { - expectedException.expect(CachePersistenceException.class); - expectedException.expectMessage("Clustered space not found for identifier"); ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE)) .autoCreate(s -> s) @@ -2032,13 +2026,13 @@ public void testGetStateRepositoryWithinWithNonExistentPersistenceSpaceIdentifie DefaultClusteringService service = new DefaultClusteringService(configuration); ClusteredCacheIdentifier cacheIdentifier = mock(ClusteredCacheIdentifier.class); doReturn("foo").when(cacheIdentifier).getId(); - service.getStateRepositoryWithin(cacheIdentifier, "myRepo"); + + CachePersistenceException thrown = assertThrows(CachePersistenceException.class, () -> service.getStateRepositoryWithin(cacheIdentifier, "myRepo")); + assertThat(thrown, hasProperty("message", startsWith("Clustered space not found for identifier"))); } @Test public void testReleaseNonExistentPersistenceSpaceIdentifierTwice() throws Exception { - expectedException.expect(CachePersistenceException.class); - expectedException.expectMessage("Unknown identifier"); ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE)) .autoCreate(s -> s) @@ -2046,13 +2040,13 @@ public void testReleaseNonExistentPersistenceSpaceIdentifierTwice() throws Excep DefaultClusteringService service = new DefaultClusteringService(configuration); ClusteredCacheIdentifier cacheIdentifier = mock(ClusteredCacheIdentifier.class); doReturn("foo").when(cacheIdentifier).getId(); - service.releasePersistenceSpaceIdentifier(cacheIdentifier); + + CachePersistenceException thrown = assertThrows(CachePersistenceException.class, () -> service.releasePersistenceSpaceIdentifier(cacheIdentifier)); + assertThat(thrown, hasProperty("message", startsWith("Unknown identifier"))); } @Test public void testReleasePersistenceSpaceIdentifierTwice() throws Exception { - expectedException.expect(CachePersistenceException.class); - expectedException.expectMessage("Unknown identifier"); ClusteringServiceConfiguration configuration = ClusteringServiceConfigurationBuilder.cluster(URI.create(CLUSTER_URI_BASE)) .autoCreate(s -> s) @@ -2064,7 +2058,8 @@ public void testReleasePersistenceSpaceIdentifierTwice() throws Exception { } catch (CachePersistenceException e) { fail("First invocation of releasePersistenceSpaceIdentifier should not have failed"); } - service.releasePersistenceSpaceIdentifier(cacheIdentifier); + CachePersistenceException thrown = assertThrows(CachePersistenceException.class, () -> service.releasePersistenceSpaceIdentifier(cacheIdentifier)); + assertThat(thrown, hasProperty("message", startsWith("Unknown identifier"))); } @Test diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java index 70f253f99e..3e78662c29 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java @@ -20,7 +20,6 @@ import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.internal.MockConnectionService; import org.hamcrest.Matchers; -import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; import org.terracotta.connection.Connection; @@ -31,6 +30,8 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import static org.hamcrest.MatcherAssert.assertThat; + public class ReconnectTest { private static URI CLUSTER_URI = URI.create("mock://localhost:9510"); @@ -79,10 +80,10 @@ public void testAfterConnectionReconnectHappensEvenAfterConnectionException() th try { future.get(); } catch (ExecutionException e) { - Assert.assertThat(e.getCause().getMessage(), Matchers.is("Stop reconnecting")); + assertThat(e.getCause().getMessage(), Matchers.is("Stop reconnecting")); } - Assert.assertThat(connectionState.getReconnectCount(), Matchers.is(1)); + assertThat(connectionState.getReconnectCount(), Matchers.is(1)); } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java index b8d188035e..ffe57b376c 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java @@ -50,9 +50,9 @@ import static org.ehcache.config.Eviction.noAdvice; import static org.ehcache.config.builders.ExpiryPolicyBuilder.noExpiration; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ChainBuilderTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ChainBuilderTest.java index e15ffd2b58..56abb981a2 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ChainBuilderTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ChainBuilderTest.java @@ -21,8 +21,8 @@ import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.Matchers.hasPayloads; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** */ diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java index e585eb7cd3..814b8886ff 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java @@ -53,9 +53,10 @@ import java.util.Map; import static org.ehcache.core.spi.ServiceLocator.dependencySet; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.startsWith; -import static org.junit.Assert.*; +import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; /** diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java index b4fda00755..143a87c28f 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java @@ -72,8 +72,9 @@ import static org.ehcache.core.spi.store.Store.ValueHolder.NO_EXPIRE; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.CombinableMatcher.either; -import static org.junit.Assert.*; +import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java index 14cb53765b..ecf7984dad 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java @@ -23,7 +23,6 @@ import org.ehcache.clustered.server.store.ObservableClusterTierServerEntityService; import org.hamcrest.CoreMatchers; import org.hamcrest.Matcher; -import org.hamcrest.MatcherAssert; import org.hamcrest.core.Is; import org.junit.Test; @@ -37,11 +36,11 @@ import static org.ehcache.clustered.ChainUtils.chainOf; import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.Matchers.hasPayloads; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.CombinableMatcher.either; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; @@ -142,7 +141,7 @@ public void compact(ServerStoreProxy.ChainEntry chain) { for (int i = 0; i < ITERATIONS; i++) { Chain elements1 = serverStoreProxy1.get(i); Chain elements2 = serverStoreProxy2.get(i); - MatcherAssert.assertThat(elements1, Matchers.matchesChain(elements2)); + assertThat(elements1, Matchers.matchesChain(elements2)); if (!elements1.isEmpty()) { entryCount++; } else { @@ -151,14 +150,14 @@ public void compact(ServerStoreProxy.ChainEntry chain) { } // there has to be server-side evictions, otherwise this test is useless - MatcherAssert.assertThat(store1InvalidatedHashes.size(), greaterThan(0)); + assertThat(store1InvalidatedHashes.size(), greaterThan(0)); // test that each time the server evicted, the originating client got notified - MatcherAssert.assertThat(store1InvalidatedHashes.size(), Is.is(ITERATIONS - entryCount)); + assertThat(store1InvalidatedHashes.size(), Is.is(ITERATIONS - entryCount)); // test that each time the server evicted, the other client got notified on top of normal invalidations - MatcherAssert.assertThat(store2InvalidatedHashes.size(), Is.is(ITERATIONS + evictionCount)); + assertThat(store2InvalidatedHashes.size(), Is.is(ITERATIONS + evictionCount)); // test that we got evicted chains - MatcherAssert.assertThat(store1InvalidatedChains.size(), greaterThan(0)); - MatcherAssert.assertThat(store2InvalidatedChains.size(), is(store1InvalidatedChains.size())); + assertThat(store1InvalidatedChains.size(), greaterThan(0)); + assertThat(store2InvalidatedChains.size(), is(store1InvalidatedChains.size())); assertThatClientsWaitingForInvalidationIsEmpty("testInvalidationsContainChains"); assertThat(store1InvalidatedAll.get(), is(false)); @@ -263,7 +262,7 @@ private static void assertThatClientsWaitingForInvalidationIsEmpty(String name) ObservableClusterTierServerEntityService.ObservableClusterTierActiveEntity activeEntity = observableClusterTierService.getServedActiveEntitiesFor(name).get(0); long now = System.currentTimeMillis(); while (System.currentTimeMillis() < now + 5000 && activeEntity.getClientsWaitingForInvalidation().size() != 0); - MatcherAssert.assertThat(activeEntity.getClientsWaitingForInvalidation().size(), Is.is(0)); + assertThat(activeEntity.getClientsWaitingForInvalidation().size(), Is.is(0)); } @Test diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxyTest.java index 5a05b4cbf3..7ab175942c 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxyTest.java @@ -17,7 +17,6 @@ import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; @@ -26,6 +25,7 @@ import java.nio.ByteBuffer; +import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.doThrow; @@ -41,9 +41,6 @@ public class ReconnectingServerStoreProxyTest { @Mock Runnable runnable; - @Rule - public ExpectedException exception = ExpectedException.none(); - private final ServerStoreProxyException storeProxyException = new ServerStoreProxyException(new ConnectionClosedException("Connection Closed")); @InjectMocks @@ -51,20 +48,16 @@ public class ReconnectingServerStoreProxyTest { @Test public void testAppend() throws Exception { - doThrow(storeProxyException).when(proxy).append(anyLong(), any(ByteBuffer.class)); - exception.expect(ReconnectInProgressException.class); - serverStoreProxy.append(0, ByteBuffer.allocate(2)); + assertThrows(ReconnectInProgressException.class, () -> serverStoreProxy.append(0, ByteBuffer.allocate(2))); } @Test public void testGetAndAppend() throws Exception { - doThrow(storeProxyException).when(proxy).getAndAppend(anyLong(), any(ByteBuffer.class)); - exception.expect(ReconnectInProgressException.class); - serverStoreProxy.getAndAppend(0, ByteBuffer.allocate(2)); + assertThrows(ReconnectInProgressException.class, () -> serverStoreProxy.getAndAppend(0, ByteBuffer.allocate(2))); } @Test @@ -72,15 +65,13 @@ public void testGet() throws Exception { doThrow(storeProxyException).when(proxy).get(anyLong()); - exception.expect(ReconnectInProgressException.class); - serverStoreProxy.get(0); + assertThrows(ReconnectInProgressException.class, () -> serverStoreProxy.get(0)); } @Test public void testIterator() throws Exception { doThrow(storeProxyException).when(proxy).iterator(); - exception.expect(ReconnectInProgressException.class); - serverStoreProxy.iterator(); + assertThrows(ReconnectInProgressException.class, () -> serverStoreProxy.iterator()); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerTest.java index f5ddf3f6bd..de51c9f1e3 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerTest.java @@ -33,10 +33,10 @@ import static org.ehcache.clustered.ChainUtils.chainOf; import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.lockFailure; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java index 03a2e0b5e5..c443c8776f 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java @@ -47,8 +47,8 @@ import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.clustered.client.internal.UnitTestConnectionService.getOffheapResourcesType; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; public class LockRetentionDuringFailoverTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java index c8e13c12f1..b9f1d55306 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java @@ -44,12 +44,12 @@ import java.util.concurrent.TimeoutException; import static java.util.Collections.emptyMap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.emptyIterable; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperationTest.java index d512e4838f..c87b1ebd6f 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperationTest.java @@ -27,8 +27,12 @@ import static org.ehcache.clustered.common.internal.store.operations.Operation.BYTE_SIZE_BYTES; import static org.ehcache.clustered.common.internal.store.operations.Operation.INT_SIZE_BYTES; import static org.ehcache.clustered.common.internal.store.operations.Operation.LONG_SIZE_BYTES; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; public class ConditionalReplaceOperationTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java index b734c4312f..e17bc673ef 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java @@ -34,11 +34,11 @@ import static java.time.Duration.ofMillis; import static java.util.Collections.emptyMap; import static org.ehcache.config.builders.ExpiryPolicyBuilder.timeToLiveExpiration; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.emptyIterable; import static org.hamcrest.Matchers.is; import static org.hamcrest.core.IsNull.nullValue; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/LazyValueHolderTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/LazyValueHolderTest.java index 00ae6f6122..d9d0a9f163 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/LazyValueHolderTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/LazyValueHolderTest.java @@ -25,8 +25,8 @@ import java.nio.ByteBuffer; import java.util.Date; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.sameInstance; -import static org.junit.Assert.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperationTest.java index 1b72b22d4f..80a990ade7 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperationTest.java @@ -26,12 +26,11 @@ import static org.ehcache.clustered.common.internal.store.operations.Operation.BYTE_SIZE_BYTES; import static org.ehcache.clustered.common.internal.store.operations.Operation.LONG_SIZE_BYTES; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsNull.nullValue; import static org.hamcrest.core.IsSame.sameInstance; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; public class TimestampOperationTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java index 83d76d712c..83baff2609 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java @@ -41,8 +41,8 @@ import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.config.builders.CacheConfigurationBuilder.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -import static org.junit.Assert.assertThat; public class BasicClusteredLoaderWriterTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java index e6f1ad7982..9175f25a83 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java @@ -41,9 +41,9 @@ import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; public class BasicClusteredWriteBehindPassthroughTest { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/util/StatisticsTestUtils.java b/clustered/client/src/test/java/org/ehcache/clustered/util/StatisticsTestUtils.java index e7cb278e0f..e17f9f66fb 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/util/StatisticsTestUtils.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/util/StatisticsTestUtils.java @@ -21,7 +21,6 @@ import org.hamcrest.Factory; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; -import org.junit.Assert; import org.terracotta.context.ContextManager; import org.terracotta.context.TreeNode; import org.terracotta.statistics.OperationStatistic; @@ -31,6 +30,8 @@ import java.util.EnumSet; import java.util.List; +import static org.hamcrest.MatcherAssert.assertThat; + /** * StatisticsTestUtils */ @@ -62,18 +63,18 @@ public static > void validateStats(final Store store, fi final OperationStatistic operationStatistic = getOperationStatistic(store, statsClass); for (final E statId : changed) { - Assert.assertThat(String.format("Value for %s.%s", statId.getDeclaringClass().getName(), statId.name()), + assertThat(String.format("Value for %s.%s", statId.getDeclaringClass().getName(), statId.name()), getStatistic(operationStatistic, statId), StatisticMatcher.equalTo(1L)); } for (final E statId : unchanged) { - Assert.assertThat(String.format("Value for %s.%s", statId.getDeclaringClass().getName(), statId.name()), + assertThat(String.format("Value for %s.%s", statId.getDeclaringClass().getName(), statId.name()), getStatistic(operationStatistic, statId), StatisticMatcher.equalTo(0L)); } } public static > void validateStat(final Store store, E outcome, long count) { OperationStatistic operationStatistic = getOperationStatistic(store, outcome.getDeclaringClass()); - Assert.assertThat(getStatistic(operationStatistic, outcome), StatisticMatcher.equalTo(count)); + assertThat(getStatistic(operationStatistic, outcome), StatisticMatcher.equalTo(count)); } /** diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java index 920ac6a627..cfad3d3a7e 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java @@ -19,7 +19,6 @@ import org.ehcache.clustered.common.internal.store.Util; import org.ehcache.clustered.common.internal.store.ValueWrapper; import org.hamcrest.Matchers; -import org.junit.Assert; import org.junit.Test; import java.io.ObjectStreamClass; @@ -29,6 +28,7 @@ import java.util.function.Predicate; import static org.ehcache.clustered.common.internal.messages.StateRepositoryOpCodec.WHITELIST_PREDICATE; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -52,7 +52,7 @@ public void unmarshallingNonWhitelistedClassTest() { private void unmarshallingCheck(T t, Predicate> isClassPermitted) { @SuppressWarnings("unchecked") T unmarshalled = (T) Util.unmarshall(ByteBuffer.wrap(Util.marshall(t)), isClassPermitted); - Assert.assertThat(unmarshalled, Matchers.is(t)); + assertThat(unmarshalled, Matchers.is(t)); } private void unmarshallingStateRepoMessagesCheck(T t) { diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/operations/OperationCodeTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/operations/OperationCodeTest.java index 2eebae5e70..d874005f94 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/operations/OperationCodeTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/operations/OperationCodeTest.java @@ -20,8 +20,8 @@ import java.util.Arrays; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.*; public class OperationCodeTest { diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/BaseClusteredEhcacheExceptionTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/BaseClusteredEhcacheExceptionTest.java index 8c5b68f8e1..408a265d5f 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/BaseClusteredEhcacheExceptionTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/BaseClusteredEhcacheExceptionTest.java @@ -22,12 +22,12 @@ import java.lang.reflect.Constructor; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.typeCompatibleWith; -import static org.junit.Assert.assertThat; /** * Foundation for tests on {@link ClusterException} subclasses. diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java index 99f5724e89..8021e729e5 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java @@ -28,7 +28,7 @@ import static org.ehcache.clustered.ChainUtils.sequencedChainOf; import static org.ehcache.clustered.Matchers.hasPayloads; import static org.ehcache.clustered.Matchers.sameSequenceAs; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; public class ChainCodecTest { diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodecTest.java index 677c98aa5e..5732cda349 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodecTest.java @@ -31,9 +31,9 @@ import java.util.Collections; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.SERVER_STORE_NAME_FIELD; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasKey; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.*; import static org.mockito.Mockito.mock; import static org.terracotta.runnel.EnumMappingBuilder.newEnumMappingBuilder; import static org.terracotta.runnel.StructBuilder.newStructBuilder; diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodecTest.java index f031e0a896..7c1e2a98bb 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodecTest.java @@ -26,9 +26,9 @@ import java.util.Collections; import static java.nio.ByteBuffer.wrap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * LifeCycleMessageCodecTest diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodecTest.java index 7c99c360be..26955fe38a 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodecTest.java @@ -22,10 +22,10 @@ import java.util.HashSet; import java.util.Set; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; public class ReconnectMessageCodecTest { diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java index 9da75e5bd6..f983e37faf 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java @@ -41,10 +41,10 @@ import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.prepareForDestroy; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.serverInvalidateHash; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.success; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; public class ResponseCodecTest { diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java index bf8854603d..2b25c1495f 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java @@ -26,8 +26,8 @@ import static org.ehcache.clustered.ChainUtils.readPayload; import static org.ehcache.clustered.ChainUtils.sequencedChainOf; import static org.ehcache.clustered.Matchers.hasPayloads; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; public class ServerStoreOpCodecTest { diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index b8b8276bdb..68d9e3207a 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -67,3 +67,12 @@ test { // testLogging.showStandardStreams = true } +configurations.all { + resolutionStrategy { + dependencySubstitution { + substitute(module('junit:junit:4.12')) + .because('CVE-2020-15250') + .with(module('junit:junit:4.13.1')) + } + } +} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index 8e673a2ccb..62aa35b1ab 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -45,9 +45,9 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.testing.StandardTimeouts.eventually; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; /** diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java index 19dd4439af..e5bfc5a8e9 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java @@ -42,12 +42,12 @@ import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.collection.IsIterableWithSize.iterableWithSize; -import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; public class BasicClusteredCacheOpsTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java index 133515ec44..1a446f7c27 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java @@ -46,9 +46,9 @@ import static java.util.Collections.emptyMap; import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.config.units.EntryUnit.ENTRIES; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java index 369727cef0..15056b0a16 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java @@ -53,8 +53,8 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManager; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java index f4a0b8643a..7e22bf2561 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java @@ -33,10 +33,10 @@ import org.terracotta.exception.EntityNotFoundException; import org.terracotta.testing.rules.Cluster; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.notNullValue; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java index 75cdfde622..03ad8d85a5 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java @@ -38,12 +38,12 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.collection.IsIn.isIn; import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsInstanceOf.any; import static org.hamcrest.core.IsNull.notNullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java index 15c9140f3e..1fff9ad9ef 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java @@ -50,9 +50,9 @@ import java.util.concurrent.atomic.AtomicInteger; import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; @RunWith(Parameterized.class) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java index 8e7ef4c528..e6e44313d1 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java @@ -41,7 +41,7 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; public class DestroyLoopTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index 5316b60bd1..c7554e84a9 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -60,13 +60,13 @@ import static org.ehcache.event.EventType.EXPIRED; import static org.ehcache.event.EventType.REMOVED; import static org.ehcache.event.EventType.UPDATED; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.either; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isOneOf; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; /* diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java index 5c018c8b1a..e2e05a6f68 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java @@ -46,11 +46,11 @@ import static java.util.stream.Collectors.toMap; import static java.util.stream.LongStream.range; import static org.ehcache.clustered.client.config.builders.TimeoutsBuilder.timeouts; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.either; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.core.IsNull.notNullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java index 102d53a1b2..be29ddd8f7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java @@ -41,8 +41,8 @@ import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.testing.StandardTimeouts.eventually; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java index 399e4f83fb..a1ad5c458e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java @@ -31,10 +31,10 @@ import java.util.Arrays; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; public class OversizedCacheOpsTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java index 427240e26b..e8ca590987 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -52,8 +52,8 @@ import static java.time.Duration.ofSeconds; import static org.ehcache.clustered.common.EhcacheEntityVersion.ENTITY_VERSION; import static org.ehcache.testing.StandardTimeouts.eventually; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java index 5b01130706..7cb99a9fb4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java @@ -33,9 +33,9 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.startsWith; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java index 0fbde0ca69..854ccaf030 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java @@ -34,8 +34,8 @@ import org.terracotta.connection.Connection; import org.terracotta.testing.rules.Cluster; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 96e1afecdb..8f277b768c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -61,7 +61,7 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.rules.RuleChain.outerRule; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java index 2c0037066c..c4b682ec1c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java @@ -36,8 +36,8 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; public class CMClosedEventSentTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java index 2c43116e23..9e59520677 100755 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteredStatisticsCountTest.java @@ -16,13 +16,13 @@ package org.ehcache.clustered.management; import org.ehcache.Cache; -import org.junit.Assert; import org.junit.Test; import org.terracotta.management.model.stats.ContextualStatistics; import java.util.List; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; public class ClusteredStatisticsCountTest extends AbstractClusteringManagementTest { @@ -80,10 +80,10 @@ public void countTest() throws Exception { (cacheMissCount != CACHE_MISS_COUNT) || (clusteredMissCount != CLUSTERED_MISS_COUNT))); - Assert.assertThat(cacheHitCount,is(CACHE_HIT_COUNT)); - Assert.assertThat(clusteredHitCount,is(CLUSTERED_HIT_COUNT)); - Assert.assertThat(cacheMissCount,is(CACHE_MISS_COUNT)); - Assert.assertThat(clusteredMissCount,is(CLUSTERED_MISS_COUNT)); + assertThat(cacheHitCount,is(CACHE_HIT_COUNT)); + assertThat(clusteredHitCount,is(CLUSTERED_HIT_COUNT)); + assertThat(cacheMissCount,is(CACHE_MISS_COUNT)); + assertThat(clusteredMissCount,is(CLUSTERED_MISS_COUNT)); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java index 356fcc0f65..5da65a69e6 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheManagerToStringTest.java @@ -36,9 +36,9 @@ import java.util.concurrent.TimeUnit; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; -import static org.junit.Assert.assertThat; public class EhcacheManagerToStringTest extends AbstractClusteringManagementTest { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index d4f01ed585..1e93df16d7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -27,7 +27,6 @@ import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; import org.hamcrest.Matchers; import org.junit.AfterClass; -import org.junit.Assert; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; @@ -51,7 +50,7 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; @@ -143,7 +142,7 @@ public void test_reconnection() throws Exception { .containsAll(Arrays.asList("webapp-1", "server-node-1"))) .count(); - Assert.assertThat(count, Matchers.equalTo(1L)); + assertThat(count, Matchers.equalTo(1L)); String instanceId = getInstanceId(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java index 8080911f67..2c5d6464a4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java @@ -43,10 +43,10 @@ import java.util.concurrent.TimeUnit; import static java.time.Duration.ofSeconds; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index b69c86c8fd..f2bcecfd42 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -53,9 +53,9 @@ import static java.time.Duration.ofSeconds; import static org.ehcache.testing.StandardTimeouts.eventually; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index 26a57e29ac..c686cc61da 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -64,10 +64,10 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java index 2a2e5792d3..5d2ebec90b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java @@ -49,10 +49,10 @@ import java.util.Map; import java.util.Set; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; @RunWith(ParallelParameterized.class) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java index ad6b72c90c..5240038ea3 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java @@ -54,10 +54,10 @@ import java.util.Set; import java.util.stream.LongStream; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; /** diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java index 6bd054bbc4..4c168fa527 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java @@ -39,9 +39,9 @@ import java.util.ArrayList; import java.util.List; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; public class BasicClusteredCacheOpsReplicationWithServersApiTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java index a61ea78543..b98f2adcb8 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java @@ -35,8 +35,8 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.ehcache.config.units.MemoryUnit.MB; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java index 0efb52e800..6e2081daa4 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java @@ -45,9 +45,9 @@ import static java.util.concurrent.TimeUnit.MINUTES; import static org.ehcache.testing.StandardTimeouts.eventually; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assume.assumeThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java index feba1e4e0d..af5ef41aee 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java @@ -36,9 +36,9 @@ import java.util.concurrent.atomic.AtomicBoolean; import static org.ehcache.testing.StandardTimeouts.eventually; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; public class PassiveSyncTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java index 87378678ad..c31652c89d 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java @@ -32,8 +32,8 @@ import java.util.Arrays; import java.util.concurrent.TimeUnit; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; public class BasicClusteredWriteBehindTest extends WriteBehindTestBase { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java index cb16fcd4f0..d6162fb412 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/WriteBehindTestBase.java @@ -41,8 +41,8 @@ import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; public class WriteBehindTestBase extends ClusteredTests { diff --git a/clustered/ops-tool/src/test/java/org/ehcache/clustered/operations/OperationsToolTest.java b/clustered/ops-tool/src/test/java/org/ehcache/clustered/operations/OperationsToolTest.java index cebd4ab66e..754d1e0612 100644 --- a/clustered/ops-tool/src/test/java/org/ehcache/clustered/operations/OperationsToolTest.java +++ b/clustered/ops-tool/src/test/java/org/ehcache/clustered/operations/OperationsToolTest.java @@ -16,8 +16,9 @@ package org.ehcache.clustered.operations; import java.io.IOException; + +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import org.junit.Test; public class OperationsToolTest { diff --git a/clustered/osgi-test/build.gradle b/clustered/osgi-test/build.gradle index 90fe431e38..8399d48536 100644 --- a/clustered/osgi-test/build.gradle +++ b/clustered/osgi-test/build.gradle @@ -67,6 +67,10 @@ configurations.all { substitute(module('org.ops4j.pax.url:pax-url-link:2.4.5')) .because('https://ops4j1.jira.com/browse/PAXURL-341') .with(module('org.ops4j.pax.url:pax-url-link:2.6.1')) + + substitute(module('junit:junit:4.12')) + .because('CVE-2020-15250') + .with(module('junit:junit:4.13.1')) } } } diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java index 84330f8f7d..8dcaa04fe4 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java @@ -63,9 +63,9 @@ import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; import static org.ehcache.osgi.OsgiTestUtils.startServer; import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsCollectionContaining.hasItems; -import static org.junit.Assert.assertThat; import static org.ops4j.pax.exam.CoreOptions.options; @RunWith(PaxExam.class) diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java index 3dd2518779..da9ed5beb1 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java @@ -32,8 +32,8 @@ import static org.ehcache.clustered.common.internal.lock.LockMessaging.HoldType.READ; import static org.ehcache.clustered.common.internal.lock.LockMessaging.HoldType.WRITE; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java index aa8f959f69..77632737f2 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java @@ -47,13 +47,13 @@ import java.util.Map; import java.util.Set; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java index 2353242754..e3eed2ed69 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java @@ -46,11 +46,11 @@ import java.util.Map; import java.util.Set; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java index 53fbdfd04a..19e81870e4 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java @@ -25,9 +25,9 @@ import org.ehcache.clustered.common.PoolAllocation.Unknown; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; /** diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java index 414125bd9a..ab5ab59a55 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java @@ -19,7 +19,7 @@ import org.ehcache.clustered.common.internal.messages.ResponseCodec; import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.server.TestClientSourceId; -import org.junit.Assert; +import org.hamcrest.MatcherAssert; import org.junit.Test; import java.util.HashMap; @@ -51,9 +51,9 @@ public void testDataSyncMessageEncodeDecode() throws Exception { EhcacheDataSyncMessage decoded = (EhcacheDataSyncMessage) codec.decode(0, encodedMessage); Map decodedChainMap = decoded.getChainMap(); assertThat(decodedChainMap).hasSize(3); - Assert.assertThat(decodedChainMap.get(1L), matchesChain(chain)); - Assert.assertThat(decodedChainMap.get(2L), matchesChain(chain)); - Assert.assertThat(decodedChainMap.get(3L), matchesChain(chain)); + MatcherAssert.assertThat(decodedChainMap.get(1L), matchesChain(chain)); + MatcherAssert.assertThat(decodedChainMap.get(2L), matchesChain(chain)); + MatcherAssert.assertThat(decodedChainMap.get(3L), matchesChain(chain)); } @Test diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java index 1e9cde4484..68054367ee 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java @@ -27,10 +27,9 @@ import static org.ehcache.clustered.ChainUtils.chainOf; import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.Matchers.matchesChain; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - public class PassiveReplicationMessageCodecTest { diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index 6bae4a1f30..d10a141ad6 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -85,6 +85,7 @@ import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.Matchers.hasPayloads; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; @@ -97,7 +98,6 @@ import static org.hamcrest.Matchers.sameInstance; import static org.hamcrest.core.CombinableMatcher.both; import static org.hamcrest.core.CombinableMatcher.either; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java index ee18650c0b..a01df038d3 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java @@ -55,11 +55,11 @@ import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.ChainUtils.sequencedChainOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java index ce4165126b..ea406743e2 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java @@ -26,9 +26,9 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; diff --git a/clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/ServerStateRepositoryTest.java b/clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/ServerStateRepositoryTest.java index c2201f369d..5e5e275bfd 100644 --- a/clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/ServerStateRepositoryTest.java +++ b/clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/ServerStateRepositoryTest.java @@ -25,10 +25,10 @@ import java.util.Map; import java.util.Set; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.*; public class ServerStateRepositoryTest { diff --git a/clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/StateRepositoryManagerTest.java b/clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/StateRepositoryManagerTest.java index b5decac5e6..9efda648a1 100644 --- a/clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/StateRepositoryManagerTest.java +++ b/clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/StateRepositoryManagerTest.java @@ -20,9 +20,9 @@ import org.ehcache.clustered.common.internal.messages.StateRepositoryOpMessage; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; public class StateRepositoryManagerTest { diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/EhcacheStateServiceImplTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/EhcacheStateServiceImplTest.java index 865f060072..b9507ea57a 100644 --- a/clustered/server/service/src/test/java/org/ehcache/clustered/server/EhcacheStateServiceImplTest.java +++ b/clustered/server/service/src/test/java/org/ehcache/clustered/server/EhcacheStateServiceImplTest.java @@ -19,10 +19,10 @@ import org.ehcache.clustered.common.internal.exceptions.DestroyInProgressException; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; public class EhcacheStateServiceImplTest { diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java index 560f786c4c..8a79bd0daf 100644 --- a/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java +++ b/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java @@ -41,9 +41,9 @@ import static java.util.Collections.emptyList; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.emptyIterable; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; -import static org.junit.Assert.assertThat; /** * Test extensibility of chain map storage engine, including binary engine capabilities. diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java index ce72756e33..d3f95b0770 100644 --- a/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java +++ b/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java @@ -45,12 +45,12 @@ import static java.util.Arrays.asList; import static org.ehcache.clustered.ChainUtils.chainOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.lessThan; import static org.hamcrest.collection.IsEmptyIterable.emptyIterable; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.terracotta.offheapstore.util.MemoryUnit.KILOBYTES; diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java index 0df77069e1..bc71b29b54 100644 --- a/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java +++ b/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java @@ -28,7 +28,6 @@ import org.ehcache.clustered.server.store.ElementBuilder; import org.ehcache.clustered.common.internal.store.ServerStore; import org.ehcache.clustered.server.store.ServerStoreTest; -import org.junit.Assert; import org.junit.Test; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -310,14 +309,14 @@ public void testServerSideUsageStats() { store.getAndAppend(i, smallValue.duplicate()); } - Assert.assertThat(store.getAllocatedMemory(),lessThanOrEqualTo(maxBytes)); - Assert.assertThat(store.getAllocatedMemory(),greaterThanOrEqualTo(smallLoopCount * oneKb)); - Assert.assertThat(store.getAllocatedMemory(),greaterThanOrEqualTo(store.getOccupiedMemory())); + assertThat(store.getAllocatedMemory(),lessThanOrEqualTo(maxBytes)); + assertThat(store.getAllocatedMemory(),greaterThanOrEqualTo(smallLoopCount * oneKb)); + assertThat(store.getAllocatedMemory(),greaterThanOrEqualTo(store.getOccupiedMemory())); //asserts above already guarantee that occupiedMemory <= maxBytes and that occupiedMemory <= allocatedMemory - Assert.assertThat(store.getOccupiedMemory(),greaterThanOrEqualTo(smallLoopCount * oneKb)); + assertThat(store.getOccupiedMemory(),greaterThanOrEqualTo(smallLoopCount * oneKb)); - Assert.assertThat(store.getSize(), is(smallLoopCount)); + assertThat(store.getSize(), is(smallLoopCount)); int multiplier = 100; long largeLoopCount = 5 + smallLoopCount; @@ -326,14 +325,14 @@ public void testServerSideUsageStats() { store.getAndAppend(i, largeValue.duplicate()); } - Assert.assertThat(store.getAllocatedMemory(),lessThanOrEqualTo(maxBytes)); - Assert.assertThat(store.getAllocatedMemory(),greaterThanOrEqualTo( (smallLoopCount * oneKb) + ( (largeLoopCount - smallLoopCount) * oneKb * multiplier) )); - Assert.assertThat(store.getAllocatedMemory(),greaterThanOrEqualTo(store.getOccupiedMemory())); + assertThat(store.getAllocatedMemory(),lessThanOrEqualTo(maxBytes)); + assertThat(store.getAllocatedMemory(),greaterThanOrEqualTo( (smallLoopCount * oneKb) + ( (largeLoopCount - smallLoopCount) * oneKb * multiplier) )); + assertThat(store.getAllocatedMemory(),greaterThanOrEqualTo(store.getOccupiedMemory())); //asserts above already guarantee that occupiedMemory <= maxBytes and that occupiedMemory <= allocatedMemory - Assert.assertThat(store.getOccupiedMemory(),greaterThanOrEqualTo(smallLoopCount * oneKb)); + assertThat(store.getOccupiedMemory(),greaterThanOrEqualTo(smallLoopCount * oneKb)); - Assert.assertThat(store.getSize(), is(smallLoopCount + (largeLoopCount - smallLoopCount))); + assertThat(store.getSize(), is(smallLoopCount + (largeLoopCount - smallLoopCount))); } diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java index 1b455ccbcb..39b699acf3 100644 --- a/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java +++ b/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java @@ -31,8 +31,8 @@ import static org.ehcache.clustered.common.internal.store.operations.OperationCode.REMOVE_CONDITIONAL; import static org.ehcache.clustered.common.internal.store.operations.OperationCode.REPLACE; import static org.ehcache.clustered.common.internal.store.operations.OperationCode.REPLACE_CONDITIONAL; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; public class PinningOffHeapChainMapTest { @Test diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/state/EhcacheStateServiceProviderTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/state/EhcacheStateServiceProviderTest.java index 00fd836a27..fc1e2881ad 100644 --- a/clustered/server/service/src/test/java/org/ehcache/clustered/server/state/EhcacheStateServiceProviderTest.java +++ b/clustered/server/service/src/test/java/org/ehcache/clustered/server/state/EhcacheStateServiceProviderTest.java @@ -36,12 +36,12 @@ import java.util.Collections; import static java.util.Collections.emptyMap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.sameInstance; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java index be1f6da111..20247cd95b 100644 --- a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java +++ b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java @@ -33,10 +33,10 @@ import static org.ehcache.clustered.ChainUtils.readPayload; import static org.ehcache.clustered.Matchers.hasPayloads; import static java.util.stream.LongStream.range; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsCollectionContaining.hasItem; import static org.hamcrest.core.IsCollectionContaining.hasItems; import static org.hamcrest.core.IsNot.not; -import static org.junit.Assert.assertThat; import static org.hamcrest.core.Is.is; import static org.junit.Assert.fail; diff --git a/config/checkstyle.xml b/config/checkstyle.xml index 326add3b8f..6a9374d111 100644 --- a/config/checkstyle.xml +++ b/config/checkstyle.xml @@ -38,7 +38,7 @@ - + diff --git a/config/owasp-supressions.xml b/config/owasp-supressions.xml index bfb162d6c3..19b18f49f3 100644 --- a/config/owasp-supressions.xml +++ b/config/owasp-supressions.xml @@ -24,4 +24,10 @@ ^pkg:maven/org\.terracotta/tc\-tripwire\-plugin@.*$ cpe:/a:tripwire:tripwire + + + Ehcache 3 builds require with Java 8+ : 4.13.1 is safe + pkg:maven/junit/junit@4.13.1 + CVE-2020-15250 + diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreExpiryEventListenerTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreExpiryEventListenerTest.java index c450f2e439..2e260e4dac 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreExpiryEventListenerTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreExpiryEventListenerTest.java @@ -32,8 +32,8 @@ import java.time.Duration; import static org.ehcache.internal.store.StoreCreationEventListenerTest.eventType; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.hamcrest.MockitoHamcrest.argThat; diff --git a/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierInvalidate.java b/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierInvalidate.java index e71f8550fa..1ef04603e4 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierInvalidate.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/tier/CachingTierInvalidate.java @@ -28,8 +28,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * CachingTierInvalidate diff --git a/core/src/test/java/org/ehcache/core/CacheTest.java b/core/src/test/java/org/ehcache/core/CacheTest.java index 0d48d911c2..fdca889473 100644 --- a/core/src/test/java/org/ehcache/core/CacheTest.java +++ b/core/src/test/java/org/ehcache/core/CacheTest.java @@ -33,7 +33,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicClearTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicClearTest.java index d2febd7903..8b8e3579b6 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicClearTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicClearTest.java @@ -26,8 +26,8 @@ import org.junit.Test; import org.slf4j.LoggerFactory; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.spy; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicContainsKeyTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicContainsKeyTest.java index 7cc107f1e7..75ec6225f4 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicContainsKeyTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicContainsKeyTest.java @@ -26,8 +26,8 @@ import org.junit.Test; import org.slf4j.LoggerFactory; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java b/core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java index 88f9731644..ab019d6d1b 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java @@ -59,7 +59,7 @@ import java.util.function.Function; import java.util.function.Supplier; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.ArgumentMatchers.any; /** diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java index aabc45a006..55df1a5c08 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java @@ -40,10 +40,10 @@ import static org.ehcache.core.EhcacheBasicBulkUtil.getEntryMap; import static org.ehcache.core.EhcacheBasicBulkUtil.getNullEntryMap; import static org.ehcache.core.EhcacheBasicBulkUtil.union; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicGetTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicGetTest.java index ba707db0bd..e7bbfde935 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicGetTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicGetTest.java @@ -28,7 +28,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicIteratorTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicIteratorTest.java index 627864f345..097ae95c6e 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicIteratorTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicIteratorTest.java @@ -32,11 +32,11 @@ import java.util.Map; import java.util.NoSuchElementException; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.hasEntry; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicPutAllTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicPutAllTest.java index e47b3daa14..c0f49692c3 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicPutAllTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicPutAllTest.java @@ -58,11 +58,11 @@ import static org.ehcache.core.EhcacheBasicBulkUtil.getAltEntryMap; import static org.ehcache.core.EhcacheBasicBulkUtil.getEntryMap; import static org.ehcache.core.EhcacheBasicBulkUtil.union; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.everyItem; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isIn; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java index d92c20d9e6..a22f3df49d 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java @@ -25,10 +25,10 @@ import org.junit.Test; import org.slf4j.LoggerFactory; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicPutTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicPutTest.java index 24142a3fdd..308f1f04e9 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicPutTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicPutTest.java @@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveAllTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveAllTest.java index e2d2b0fb35..687d6862d3 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveAllTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveAllTest.java @@ -53,11 +53,11 @@ import static org.ehcache.core.EhcacheBasicBulkUtil.copyWithout; import static org.ehcache.core.EhcacheBasicBulkUtil.fanIn; import static org.ehcache.core.EhcacheBasicBulkUtil.getEntryMap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.everyItem; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isIn; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveTest.java index a7fb480665..00fa591ada 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveTest.java @@ -26,7 +26,7 @@ import org.slf4j.LoggerFactory; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveValueTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveValueTest.java index 6bb50c2c30..ca5d172e8f 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveValueTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveValueTest.java @@ -27,8 +27,8 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicReplaceTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicReplaceTest.java index 1b8a61603e..f55a9482b7 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicReplaceTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicReplaceTest.java @@ -27,8 +27,8 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicReplaceValueTest.java b/core/src/test/java/org/ehcache/core/EhcacheBasicReplaceValueTest.java index 5fbc355b05..520d877310 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBasicReplaceValueTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBasicReplaceValueTest.java @@ -27,8 +27,8 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; diff --git a/core/src/test/java/org/ehcache/core/EhcacheBulkMethodsTest.java b/core/src/test/java/org/ehcache/core/EhcacheBulkMethodsTest.java index 493dde3052..2e55654ab4 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheBulkMethodsTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheBulkMethodsTest.java @@ -33,9 +33,9 @@ import java.util.concurrent.TimeUnit; import java.util.function.Function; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.core.IsCollectionContaining.hasItems; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; diff --git a/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java b/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java index 67fb3359b9..56c239ae83 100644 --- a/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java +++ b/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java @@ -48,9 +48,7 @@ import org.ehcache.spi.service.ServiceProvider; import org.hamcrest.CoreMatchers; import org.junit.Ignore; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.mockito.ArgumentMatchers; import org.mockito.Mockito; @@ -68,12 +66,14 @@ import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; @@ -90,9 +90,6 @@ @SuppressWarnings({ "unchecked", "rawtypes" }) public class EhcacheManagerTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - private static Map> newCacheMap() { return new HashMap<>(); } @@ -834,10 +831,8 @@ public void testDestroyCacheFailsIfAlreadyInMaintenanceMode() throws CachePersis thread.start(); thread.join(1000); - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("State is MAINTENANCE, yet you don't own it!"); - - manager.destroyCache("test"); + IllegalStateException thrown = assertThrows(IllegalStateException.class, () -> manager.destroyCache("test")); + assertThat(thrown, hasProperty("message", is("State is MAINTENANCE, yet you don't own it!"))); } @Test @@ -852,10 +847,8 @@ public void testDestroyCacheFailsAndStopIfStartingServicesFails() throws CachePe EhcacheManager manager = new EhcacheManager(config, services); - expectedException.expect(StateTransitionException.class); - expectedException.expectMessage("failed"); - - manager.destroyCache("test"); + StateTransitionException thrown = assertThrows(StateTransitionException.class, () -> manager.destroyCache("test")); + assertThat(thrown, hasProperty("message", is("failed"))); assertThat(manager.getStatus(), equalTo(Status.UNINITIALIZED)); } diff --git a/core/src/test/java/org/ehcache/core/StatusTransitionerTest.java b/core/src/test/java/org/ehcache/core/StatusTransitionerTest.java index 415c8c2d43..a58e6e9e71 100644 --- a/core/src/test/java/org/ehcache/core/StatusTransitionerTest.java +++ b/core/src/test/java/org/ehcache/core/StatusTransitionerTest.java @@ -31,8 +31,8 @@ import static java.util.Arrays.asList; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; diff --git a/core/src/test/java/org/ehcache/core/UserManagedCacheTest.java b/core/src/test/java/org/ehcache/core/UserManagedCacheTest.java index 3d792887f6..8bc98b97da 100644 --- a/core/src/test/java/org/ehcache/core/UserManagedCacheTest.java +++ b/core/src/test/java/org/ehcache/core/UserManagedCacheTest.java @@ -29,7 +29,7 @@ import org.slf4j.LoggerFactory; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; diff --git a/core/src/test/java/org/ehcache/core/collections/ConcurrentWeakIdentityHashMapTest.java b/core/src/test/java/org/ehcache/core/collections/ConcurrentWeakIdentityHashMapTest.java index 0b65f80240..0f8bd3c5bb 100644 --- a/core/src/test/java/org/ehcache/core/collections/ConcurrentWeakIdentityHashMapTest.java +++ b/core/src/test/java/org/ehcache/core/collections/ConcurrentWeakIdentityHashMapTest.java @@ -25,12 +25,12 @@ import java.util.Set; import java.util.concurrent.ConcurrentMap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; /** * @author Alex Snaps diff --git a/core/src/test/java/org/ehcache/core/config/CoreConfigurationBuilderTest.java b/core/src/test/java/org/ehcache/core/config/CoreConfigurationBuilderTest.java index 78e54d6596..92d3a9969f 100644 --- a/core/src/test/java/org/ehcache/core/config/CoreConfigurationBuilderTest.java +++ b/core/src/test/java/org/ehcache/core/config/CoreConfigurationBuilderTest.java @@ -19,8 +19,8 @@ import org.ehcache.core.util.ClassLoading; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; public class CoreConfigurationBuilderTest { diff --git a/core/src/test/java/org/ehcache/core/config/store/StoreStatisticsConfigurationTest.java b/core/src/test/java/org/ehcache/core/config/store/StoreStatisticsConfigurationTest.java index 5b95d8201a..cc3215e927 100644 --- a/core/src/test/java/org/ehcache/core/config/store/StoreStatisticsConfigurationTest.java +++ b/core/src/test/java/org/ehcache/core/config/store/StoreStatisticsConfigurationTest.java @@ -18,10 +18,10 @@ import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; public class StoreStatisticsConfigurationTest { diff --git a/core/src/test/java/org/ehcache/core/spi/ServiceLocatorPluralTest.java b/core/src/test/java/org/ehcache/core/spi/ServiceLocatorPluralTest.java index d6e4c0f937..11c14f3f95 100644 --- a/core/src/test/java/org/ehcache/core/spi/ServiceLocatorPluralTest.java +++ b/core/src/test/java/org/ehcache/core/spi/ServiceLocatorPluralTest.java @@ -27,11 +27,11 @@ import java.util.concurrent.atomic.AtomicReference; import static org.ehcache.core.spi.ServiceLocator.dependencySet; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.everyItem; import static org.hamcrest.Matchers.isOneOf; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; /** diff --git a/core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java b/core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java index 4be41d6098..6ff0384d7a 100644 --- a/core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java +++ b/core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java @@ -48,8 +48,8 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.sameInstance; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; diff --git a/core/src/test/java/org/ehcache/core/store/StoreSupportTest.java b/core/src/test/java/org/ehcache/core/store/StoreSupportTest.java index eb6eb4b48c..ec93741041 100644 --- a/core/src/test/java/org/ehcache/core/store/StoreSupportTest.java +++ b/core/src/test/java/org/ehcache/core/store/StoreSupportTest.java @@ -33,11 +33,12 @@ import static java.util.Arrays.asList; import static org.ehcache.core.spi.ServiceLocator.dependencySet; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.startsWith; -import static org.junit.Assert.*; +import static org.junit.Assert.fail; /** * Tests functionality of {@link StoreSupport} methods. diff --git a/core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java b/core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java index cf8a9216f8..2e762b1ba3 100644 --- a/core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java +++ b/core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java @@ -18,9 +18,12 @@ import static java.util.Collections.list; import static org.ehcache.core.util.ClassLoading.getDefaultClassLoader; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/gradle.properties b/gradle.properties index 0752f37f88..7422144cda 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,7 +17,7 @@ terracottaPassthroughTestingVersion = 1.7.0 terracottaUtilitiesVersion = 0.0.6 # Test lib versions -junitVersion = 4.12 +junitVersion = 4.13.1 assertjVersion = 3.9.0 hamcrestVersion = 1.3 mockitoVersion = 2.23.4 diff --git a/impl/src/slow-test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapITest.java b/impl/src/slow-test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapITest.java index 7932ba1919..84f8356cce 100644 --- a/impl/src/slow-test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapITest.java +++ b/impl/src/slow-test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapITest.java @@ -29,7 +29,7 @@ import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; /** * @author Ludovic Orban diff --git a/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java b/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java index 9b827e270a..0638e2c04a 100644 --- a/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java @@ -30,8 +30,8 @@ import org.ehcache.config.units.MemoryUnit; import org.terracotta.org.junit.rules.TemporaryFolder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; /** diff --git a/impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java b/impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java index 38ded14a0c..4eaa86f64b 100644 --- a/impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java +++ b/impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java @@ -49,9 +49,9 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; import static org.ehcache.test.MockitoUtil.mock; import static org.junit.Assert.fail; diff --git a/impl/src/test/java/org/ehcache/config/builders/CacheManagerBuilderTest.java b/impl/src/test/java/org/ehcache/config/builders/CacheManagerBuilderTest.java index bcdf46f2ab..86ef50c253 100644 --- a/impl/src/test/java/org/ehcache/config/builders/CacheManagerBuilderTest.java +++ b/impl/src/test/java/org/ehcache/config/builders/CacheManagerBuilderTest.java @@ -25,9 +25,7 @@ import org.ehcache.impl.serialization.CompactJavaSerializer; import org.ehcache.impl.serialization.JavaSerializer; import org.ehcache.spi.serialization.Serializer; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import java.util.concurrent.atomic.AtomicInteger; @@ -37,9 +35,6 @@ public class CacheManagerBuilderTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Test public void testIsExtensible() { diff --git a/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java b/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java index deba017529..917233b758 100644 --- a/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java +++ b/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java @@ -23,7 +23,6 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; @@ -33,9 +32,12 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.impl.internal.util.FileExistenceMatchers.containsCacheDirectory; import static org.ehcache.impl.internal.util.FileExistenceMatchers.isLocked; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.terracotta.utilities.io.Files.delete; @@ -46,9 +48,6 @@ public class PersistentCacheManagerTest { private static final String TEST_CACHE_ALIAS = "test123"; - @Rule - public ExpectedException thrown = ExpectedException.none(); - @Rule public final TemporaryFolder folder = new TemporaryFolder(); @@ -80,9 +79,8 @@ public void testInitializesLocalPersistenceServiceAndCreateCache() throws IOExce @Test public void testDestroyCache_NullAliasNotAllowed() throws CachePersistenceException { PersistentCacheManager manager = builder.build(true); - thrown.expect(NullPointerException.class); - thrown.expectMessage("Alias cannot be null"); - manager.destroyCache(null); + NullPointerException thrown = assertThrows(NullPointerException.class, () -> manager.destroyCache(null)); + assertThat(thrown, hasProperty("message", is("Alias cannot be null"))); } @Test diff --git a/impl/src/test/java/org/ehcache/config/builders/ResourcePoolsBuilderTest.java b/impl/src/test/java/org/ehcache/config/builders/ResourcePoolsBuilderTest.java index f87c8d76cc..522676ff9c 100644 --- a/impl/src/test/java/org/ehcache/config/builders/ResourcePoolsBuilderTest.java +++ b/impl/src/test/java/org/ehcache/config/builders/ResourcePoolsBuilderTest.java @@ -27,9 +27,10 @@ import static org.ehcache.config.ResourceType.Core.HEAP; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.*; +import static org.junit.Assert.fail; public class ResourcePoolsBuilderTest { diff --git a/impl/src/test/java/org/ehcache/config/builders/WriteBehindConfigurationBuilderTest.java b/impl/src/test/java/org/ehcache/config/builders/WriteBehindConfigurationBuilderTest.java index 632177f00d..b7f93b975c 100644 --- a/impl/src/test/java/org/ehcache/config/builders/WriteBehindConfigurationBuilderTest.java +++ b/impl/src/test/java/org/ehcache/config/builders/WriteBehindConfigurationBuilderTest.java @@ -19,9 +19,9 @@ import java.util.concurrent.TimeUnit; import static org.ehcache.config.builders.WriteBehindConfigurationBuilder.newBatchedWriteBehindConfiguration; import static org.ehcache.config.builders.WriteBehindConfigurationBuilder.newUnBatchedWriteBehindConfiguration; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.nullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import org.junit.Test; diff --git a/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerInteractionsTest.java b/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerInteractionsTest.java index bb67642410..6a51a5fe7c 100644 --- a/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerInteractionsTest.java +++ b/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerInteractionsTest.java @@ -27,8 +27,8 @@ import org.junit.Test; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNotNull; diff --git a/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java b/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java index c20957f381..e1f2017efc 100644 --- a/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java +++ b/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java @@ -26,7 +26,6 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.terracotta.org.junit.rules.TemporaryFolder; import static org.ehcache.config.units.MemoryUnit.MB; @@ -42,9 +41,6 @@ public class CacheManagerListenerTest { @Rule public TemporaryFolder folder = new TemporaryFolder(); - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Before public void before() { CacheConfigurationBuilder cacheConfiguration = diff --git a/impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java b/impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java index 5d8809d0f2..784b5132f4 100644 --- a/impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java +++ b/impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java @@ -29,7 +29,7 @@ import org.mockito.Answers; import static org.ehcache.core.spi.ServiceLocator.dependencySet; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; /** diff --git a/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java b/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java index 381ef9cc0c..1e74b8bcdd 100644 --- a/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java +++ b/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java @@ -43,7 +43,6 @@ import org.hamcrest.core.IsNot; import org.hamcrest.core.IsNull; import org.hamcrest.core.IsSame; -import org.junit.Assert; import org.junit.Test; import java.io.File; @@ -52,6 +51,8 @@ import java.time.Duration; import java.util.Date; +import static org.hamcrest.MatcherAssert.assertThat; + public class ConfigurationDerivation { @Test @@ -81,8 +82,8 @@ public void withCustomClassLoader() { .build(); // end::customClassLoader[] - Assert.assertThat(configuration.getClassLoader(), Is.is(IsSame.sameInstance(ClassLoading.getDefaultClassLoader()))); - Assert.assertThat(withClassLoader.getClassLoader(), Is.is(IsSame.sameInstance(classLoader))); + assertThat(configuration.getClassLoader(), Is.is(IsSame.sameInstance(ClassLoading.getDefaultClassLoader()))); + assertThat(withClassLoader.getClassLoader(), Is.is(IsSame.sameInstance(classLoader))); } @Test @@ -96,8 +97,8 @@ public void withCache() { .build(); //end::withCache[] - Assert.assertThat(configuration.getCacheConfigurations().keySet(), Is.is(IsEmptyCollection.empty())); - Assert.assertThat(withCache.getCacheConfigurations().keySet(), IsIterableContainingInAnyOrder.containsInAnyOrder("cache")); + assertThat(configuration.getCacheConfigurations().keySet(), Is.is(IsEmptyCollection.empty())); + assertThat(withCache.getCacheConfigurations().keySet(), IsIterableContainingInAnyOrder.containsInAnyOrder("cache")); } @Test @@ -112,8 +113,8 @@ public void withoutCache() { .build(); //end::withoutCache[] - Assert.assertThat(configuration.getCacheConfigurations().keySet(), IsIterableContainingInAnyOrder.containsInAnyOrder("cache")); - Assert.assertThat(withoutCache.getCacheConfigurations().keySet(), Is.is(IsEmptyCollection.empty())); + assertThat(configuration.getCacheConfigurations().keySet(), IsIterableContainingInAnyOrder.containsInAnyOrder("cache")); + assertThat(withoutCache.getCacheConfigurations().keySet(), Is.is(IsEmptyCollection.empty())); } @Test @@ -131,8 +132,8 @@ public void updateCache() { .build(); //end::updateCache[] - Assert.assertThat(configuration.getCacheConfigurations().get("cache").getResourcePools().getResourceTypeSet(), IsIterableContainingInAnyOrder.containsInAnyOrder(ResourceType.Core.HEAP)); - Assert.assertThat(withOffHeap.getCacheConfigurations().get("cache").getResourcePools().getResourceTypeSet(), IsIterableContainingInAnyOrder.containsInAnyOrder(ResourceType.Core.HEAP, ResourceType.Core.OFFHEAP)); + assertThat(configuration.getCacheConfigurations().get("cache").getResourcePools().getResourceTypeSet(), IsIterableContainingInAnyOrder.containsInAnyOrder(ResourceType.Core.HEAP)); + assertThat(withOffHeap.getCacheConfigurations().get("cache").getResourcePools().getResourceTypeSet(), IsIterableContainingInAnyOrder.containsInAnyOrder(ResourceType.Core.HEAP, ResourceType.Core.OFFHEAP)); } @Test @@ -148,13 +149,13 @@ public void withServiceCreation() { .build(); //end::withServiceCreation[] - Assert.assertThat(configuration.getServiceCreationConfigurations(), IsNot.not(IsCollectionContaining.hasItem(IsInstanceOf.instanceOf(PooledExecutionServiceConfiguration.class)))); + assertThat(configuration.getServiceCreationConfigurations(), IsNot.not(IsCollectionContaining.hasItem(IsInstanceOf.instanceOf(PooledExecutionServiceConfiguration.class)))); PooledExecutionServiceConfiguration serviceCreationConfiguration = ServiceUtils.findSingletonAmongst(PooledExecutionServiceConfiguration.class, withBoundedThreads.getServiceCreationConfigurations()); - Assert.assertThat(serviceCreationConfiguration.getDefaultPoolAlias(), Is.is("default")); - Assert.assertThat(serviceCreationConfiguration.getPoolConfigurations().keySet(), IsIterableContainingInAnyOrder.containsInAnyOrder("default")); + assertThat(serviceCreationConfiguration.getDefaultPoolAlias(), Is.is("default")); + assertThat(serviceCreationConfiguration.getPoolConfigurations().keySet(), IsIterableContainingInAnyOrder.containsInAnyOrder("default")); PooledExecutionServiceConfiguration.PoolConfiguration pool = serviceCreationConfiguration.getPoolConfigurations().get("default"); - Assert.assertThat(pool.minSize(), Is.is(1)); - Assert.assertThat(pool.maxSize(), Is.is(16)); + assertThat(pool.minSize(), Is.is(1)); + assertThat(pool.maxSize(), Is.is(16)); } @Test @@ -173,10 +174,10 @@ public void updateServiceCreation() { //end::updateServiceCreation[] DefaultPersistenceConfiguration initialPersistenceConfiguration = ServiceUtils.findSingletonAmongst(DefaultPersistenceConfiguration.class, configuration.getServiceCreationConfigurations()); - Assert.assertThat(initialPersistenceConfiguration.getRootDirectory(), Is.is(new File("temp"))); + assertThat(initialPersistenceConfiguration.getRootDirectory(), Is.is(new File("temp"))); DefaultPersistenceConfiguration revisedPersistenceConfiguration = ServiceUtils.findSingletonAmongst(DefaultPersistenceConfiguration.class, withUpdatedPersistence.getServiceCreationConfigurations()); - Assert.assertThat(revisedPersistenceConfiguration.getRootDirectory(), Is.is(new File("/var/persistence/path"))); + assertThat(revisedPersistenceConfiguration.getRootDirectory(), Is.is(new File("/var/persistence/path"))); } @Test @@ -194,13 +195,13 @@ public void withService() { //end::withService[] - Assert.assertThat(configuration.getServiceCreationConfigurations(), IsNot.not(IsCollectionContaining.hasItem( + assertThat(configuration.getServiceCreationConfigurations(), IsNot.not(IsCollectionContaining.hasItem( IsInstanceOf.instanceOf(DefaultResilienceStrategyConfiguration.class)))); DefaultResilienceStrategyConfiguration resilienceStrategyConfiguration = ServiceUtils.findSingletonAmongst(DefaultResilienceStrategyConfiguration.class, withThrowingStrategy.getCacheConfigurations().get("cache").getServiceConfigurations()); - Assert.assertThat(resilienceStrategyConfiguration.getInstance(), IsInstanceOf.instanceOf(ThrowingResilienceStrategy.class)); + assertThat(resilienceStrategyConfiguration.getInstance(), IsInstanceOf.instanceOf(ThrowingResilienceStrategy.class)); } public static final class OptimizedDateSerializer implements Serializer { diff --git a/impl/src/test/java/org/ehcache/docs/GettingStarted.java b/impl/src/test/java/org/ehcache/docs/GettingStarted.java index 4b97f7c127..0bb34c394e 100644 --- a/impl/src/test/java/org/ehcache/docs/GettingStarted.java +++ b/impl/src/test/java/org/ehcache/docs/GettingStarted.java @@ -50,9 +50,9 @@ import java.util.function.Supplier; import static java.util.Collections.singletonMap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * Samples to get started with Ehcache 3 diff --git a/impl/src/test/java/org/ehcache/docs/Tiering.java b/impl/src/test/java/org/ehcache/docs/Tiering.java index e647084165..8438a0936a 100644 --- a/impl/src/test/java/org/ehcache/docs/Tiering.java +++ b/impl/src/test/java/org/ehcache/docs/Tiering.java @@ -38,8 +38,8 @@ import org.junit.Test; import org.terracotta.org.junit.rules.TemporaryFolder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * Tiering diff --git a/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java b/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java index 02b73fa964..88502394d7 100644 --- a/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java +++ b/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java @@ -37,8 +37,8 @@ import java.io.IOException; import java.util.concurrent.Executors; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * UserManagedCaches diff --git a/impl/src/test/java/org/ehcache/impl/config/BaseCacheConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/BaseCacheConfigurationTest.java index a91cbbc7ba..f1d5ab30e7 100644 --- a/impl/src/test/java/org/ehcache/impl/config/BaseCacheConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/BaseCacheConfigurationTest.java @@ -17,10 +17,12 @@ package org.ehcache.impl.config; import org.ehcache.config.ResourcePools; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.mock; /** @@ -28,34 +30,27 @@ */ public class BaseCacheConfigurationTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Test public void testThrowsWithNullKeyType() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("keyType"); - - new BaseCacheConfiguration<>(null, String.class, null, - null, null, mock(ResourcePools.class)); + NullPointerException thrown = assertThrows(NullPointerException.class, () -> new BaseCacheConfiguration<>(null, String.class, null, + null, null, mock(ResourcePools.class))); + assertThat(thrown, hasProperty("message", startsWith("keyType"))); } @Test public void testThrowsWithNullValueType() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("valueType"); - - new BaseCacheConfiguration<>(Long.class, null, null, - null, null, mock(ResourcePools.class)); + NullPointerException thrown = assertThrows(NullPointerException.class, () -> + new BaseCacheConfiguration<>(Long.class, null, null, + null, null, mock(ResourcePools.class))); + assertThat(thrown, hasProperty("message", startsWith("valueType"))); } @Test public void testThrowsWithNullResourcePools() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("resourcePools"); - - new BaseCacheConfiguration<>(Long.class, String.class, null, - null, null, null); + NullPointerException thrown = assertThrows(NullPointerException.class, () -> + new BaseCacheConfiguration<>(Long.class, String.class, null, + null, null, null)); + assertThat(thrown, hasProperty("message", startsWith("resourcePools"))); } } diff --git a/impl/src/test/java/org/ehcache/impl/config/ResourcePoolsImplTest.java b/impl/src/test/java/org/ehcache/impl/config/ResourcePoolsImplTest.java index 0a0ad4f10a..d8a1793c6e 100644 --- a/impl/src/test/java/org/ehcache/impl/config/ResourcePoolsImplTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/ResourcePoolsImplTest.java @@ -37,8 +37,8 @@ import static org.ehcache.config.units.MemoryUnit.KB; import static org.ehcache.config.units.MemoryUnit.MB; import static org.ehcache.impl.config.ResourcePoolsImpl.validateResourcePools; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; /** diff --git a/impl/src/test/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfigurationTest.java index 2fa864af79..d8a31ad627 100644 --- a/impl/src/test/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfigurationTest.java @@ -19,10 +19,10 @@ import org.ehcache.impl.copy.IdentityCopier; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; public class DefaultCopyProviderConfigurationTest { diff --git a/impl/src/test/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfigurationTest.java index c4a4aa2608..3386e7d447 100644 --- a/impl/src/test/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfigurationTest.java @@ -18,10 +18,10 @@ import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; public class CacheEventDispatcherFactoryConfigurationTest { diff --git a/impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfigurationTest.java index 2b827a021c..71bec44e2b 100644 --- a/impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfigurationTest.java @@ -18,10 +18,10 @@ import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; public class DefaultCacheEventDispatcherConfigurationTest { diff --git a/impl/src/test/java/org/ehcache/impl/config/event/DefaultEventSourceConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/event/DefaultEventSourceConfigurationTest.java index 6aeb51982a..0774c54281 100644 --- a/impl/src/test/java/org/ehcache/impl/config/event/DefaultEventSourceConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/event/DefaultEventSourceConfigurationTest.java @@ -18,10 +18,10 @@ import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; public class DefaultEventSourceConfigurationTest { diff --git a/impl/src/test/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfigurationTest.java index 0ebf3c9f0b..a0a7396526 100644 --- a/impl/src/test/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfigurationTest.java @@ -18,10 +18,10 @@ import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; public class PooledExecutionServiceConfigurationTest { diff --git a/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfigurationTest.java index 39ac3e68db..02b0641b88 100644 --- a/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfigurationTest.java @@ -20,10 +20,10 @@ import org.junit.Test; import static org.ehcache.test.MockitoUtil.mock; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; public class DefaultCacheLoaderWriterConfigurationTest { diff --git a/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfigurationTest.java index 0f6c2e4d69..a55d57444d 100644 --- a/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfigurationTest.java @@ -20,10 +20,10 @@ import org.junit.Test; import static org.ehcache.test.MockitoUtil.mock; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; public class DefaultCacheLoaderWriterProviderConfigurationTest { diff --git a/impl/src/test/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfigurationTest.java index 3acf766d2b..df541d270d 100644 --- a/impl/src/test/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfigurationTest.java @@ -18,10 +18,10 @@ import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; public class WriteBehindProviderConfigurationTest { diff --git a/impl/src/test/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfigurationTest.java index 1ac0882491..83a4fc3787 100644 --- a/impl/src/test/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfigurationTest.java @@ -20,10 +20,10 @@ import java.io.File; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; public class DefaultPersistenceConfigurationTest { diff --git a/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java index 65d2969c5f..044e8b7f09 100644 --- a/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java @@ -22,12 +22,12 @@ import org.junit.Test; import static org.ehcache.test.MockitoUtil.mock; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.collection.IsArrayContainingInOrder.arrayContaining; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsNull.nullValue; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; public class DefaultResilienceStrategyConfigurationTest { diff --git a/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfigurationTest.java index ddefe0f673..e1950302f1 100644 --- a/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfigurationTest.java @@ -20,10 +20,10 @@ import org.junit.Test; import static org.ehcache.test.MockitoUtil.mock; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; public class DefaultResilienceStrategyProviderConfigurationTest { diff --git a/impl/src/test/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfigurationTest.java index 523f98ca2f..cb26efaf69 100644 --- a/impl/src/test/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfigurationTest.java @@ -22,22 +22,22 @@ import org.ehcache.spi.serialization.Serializer; import org.ehcache.core.spi.service.FileBasedPersistenceContext; import org.ehcache.spi.serialization.StatefulSerializer; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import java.nio.ByteBuffer; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.*; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThrows; public class DefaultSerializationProviderConfigurationTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Test public void testAddSerializerFor() throws Exception { DefaultSerializationProviderConfiguration config = new DefaultSerializationProviderConfiguration(); @@ -50,17 +50,15 @@ public void testAddSerializerFor() throws Exception { public void testAddSerializerForDuplicateThrows() throws Exception { DefaultSerializationProviderConfiguration config = new DefaultSerializationProviderConfiguration(); config.addSerializerFor(Long.class, MinimalSerializer.class); - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Duplicate serializer for class"); - config.addSerializerFor(Long.class, MinimalSerializer.class); + IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> config.addSerializerFor(Long.class, MinimalSerializer.class)); + assertThat(thrown, hasProperty("message", startsWith("Duplicate serializer for class"))); } @Test public void testAddSerializerForConstructorless() throws Exception { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("does not have a constructor that takes in a ClassLoader."); DefaultSerializationProviderConfiguration config = new DefaultSerializationProviderConfiguration(); - config.addSerializerFor(Long.class, UnusableSerializer.class); + IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> config.addSerializerFor(Long.class, UnusableSerializer.class)); + assertThat(thrown, hasProperty("message", endsWith("does not have a constructor that takes in a ClassLoader."))); } @Test @@ -72,18 +70,16 @@ public void testAddSerializerForStatefulSerializer() throws Exception { @Test public void testAddSerializerForStatefulConstructorless() throws Exception { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("does not have a constructor that takes in a ClassLoader."); DefaultSerializationProviderConfiguration config = new DefaultSerializationProviderConfiguration(); - config.addSerializerFor(Long.class, UnusableStatefulSerializer.class); + IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> config.addSerializerFor(Long.class, UnusableStatefulSerializer.class)); + assertThat(thrown, hasProperty("message", endsWith("does not have a constructor that takes in a ClassLoader."))); } @Test public void testAddSerializerForLegacySerializer() throws Exception { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("does not have a constructor that takes in a ClassLoader."); DefaultSerializationProviderConfiguration config = new DefaultSerializationProviderConfiguration(); - config.addSerializerFor(Long.class, LegacySerializer.class); + IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> config.addSerializerFor(Long.class, LegacySerializer.class)); + assertThat(thrown, hasProperty("message", endsWith("does not have a constructor that takes in a ClassLoader."))); } @Test @SuppressWarnings("unchecked") diff --git a/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java b/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java index 6a436f3bbe..e0613188f2 100644 --- a/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java @@ -42,8 +42,8 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * SerializerCountingTest diff --git a/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfigurationTest.java index 903a45a4a3..c22d4c6132 100644 --- a/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfigurationTest.java @@ -18,10 +18,10 @@ import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; public class OffHeapDiskStoreConfigurationTest { diff --git a/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfigurationTest.java index af0ac2fffb..aca89ecc60 100644 --- a/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfigurationTest.java @@ -18,10 +18,10 @@ import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; public class OffHeapDiskStoreProviderConfigurationTest { diff --git a/impl/src/test/java/org/ehcache/impl/internal/DefaultTimeSourceServiceTest.java b/impl/src/test/java/org/ehcache/impl/internal/DefaultTimeSourceServiceTest.java index d6a1d2f579..e22c643ef0 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/DefaultTimeSourceServiceTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/DefaultTimeSourceServiceTest.java @@ -24,7 +24,7 @@ import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.hamcrest.CoreMatchers.sameInstance; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; /** diff --git a/impl/src/test/java/org/ehcache/impl/internal/TimeSourceConfigurationTest.java b/impl/src/test/java/org/ehcache/impl/internal/TimeSourceConfigurationTest.java index 8f71faa7a6..eec92b7ac9 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/TimeSourceConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/TimeSourceConfigurationTest.java @@ -19,10 +19,10 @@ import org.ehcache.core.spi.time.TimeSource; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; public class TimeSourceConfigurationTest { diff --git a/impl/src/test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapTest.java b/impl/src/test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapTest.java index ff3bdb1180..d5c93b27b4 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapTest.java @@ -25,10 +25,10 @@ import static org.ehcache.config.Eviction.noAdvice; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsNull.notNullValue; import static org.hamcrest.core.IsNull.nullValue; import static org.hamcrest.number.OrderingComparison.greaterThan; -import static org.junit.Assert.assertThat; /** * @author Alex Snaps diff --git a/impl/src/test/java/org/ehcache/impl/internal/concurrent/otherPackage/V8FeaturesTest.java b/impl/src/test/java/org/ehcache/impl/internal/concurrent/otherPackage/V8FeaturesTest.java index be4efb1f09..167e0b3189 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/concurrent/otherPackage/V8FeaturesTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/concurrent/otherPackage/V8FeaturesTest.java @@ -25,10 +25,10 @@ import java.util.concurrent.atomic.AtomicInteger; import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; /** * @author Ludovic Orban diff --git a/impl/src/test/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImplTest.java b/impl/src/test/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImplTest.java index 879cc86633..ee7193de05 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImplTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImplTest.java @@ -28,8 +28,8 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; diff --git a/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedOrderedExecutorTest.java b/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedOrderedExecutorTest.java index 91005b0c87..2e93bafd50 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedOrderedExecutorTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedOrderedExecutorTest.java @@ -33,10 +33,11 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MINUTES; import java.util.concurrent.atomic.AtomicInteger; + +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.hamcrest.collection.IsEmptyCollection.empty; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; diff --git a/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedScheduledExecutorTest.java b/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedScheduledExecutorTest.java index a736abddc0..fed0fc7cab 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedScheduledExecutorTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedScheduledExecutorTest.java @@ -35,10 +35,10 @@ import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.SECONDS; import static org.ehcache.impl.internal.executor.ExecutorUtil.waitFor; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.hamcrest.collection.IsEmptyCollection.empty; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; public class PartitionedScheduledExecutorTest { diff --git a/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedUnorderedExecutorTest.java b/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedUnorderedExecutorTest.java index a1d15ad348..1f787f0684 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedUnorderedExecutorTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedUnorderedExecutorTest.java @@ -29,10 +29,10 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MINUTES; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.hamcrest.collection.IsEmptyCollection.empty; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; diff --git a/impl/src/test/java/org/ehcache/impl/internal/executor/PooledExecutionServiceTest.java b/impl/src/test/java/org/ehcache/impl/internal/executor/PooledExecutionServiceTest.java index 3c18d4758f..8d5dc1f00f 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/executor/PooledExecutionServiceTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/executor/PooledExecutionServiceTest.java @@ -18,9 +18,7 @@ import org.ehcache.impl.config.executor.PooledExecutionServiceConfiguration; import org.ehcache.impl.internal.util.ThreadFactoryUtil; import org.junit.After; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import java.io.PrintWriter; import java.io.StringWriter; @@ -28,101 +26,95 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; /** * @author Ludovic Orban */ public class PooledExecutionServiceTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - PooledExecutionService pooledExecutionService; - - @After - public void after() { - if(pooledExecutionService != null) { - pooledExecutionService.stop(); - } - } - @Test public void testEmptyConfigThrowsAtStart() throws Exception { PooledExecutionServiceConfiguration configuration = new PooledExecutionServiceConfiguration(); - pooledExecutionService = new PooledExecutionService(configuration); - - expectedException.expectMessage("Pool configuration is empty"); - pooledExecutionService.start(null); + PooledExecutionService pooledExecutionService = new PooledExecutionService(configuration); + assertThatThrownBy(() -> pooledExecutionService.start(null)) + .isInstanceOf(IllegalStateException.class).hasMessage("Pool configuration is empty"); } @Test public void testGetOrderedExecutorFailsOnNonExistentPool() throws Exception { PooledExecutionServiceConfiguration configuration = new PooledExecutionServiceConfiguration(); configuration.addPool("getOrderedExecutorFailsOnNonExistentPool", 0, 1); - pooledExecutionService = new PooledExecutionService(configuration); - + PooledExecutionService pooledExecutionService = new PooledExecutionService(configuration); pooledExecutionService.start(null); - - expectedException.expectMessage("Pool 'abc' is not in the set of available pools [getOrderedExecutorFailsOnNonExistentPool]"); - pooledExecutionService.getOrderedExecutor("abc", new LinkedBlockingDeque<>()); + try { + assertThatThrownBy(() -> pooledExecutionService.getOrderedExecutor("abc", new LinkedBlockingDeque<>())) + .isInstanceOf(IllegalArgumentException.class).hasMessage("Pool 'abc' is not in the set of available pools [getOrderedExecutorFailsOnNonExistentPool]"); + } finally { + pooledExecutionService.stop(); + } } @Test public void testGetOrderedExecutorFailsOnNonExistentDefaultPool() throws Exception { PooledExecutionServiceConfiguration configuration = new PooledExecutionServiceConfiguration(); configuration.addPool("getOrderedExecutorFailsOnNonExistentDefaultPool", 0, 1); - pooledExecutionService = new PooledExecutionService(configuration); - + PooledExecutionService pooledExecutionService = new PooledExecutionService(configuration); pooledExecutionService.start(null); - - expectedException.expectMessage("Null pool alias provided and no default pool configured"); - pooledExecutionService.getOrderedExecutor(null, new LinkedBlockingDeque<>()); + try { + assertThatThrownBy(() -> pooledExecutionService.getOrderedExecutor(null, new LinkedBlockingDeque<>())) + .isInstanceOf(IllegalArgumentException.class).hasMessage("Null pool alias provided and no default pool configured"); + } finally { + pooledExecutionService.stop(); + } } @Test public void testGetOrderedExecutorSucceedsOnExistingPool() throws Exception { PooledExecutionServiceConfiguration configuration = new PooledExecutionServiceConfiguration(); configuration.addPool("getOrderedExecutorSucceedsOnExistingPool", 0, 1); - pooledExecutionService = new PooledExecutionService(configuration); - + PooledExecutionService pooledExecutionService = new PooledExecutionService(configuration); pooledExecutionService.start(null); - - ExecutorService aaa = pooledExecutionService.getOrderedExecutor("getOrderedExecutorSucceedsOnExistingPool", new LinkedBlockingDeque<>()); - aaa.shutdown(); + try { + pooledExecutionService.getOrderedExecutor("getOrderedExecutorSucceedsOnExistingPool", new LinkedBlockingDeque<>()).shutdown(); + } finally { + pooledExecutionService.stop(); + } } @Test public void testGetOrderedExecutorSucceedsOnExistingDefaultPool() throws Exception { PooledExecutionServiceConfiguration configuration = new PooledExecutionServiceConfiguration(); configuration.addDefaultPool("getOrderedExecutorSucceedsOnExistingDefaultPool", 0, 1); - pooledExecutionService = new PooledExecutionService(configuration); - + PooledExecutionService pooledExecutionService = new PooledExecutionService(configuration); pooledExecutionService.start(null); - - ExecutorService dflt = pooledExecutionService.getOrderedExecutor(null, new LinkedBlockingDeque<>()); - dflt.shutdown(); + try { + pooledExecutionService.getOrderedExecutor(null, new LinkedBlockingDeque<>()).shutdown(); + } finally { + pooledExecutionService.stop(); + } } @Test public void testAllThreadsAreStopped() throws Exception { PooledExecutionServiceConfiguration configuration = new PooledExecutionServiceConfiguration(); configuration.addDefaultPool("allThreadsAreStopped", 0, 1); - pooledExecutionService = new PooledExecutionService(configuration); + PooledExecutionService pooledExecutionService = new PooledExecutionService(configuration); pooledExecutionService.start(null); + try { + final CountDownLatch latch = new CountDownLatch(1); - final CountDownLatch latch = new CountDownLatch(1); - - pooledExecutionService.getScheduledExecutor("allThreadsAreStopped") - .execute(latch::countDown); + pooledExecutionService.getScheduledExecutor("allThreadsAreStopped") + .execute(latch::countDown); - assertThat(latch.await(30, TimeUnit.SECONDS)).isTrue(); - - pooledExecutionService.stop(); + assertThat(latch.await(30, TimeUnit.SECONDS)).isTrue(); + } finally { + pooledExecutionService.stop(); + } assertThat(Thread.currentThread().isInterrupted()).isFalse(); diff --git a/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehindTestBase.java b/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehindTestBase.java index 649e38b655..b7d4096761 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehindTestBase.java +++ b/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehindTestBase.java @@ -43,10 +43,10 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.ehcache.config.builders.WriteBehindConfigurationBuilder.newBatchedWriteBehindConfiguration; import static org.ehcache.config.builders.WriteBehindConfigurationBuilder.newUnBatchedWriteBehindConfiguration; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; diff --git a/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactoryTest.java b/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactoryTest.java index aedfb3b3b4..e60ff8b3fa 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactoryTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactoryTest.java @@ -26,26 +26,24 @@ import org.ehcache.spi.loaderwriter.WriteBehindConfiguration; import org.ehcache.spi.service.ServiceConfiguration; import org.hamcrest.core.IsCollectionContaining; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import java.util.Collection; import java.util.Map; import static java.util.concurrent.TimeUnit.SECONDS; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.is; import static org.hamcrest.core.IsInstanceOf.instanceOf; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertThrows; /** * @author rism */ public class WriteBehindProviderFactoryTest { - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - @SuppressWarnings("unchecked") @Test public void testAddingWriteBehindConfigurationAtCacheLevel() { @@ -69,11 +67,9 @@ public void testAddingWriteBehindConfigurationAtCacheLevel() { @Test public void testWriteBehindWithoutCacheLoaderWriter() { - expectedEx.expect(NullPointerException.class); - expectedEx.expectMessage("WriteBehind requires a non null CacheLoaderWriter"); - WriteBehindProviderFactory factory = new WriteBehindProviderFactory(); - factory.create(null).createWriteBehindLoaderWriter(null, null); + NullPointerException thrown = assertThrows(NullPointerException.class, () -> factory.create(null).createWriteBehindLoaderWriter(null, null)); + assertThat(thrown, hasProperty("message", is("WriteBehind requires a non null CacheLoaderWriter."))); } public static class SampleLoaderWriter implements CacheLoaderWriter { diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderTest.java index a7e5dfc595..4784034d91 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderTest.java @@ -27,10 +27,10 @@ import java.io.Closeable; import java.io.IOException; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.sameInstance; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; /** diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderTest.java index 73426d0d0b..c028c8bccb 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderTest.java @@ -36,8 +36,8 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsInstanceOf.instanceOf; -import static org.junit.Assert.assertThat; /** * @author rism diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderTest.java index 0af0a4bee4..b1054404d9 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderTest.java @@ -38,8 +38,8 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsInstanceOf.instanceOf; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; public class DefaultCacheLoaderWriterProviderTest { diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactoryTest.java b/impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactoryTest.java index fc873a6689..cd6c9d118d 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactoryTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactoryTest.java @@ -24,9 +24,10 @@ import org.junit.Test; import static org.ehcache.test.MockitoUtil.mock; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsNull.notNullValue; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.*; +import static org.junit.Assert.fail; public class DefaultResilienceStrategyProviderFactoryTest { diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderTest.java index 4c27ba13ea..ec62ea981a 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderTest.java @@ -27,10 +27,10 @@ import java.util.Collections; import static org.ehcache.test.MockitoUtil.mock; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.when; public class DefaultResilienceStrategyProviderTest { diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java index ebedffeb8a..aeee5e3b7b 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java @@ -39,7 +39,6 @@ import org.hamcrest.Matchers; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.Closeable; @@ -53,9 +52,12 @@ import static org.ehcache.impl.internal.spi.TestServiceProvider.providerContaining; import static org.ehcache.test.MockitoUtil.mock; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; @@ -70,9 +72,6 @@ public class DefaultSerializationProviderTest { @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Test public void testCreateSerializerNoConfig() throws Exception { DefaultSerializationProviderConfiguration dspfConfig = new DefaultSerializationProviderConfiguration(); @@ -308,54 +307,50 @@ public void testDefaultByteArraySerializer() throws Exception { @Test public void testCreateTransientSerializerWithoutConstructor() throws Exception { - expectedException.expect(RuntimeException.class); - expectedException.expectMessage("does not have a constructor that takes in a ClassLoader."); DefaultSerializationProvider provider = new DefaultSerializationProvider(null); provider.start(providerContaining()); @SuppressWarnings("unchecked") Class> serializerClass = (Class) BaseSerializer.class; DefaultSerializerConfiguration configuration = new DefaultSerializerConfiguration<>(serializerClass, DefaultSerializerConfiguration.Type.VALUE); - provider.createValueSerializer(Object.class, ClassLoader.getSystemClassLoader(), configuration); + RuntimeException thrown = assertThrows(RuntimeException.class, () -> provider.createValueSerializer(Object.class, getSystemClassLoader(), configuration)); + assertThat(thrown, hasProperty("message", endsWith("does not have a constructor that takes in a ClassLoader."))); } @Test public void testCreatePersistentSerializerWithoutConstructor() throws Exception { - expectedException.expect(RuntimeException.class); - expectedException.expectMessage("does not have a constructor that takes in a ClassLoader."); DefaultSerializationProvider provider = new DefaultSerializationProvider(null); provider.start(providerContaining()); @SuppressWarnings("unchecked") Class> serializerClass = (Class) BaseSerializer.class; DefaultSerializerConfiguration configuration = new DefaultSerializerConfiguration<>(serializerClass, DefaultSerializerConfiguration.Type.VALUE); - provider.createValueSerializer(Object.class, ClassLoader.getSystemClassLoader(), configuration, getPersistenceSpaceIdentifierMock()); + RuntimeException thrown = assertThrows(RuntimeException.class, () -> provider.createValueSerializer(Object.class, getSystemClassLoader(), configuration, getPersistenceSpaceIdentifierMock())); + assertThat(thrown, hasProperty("message", endsWith("does not have a constructor that takes in a ClassLoader."))); } @Test public void testCreateTransientStatefulSerializerWithoutConstructor() throws Exception { - expectedException.expect(RuntimeException.class); - expectedException.expectMessage("does not have a constructor that takes in a ClassLoader."); DefaultSerializationProvider provider = new DefaultSerializationProvider(null); provider.start(providerContaining()); @SuppressWarnings("unchecked") Class> serializerClass = (Class) StatefulBaseSerializer.class; DefaultSerializerConfiguration configuration = new DefaultSerializerConfiguration<>(serializerClass, DefaultSerializerConfiguration.Type.VALUE); - provider.createValueSerializer(Object.class, ClassLoader.getSystemClassLoader(), configuration); + RuntimeException thrown = assertThrows(RuntimeException.class, () -> provider.createValueSerializer(Object.class, getSystemClassLoader(), configuration)); + assertThat(thrown, hasProperty("message", endsWith("does not have a constructor that takes in a ClassLoader."))); } @Test public void testCreatePersistentStatefulSerializerWithoutConstructor() throws Exception { - expectedException.expect(RuntimeException.class); - expectedException.expectMessage("does not have a constructor that takes in a ClassLoader."); DefaultSerializationProvider provider = new DefaultSerializationProvider(null); provider.start(providerContaining()); @SuppressWarnings("unchecked") Class> serializerClass = (Class) StatefulBaseSerializer.class; DefaultSerializerConfiguration configuration = new DefaultSerializerConfiguration<>(serializerClass, DefaultSerializerConfiguration.Type.VALUE); - provider.createValueSerializer(Object.class, ClassLoader.getSystemClassLoader(), configuration, getPersistenceSpaceIdentifierMock()); + RuntimeException thrown = assertThrows(RuntimeException.class, () -> provider.createValueSerializer(Object.class, getSystemClassLoader(), configuration, getPersistenceSpaceIdentifierMock())); + assertThat(thrown, hasProperty("message", endsWith("does not have a constructor that takes in a ClassLoader."))); } @Test @@ -420,15 +415,14 @@ public void testPersistentMinimalStatefulSerializer() throws Exception { @Test public void testTransientLegacySerializer() throws Exception { - expectedException.expect(RuntimeException.class); - expectedException.expectMessage("does not have a constructor that takes in a ClassLoader."); DefaultSerializationProvider provider = new DefaultSerializationProvider(null); provider.start(providerContaining()); @SuppressWarnings("unchecked") Class> serializerClass = (Class) LegacySerializer.class; DefaultSerializerConfiguration configuration = new DefaultSerializerConfiguration<>(serializerClass, DefaultSerializerConfiguration.Type.VALUE); - provider.createValueSerializer(Object.class, ClassLoader.getSystemClassLoader(), configuration); + RuntimeException thrown = assertThrows(RuntimeException.class, () -> provider.createValueSerializer(Object.class, getSystemClassLoader(), configuration)); + assertThat(thrown, hasProperty("message", endsWith("does not have a constructor that takes in a ClassLoader."))); } @Test @@ -439,12 +433,8 @@ public void testPersistentLegacySerializer() throws Exception { @SuppressWarnings("unchecked") Class> serializerClass = (Class) LegacySerializer.class; DefaultSerializerConfiguration configuration = new DefaultSerializerConfiguration<>(serializerClass, DefaultSerializerConfiguration.Type.VALUE); - expectedException.expect(RuntimeException.class); - expectedException.expectMessage("does not have a constructor that takes in a ClassLoader."); - Serializer valueSerializer = - provider.createValueSerializer(Object.class, ClassLoader.getSystemClassLoader(), configuration, getPersistenceSpaceIdentifierMock()); - assertThat(valueSerializer, instanceOf(LegacySerializer.class)); - assertThat(LegacySerializer.legacyConstructorInvoked, is(true)); + RuntimeException thrown = assertThrows(RuntimeException.class, () -> provider.createValueSerializer(Object.class, getSystemClassLoader(), configuration, getPersistenceSpaceIdentifierMock())); + assertThat(thrown, hasProperty("message", endsWith("does not have a constructor that takes in a ClassLoader."))); } @Test @@ -482,28 +472,26 @@ public void testPersistentLegacyComboSerializer() throws Exception { @Test public void testCreateTransientStatefulLegacySerializer() throws Exception { - expectedException.expect(RuntimeException.class); - expectedException.expectMessage("does not have a constructor that takes in a ClassLoader."); DefaultSerializationProvider provider = new DefaultSerializationProvider(null); provider.start(providerContaining()); @SuppressWarnings("unchecked") Class> serializerClass = (Class) StatefulLegacySerializer.class; DefaultSerializerConfiguration configuration = new DefaultSerializerConfiguration<>(serializerClass, DefaultSerializerConfiguration.Type.VALUE); - provider.createValueSerializer(Object.class, ClassLoader.getSystemClassLoader(), configuration); + RuntimeException thrown = assertThrows(RuntimeException.class, () -> provider.createValueSerializer(Object.class, getSystemClassLoader(), configuration)); + assertThat(thrown, hasProperty("message", endsWith("does not have a constructor that takes in a ClassLoader."))); } @Test public void testCreatePersistentStatefulLegacySerializer() throws Exception { - expectedException.expect(RuntimeException.class); - expectedException.expectMessage("does not have a constructor that takes in a ClassLoader."); DefaultSerializationProvider provider = new DefaultSerializationProvider(null); provider.start(providerContaining()); @SuppressWarnings("unchecked") Class> serializerClass = (Class) StatefulLegacySerializer.class; DefaultSerializerConfiguration configuration = new DefaultSerializerConfiguration<>(serializerClass, DefaultSerializerConfiguration.Type.VALUE); - provider.createValueSerializer(Object.class, ClassLoader.getSystemClassLoader(), configuration, getPersistenceSpaceIdentifierMock()); + RuntimeException thrown = assertThrows(RuntimeException.class, () -> provider.createValueSerializer(Object.class, getSystemClassLoader(), configuration, getPersistenceSpaceIdentifierMock())); + assertThat(thrown, hasProperty("message", endsWith("does not have a constructor that takes in a ClassLoader."))); } @Test diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java index 2e5f8c4005..cca3470c3d 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java @@ -25,20 +25,16 @@ import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.spi.test.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import static org.assertj.core.api.Assertions.assertThat; import static org.ehcache.config.units.MemoryUnit.MB; +import static org.junit.Assert.assertThrows; public class DefaultStatisticsServiceTest { private static final String CACHE = "myCache"; - @Rule - public ExpectedException expectedException = ExpectedException.none(); - private final DefaultStatisticsService service = new DefaultStatisticsService(); private CacheManager cacheManager; @@ -89,8 +85,7 @@ public void startStopStart() throws Exception { @Test public void startInMaintenance() throws Exception { - expectedException.expect(IllegalStateException.class); - service.stateTransition(Status.UNINITIALIZED, Status.MAINTENANCE); + assertThrows(IllegalStateException.class, () -> service.stateTransition(Status.UNINITIALIZED, Status.MAINTENANCE)); } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java index ad36a9f990..661bb436d7 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java @@ -27,9 +27,7 @@ import org.ehcache.core.statistics.TierOperationOutcomes; import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.terracotta.context.ContextManager; import org.terracotta.context.TreeNode; import org.terracotta.context.query.Matchers; @@ -46,6 +44,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.ehcache.core.statistics.StatsUtils.*; +import static org.junit.Assert.assertThrows; import static org.terracotta.context.query.Matchers.attributes; import static org.terracotta.context.query.Matchers.context; import static org.terracotta.context.query.Matchers.hasAttribute; @@ -55,9 +54,6 @@ public class StatsUtilsTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - CacheManager cacheManager; Cache cache; @@ -176,8 +172,7 @@ public void testFindCacheStatistic() { @Test public void testFindCacheStatistic_notExisting() { - expectedException.expect(RuntimeException.class); - findOperationStatisticOnChildren(cache, CacheOperationOutcomes.GetOutcome.class, "xxx"); + assertThrows(RuntimeException.class, () -> findOperationStatisticOnChildren(cache, CacheOperationOutcomes.GetOutcome.class, "xxx")); } @Test @@ -206,8 +201,7 @@ public void testFindLowerTier_three() { @Test public void testFindLowerTier_none() { - expectedException.expect(RuntimeException.class); - findLowestTier(new String[0]); + assertThrows(RuntimeException.class, () -> findLowestTier(new String[0])); } @Test diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java index 03ac8a82ba..4d129bdc96 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java @@ -50,8 +50,8 @@ import static java.util.Collections.singleton; import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.empty; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.terracotta.context.query.Matchers.attributes; import static org.terracotta.context.query.Matchers.context; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java index 9cc393d631..8bbc9600f9 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java @@ -90,8 +90,8 @@ import static org.ehcache.impl.internal.spi.TestServiceProvider.providerContaining; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java index 99eb4f7a42..61701a3e87 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java @@ -41,7 +41,7 @@ import static org.ehcache.impl.internal.store.disk.OffHeapDiskStore.persistent; import static org.ehcache.impl.internal.spi.TestServiceProvider.providerContaining; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.terracotta.offheapstore.util.MemoryUnit.BYTES; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java index 01ccf44d80..3d88baa429 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java @@ -36,9 +36,9 @@ import java.util.concurrent.ConcurrentMap; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java index 8065e479a8..49d336c9d1 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java @@ -41,11 +41,11 @@ import static java.util.Collections.singleton; import static java.util.Collections.singletonMap; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java index d3d1af5239..5ce6156922 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java @@ -42,10 +42,10 @@ import static java.util.Collections.singletonMap; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.test.MockitoUtil.mock; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.sameInstance; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.when; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java index 784d51b1ce..7381b2299e 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java @@ -36,9 +36,9 @@ import java.util.concurrent.ConcurrentMap; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapKeyTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapKeyTest.java index c720b66969..8e0840f94a 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapKeyTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapKeyTest.java @@ -19,8 +19,8 @@ import org.ehcache.impl.copy.ReadWriteCopier; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * Created by alsu on 20/08/15. diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolderTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolderTest.java index bf71cd378a..fe4c6d68ee 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolderTest.java @@ -26,13 +26,13 @@ import java.nio.ByteBuffer; import java.util.concurrent.Exchanger; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; /** diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractEhcacheOffHeapBackingMapTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractEhcacheOffHeapBackingMapTest.java index 62a7c935d4..89f8f3ffb3 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractEhcacheOffHeapBackingMapTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractEhcacheOffHeapBackingMapTest.java @@ -26,7 +26,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; /** diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java index c7a62d5751..ad9bdad37c 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java @@ -57,11 +57,11 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.lessThan; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.atLeast; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolder.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolder.java index 2b7009d51f..35a9e6df03 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolder.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolder.java @@ -38,8 +38,8 @@ import static java.util.Arrays.asList; import static java.util.Arrays.stream; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.objectweb.asm.Opcodes.ASM6; import static org.objectweb.asm.Type.getObjectType; import static org.objectweb.asm.Type.getType; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolderTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolderTest.java index f3eb983d42..5bbdff41da 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolderTest.java @@ -19,8 +19,8 @@ import org.junit.Before; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * BasicOffHeapValueHolderTest diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolderTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolderTest.java index 06ccb60374..28c858eeb7 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolderTest.java @@ -22,8 +22,8 @@ import java.nio.ByteBuffer; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * BinaryOffHeapValueHolderTest diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolderTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolderTest.java index f4d9e68254..76f6dc0466 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolderTest.java @@ -22,9 +22,9 @@ import java.nio.ByteBuffer; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java index 2329630cf9..e29a216dbe 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java @@ -42,8 +42,8 @@ import static java.util.Collections.EMPTY_LIST; import static org.ehcache.impl.internal.spi.TestServiceProvider.providerContaining; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; public class OffHeapStoreTest extends AbstractOffHeapStoreTest { diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolderPortabilityTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolderPortabilityTest.java index 60dd0d79ad..0721e250ff 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolderPortabilityTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolderPortabilityTest.java @@ -34,7 +34,7 @@ import static org.ehcache.impl.internal.spi.TestServiceProvider.providerContaining; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentTest.java index bffa481e84..f146989f7a 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentTest.java @@ -36,7 +36,7 @@ import static org.ehcache.impl.internal.store.offheap.OffHeapStoreUtils.getBufferSource; import static org.ehcache.impl.internal.spi.TestServiceProvider.providerContaining; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierTest.java index ff5717af85..d94f97bba4 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierTest.java @@ -32,9 +32,9 @@ import java.util.function.Function; import static java.util.Collections.EMPTY_LIST; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doAnswer; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java index 341cb5f56b..65ce0eb2d5 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java @@ -47,8 +47,8 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.ehcache.test.MockitoUtil.mock; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.when; public class TieredStoreFlushWhileShutdownTest { diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java index 4cdd522f7b..39d93f1025 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java @@ -45,7 +45,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; /** * Tests for {@link TieredStore}. These tests are mainly to validate that diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java index eeec9a8fe6..f7f601e626 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java @@ -36,7 +36,6 @@ import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceProvider; import org.hamcrest.Matchers; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.Answers; @@ -57,7 +56,6 @@ import java.util.Set; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; -import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; @@ -672,7 +670,7 @@ public void testGetAuthoritativeTierProvider() { } private void assertRank(final Store.Provider provider, final int expectedRank, final ResourceType... resources) { - Assert.assertThat(provider.rank( + assertThat(provider.rank( new HashSet<>(Arrays.asList(resources)), Collections.emptyList()), Matchers.is(expectedRank)); diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/ByteBufferInputStreamTest.java b/impl/src/test/java/org/ehcache/impl/internal/util/ByteBufferInputStreamTest.java index ba522cec81..9ee202286e 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/util/ByteBufferInputStreamTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/util/ByteBufferInputStreamTest.java @@ -20,11 +20,10 @@ import java.util.Random; import org.ehcache.core.util.ByteBufferInputStream; -import org.junit.Assert; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; public class ByteBufferInputStreamTest { @@ -108,7 +107,7 @@ public void testZeroOffsetAndMaximalLength() { byte[] read = new byte[32]; stream.read(read, 0, 32); for (int i = 0; i < read.length; i++) { - Assert.assertThat(read[i], is((byte) i)); + assertThat(read[i], is((byte) i)); } } @@ -118,7 +117,7 @@ public void testMaximalOffsetAndZeroLength() { byte[] read = new byte[32]; stream.read(read, 32, 0); for (int i = 0; i < read.length; i++) { - Assert.assertThat(read[i], is((byte) 0)); + assertThat(read[i], is((byte) 0)); } } @@ -139,13 +138,13 @@ public void testLegalOffsetAndLegalLength() { byte[] read = new byte[32]; stream.read(read, 4, 16); for (int i = 0; i < 4; i++) { - Assert.assertThat(read[i], is((byte) 0)); + assertThat(read[i], is((byte) 0)); } for (int i = 4; i < 20; i++) { - Assert.assertThat(read[i], is((byte) (i - 4))); + assertThat(read[i], is((byte) (i - 4))); } for (int i = 20; i < read.length; i++) { - Assert.assertThat(read[i], is((byte) 0)); + assertThat(read[i], is((byte) 0)); } } @@ -154,9 +153,9 @@ public void testMinimalOffsetAndMaximalLength() { ByteBufferInputStream stream = createStream(); byte[] read = new byte[32]; stream.read(read, 1, 31); - Assert.assertThat(read[0], is((byte) 0)); + assertThat(read[0], is((byte) 0)); for (int i = 1; i < read.length; i++) { - Assert.assertThat(read[i], is((byte) (i - 1))); + assertThat(read[i], is((byte) (i - 1))); } } @@ -166,7 +165,7 @@ public void testZeroOffsetAndZeroLength() { byte[] read = new byte[32]; stream.read(read, 0, 0); for (int i = 0; i < read.length; i++) { - Assert.assertThat(read[i], is((byte) 0)); + assertThat(read[i], is((byte) 0)); } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java b/impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java index 55b46db5f0..db589328c8 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java @@ -26,7 +26,7 @@ import static org.ehcache.impl.internal.util.FileExistenceMatchers.containsCacheDirectory; import static org.ehcache.impl.internal.util.FileExistenceMatchers.isLocked; import static org.hamcrest.CoreMatchers.not; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; /** * @author Henri Tremblay diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/StatisticsTestUtils.java b/impl/src/test/java/org/ehcache/impl/internal/util/StatisticsTestUtils.java index 745cbd30cc..6e1da8bf8d 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/util/StatisticsTestUtils.java +++ b/impl/src/test/java/org/ehcache/impl/internal/util/StatisticsTestUtils.java @@ -21,7 +21,6 @@ import org.hamcrest.Factory; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; -import org.junit.Assert; import org.terracotta.context.ContextManager; import org.terracotta.context.TreeNode; import org.terracotta.statistics.OperationStatistic; @@ -31,6 +30,8 @@ import java.util.EnumSet; import java.util.List; +import static org.hamcrest.MatcherAssert.assertThat; + /** * StatisticsTestUtils */ @@ -62,18 +63,18 @@ public static > void validateStats(final Store store, fi final OperationStatistic operationStatistic = getOperationStatistic(store, statsClass); for (final E statId : changed) { - Assert.assertThat(String.format("Value for %s.%s", statId.getDeclaringClass().getName(), statId.name()), + assertThat(String.format("Value for %s.%s", statId.getDeclaringClass().getName(), statId.name()), getStatistic(operationStatistic, statId), StatisticMatcher.equalTo(1L)); } for (final E statId : unchanged) { - Assert.assertThat(String.format("Value for %s.%s", statId.getDeclaringClass().getName(), statId.name()), + assertThat(String.format("Value for %s.%s", statId.getDeclaringClass().getName(), statId.name()), getStatistic(operationStatistic, statId), StatisticMatcher.equalTo(0L)); } } public static > void validateStat(final Store store, E outcome, long count) { OperationStatistic operationStatistic = getOperationStatistic(store, outcome.getDeclaringClass()); - Assert.assertThat(getStatistic(operationStatistic, outcome), StatisticMatcher.equalTo(count)); + assertThat(getStatistic(operationStatistic, outcome), StatisticMatcher.equalTo(count)); } /** diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/ThreadFactoryUtilTest.java b/impl/src/test/java/org/ehcache/impl/internal/util/ThreadFactoryUtilTest.java index 33a029737d..e6a14773d7 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/util/ThreadFactoryUtilTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/util/ThreadFactoryUtilTest.java @@ -20,9 +20,9 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicReference; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.not; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; /** * @author Ludovic Orban diff --git a/impl/src/test/java/org/ehcache/impl/persistence/DefaultDiskResourceServiceTest.java b/impl/src/test/java/org/ehcache/impl/persistence/DefaultDiskResourceServiceTest.java index 41486008cb..1825d9e7c6 100644 --- a/impl/src/test/java/org/ehcache/impl/persistence/DefaultDiskResourceServiceTest.java +++ b/impl/src/test/java/org/ehcache/impl/persistence/DefaultDiskResourceServiceTest.java @@ -22,13 +22,12 @@ import org.ehcache.spi.service.ServiceProvider; import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.experimental.runners.Enclosed; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -41,9 +40,6 @@ public class DefaultDiskResourceServiceTest { public static abstract class AbstractDefaultDiskResourceServiceTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - protected DefaultDiskResourceService service = new DefaultDiskResourceService(); @SuppressWarnings("unchecked") protected ServiceProvider serviceProvider = mock(ServiceProvider.class); @@ -108,9 +104,8 @@ public void testDestroy() throws CachePersistenceException { @Test public void testCreatePersistenceContextWithin() throws CachePersistenceException { - expectedException.expect(CachePersistenceException.class); - expectedException.expectMessage("Unknown space: null"); - service.createPersistenceContextWithin(null, "test"); + assertThatThrownBy(() -> service.createPersistenceContextWithin(null, "test")) + .isInstanceOf(CachePersistenceException.class).withFailMessage("Unknown space: null"); } @Test @@ -121,16 +116,14 @@ public void testGetPersistenceSpaceIdentifier() throws CachePersistenceException @Test public void testGetStateRepositoryWithin() throws CachePersistenceException { - expectedException.expect(CachePersistenceException.class); - expectedException.expectMessage("Unknown space: null"); - assertThat(service.getStateRepositoryWithin(null, "test")).isNull(); + assertThatThrownBy(() -> service.getStateRepositoryWithin(null, "test")) + .isInstanceOf(CachePersistenceException.class).withFailMessage("Unknown space: null"); } @Test public void testReleasePersistenceSpaceIdentifier() throws CachePersistenceException { - expectedException.expect(CachePersistenceException.class); - expectedException.expectMessage("Unknown space: null"); - assertThat(service.getStateRepositoryWithin(null, "test")).isNull(); + assertThatThrownBy(() -> service.getStateRepositoryWithin(null, "test")) + .isInstanceOf(CachePersistenceException.class).withFailMessage("Unknown space: null"); } } diff --git a/impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java b/impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java index a3f468a6f7..a1225b2790 100644 --- a/impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java +++ b/impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java @@ -22,7 +22,6 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; @@ -32,16 +31,15 @@ import static org.ehcache.impl.internal.util.FileExistenceMatchers.isLocked; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; public class DefaultLocalPersistenceServiceTest { - @Rule - public final ExpectedException expectedException = ExpectedException.none(); - @Rule public final TemporaryFolder folder = new TemporaryFolder(); @@ -139,7 +137,7 @@ public void testExclusiveLock() throws IOException { // We should not be able to lock the same directory twice // And we should receive a meaningful exception about it - expectedException.expectMessage("Persistence directory already locked by this process: " + testFolder.getAbsolutePath()); - service2.start(null); + RuntimeException thrown = assertThrows(RuntimeException.class, () -> service2.start(null)); + assertThat(thrown, hasProperty("message", is("Persistence directory already locked by this process: " + testFolder.getAbsolutePath()))); } } diff --git a/impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java b/impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java index 8c71667cbd..ca423ce8a9 100644 --- a/impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java +++ b/impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java @@ -28,8 +28,8 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * FileBasedStateRepositoryTest diff --git a/impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java b/impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java index 68b3d2369a..6fb918d639 100644 --- a/impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java +++ b/impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java @@ -18,7 +18,6 @@ import org.ehcache.spi.serialization.StatefulSerializer; import org.hamcrest.core.Is; -import org.junit.Assert; import org.junit.Test; import java.io.Externalizable; @@ -32,6 +31,7 @@ import static org.ehcache.impl.serialization.SerializerTestUtilities.newClassName; import static org.ehcache.impl.serialization.SerializerTestUtilities.popTccl; import static org.ehcache.impl.serialization.SerializerTestUtilities.pushTccl; +import static org.hamcrest.MatcherAssert.assertThat; /** * @@ -51,7 +51,7 @@ public void addingSerializableField() throws Exception { pushTccl(createClassNameRewritingLoader(A_read.class, IncompatibleSerializable_read.class)); try { Serializable out = serializer.read(encodedA); - Assert.assertThat(out.getClass().getField("bar").getInt(out), Is.is(4)); + assertThat(out.getClass().getField("bar").getInt(out), Is.is(4)); } finally { popTccl(); } @@ -69,7 +69,7 @@ public void addingExternalizableField() throws Exception { pushTccl(createClassNameRewritingLoader(B_read.class)); try { Serializable out = serializer.read(encodedA); - Assert.assertThat(out.getClass().getField("bar").getInt(out), Is.is(4)); + assertThat(out.getClass().getField("bar").getInt(out), Is.is(4)); } finally { popTccl(); } diff --git a/impl/src/test/java/org/ehcache/impl/serialization/BasicSerializationTest.java b/impl/src/test/java/org/ehcache/impl/serialization/BasicSerializationTest.java index b18d69ccc5..2fbbd3755b 100644 --- a/impl/src/test/java/org/ehcache/impl/serialization/BasicSerializationTest.java +++ b/impl/src/test/java/org/ehcache/impl/serialization/BasicSerializationTest.java @@ -32,6 +32,8 @@ import org.junit.Assert; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; + /** * * @author cdennis @@ -79,8 +81,8 @@ public void testPrimitiveClasses() throws ClassNotFoundException { Class[] out = (Class[]) s.read(s.serialize(PRIMITIVE_CLASSES)); - Assert.assertThat(out, IsNot.not(IsSame.sameInstance(PRIMITIVE_CLASSES))); - Assert.assertThat(out, IsEqual.equalTo(PRIMITIVE_CLASSES)); + assertThat(out, IsNot.not(IsSame.sameInstance(PRIMITIVE_CLASSES))); + assertThat(out, IsEqual.equalTo(PRIMITIVE_CLASSES)); } @Test @@ -94,8 +96,8 @@ public void testProxyInstance() throws ClassNotFoundException { Object proxy = s.read(s.serialize((Serializable) Proxy.newProxyInstance(BasicSerializationTest.class.getClassLoader(), new Class[]{Foo.class, Bar.class}, new Handler(foo, bar)))); - Assert.assertThat(((Foo) proxy).foo(), Is.is(foo)); - Assert.assertThat(((Bar) proxy).bar(), Is.is(bar)); + assertThat(((Foo) proxy).foo(), Is.is(foo)); + assertThat(((Bar) proxy).bar(), Is.is(bar)); } interface Foo { diff --git a/impl/src/test/java/org/ehcache/impl/serialization/ByteArraySerializerTest.java b/impl/src/test/java/org/ehcache/impl/serialization/ByteArraySerializerTest.java index ff81e9c78f..8a1662781e 100644 --- a/impl/src/test/java/org/ehcache/impl/serialization/ByteArraySerializerTest.java +++ b/impl/src/test/java/org/ehcache/impl/serialization/ByteArraySerializerTest.java @@ -24,8 +24,8 @@ import java.util.Arrays; import java.util.Random; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; public class ByteArraySerializerTest { @@ -76,4 +76,4 @@ public void testReadThrowsOnNullInput() throws ClassNotFoundException { public void testSerializeThrowsOnNullInput() { new ByteArraySerializer().serialize(null); } -} \ No newline at end of file +} diff --git a/impl/src/test/java/org/ehcache/impl/serialization/CharSerializerTest.java b/impl/src/test/java/org/ehcache/impl/serialization/CharSerializerTest.java index effd7aa568..a2699ff34d 100644 --- a/impl/src/test/java/org/ehcache/impl/serialization/CharSerializerTest.java +++ b/impl/src/test/java/org/ehcache/impl/serialization/CharSerializerTest.java @@ -22,8 +22,8 @@ import java.util.Random; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; public class CharSerializerTest { @@ -52,4 +52,4 @@ public void testReadThrowsOnNullInput() throws ClassNotFoundException { public void testSerializeThrowsOnNullInput() { new CharSerializer().serialize(null); } -} \ No newline at end of file +} diff --git a/impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerTest.java b/impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerTest.java index d2c4057c69..9de204d921 100644 --- a/impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerTest.java +++ b/impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerTest.java @@ -25,9 +25,9 @@ import java.util.Date; import java.util.concurrent.atomic.AtomicBoolean; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; diff --git a/impl/src/test/java/org/ehcache/impl/serialization/DoubleSerializerTest.java b/impl/src/test/java/org/ehcache/impl/serialization/DoubleSerializerTest.java index 10c68d0428..ac4d8ea9d3 100644 --- a/impl/src/test/java/org/ehcache/impl/serialization/DoubleSerializerTest.java +++ b/impl/src/test/java/org/ehcache/impl/serialization/DoubleSerializerTest.java @@ -22,8 +22,8 @@ import java.util.Random; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; public class DoubleSerializerTest { @@ -52,4 +52,4 @@ public void testReadThrowsOnNullInput() throws ClassNotFoundException { public void testSerializeThrowsOnNullInput() { new DoubleSerializer().serialize(null); } -} \ No newline at end of file +} diff --git a/impl/src/test/java/org/ehcache/impl/serialization/EnumTest.java b/impl/src/test/java/org/ehcache/impl/serialization/EnumTest.java index 0a704aaa41..e2d0b90255 100644 --- a/impl/src/test/java/org/ehcache/impl/serialization/EnumTest.java +++ b/impl/src/test/java/org/ehcache/impl/serialization/EnumTest.java @@ -18,7 +18,6 @@ import org.ehcache.spi.serialization.StatefulSerializer; import org.hamcrest.core.IsSame; -import org.junit.Assert; import org.junit.Test; import java.io.Serializable; @@ -27,6 +26,7 @@ import static org.ehcache.impl.serialization.SerializerTestUtilities.newClassName; import static org.ehcache.impl.serialization.SerializerTestUtilities.popTccl; import static org.ehcache.impl.serialization.SerializerTestUtilities.pushTccl; +import static org.hamcrest.MatcherAssert.assertThat; /** * @@ -39,9 +39,9 @@ public void basicInstanceSerialization() throws ClassNotFoundException { StatefulSerializer s = new CompactJavaSerializer<>(null); s.init(new TransientStateRepository()); - Assert.assertThat(s.read(s.serialize(People.Alice)), IsSame.sameInstance(People.Alice)); - Assert.assertThat(s.read(s.serialize(People.Bob)), IsSame.sameInstance(People.Bob)); - Assert.assertThat(s.read(s.serialize(People.Eve)), IsSame.sameInstance(People.Eve)); + assertThat(s.read(s.serialize(People.Alice)), IsSame.sameInstance(People.Alice)); + assertThat(s.read(s.serialize(People.Bob)), IsSame.sameInstance(People.Bob)); + assertThat(s.read(s.serialize(People.Eve)), IsSame.sameInstance(People.Eve)); } @Test @@ -49,10 +49,10 @@ public void classSerialization() throws ClassNotFoundException { StatefulSerializer s = new CompactJavaSerializer<>(null); s.init(new TransientStateRepository()); - Assert.assertThat(s.read(s.serialize(Enum.class)), IsSame.sameInstance(Enum.class)); - Assert.assertThat(s.read(s.serialize(Dogs.Handel.getClass())), IsSame.sameInstance(Dogs.Handel.getClass())); - Assert.assertThat(s.read(s.serialize(Dogs.Cassie.getClass())), IsSame.sameInstance(Dogs.Cassie.getClass())); - Assert.assertThat(s.read(s.serialize(Dogs.Penny.getClass())), IsSame.sameInstance(Dogs.Penny.getClass())); + assertThat(s.read(s.serialize(Enum.class)), IsSame.sameInstance(Enum.class)); + assertThat(s.read(s.serialize(Dogs.Handel.getClass())), IsSame.sameInstance(Dogs.Handel.getClass())); + assertThat(s.read(s.serialize(Dogs.Cassie.getClass())), IsSame.sameInstance(Dogs.Cassie.getClass())); + assertThat(s.read(s.serialize(Dogs.Penny.getClass())), IsSame.sameInstance(Dogs.Penny.getClass())); } @Test @@ -72,7 +72,7 @@ public void shiftingInstanceSerialization() throws ClassNotFoundException { pushTccl(rLoader); try { for (int i = 0; i < wInstances.length; i++) { - Assert.assertThat(s.read(s.serialize((Serializable) wInstances[i])), IsSame.sameInstance(rInstances[i])); + assertThat(s.read(s.serialize((Serializable) wInstances[i])), IsSame.sameInstance(rInstances[i])); } } finally { popTccl(); diff --git a/impl/src/test/java/org/ehcache/impl/serialization/FloatSerializerTest.java b/impl/src/test/java/org/ehcache/impl/serialization/FloatSerializerTest.java index b927433767..83dca80e62 100644 --- a/impl/src/test/java/org/ehcache/impl/serialization/FloatSerializerTest.java +++ b/impl/src/test/java/org/ehcache/impl/serialization/FloatSerializerTest.java @@ -22,8 +22,8 @@ import java.util.Random; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; public class FloatSerializerTest { @@ -52,4 +52,4 @@ public void testReadThrowsOnNullInput() throws ClassNotFoundException { public void testSerializeThrowsOnNullInput() { new FloatSerializer().serialize(null); } -} \ No newline at end of file +} diff --git a/impl/src/test/java/org/ehcache/impl/serialization/IntegerSerializerTest.java b/impl/src/test/java/org/ehcache/impl/serialization/IntegerSerializerTest.java index e976a9188b..127bbe552d 100644 --- a/impl/src/test/java/org/ehcache/impl/serialization/IntegerSerializerTest.java +++ b/impl/src/test/java/org/ehcache/impl/serialization/IntegerSerializerTest.java @@ -22,8 +22,8 @@ import java.util.Random; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; public class IntegerSerializerTest { @@ -52,4 +52,4 @@ public void testReadThrowsOnNullInput() throws ClassNotFoundException { public void testSerializeThrowsOnNullInput() { new IntegerSerializer().serialize(null); } -} \ No newline at end of file +} diff --git a/impl/src/test/java/org/ehcache/impl/serialization/LongSerializerTest.java b/impl/src/test/java/org/ehcache/impl/serialization/LongSerializerTest.java index 0d87007126..87769a44a2 100644 --- a/impl/src/test/java/org/ehcache/impl/serialization/LongSerializerTest.java +++ b/impl/src/test/java/org/ehcache/impl/serialization/LongSerializerTest.java @@ -22,8 +22,8 @@ import java.util.Random; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * LongSerializerTest @@ -55,4 +55,4 @@ public void testReadThrowsOnNullInput() throws ClassNotFoundException { public void testSerializeThrowsOnNullInput() { new LongSerializer().serialize(null); } -} \ No newline at end of file +} diff --git a/impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java b/impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java index 94a197e5b3..33ca475626 100644 --- a/impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java +++ b/impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java @@ -22,13 +22,14 @@ import org.ehcache.spi.serialization.StatefulSerializer; import org.hamcrest.core.Is; -import org.junit.Assert; import org.junit.Test; import static org.ehcache.impl.serialization.SerializerTestUtilities.createClassNameRewritingLoader; import static org.ehcache.impl.serialization.SerializerTestUtilities.newClassName; import static org.ehcache.impl.serialization.SerializerTestUtilities.popTccl; import static org.ehcache.impl.serialization.SerializerTestUtilities.pushTccl; +import static org.hamcrest.MatcherAssert.assertThat; + public class SerializeAfterEvolutionTest { @Test @@ -45,11 +46,11 @@ public void test() throws Exception { pushTccl(loaderB); try { Serializable outA = s.read(encodedA); - Assert.assertThat((Integer) outA.getClass().getField("integer").get(outA), Is.is(42)); + assertThat((Integer) outA.getClass().getField("integer").get(outA), Is.is(42)); Serializable b = (Serializable) loaderB.loadClass(newClassName(A_new.class)).newInstance(); Serializable outB = s.read(s.serialize(b)); - Assert.assertThat((Integer) outB.getClass().getField("integer").get(outB), Is.is(42)); + assertThat((Integer) outB.getClass().getField("integer").get(outB), Is.is(42)); } finally { popTccl(); } diff --git a/impl/src/test/java/org/ehcache/impl/serialization/StringSerializerTest.java b/impl/src/test/java/org/ehcache/impl/serialization/StringSerializerTest.java index 09df5b15aa..606ac50311 100644 --- a/impl/src/test/java/org/ehcache/impl/serialization/StringSerializerTest.java +++ b/impl/src/test/java/org/ehcache/impl/serialization/StringSerializerTest.java @@ -21,8 +21,8 @@ import java.util.Random; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * StringSerializerTest @@ -102,4 +102,4 @@ public void testEqualsMismatchOnMissingFinalSurrogateAgainstOldFormat() throws U ByteBuffer bytes = ByteBuffer.wrap(string.getBytes("UTF-8")); assertThat(serializer.equals(trimmed, bytes), is(false)); } -} \ No newline at end of file +} diff --git a/impl/src/test/java/org/ehcache/impl/serialization/TransientStateRepositoryTest.java b/impl/src/test/java/org/ehcache/impl/serialization/TransientStateRepositoryTest.java index 8134dda8b2..7424d90bf6 100644 --- a/impl/src/test/java/org/ehcache/impl/serialization/TransientStateRepositoryTest.java +++ b/impl/src/test/java/org/ehcache/impl/serialization/TransientStateRepositoryTest.java @@ -19,8 +19,8 @@ import org.ehcache.spi.persistence.StateHolder; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.*; /** * TransientStateRepositoryTest diff --git a/impl/src/test/java/org/ehcache/impl/store/DefaultStoreEventDispatcherTest.java b/impl/src/test/java/org/ehcache/impl/store/DefaultStoreEventDispatcherTest.java index 5646070ef2..7ee9c7355a 100644 --- a/impl/src/test/java/org/ehcache/impl/store/DefaultStoreEventDispatcherTest.java +++ b/impl/src/test/java/org/ehcache/impl/store/DefaultStoreEventDispatcherTest.java @@ -32,8 +32,8 @@ import java.util.concurrent.CountDownLatch; import static org.ehcache.impl.internal.util.Matchers.eventOfType; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; diff --git a/impl/src/test/java/org/ehcache/impl/store/HashUtilsTest.java b/impl/src/test/java/org/ehcache/impl/store/HashUtilsTest.java index e82f763ae8..c74abbe1f3 100644 --- a/impl/src/test/java/org/ehcache/impl/store/HashUtilsTest.java +++ b/impl/src/test/java/org/ehcache/impl/store/HashUtilsTest.java @@ -20,8 +20,8 @@ import java.util.Random; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * HashUtilsTest diff --git a/integration-test/src/test/java/org/ehcache/integration/CacheCopierTest.java b/integration-test/src/test/java/org/ehcache/integration/CacheCopierTest.java index ad1340f521..400d032a43 100644 --- a/integration-test/src/test/java/org/ehcache/integration/CacheCopierTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/CacheCopierTest.java @@ -38,10 +38,10 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThat; /** * Created by alsu on 01/09/15. diff --git a/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java b/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java index 6aaec4556d..3416a33869 100644 --- a/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java +++ b/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java @@ -54,9 +54,9 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.ehcache.core.spi.ServiceLocator.dependencySet; import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsCollectionContaining.hasItems; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doThrow; diff --git a/integration-test/src/test/java/org/ehcache/integration/EventNotificationTest.java b/integration-test/src/test/java/org/ehcache/integration/EventNotificationTest.java index e9e3ff6c55..3d8d4a53b3 100644 --- a/integration-test/src/test/java/org/ehcache/integration/EventNotificationTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/EventNotificationTest.java @@ -48,10 +48,10 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.lessThan; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; public class EventNotificationTest { private static final TestTimeSource testTimeSource = new TestTimeSource(); diff --git a/integration-test/src/test/java/org/ehcache/integration/EvictionEhcacheTest.java b/integration-test/src/test/java/org/ehcache/integration/EvictionEhcacheTest.java index 29a3a81cb2..9653c387a0 100644 --- a/integration-test/src/test/java/org/ehcache/integration/EvictionEhcacheTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/EvictionEhcacheTest.java @@ -28,8 +28,8 @@ import java.util.Map; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; /** * @author Ludovic Orban diff --git a/integration-test/src/test/java/org/ehcache/integration/ExpiryEhcacheTestBase.java b/integration-test/src/test/java/org/ehcache/integration/ExpiryEhcacheTestBase.java index 0d88be9df1..f718351015 100644 --- a/integration-test/src/test/java/org/ehcache/integration/ExpiryEhcacheTestBase.java +++ b/integration-test/src/test/java/org/ehcache/integration/ExpiryEhcacheTestBase.java @@ -33,9 +33,9 @@ import java.util.Map; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; /** * @author Ludovic Orban diff --git a/integration-test/src/test/java/org/ehcache/integration/LoaderWriterErrorEhcacheTest.java b/integration-test/src/test/java/org/ehcache/integration/LoaderWriterErrorEhcacheTest.java index 13db25d038..f3c242a608 100644 --- a/integration-test/src/test/java/org/ehcache/integration/LoaderWriterErrorEhcacheTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/LoaderWriterErrorEhcacheTest.java @@ -38,10 +38,10 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.lessThan; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.notNullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; diff --git a/integration-test/src/test/java/org/ehcache/integration/LoaderWriterSimpleEhcacheTest.java b/integration-test/src/test/java/org/ehcache/integration/LoaderWriterSimpleEhcacheTest.java index 366928007b..6e942ec5b1 100644 --- a/integration-test/src/test/java/org/ehcache/integration/LoaderWriterSimpleEhcacheTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/LoaderWriterSimpleEhcacheTest.java @@ -29,9 +29,9 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; diff --git a/integration-test/src/test/java/org/ehcache/integration/OsgiSafetyTest.java b/integration-test/src/test/java/org/ehcache/integration/OsgiSafetyTest.java index 3380fcbc44..3728086e0b 100644 --- a/integration-test/src/test/java/org/ehcache/integration/OsgiSafetyTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/OsgiSafetyTest.java @@ -19,8 +19,8 @@ import org.ehcache.core.osgi.SafeOsgi; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; public class OsgiSafetyTest { diff --git a/integration-test/src/test/java/org/ehcache/integration/PersistentUserManagedCacheTest.java b/integration-test/src/test/java/org/ehcache/integration/PersistentUserManagedCacheTest.java index f394d7fba8..97f4de0437 100644 --- a/integration-test/src/test/java/org/ehcache/integration/PersistentUserManagedCacheTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/PersistentUserManagedCacheTest.java @@ -32,8 +32,8 @@ import java.io.File; import java.io.Serializable; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; /** * PersistentUserManagedCacheTest diff --git a/integration-test/src/test/java/org/ehcache/integration/SerializersTest.java b/integration-test/src/test/java/org/ehcache/integration/SerializersTest.java index 472c6351a0..370ae18064 100644 --- a/integration-test/src/test/java/org/ehcache/integration/SerializersTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/SerializersTest.java @@ -29,7 +29,6 @@ import org.ehcache.spi.serialization.StatefulSerializer; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.terracotta.org.junit.rules.TemporaryFolder; import java.nio.ByteBuffer; @@ -38,15 +37,13 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.persistence; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; public class SerializersTest { @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); - @Rule - public ExpectedException expectedException = ExpectedException.none(); @Test public void testStatefulSerializer() throws Exception { diff --git a/integration-test/src/test/java/org/ehcache/integration/SimpleEhcacheTest.java b/integration-test/src/test/java/org/ehcache/integration/SimpleEhcacheTest.java index a60598073d..2ff0433ba4 100644 --- a/integration-test/src/test/java/org/ehcache/integration/SimpleEhcacheTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/SimpleEhcacheTest.java @@ -30,11 +30,11 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; /** * @author Ludovic Orban diff --git a/integration-test/src/test/java/org/ehcache/integration/StatefulSerializerWithStateRepositoryTest.java b/integration-test/src/test/java/org/ehcache/integration/StatefulSerializerWithStateRepositoryTest.java index d21d13860a..258d358a48 100644 --- a/integration-test/src/test/java/org/ehcache/integration/StatefulSerializerWithStateRepositoryTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/StatefulSerializerWithStateRepositoryTest.java @@ -30,8 +30,8 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.persistence; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; public class StatefulSerializerWithStateRepositoryTest { diff --git a/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java b/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java index 934d0ff37a..dd088a52d7 100644 --- a/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java @@ -45,9 +45,9 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; import static org.terracotta.context.query.Matchers.attributes; import static org.terracotta.context.query.Matchers.context; import static org.terracotta.context.query.Matchers.hasAttribute; diff --git a/integration-test/src/test/java/org/ehcache/integration/TieringTest.java b/integration-test/src/test/java/org/ehcache/integration/TieringTest.java index 33cedcba2e..8ee077ba78 100644 --- a/integration-test/src/test/java/org/ehcache/integration/TieringTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/TieringTest.java @@ -24,8 +24,8 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; /** diff --git a/integration-test/src/test/java/org/ehcache/integration/UserManagedCacheEvictionTest.java b/integration-test/src/test/java/org/ehcache/integration/UserManagedCacheEvictionTest.java index e5e47cdaeb..7cf3387d73 100644 --- a/integration-test/src/test/java/org/ehcache/integration/UserManagedCacheEvictionTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/UserManagedCacheEvictionTest.java @@ -24,7 +24,7 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; /** * @author Anthony Dahanne diff --git a/integration-test/src/test/java/org/ehcache/integration/UserManagedCacheLoaderWriterTest.java b/integration-test/src/test/java/org/ehcache/integration/UserManagedCacheLoaderWriterTest.java index 1cfb3e0d2e..438a639649 100644 --- a/integration-test/src/test/java/org/ehcache/integration/UserManagedCacheLoaderWriterTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/UserManagedCacheLoaderWriterTest.java @@ -20,10 +20,10 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.hamcrest.Matchers; -import org.junit.Assert; import org.junit.Test; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -47,6 +47,6 @@ public void testLoaderWriterWithUserManagedCache() throws Exception { verify(cacheLoaderWriter, times(1)).write(eq(1L), eq(1L)); when(cacheLoaderWriter.load(anyLong())).thenReturn(2L); - Assert.assertThat(userManagedCache.get(2L), Matchers.is(2L)); + assertThat(userManagedCache.get(2L), Matchers.is(2L)); } } diff --git a/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java b/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java index d6ecad0dfe..a5af58be1f 100644 --- a/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java @@ -54,11 +54,11 @@ import java.util.concurrent.atomic.AtomicReference; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; /** diff --git a/management/src/test/java/org/ehcache/docs/ManagementTest.java b/management/src/test/java/org/ehcache/docs/ManagementTest.java index 236378eb8c..0c20a94e91 100644 --- a/management/src/test/java/org/ehcache/docs/ManagementTest.java +++ b/management/src/test/java/org/ehcache/docs/ManagementTest.java @@ -29,7 +29,6 @@ import org.ehcache.management.registry.DefaultManagementRegistryService; import org.ehcache.management.registry.DefaultSharedManagementService; import org.hamcrest.Matchers; -import org.junit.Assert; import org.junit.Test; import org.terracotta.management.model.call.Parameter; import org.terracotta.management.model.capabilities.Capability; @@ -45,6 +44,8 @@ import java.util.Collection; import java.util.Iterator; +import static org.hamcrest.MatcherAssert.assertThat; + public class ManagementTest { @Test @@ -94,7 +95,7 @@ public void usingManagementRegistry() throws Exception { ContextualStatistics statisticsContext = counters.getResult(context); - Assert.assertThat(counters.size(), Matchers.is(1)); + assertThat(counters.size(), Matchers.is(1)); } finally { if(cacheManager != null) cacheManager.close(); @@ -118,30 +119,30 @@ public void capabilitiesAndContexts() throws Exception { Collection capabilities = managementRegistry.getCapabilities(); // <1> - Assert.assertThat(capabilities.isEmpty(), Matchers.is(false)); + assertThat(capabilities.isEmpty(), Matchers.is(false)); Capability capability = capabilities.iterator().next(); String capabilityName = capability.getName(); // <2> Collection capabilityDescriptions = capability.getDescriptors(); // <3> - Assert.assertThat(capabilityDescriptions.isEmpty(), Matchers.is(false)); + assertThat(capabilityDescriptions.isEmpty(), Matchers.is(false)); CapabilityContext capabilityContext = capability.getCapabilityContext(); Collection attributes = capabilityContext.getAttributes(); // <4> - Assert.assertThat(attributes.size(), Matchers.is(2)); + assertThat(attributes.size(), Matchers.is(2)); Iterator iterator = attributes.iterator(); CapabilityContext.Attribute attribute1 = iterator.next(); - Assert.assertThat(attribute1.getName(), Matchers.equalTo("cacheManagerName")); // <5> - Assert.assertThat(attribute1.isRequired(), Matchers.is(true)); + assertThat(attribute1.getName(), Matchers.equalTo("cacheManagerName")); // <5> + assertThat(attribute1.isRequired(), Matchers.is(true)); CapabilityContext.Attribute attribute2 = iterator.next(); - Assert.assertThat(attribute2.getName(), Matchers.equalTo("cacheName")); // <6> - Assert.assertThat(attribute2.isRequired(), Matchers.is(true)); + assertThat(attribute2.getName(), Matchers.equalTo("cacheName")); // <6> + assertThat(attribute2.isRequired(), Matchers.is(true)); ContextContainer contextContainer = managementRegistry.getContextContainer(); // <7> - Assert.assertThat(contextContainer.getName(), Matchers.equalTo("cacheManagerName")); // <8> - Assert.assertThat(contextContainer.getValue(), Matchers.startsWith("cache-manager-")); + assertThat(contextContainer.getName(), Matchers.equalTo("cacheManagerName")); // <8> + assertThat(contextContainer.getValue(), Matchers.startsWith("cache-manager-")); Collection subContexts = contextContainer.getSubContexts(); - Assert.assertThat(subContexts.size(), Matchers.is(1)); + assertThat(subContexts.size(), Matchers.is(1)); ContextContainer subContextContainer = subContexts.iterator().next(); - Assert.assertThat(subContextContainer.getName(), Matchers.equalTo("cacheName")); // <9> - Assert.assertThat(subContextContainer.getValue(), Matchers.equalTo("aCache")); + assertThat(subContextContainer.getName(), Matchers.equalTo("cacheName")); // <9> + assertThat(subContextContainer.getValue(), Matchers.equalTo("aCache")); } finally { if(cacheManager != null) cacheManager.close(); @@ -175,7 +176,7 @@ public void actionCall() throws Exception { .build() .execute(); - Assert.assertThat(aCache.get(0L), Matchers.is(Matchers.nullValue())); // <4> + assertThat(aCache.get(0L), Matchers.is(Matchers.nullValue())); // <4> } finally { if(cacheManager != null) cacheManager.close(); diff --git a/management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java b/management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java index c1e7bc65b2..79843c1454 100644 --- a/management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java +++ b/management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java @@ -23,7 +23,7 @@ import java.net.URL; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java index 3bce9d8470..db775ea0e3 100755 --- a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java @@ -33,7 +33,6 @@ import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; import org.ehcache.management.registry.DefaultManagementRegistryService; import org.hamcrest.Matchers; -import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.Timeout; @@ -51,7 +50,7 @@ import static org.ehcache.config.units.EntryUnit.ENTRIES; import static org.ehcache.config.units.MemoryUnit.MB; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; @RunWith(Parameterized.class) public class StandardEhCacheStatisticsQueryTest { @@ -132,7 +131,7 @@ public void test() throws IOException { } long cacheHitCount = getAndAssertExpectedValueFromCounter("Cache:HitCount", context, managementRegistry, cacheExpectedValue); - Assert.assertThat(tierHitCountSum, is(cacheHitCount)); + assertThat(tierHitCountSum, is(cacheHitCount)); } } diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StatsUtil.java b/management/src/test/java/org/ehcache/management/providers/statistics/StatsUtil.java index 8a792fc60e..76625b0c52 100755 --- a/management/src/test/java/org/ehcache/management/providers/statistics/StatsUtil.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/StatsUtil.java @@ -24,7 +24,7 @@ import org.terracotta.management.registry.StatisticQuery; import static java.util.Collections.singletonList; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class StatsUtil { diff --git a/management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java b/management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java index 71b3c9b4ad..a4cf0f9108 100644 --- a/management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java +++ b/management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java @@ -41,7 +41,7 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class DefaultCollectorServiceTest { diff --git a/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java b/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java index e7f239e73d..290dbf38bf 100644 --- a/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java +++ b/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java @@ -37,7 +37,6 @@ import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.rules.Timeout; import org.terracotta.management.model.call.ContextualReturn; import org.terracotta.management.model.capabilities.Capability; @@ -51,6 +50,7 @@ import org.terracotta.org.junit.rules.TemporaryFolder; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.config.units.MemoryUnit.MB; @@ -64,9 +64,6 @@ public class DefaultManagementRegistryServiceTest { private static final Collection DISK_DESCRIPTORS = new ArrayList<>(); private static final Collection CACHE_DESCRIPTORS = new ArrayList<>(); - @Rule - public final ExpectedException expectedException = ExpectedException.none(); - @Rule public final TemporaryFolder diskPath = new TemporaryFolder(); @@ -406,8 +403,7 @@ public void testCallOnInexistignContext() throws ExecutionException { assertThat(results.size()).isEqualTo(1); assertThat(results.getSingleResult().hasExecuted()).isFalse(); - expectedException.expect(NoSuchElementException.class); - results.getSingleResult().getValue(); + assertThatThrownBy(() -> results.getSingleResult().getValue()).isInstanceOf(NoSuchElementException.class); } } diff --git a/management/src/test/java/org/ehcache/management/registry/DefaultSharedManagementServiceTest.java b/management/src/test/java/org/ehcache/management/registry/DefaultSharedManagementServiceTest.java index a05a4bda98..351e9711c9 100644 --- a/management/src/test/java/org/ehcache/management/registry/DefaultSharedManagementServiceTest.java +++ b/management/src/test/java/org/ehcache/management/registry/DefaultSharedManagementServiceTest.java @@ -51,10 +51,10 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.isIn; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; @RunWith(JUnit4.class) diff --git a/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java b/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java index 5c5d08ca9c..79bd415c24 100644 --- a/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java +++ b/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java @@ -20,7 +20,7 @@ import org.xmlunit.diff.DefaultNodeMatcher; import org.xmlunit.diff.ElementSelectors; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** diff --git a/management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java b/management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java index e2e97e3a7a..6b9edebb87 100644 --- a/management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java +++ b/management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java @@ -30,7 +30,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; @RunWith(Parameterized.class) public class XmlConfigTest { diff --git a/osgi-test/build.gradle b/osgi-test/build.gradle index 0c1262d75a..797569757d 100644 --- a/osgi-test/build.gradle +++ b/osgi-test/build.gradle @@ -77,6 +77,10 @@ configurations.all { substitute(module('org.ops4j.pax.url:pax-url-link:2.4.5')) .because('https://ops4j1.jira.com/browse/PAXURL-341') .with(module('org.ops4j.pax.url:pax-url-link:2.6.1')) + + substitute(module('junit:junit:4.12')) + .because('CVE-2020-15250') + .with(module('junit:junit:4.13.1')) } } } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java index f6b4b82be5..fe466026a5 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java @@ -44,9 +44,9 @@ import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsCollectionContaining.hasItems; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; import static org.ops4j.pax.exam.CoreOptions.options; /** diff --git a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java index a2ec69224c..cc072fefb7 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java @@ -49,9 +49,9 @@ import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsCollectionContaining.hasItems; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.ops4j.pax.exam.CoreOptions.frameworkProperty; import static org.ops4j.pax.exam.CoreOptions.options; diff --git a/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java b/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java index e670f5cca9..da2e333762 100644 --- a/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java +++ b/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java @@ -49,8 +49,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import static java.util.Collections.singletonMap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; /** diff --git a/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java b/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java index 2c07e5f62d..c662f32ab7 100644 --- a/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java @@ -32,8 +32,8 @@ import static java.util.Spliterators.spliterator; import static java.util.stream.Collectors.toList; import static java.util.stream.StreamSupport.stream; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsCollectionContaining.hasItems; -import static org.junit.Assert.assertThat; /** * Ensures that a non-XA {@code CacheManager} can be created when XA classes are diff --git a/transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java b/transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java index 99662a1b83..4ef9d0d9a1 100644 --- a/transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java +++ b/transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java @@ -23,7 +23,7 @@ import java.net.URL; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** diff --git a/transactions/src/test/java/org/ehcache/transactions/XmlConfigTest.java b/transactions/src/test/java/org/ehcache/transactions/XmlConfigTest.java index 46912b8fff..2334523844 100644 --- a/transactions/src/test/java/org/ehcache/transactions/XmlConfigTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/XmlConfigTest.java @@ -28,8 +28,8 @@ import java.net.URL; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * @author Ludovic Orban diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/configuration/XAStoreConfigurationTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/configuration/XAStoreConfigurationTest.java index c57c4be428..6d05489192 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/configuration/XAStoreConfigurationTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/configuration/XAStoreConfigurationTest.java @@ -19,9 +19,9 @@ import org.hamcrest.core.IsNot; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; public class XAStoreConfigurationTest { diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/EhcacheXAResourceTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/EhcacheXAResourceTest.java index 4129ce1c1b..34a17f97bb 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/EhcacheXAResourceTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/EhcacheXAResourceTest.java @@ -32,8 +32,8 @@ import java.util.Collection; import java.util.Collections; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java index 30b0bd2230..be637928f8 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java @@ -93,11 +93,11 @@ import static java.util.Collections.emptySet; import static org.ehcache.config.builders.ExpiryPolicyBuilder.timeToLiveExpiration; import static org.ehcache.core.spi.ServiceLocator.dependencySet; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java index 724d5952d6..a1989cf3a9 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java @@ -26,7 +26,6 @@ import org.ehcache.transactions.xa.internal.journal.Journal; import org.ehcache.core.spi.store.Store.ReplaceStatus; import org.ehcache.transactions.xa.utils.TestXid; -import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; @@ -235,7 +234,7 @@ public void testPrepare() throws Exception { assertThat(xaTransactionContext.prepare(), is(3)); - Assert.assertThat(savedInDoubt.get(), containsInAnyOrder(1L, 2L, 3L)); + assertThat(savedInDoubt.get(), containsInAnyOrder(1L, 2L, 3L)); verify(journal, times(1)).saveInDoubt(eq(new TransactionId(new TestXid(0, 0))), any(Collection.class)); verify(journal, times(0)).saveCommitted(eq(new TransactionId(new TestXid(0, 0))), anyBoolean()); @@ -376,7 +375,7 @@ public Object get() { xaTransactionContext.commitInOnePhase(); - Assert.assertThat(savedInDoubtCollectionRef.get(), containsInAnyOrder(1L, 2L, 3L)); + assertThat(savedInDoubtCollectionRef.get(), containsInAnyOrder(1L, 2L, 3L)); verify(journal, times(1)).saveCommitted(eq(new TransactionId(new TestXid(0, 0))), eq(false)); verify(journal, times(0)).saveRolledBack(eq(new TransactionId(new TestXid(0, 0))), anyBoolean()); diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAValueHolderTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAValueHolderTest.java index f80ed61687..7419cf27a0 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAValueHolderTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAValueHolderTest.java @@ -25,8 +25,8 @@ import java.time.Duration; import java.util.concurrent.TimeUnit; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * XAValueHolderTest diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/AbstractJournalTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/AbstractJournalTest.java index 23db80924b..754f756936 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/AbstractJournalTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/AbstractJournalTest.java @@ -27,10 +27,10 @@ import java.util.Collection; import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; /** diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java index 0028025b0d..8680bc7662 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java @@ -25,9 +25,9 @@ import java.util.Arrays; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; /** * @author Ludovic Orban diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java index b52d0c9cbe..53f2cbecb4 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java @@ -23,7 +23,7 @@ import org.xmlunit.diff.ElementSelectors; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java index 9cd5276ef8..234784d74b 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java @@ -21,7 +21,7 @@ import org.xmlunit.diff.DefaultNodeMatcher; import org.xmlunit.diff.ElementSelectors; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfigurationTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfigurationTest.java index f5425eedad..8211c1456c 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfigurationTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfigurationTest.java @@ -18,10 +18,10 @@ import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; public class LookupTransactionManagerProviderConfigurationTest { diff --git a/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java b/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java index c58a20cb83..397184bf94 100644 --- a/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java +++ b/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java @@ -23,7 +23,6 @@ import org.hamcrest.collection.IsMapContaining; import org.hamcrest.core.AllOf; import org.hamcrest.core.Is; -import org.junit.Assert; import org.junit.Test; import org.w3c.dom.Document; @@ -32,6 +31,8 @@ import java.util.function.Function; import java.util.stream.Collectors; +import static org.hamcrest.MatcherAssert.assertThat; + public class MultiGettingStarted { @Test @@ -44,7 +45,7 @@ public void multipleConfigurations() { Configuration fooConfiguration = multipleConfiguration.configuration("foo-manager"); // <3> //end::multipleManagers[] - Assert.assertThat(resourceMap(multipleConfiguration.identities().stream().collect( + assertThat(resourceMap(multipleConfiguration.identities().stream().collect( Collectors.toMap(Function.identity(), multipleConfiguration::configuration) )), AllOf.allOf( IsMapContaining.hasEntry(Is.is("foo-manager"), IsMapContaining.hasEntry(Is.is("foo"), IsIterableContainingInAnyOrder.containsInAnyOrder(ResourceType.Core.HEAP, ResourceType.Core.OFFHEAP))), @@ -62,14 +63,14 @@ public void multipleVariants() { Configuration fooConfiguration = variantConfiguration.configuration("foo-manager", "offheap"); // <1> //end::multipleVariants[] - Assert.assertThat(resourceMap(variantConfiguration.identities().stream().collect( + assertThat(resourceMap(variantConfiguration.identities().stream().collect( Collectors.toMap(Function.identity(), i -> variantConfiguration.configuration(i, "offheap")) )), AllOf.allOf( IsMapContaining.hasEntry(Is.is("foo-manager"), IsMapContaining.hasEntry(Is.is("foo"), IsIterableContainingInAnyOrder.containsInAnyOrder(ResourceType.Core.HEAP, ResourceType.Core.OFFHEAP))), IsMapContaining.hasEntry(Is.is("bar-manager"), IsMapContaining.hasEntry(Is.is("bar"), IsIterableContainingInAnyOrder.containsInAnyOrder(ResourceType.Core.HEAP))) )); - Assert.assertThat(resourceMap(variantConfiguration.identities().stream().collect( + assertThat(resourceMap(variantConfiguration.identities().stream().collect( Collectors.toMap(Function.identity(), i -> variantConfiguration.configuration(i, "heap")) )), AllOf.allOf( IsMapContaining.hasEntry(Is.is("foo-manager"), IsMapContaining.hasEntry(Is.is("foo"), IsIterableContainingInAnyOrder.containsInAnyOrder(ResourceType.Core.HEAP))), @@ -93,12 +94,12 @@ public void multipleRetrieval() { .collect(Collectors.toMap(i -> i, i -> variantConfiguration.configuration(i, "offheap"))); // <3> //end::multipleRetrieval[] - Assert.assertThat(resourceMap(allConfigurations), AllOf.allOf( + assertThat(resourceMap(allConfigurations), AllOf.allOf( IsMapContaining.hasEntry(Is.is("foo-manager"), IsMapContaining.hasEntry(Is.is("foo"), IsIterableContainingInAnyOrder.containsInAnyOrder(ResourceType.Core.HEAP, ResourceType.Core.OFFHEAP))), IsMapContaining.hasEntry(Is.is("bar-manager"), IsMapContaining.hasEntry(Is.is("bar"), IsIterableContainingInAnyOrder.containsInAnyOrder(ResourceType.Core.HEAP, ResourceType.Core.OFFHEAP))) )); - Assert.assertThat(resourceMap(offheapConfigurations), AllOf.allOf( + assertThat(resourceMap(offheapConfigurations), AllOf.allOf( IsMapContaining.hasEntry(Is.is("foo-manager"), IsMapContaining.hasEntry(Is.is("foo"), IsIterableContainingInAnyOrder.containsInAnyOrder(ResourceType.Core.HEAP, ResourceType.Core.OFFHEAP))), IsMapContaining.hasEntry(Is.is("bar-manager"), IsMapContaining.hasEntry(Is.is("bar"), IsIterableContainingInAnyOrder.containsInAnyOrder(ResourceType.Core.HEAP))) )); diff --git a/xml/src/test/java/org/ehcache/xml/ConfigurationParserTestHelper.java b/xml/src/test/java/org/ehcache/xml/ConfigurationParserTestHelper.java index 4a75ddd7f2..f92295e6b9 100644 --- a/xml/src/test/java/org/ehcache/xml/ConfigurationParserTestHelper.java +++ b/xml/src/test/java/org/ehcache/xml/ConfigurationParserTestHelper.java @@ -20,7 +20,6 @@ import org.xmlunit.diff.DefaultNodeMatcher; import org.xmlunit.diff.ElementSelectors; -import static org.junit.Assert.assertThat; import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** diff --git a/xml/src/test/java/org/ehcache/xml/CoreCacheConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/CoreCacheConfigurationParserTest.java index fff46bcfb2..5768e79f10 100644 --- a/xml/src/test/java/org/ehcache/xml/CoreCacheConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/CoreCacheConfigurationParserTest.java @@ -39,8 +39,8 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; public class CoreCacheConfigurationParserTest { diff --git a/xml/src/test/java/org/ehcache/xml/FromTemplateCacheConfigurationBuilderDefaultTest.java b/xml/src/test/java/org/ehcache/xml/FromTemplateCacheConfigurationBuilderDefaultTest.java index b4a4b19917..ee4a219dce 100644 --- a/xml/src/test/java/org/ehcache/xml/FromTemplateCacheConfigurationBuilderDefaultTest.java +++ b/xml/src/test/java/org/ehcache/xml/FromTemplateCacheConfigurationBuilderDefaultTest.java @@ -21,8 +21,8 @@ import org.junit.Test; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * TemplateDefaultTest diff --git a/xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java index 3c5cd03aa5..e77d27dbd2 100644 --- a/xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java @@ -51,11 +51,11 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.StringContains.containsString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; /** diff --git a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java index e1a1ff31bb..988e68d9d3 100644 --- a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java @@ -49,9 +49,7 @@ import org.hamcrest.core.IsCollectionContaining; import org.hamcrest.core.IsEqual; import org.hamcrest.core.IsNull; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -98,7 +96,9 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.isIn; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; @@ -111,7 +111,7 @@ import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; @@ -122,9 +122,6 @@ */ public class XmlConfigurationTest { - @Rule - public ExpectedException thrown = ExpectedException.none(); - @Test public void testDefaultTypesConfig() throws Exception { URL resource = XmlConfigurationTest.class.getResource("/configs/defaultTypes-cache.xml"); @@ -623,23 +620,20 @@ public void testDiskStoreSettings() throws Exception { @Test public void testNullUrlInConstructorThrowsNPE() throws Exception { - thrown.expect(NullPointerException.class); - thrown.expectMessage("The url can not be null"); - new XmlConfiguration((URL) null, mock(ClassLoader.class), getClassLoaderMapMock()); + NullPointerException thrown = assertThrows(NullPointerException.class, () -> new XmlConfiguration((URL) null, mock(ClassLoader.class), getClassLoaderMapMock())); + assertThat(thrown, hasProperty("message", Matchers.is("The url can not be null"))); } @Test public void testNullClassLoaderInConstructorThrowsNPE() throws Exception { - thrown.expect(NullPointerException.class); - thrown.expectMessage("The classLoader can not be null"); - new XmlConfiguration(XmlConfigurationTest.class.getResource("/configs/one-cache.xml"), null, getClassLoaderMapMock()); + NullPointerException thrown = assertThrows(NullPointerException.class, () -> new XmlConfiguration(XmlConfigurationTest.class.getResource("/configs/one-cache.xml"), null, getClassLoaderMapMock())); + assertThat(thrown, hasProperty("message", Matchers.is("The classLoader can not be null"))); } @Test public void testNullCacheClassLoaderMapInConstructorThrowsNPE() throws Exception { - thrown.expect(NullPointerException.class); - thrown.expectMessage("The cacheClassLoaders map can not be null"); - new XmlConfiguration(XmlConfigurationTest.class.getResource("/configs/one-cache.xml"), mock(ClassLoader.class), null); + NullPointerException thrown = assertThrows(NullPointerException.class, () -> new XmlConfiguration(XmlConfigurationTest.class.getResource("/configs/one-cache.xml"), mock(ClassLoader.class), null)); + assertThat(thrown, hasProperty("message", Matchers.is("The cacheClassLoaders map can not be null"))); } @Test diff --git a/xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java index a44145115c..16c2bbff09 100644 --- a/xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java @@ -27,6 +27,7 @@ import java.net.URISyntaxException; import java.net.URL; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.collection.IsEmptyCollection.empty; import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; @@ -34,7 +35,6 @@ import static org.hamcrest.core.IsNull.notNullValue; import static org.hamcrest.core.IsNull.nullValue; import static org.hamcrest.core.IsSame.sameInstance; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.xmlunit.diff.ElementSelectors.and; import static org.xmlunit.diff.ElementSelectors.byNameAndAllAttributes; From d5a82f92b9807e5bf6c8f771b7929db8ccdbd47b Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 16 Nov 2020 17:03:32 -0500 Subject: [PATCH 302/372] Move back to org.junit.rules.TemporaryFolder --- .../ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java | 2 +- .../test/java/org/ehcache/jsr107/ResourceCombinationsTest.java | 2 +- .../ClusteringCacheManagerServiceConfigurationParserTest.java | 2 +- .../src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java | 2 +- .../test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java | 2 +- .../org/ehcache/config/builders/PersistentCacheManagerTest.java | 2 +- .../java/org/ehcache/core/events/CacheManagerListenerTest.java | 2 +- impl/src/test/java/org/ehcache/docs/GettingStarted.java | 2 +- impl/src/test/java/org/ehcache/docs/ThreadPools.java | 2 +- impl/src/test/java/org/ehcache/docs/Tiering.java | 2 +- impl/src/test/java/org/ehcache/docs/UserManagedCaches.java | 2 +- .../ehcache/impl/config/serializer/SerializerCountingTest.java | 2 +- .../persistence/CacheManagerDestroyRemovesPersistenceTest.java | 2 +- .../impl/internal/persistence/TestDiskResourceService.java | 2 +- .../spi/serialization/DefaultSerializationProviderTest.java | 2 +- .../disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java | 2 +- .../impl/internal/store/disk/OffHeapDiskStoreSPITest.java | 2 +- .../ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java | 2 +- .../store/disk/factories/EhcachePersistentSegmentTest.java | 2 +- .../store/tiering/TieredStoreFlushWhileShutdownTest.java | 2 +- .../ehcache/impl/internal/store/tiering/TieredStoreSPITest.java | 2 +- .../internal/store/tiering/TieredStoreWith3TiersSPITest.java | 2 +- .../ehcache/impl/internal/util/FileExistenceMatchersTest.java | 2 +- .../impl/persistence/DefaultLocalPersistenceServiceTest.java | 2 +- .../ehcache/impl/persistence/FileBasedStateRepositoryTest.java | 2 +- .../src/test/java/org/ehcache/integration/ExpiryEventsTest.java | 2 +- .../test/java/org/ehcache/integration/PersistentCacheTest.java | 2 +- .../org/ehcache/integration/PersistentUserManagedCacheTest.java | 2 +- .../src/test/java/org/ehcache/integration/SerializersTest.java | 2 +- .../integration/StatefulSerializerWithStateRepositoryTest.java | 2 +- .../test/java/org/ehcache/integration/StoreStatisticsTest.java | 2 +- .../ehcache/integration/statistics/AbstractCalculationTest.java | 2 +- .../org/ehcache/integration/transactions/xa/XACacheTest.java | 2 +- .../providers/settings/EhcacheSettingsProviderTest.java | 2 +- .../statistics/StandardEhCacheStatisticsQueryTest.java | 2 +- .../registry/DefaultManagementRegistryServiceTest.java | 2 +- .../java/org/ehcache/docs/transactions/xa/XAGettingStarted.java | 2 +- .../transactions/xa/internal/journal/PersistentJournalTest.java | 2 +- xml/src/test/java/org/ehcache/docs/GettingStarted.java | 2 +- 39 files changed, 39 insertions(+), 39 deletions(-) diff --git a/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java b/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java index da71667b2e..165fa321d6 100644 --- a/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java +++ b/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java @@ -29,12 +29,12 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.pany.domain.Client; import com.pany.domain.Product; -import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; import java.util.Random; diff --git a/107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java b/107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java index 6232144fa4..d8964866fa 100644 --- a/107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java +++ b/107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java @@ -30,10 +30,10 @@ import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; -import org.terracotta.org.junit.rules.TemporaryFolder; import static java.util.Arrays.asList; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java index 6012172727..a3e3cddd7e 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java @@ -32,8 +32,8 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.junit.rules.TestName; -import org.terracotta.org.junit.rules.TemporaryFolder; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.xmlunit.diff.DefaultNodeMatcher; diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java index 8dcaa04fe4..b664b7e9b1 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java @@ -26,6 +26,7 @@ import org.ehcache.xml.XmlConfiguration; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Configuration; import org.ops4j.pax.exam.Option; @@ -33,7 +34,6 @@ import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerMethod; import org.osgi.framework.wiring.BundleWiring; -import org.terracotta.org.junit.rules.TemporaryFolder; import org.w3c.dom.Document; import org.w3c.dom.Node; diff --git a/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java b/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java index 0638e2c04a..570feecd3e 100644 --- a/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java +++ b/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java @@ -26,9 +26,9 @@ import org.ehcache.config.units.EntryUnit; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.ehcache.config.units.MemoryUnit; -import org.terracotta.org.junit.rules.TemporaryFolder; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; diff --git a/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java b/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java index 917233b758..a2ba2fa045 100644 --- a/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java +++ b/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java @@ -23,7 +23,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java b/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java index e1f2017efc..9b09f4fcb6 100644 --- a/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java +++ b/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java @@ -26,7 +26,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import static org.ehcache.config.units.MemoryUnit.MB; import static org.mockito.Mockito.mock; diff --git a/impl/src/test/java/org/ehcache/docs/GettingStarted.java b/impl/src/test/java/org/ehcache/docs/GettingStarted.java index 0bb34c394e..f3429094e9 100644 --- a/impl/src/test/java/org/ehcache/docs/GettingStarted.java +++ b/impl/src/test/java/org/ehcache/docs/GettingStarted.java @@ -39,7 +39,7 @@ import org.ehcache.impl.copy.ReadWriteCopier; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/docs/ThreadPools.java b/impl/src/test/java/org/ehcache/docs/ThreadPools.java index 12f3faf63e..9a8e07a2ae 100644 --- a/impl/src/test/java/org/ehcache/docs/ThreadPools.java +++ b/impl/src/test/java/org/ehcache/docs/ThreadPools.java @@ -32,7 +32,7 @@ import org.ehcache.config.builders.PooledExecutionServiceConfigurationBuilder; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/docs/Tiering.java b/impl/src/test/java/org/ehcache/docs/Tiering.java index 8438a0936a..6d1cb8d3e9 100644 --- a/impl/src/test/java/org/ehcache/docs/Tiering.java +++ b/impl/src/test/java/org/ehcache/docs/Tiering.java @@ -36,7 +36,7 @@ import org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; diff --git a/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java b/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java index 88502394d7..07be4a80f3 100644 --- a/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java +++ b/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java @@ -31,7 +31,7 @@ import org.ehcache.impl.config.persistence.UserManagedPersistenceContext; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java b/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java index e0613188f2..0b15b4d954 100644 --- a/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java +++ b/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java @@ -31,7 +31,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.Serializable; import java.nio.ByteBuffer; diff --git a/impl/src/test/java/org/ehcache/impl/internal/persistence/CacheManagerDestroyRemovesPersistenceTest.java b/impl/src/test/java/org/ehcache/impl/internal/persistence/CacheManagerDestroyRemovesPersistenceTest.java index 4b95bfb10b..ac5137dfce 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/persistence/CacheManagerDestroyRemovesPersistenceTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/persistence/CacheManagerDestroyRemovesPersistenceTest.java @@ -24,7 +24,7 @@ import org.ehcache.impl.config.persistence.CacheManagerPersistenceConfiguration; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/impl/internal/persistence/TestDiskResourceService.java b/impl/src/test/java/org/ehcache/impl/internal/persistence/TestDiskResourceService.java index d3a5199598..2538215160 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/persistence/TestDiskResourceService.java +++ b/impl/src/test/java/org/ehcache/impl/internal/persistence/TestDiskResourceService.java @@ -30,8 +30,8 @@ import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceProvider; import org.junit.rules.ExternalResource; +import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; -import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java index aeee5e3b7b..4c07aca184 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java @@ -39,7 +39,7 @@ import org.hamcrest.Matchers; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.Closeable; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java index 40bb6539cd..132ae1aa9c 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java @@ -29,11 +29,11 @@ import org.ehcache.spi.serialization.Serializer; import org.ehcache.spi.serialization.UnsupportedTypeException; import org.junit.Rule; +import org.junit.rules.TemporaryFolder; import org.terracotta.offheapstore.disk.paging.MappedPageSource; import org.terracotta.offheapstore.disk.persistent.PersistentPortability; import org.terracotta.offheapstore.disk.storage.FileBackedStorageEngine; import org.terracotta.offheapstore.util.Factory; -import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java index 20244a7ca4..c855aa6a77 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java @@ -47,7 +47,7 @@ import org.ehcache.spi.test.After; import org.junit.Before; import org.junit.Rule; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import org.terracotta.statistics.StatisticsManager; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java index 8bbc9600f9..eeea3f8a10 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java @@ -55,11 +55,11 @@ import org.ehcache.test.MockitoUtil; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.mockito.Answers; import org.terracotta.context.query.Matcher; import org.terracotta.context.query.Query; import org.terracotta.context.query.QueryBuilder; -import org.terracotta.org.junit.rules.TemporaryFolder; import org.terracotta.statistics.OperationStatistic; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java index 61701a3e87..611c846a25 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java @@ -29,11 +29,11 @@ import org.ehcache.spi.serialization.UnsupportedTypeException; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.terracotta.offheapstore.disk.paging.MappedPageSource; import org.terracotta.offheapstore.disk.persistent.PersistentPortability; import org.terracotta.offheapstore.disk.storage.FileBackedStorageEngine; import org.terracotta.offheapstore.util.Factory; -import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java index 65ce0eb2d5..bede68ca2c 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java @@ -38,9 +38,9 @@ import org.ehcache.spi.persistence.PersistableResourceService.PersistenceSpaceIdentifier; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.mockito.Answers; import org.mockito.Mockito; -import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java index 6d0bad8aed..e51e7f849f 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java @@ -58,7 +58,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Rule; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.IOException; import java.util.Arrays; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java index a725c2be0e..6474aef6cc 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java @@ -61,7 +61,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Rule; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.IOException; import java.util.Arrays; diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java b/impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java index db589328c8..eb2d8053f0 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java @@ -18,7 +18,7 @@ import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java b/impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java index a1225b2790..4281cc9345 100644 --- a/impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java +++ b/impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java @@ -22,7 +22,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; diff --git a/impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java b/impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java index ca423ce8a9..55ba86bb69 100644 --- a/impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java +++ b/impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java @@ -20,7 +20,7 @@ import org.ehcache.spi.persistence.StateHolder; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.FileInputStream; diff --git a/integration-test/src/test/java/org/ehcache/integration/ExpiryEventsTest.java b/integration-test/src/test/java/org/ehcache/integration/ExpiryEventsTest.java index 38f2f98dc6..30fd427980 100644 --- a/integration-test/src/test/java/org/ehcache/integration/ExpiryEventsTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/ExpiryEventsTest.java @@ -35,7 +35,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.IOException; import java.time.Duration; diff --git a/integration-test/src/test/java/org/ehcache/integration/PersistentCacheTest.java b/integration-test/src/test/java/org/ehcache/integration/PersistentCacheTest.java index 29adf0d7c0..b1e72ca780 100644 --- a/integration-test/src/test/java/org/ehcache/integration/PersistentCacheTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/PersistentCacheTest.java @@ -27,7 +27,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.Serializable; diff --git a/integration-test/src/test/java/org/ehcache/integration/PersistentUserManagedCacheTest.java b/integration-test/src/test/java/org/ehcache/integration/PersistentUserManagedCacheTest.java index 97f4de0437..c3921d46c1 100644 --- a/integration-test/src/test/java/org/ehcache/integration/PersistentUserManagedCacheTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/PersistentUserManagedCacheTest.java @@ -27,7 +27,7 @@ import org.ehcache.impl.persistence.DefaultLocalPersistenceService; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.Serializable; diff --git a/integration-test/src/test/java/org/ehcache/integration/SerializersTest.java b/integration-test/src/test/java/org/ehcache/integration/SerializersTest.java index 370ae18064..0fa71ab5a6 100644 --- a/integration-test/src/test/java/org/ehcache/integration/SerializersTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/SerializersTest.java @@ -29,7 +29,7 @@ import org.ehcache.spi.serialization.StatefulSerializer; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.nio.ByteBuffer; diff --git a/integration-test/src/test/java/org/ehcache/integration/StatefulSerializerWithStateRepositoryTest.java b/integration-test/src/test/java/org/ehcache/integration/StatefulSerializerWithStateRepositoryTest.java index 258d358a48..5b8f076b00 100644 --- a/integration-test/src/test/java/org/ehcache/integration/StatefulSerializerWithStateRepositoryTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/StatefulSerializerWithStateRepositoryTest.java @@ -24,7 +24,7 @@ import org.ehcache.integration.domain.Person; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; diff --git a/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java b/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java index dd088a52d7..e086204646 100644 --- a/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/StoreStatisticsTest.java @@ -29,12 +29,12 @@ import org.ehcache.impl.config.persistence.CacheManagerPersistenceConfiguration; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.terracotta.context.ContextManager; import org.terracotta.context.TreeNode; import org.terracotta.context.query.Matcher; import org.terracotta.context.query.Matchers; import org.terracotta.context.query.Query; -import org.terracotta.org.junit.rules.TemporaryFolder; import org.terracotta.statistics.OperationStatistic; import java.io.File; diff --git a/integration-test/src/test/java/org/ehcache/integration/statistics/AbstractCalculationTest.java b/integration-test/src/test/java/org/ehcache/integration/statistics/AbstractCalculationTest.java index f9a7dfaa51..5d96210727 100644 --- a/integration-test/src/test/java/org/ehcache/integration/statistics/AbstractCalculationTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/statistics/AbstractCalculationTest.java @@ -27,11 +27,11 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.junit.Rule; +import org.junit.rules.TemporaryFolder; import org.junit.rules.TestWatcher; import org.junit.runner.Description; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.terracotta.org.junit.rules.TemporaryFolder; import static org.assertj.core.api.Assertions.assertThat; diff --git a/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java b/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java index a5af58be1f..5d5f159fd1 100644 --- a/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/transactions/xa/XACacheTest.java @@ -39,7 +39,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import javax.transaction.RollbackException; import javax.transaction.Status; diff --git a/management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java b/management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java index 31215470c1..2e97b92a45 100644 --- a/management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java +++ b/management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java @@ -32,11 +32,11 @@ import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.terracotta.management.model.capabilities.Capability; import org.terracotta.management.model.capabilities.context.CapabilityContext; -import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.FileNotFoundException; import java.io.IOException; diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java index db775ea0e3..ff3e70125b 100755 --- a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java @@ -35,6 +35,7 @@ import org.hamcrest.Matchers; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.junit.rules.Timeout; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -42,7 +43,6 @@ import org.terracotta.management.model.stats.ContextualStatistics; import org.terracotta.management.registry.ResultSet; import org.terracotta.management.registry.StatisticQuery; -import org.terracotta.org.junit.rules.TemporaryFolder; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; diff --git a/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java b/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java index 290dbf38bf..982bed6dad 100644 --- a/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java +++ b/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java @@ -37,6 +37,7 @@ import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.junit.rules.Timeout; import org.terracotta.management.model.call.ContextualReturn; import org.terracotta.management.model.capabilities.Capability; @@ -47,7 +48,6 @@ import org.terracotta.management.model.stats.ContextualStatistics; import org.terracotta.management.registry.ResultSet; import org.terracotta.management.registry.StatisticQuery.Builder; -import org.terracotta.org.junit.rules.TemporaryFolder; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; diff --git a/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java b/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java index da2e333762..5caf90a9d7 100644 --- a/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java +++ b/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java @@ -37,9 +37,9 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.terracotta.org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java index 8680bc7662..0a8685d48f 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java @@ -21,7 +21,7 @@ import org.ehcache.transactions.xa.utils.TestXid; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.util.Arrays; diff --git a/xml/src/test/java/org/ehcache/docs/GettingStarted.java b/xml/src/test/java/org/ehcache/docs/GettingStarted.java index 584790cb5d..f4a8f1516f 100644 --- a/xml/src/test/java/org/ehcache/docs/GettingStarted.java +++ b/xml/src/test/java/org/ehcache/docs/GettingStarted.java @@ -27,7 +27,7 @@ import org.ehcache.xml.XmlConfiguration; import org.junit.Rule; import org.junit.Test; -import org.terracotta.org.junit.rules.TemporaryFolder; +import org.junit.rules.TemporaryFolder; import java.io.IOException; import java.net.URL; From 91107968c1f068e7fc37bfcb96b76e9d5dc4596a Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 20 Nov 2020 11:02:31 -0500 Subject: [PATCH 303/372] Fix XML-Unit assertions to be correctly tolerant of element ordering --- clustered/client/build.gradle | 3 +- .../ClusteredCacheConfigurationParserIT.java | 7 +- ...steredResourceConfigurationParserTest.java | 13 ++-- ...ManagerServiceConfigurationParserTest.java | 16 ++--- ...ngCacheServiceConfigurationParserTest.java | 7 +- management/build.gradle | 3 +- ...tRegistryServiceConfigurationParserIT.java | 10 +-- ...egistryServiceConfigurationParserTest.java | 10 +-- transactions/build.gradle | 3 +- .../TransactionalCacheParserIT.java | 8 +-- ...ManagerServiceConfigurationParserTest.java | 8 +-- ...TxCacheServiceConfigurationParserTest.java | 7 +- xml/build.gradle | 3 +- .../org/ehcache/xml/XmlConfigurationTest.java | 6 +- .../xml/multi/XmlMultiConfigurationTest.java | 66 ++++++++----------- .../ehcache/xml/XmlConfigurationMatchers.java | 57 ++++++++++++++++ 16 files changed, 119 insertions(+), 108 deletions(-) create mode 100644 xml/src/testFixtures/java/org/ehcache/xml/XmlConfigurationMatchers.java diff --git a/clustered/client/build.gradle b/clustered/client/build.gradle index aa134c0eec..33474da992 100644 --- a/clustered/client/build.gradle +++ b/clustered/client/build.gradle @@ -47,7 +47,6 @@ dependencies { testImplementation (group: 'org.codehaus.btm', name: 'btm', version: '2.1.4') { exclude group:'org.slf4j', module:'slf4j-api' } - testImplementation 'org.xmlunit:xmlunit-core:2.6.0' - testImplementation 'org.xmlunit:xmlunit-matchers:2.6.0' + testImplementation testFixtures(project(':xml')) testImplementation ("org.terracotta:statistics:$parent.statisticVersion") } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java index f8f5880ce4..3b90be498b 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java @@ -18,13 +18,11 @@ import org.ehcache.config.Configuration; import org.ehcache.xml.XmlConfiguration; import org.junit.Test; -import org.xmlunit.diff.DefaultNodeMatcher; -import org.xmlunit.diff.ElementSelectors; import java.net.URL; +import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.hamcrest.MatcherAssert.assertThat; -import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** * ClusteredCacheConfigurationParserIT @@ -36,7 +34,6 @@ public void testClusteredCacheXmlTranslationToString() { URL resource = ClusteredCacheConfigurationParserIT.class.getResource("/configs/clustered-cache.xml"); Configuration config = new XmlConfiguration(resource); XmlConfiguration xmlConfig = new XmlConfiguration(config); - assertThat(xmlConfig.toString(), isSimilarTo(resource).ignoreComments().ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndAllAttributes))); + assertThat(xmlConfig.toString(), isSameConfigurationAs(resource)); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java index d8de0c7cdc..8eb8f5784f 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java @@ -21,11 +21,9 @@ import org.ehcache.config.units.MemoryUnit; import org.junit.Test; import org.w3c.dom.Node; -import org.xmlunit.diff.DefaultNodeMatcher; -import org.xmlunit.diff.ElementSelectors; +import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.hamcrest.MatcherAssert.assertThat; -import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** * ClusteredResourceConfigurationParserTest @@ -38,8 +36,7 @@ public void testTranslateClusteredResourcePoolConfiguration() { ClusteredResourcePoolImpl clusteredResourcePool = new ClusteredResourcePoolImpl(); Node retElement = configTranslator.unparseResourcePool(clusteredResourcePool); String inputString = ""; - assertThat(retElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(retElement, isSameConfigurationAs(inputString)); } @Test @@ -49,8 +46,7 @@ public void testTranslateDedicatedResourcePoolConfiguration() { Node retElement = configTranslator.unparseResourcePool(dedicatedClusteredResourcePool); String inputString = "12"; - assertThat(retElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(retElement, isSameConfigurationAs(inputString)); } @Test @@ -60,8 +56,7 @@ public void testTranslateSharedResourcePoolConfiguration() { Node retElement = configTranslator.unparseResourcePool(sharedResourcePool); String inputString = ""; - assertThat(retElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(retElement, isSameConfigurationAs(inputString)); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java index a3e3cddd7e..dc933e2b7f 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java @@ -36,8 +36,6 @@ import org.junit.rules.TestName; import org.w3c.dom.Attr; import org.w3c.dom.Element; -import org.xmlunit.diff.DefaultNodeMatcher; -import org.xmlunit.diff.ElementSelectors; import java.io.File; import java.io.FileOutputStream; @@ -63,6 +61,7 @@ import static java.util.Spliterators.spliterator; import static java.util.stream.StreamSupport.stream; import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; +import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.ehcache.xml.XmlModel.convertToJavaTimeUnit; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; @@ -73,7 +72,6 @@ import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.IsCollectionContaining.hasItem; import static org.junit.Assert.fail; -import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; public class ClusteringCacheManagerServiceConfigurationParserTest { @@ -513,8 +511,7 @@ public void testTranslateServiceCreationConfiguration() throws Exception { "5368709120" + "10737418240" + ""; - assertThat(returnElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(returnElement, isSameConfigurationAs(inputString)); } @Test @@ -537,8 +534,7 @@ public void testTranslateServiceCreationConfigurationWithNoResourcePoolAndAutoCr "" + "" + ""; - assertThat(returnElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(returnElement, isSameConfigurationAs(inputString)); } @Test @@ -557,8 +553,7 @@ public void testTranslateServiceCreationConfigurationWithNoServerSideConfig() th "5" + "150" + ""; - assertThat(returnElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(returnElement, isSameConfigurationAs(inputString)); } @Test @@ -588,8 +583,7 @@ public void testTranslateServiceCreationConfigurationWithInetSocketAddress() { "5" + "150" + ""; - assertThat(returnElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(returnElement, isSameConfigurationAs(inputString)); } /** diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java index ae1694471d..a1829d7f7d 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java @@ -19,11 +19,9 @@ import org.ehcache.clustered.common.Consistency; import org.junit.Test; import org.w3c.dom.Node; -import org.xmlunit.diff.DefaultNodeMatcher; -import org.xmlunit.diff.ElementSelectors; +import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.hamcrest.MatcherAssert.assertThat; -import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; public class ClusteringCacheServiceConfigurationParserTest { @@ -36,7 +34,6 @@ public void testTranslateServiceStoreConfiguration() { String inputString = ""; - assertThat(retNode, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(retNode, isSameConfigurationAs(inputString)); } } diff --git a/management/build.gradle b/management/build.gradle index ffa4b3a93e..dcff645726 100644 --- a/management/build.gradle +++ b/management/build.gradle @@ -37,6 +37,5 @@ dependencies { testImplementation project(':xml') testImplementation project(':impl') testImplementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" - testImplementation 'org.xmlunit:xmlunit-core:2.6.0' - testImplementation 'org.xmlunit:xmlunit-matchers:2.6.0' + testImplementation testFixtures(project(':xml')) } diff --git a/management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java b/management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java index 79843c1454..4c33101298 100644 --- a/management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java +++ b/management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java @@ -18,13 +18,14 @@ import org.ehcache.config.Configuration; import org.ehcache.xml.XmlConfiguration; import org.junit.Test; -import org.xmlunit.diff.DefaultNodeMatcher; -import org.xmlunit.diff.ElementSelectors; +import javax.xml.namespace.QName; import java.net.URL; +import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.hamcrest.MatcherAssert.assertThat; -import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; +import static org.xmlunit.diff.ElementSelectors.byNameAndText; +import static org.xmlunit.diff.ElementSelectors.selectorForElementNamed; /** * ManagementRegistryServiceConfigurationParserIT @@ -36,7 +37,6 @@ public void testManagementRegistryXmlTranslationToString() { URL resource = ManagementRegistryServiceConfigurationParserIT.class.getResource("/ehcache-management.xml"); Configuration config = new XmlConfiguration(resource); XmlConfiguration xmlConfig = new XmlConfiguration(config); - assertThat(xmlConfig.toString(), isSimilarTo(resource).ignoreComments().ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(xmlConfig.toString(), isSameConfigurationAs(resource, selectorForElementNamed(new QName("http://www.ehcache.org/v3/management", "tag"), byNameAndText))); } } diff --git a/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java b/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java index 79bd415c24..4e24db76f2 100644 --- a/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java +++ b/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java @@ -17,11 +17,9 @@ import org.junit.Test; import org.w3c.dom.Node; -import org.xmlunit.diff.DefaultNodeMatcher; -import org.xmlunit.diff.ElementSelectors; +import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.hamcrest.MatcherAssert.assertThat; -import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** * ManagementRegistryServiceConfigurationParserTest @@ -40,8 +38,7 @@ public void testTranslateServiceCreationConfiguration() { String inputString = "" + "tag1tag2"; - assertThat(retElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(retElement, isSameConfigurationAs(inputString)); } @Test @@ -55,8 +52,7 @@ public void testTranslateServiceCreationConfigurationWithoutTags() { Node retElement = configTranslator.unparseServiceCreationConfiguration(defaultManagementRegistryConfiguration); String inputString = ""; - assertThat(retElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(retElement, isSameConfigurationAs(inputString)); } } diff --git a/transactions/build.gradle b/transactions/build.gradle index 9143371a5b..0f8fb20ac7 100644 --- a/transactions/build.gradle +++ b/transactions/build.gradle @@ -32,9 +32,8 @@ dependencies { } compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':core-spi-test') + testImplementation testFixtures(project(':xml')) testImplementation "org.terracotta:statistics:$statisticVersion" - testImplementation 'org.xmlunit:xmlunit-core:2.6.0' - testImplementation 'org.xmlunit:xmlunit-matchers:2.6.0' } // For EhPomMangle diff --git a/transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java b/transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java index 4ef9d0d9a1..9a1d723fc8 100644 --- a/transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java +++ b/transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java @@ -18,13 +18,11 @@ import org.ehcache.config.Configuration; import org.ehcache.xml.XmlConfiguration; import org.junit.Test; -import org.xmlunit.diff.DefaultNodeMatcher; -import org.xmlunit.diff.ElementSelectors; import java.net.URL; +import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.hamcrest.MatcherAssert.assertThat; -import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** * TransactionalCacheParserIT @@ -36,8 +34,6 @@ public void testTransactionalCacheXmlTranslationToString() { URL resource = TransactionalCacheParserIT.class.getResource("/configs/transactional-cache.xml"); Configuration config = new XmlConfiguration(resource); XmlConfiguration xmlConfig = new XmlConfiguration(config); - assertThat(xmlConfig.toString(), isSimilarTo(resource).ignoreComments() - .ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(xmlConfig.toString(), isSameConfigurationAs(resource)); } } diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java index 53f2cbecb4..7967d1791e 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java @@ -19,12 +19,9 @@ import org.ehcache.transactions.xa.txmgr.provider.LookupTransactionManagerProviderConfiguration; import org.junit.Test; import org.w3c.dom.Node; -import org.xmlunit.diff.DefaultNodeMatcher; -import org.xmlunit.diff.ElementSelectors; - +import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.hamcrest.MatcherAssert.assertThat; -import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** * TxCacheManagerServiceConfigurationParserTest @@ -41,8 +38,7 @@ public void testTranslateServiceCreationConfiguration() { String inputString = ""; - assertThat(retElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndAllAttributes))); + assertThat(retElement, isSameConfigurationAs(inputString)); } } diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java index 234784d74b..c232c962c5 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java @@ -18,11 +18,9 @@ import org.ehcache.transactions.xa.configuration.XAStoreConfiguration; import org.junit.Test; import org.w3c.dom.Node; -import org.xmlunit.diff.DefaultNodeMatcher; -import org.xmlunit.diff.ElementSelectors; +import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.hamcrest.MatcherAssert.assertThat; -import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** * TxCacheServiceConfigurationParserTest @@ -37,8 +35,7 @@ public void testTranslateServiceConfiguration() { Node retElement = configTranslator.unparseServiceConfiguration(storeConfiguration); String inputString = ""; - assertThat(retElement, isSimilarTo(inputString).ignoreComments().ignoreWhitespace() - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndAllAttributes))); + assertThat(retElement, isSameConfigurationAs(inputString)); } } diff --git a/xml/build.gradle b/xml/build.gradle index cef41b55af..6b5754b54e 100644 --- a/xml/build.gradle +++ b/xml/build.gradle @@ -18,6 +18,7 @@ plugins { id 'org.unbroken-dome.xjc' id 'org.ehcache.build.deploy' id 'biz.aQute.bnd.builder' + id 'java-test-fixtures' } dependencies { @@ -26,7 +27,7 @@ dependencies { implementation project(':impl') implementation "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" - testImplementation 'org.xmlunit:xmlunit-core:2.6.0', 'org.xmlunit:xmlunit-matchers:2.6.0' + testFixturesApi 'org.xmlunit:xmlunit-core:2.6.0', 'org.xmlunit:xmlunit-matchers:2.6.0' xjcClasspath 'org.jvnet.jaxb2_commons:jaxb2-fluent-api:3.0' xjcClasspath 'org.jvnet.jaxb2_commons:jaxb2-basics-annotate:1.1.0' } diff --git a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java index 988e68d9d3..49ca059aa9 100644 --- a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java @@ -54,8 +54,6 @@ import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXParseException; -import org.xmlunit.diff.DefaultNodeMatcher; -import org.xmlunit.diff.ElementSelectors; import com.pany.ehcache.copier.AnotherPersonCopier; import com.pany.ehcache.copier.Description; @@ -93,6 +91,7 @@ import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; import static org.ehcache.core.util.ClassLoading.getDefaultClassLoader; import static org.ehcache.xml.XmlConfiguration.getClassForName; +import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; @@ -114,7 +113,6 @@ import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; -import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** * @@ -768,7 +766,7 @@ public void testCompleteXmlToString() { URL resource = XmlConfigurationTest.class.getResource("/configs/ehcache-complete.xml"); Configuration config = new XmlConfiguration(resource); XmlConfiguration xmlConfig = new XmlConfiguration(config); - assertThat(xmlConfig.toString(), isSimilarTo(resource).ignoreComments().ignoreWhitespace().withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(xmlConfig.toString(), isSameConfigurationAs(resource)); } @Test diff --git a/xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java index 16c2bbff09..d2e9f45be1 100644 --- a/xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java @@ -18,15 +18,16 @@ import org.ehcache.config.Configuration; import org.ehcache.config.builders.ConfigurationBuilder; import org.ehcache.xml.XmlConfiguration; +import org.ehcache.xml.XmlConfigurationMatchers; import org.ehcache.xml.XmlConfigurationTest; import org.ehcache.xml.exceptions.XmlConfigurationException; import org.junit.Test; -import org.xmlunit.builder.Input; import org.xmlunit.diff.DefaultNodeMatcher; import java.net.URISyntaxException; import java.net.URL; +import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.collection.IsEmptyCollection.empty; @@ -36,10 +37,10 @@ import static org.hamcrest.core.IsNull.nullValue; import static org.hamcrest.core.IsSame.sameInstance; import static org.junit.Assert.fail; +import static org.xmlunit.builder.Input.fromURI; import static org.xmlunit.diff.ElementSelectors.and; import static org.xmlunit.diff.ElementSelectors.byNameAndAllAttributes; import static org.xmlunit.diff.ElementSelectors.byNameAndText; -import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; public class XmlMultiConfigurationTest { @@ -54,7 +55,7 @@ public void testEmptyConfigurationFromBuilder() { assertThrows(() -> xmlMultiConfiguration.variants("foo"), IllegalArgumentException.class); assertThat(xmlMultiConfiguration.toString(), - isSimilarTo("").ignoreWhitespace().ignoreComments()); + isSameConfigurationAs("")); } @Test @@ -70,10 +71,9 @@ public void testSimpleConfigurationBuiltFromEmpty() { assertThat(xmlMultiConfiguration.variants("foo"), empty()); assertThat(xmlMultiConfiguration.toString(), - isSimilarTo( - "" + + isSameConfigurationAs("" + "" + - "").ignoreWhitespace().ignoreComments()); + "")); } @Test @@ -91,13 +91,12 @@ public void testVariantConfigurationBuiltFromEmpty() { assertThat(xmlMultiConfiguration.identities(), containsInAnyOrder("foo")); assertThat(xmlMultiConfiguration.variants("foo"), containsInAnyOrder("bar", "baz")); - assertThat(xmlMultiConfiguration.toString(), isSimilarTo( - "" + + assertThat(xmlMultiConfiguration.toString(), isSameConfigurationAs("" + "" + "" + "" + "" + - "").ignoreWhitespace().ignoreComments()); + "")); } @Test @@ -124,8 +123,7 @@ public void testMixedConfigurationBuiltFromEmpty() { assertThat(xmlMultiConfiguration.variants("fum"), containsInAnyOrder("bar")); assertThat(xmlMultiConfiguration.variants("fii"), empty()); - assertThat(xmlMultiConfiguration.toString(), isSimilarTo( - "" + + assertThat(xmlMultiConfiguration.toString(), isSameConfigurationAs("" + "" + "" + "" + @@ -136,7 +134,7 @@ public void testMixedConfigurationBuiltFromEmpty() { "" + "" + "" + - "").ignoreWhitespace().ignoreComments()); + "")); } @Test @@ -151,7 +149,7 @@ public void testEmptyConfigurationFromXml() throws URISyntaxException { assertThat(xmlMultiConfiguration.identities(), empty()); assertThrows(() -> xmlMultiConfiguration.variants("foo"), IllegalArgumentException.class); - assertThat(xmlMultiConfiguration.toString(), isSimilarTo(Input.fromURI(resource.toURI())).ignoreWhitespace().ignoreComments()); + assertThat(xmlMultiConfiguration.toString(), isSameConfigurationAs(fromURI(resource.toURI()))); } @Test @@ -169,7 +167,7 @@ public void testMultipleConfigurationsFromXml() throws URISyntaxException { assertThat(xmlMultiConfiguration.variants("foo"), empty()); assertThat(xmlMultiConfiguration.variants("bar"), empty()); - assertThat(xmlMultiConfiguration.toString(), isSimilarTo(Input.fromURI(resource.toURI())).ignoreWhitespace().ignoreComments()); + assertThat(xmlMultiConfiguration.toString(), isSameConfigurationAs(fromURI(resource.toURI()))); } @Test @@ -189,7 +187,7 @@ public void testMultipleVariantsFromXml() throws URISyntaxException { assertThat(xmlMultiConfiguration.variants("foo"), containsInAnyOrder("development", "production")); assertThat(xmlMultiConfiguration.variants("bar"), containsInAnyOrder("development", "production")); - assertThat(xmlMultiConfiguration.toString(), isSimilarTo(Input.fromURI(resource.toURI())).ignoreWhitespace().ignoreComments()); + assertThat(xmlMultiConfiguration.toString(), isSameConfigurationAs(fromURI(resource.toURI()))); } @Test @@ -206,14 +204,13 @@ public void testManagerRemovedFromXml() throws URISyntaxException { assertThat(xmlMultiConfiguration.identities(), containsInAnyOrder("foo")); assertThat(xmlMultiConfiguration.variants("foo"), empty()); - assertThat(xmlMultiConfiguration.toString(), isSimilarTo( - "" + + assertThat(xmlMultiConfiguration.toString(), isSameConfigurationAs("" + "" + "" + "100" + "" + "" + - "").ignoreWhitespace().ignoreComments()); + "")); } @Test @@ -231,8 +228,7 @@ public void testManagerRemovedFromXmlAndReadded() throws URISyntaxException { assertThat(xmlMultiConfiguration.variants("foo"), empty()); assertThat(xmlMultiConfiguration.variants("bar"), empty()); - assertThat(xmlMultiConfiguration.toString(), isSimilarTo( - "" + + assertThat(xmlMultiConfiguration.toString(), isSameConfigurationAs("" + "" + "" + "" + @@ -241,7 +237,7 @@ public void testManagerRemovedFromXmlAndReadded() throws URISyntaxException { "100" + "" + "" + - "").ignoreWhitespace().ignoreComments()); + "")); } @Test @@ -262,8 +258,7 @@ public void testManagerAddedToXml() throws URISyntaxException { assertThat(xmlMultiConfiguration.variants("bar"), empty()); assertThat(xmlMultiConfiguration.variants("baz"), empty()); - assertThat(xmlMultiConfiguration.toString(), isSimilarTo( - "" + + assertThat(xmlMultiConfiguration.toString(), isSameConfigurationAs("" + "" + "" + "100" + @@ -277,7 +272,7 @@ public void testManagerAddedToXml() throws URISyntaxException { "100" + "" + "" + - "").ignoreWhitespace().ignoreComments()); + "")); } @Test @@ -293,7 +288,7 @@ public void testManagerRemovedFromConfig() throws URISyntaxException { assertThrows(() -> xmlMultiConfiguration.variants("foo"), IllegalArgumentException.class); assertThat(xmlMultiConfiguration.toString(), - isSimilarTo("").ignoreWhitespace().ignoreComments()); + isSameConfigurationAs("")); } @Test @@ -308,10 +303,9 @@ public void testManagerRemovedFromConfigAndReadded() throws URISyntaxException { assertThat(xmlMultiConfiguration.identities(), containsInAnyOrder("foo")); assertThat(xmlMultiConfiguration.variants("foo"), empty()); - assertThat(xmlMultiConfiguration.toString(), isSimilarTo( - "" + + assertThat(xmlMultiConfiguration.toString(), isSameConfigurationAs("" + "" + - "").ignoreWhitespace().ignoreComments()); + "")); } @Test @@ -329,12 +323,10 @@ public void testManagerAddedToConfig() throws URISyntaxException { assertThat(xmlMultiConfiguration.variants("foo"), empty()); assertThat(xmlMultiConfiguration.variants("baz"), empty()); - assertThat(xmlMultiConfiguration.toString(), isSimilarTo( - "" + + assertThat(xmlMultiConfiguration.toString(), isSameConfigurationAs("" + "" + "" + - "").ignoreWhitespace().ignoreComments().withNodeMatcher( - new DefaultNodeMatcher(and(byNameAndText, byNameAndAllAttributes)))); + "")); } @Test @@ -348,8 +340,7 @@ public void testGenerateExtendedConfiguration() throws URISyntaxException { assertThat(xmlMultiConfiguration.identities(), containsInAnyOrder("foo")); assertThat(xmlMultiConfiguration.variants("foo"), empty()); - assertThat(xmlMultiConfiguration.toString(), isSimilarTo( - "" + + assertThat(xmlMultiConfiguration.toString(), isSameConfigurationAs("" + "" + "" + "" + @@ -364,7 +355,7 @@ public void testGenerateExtendedConfiguration() throws URISyntaxException { "" + "" + "" + - "").ignoreWhitespace().ignoreComments()); + "")); } @Test @@ -376,8 +367,7 @@ public void testParseExtendedConfiguration() { assertThat(xmlMultiConfiguration.identities(), containsInAnyOrder("foo")); assertThat(xmlMultiConfiguration.variants("foo"), empty()); - assertThat(xmlMultiConfiguration.toString(), isSimilarTo( - "" + + assertThat(xmlMultiConfiguration.toString(), isSameConfigurationAs("" + "" + "" + "" + @@ -392,7 +382,7 @@ public void testParseExtendedConfiguration() { "" + "" + "" + - "").ignoreWhitespace().ignoreComments()); + "")); } @Test(expected = XmlConfigurationException.class) diff --git a/xml/src/testFixtures/java/org/ehcache/xml/XmlConfigurationMatchers.java b/xml/src/testFixtures/java/org/ehcache/xml/XmlConfigurationMatchers.java new file mode 100644 index 0000000000..318ee81ca7 --- /dev/null +++ b/xml/src/testFixtures/java/org/ehcache/xml/XmlConfigurationMatchers.java @@ -0,0 +1,57 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.xml; + +import org.xmlunit.diff.DefaultNodeMatcher; +import org.xmlunit.diff.ElementSelector; +import org.xmlunit.matchers.CompareMatcher; +import org.xmlunit.util.Nodes; + +import javax.xml.namespace.QName; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.xmlunit.diff.ElementSelectors.Default; +import static org.xmlunit.diff.ElementSelectors.byName; +import static org.xmlunit.diff.ElementSelectors.byNameAndAttributes; +import static org.xmlunit.diff.ElementSelectors.byNameAndText; +import static org.xmlunit.diff.ElementSelectors.conditionalSelector; +import static org.xmlunit.diff.ElementSelectors.selectorForElementNamed; + +public class XmlConfigurationMatchers { + + private static final String EHCACHE_NAMESPACE = "http://www.ehcache.org/v3"; + private static final QName CACHE_QNAME = new QName(EHCACHE_NAMESPACE, "cache"); + private static final QName RESOURCES_QNAME = new QName(EHCACHE_NAMESPACE, "resources"); + private static final QName EVENTS_TO_FIRE_ON_QNAME = new QName(EHCACHE_NAMESPACE, "events-to-fire-on"); + + private static final String MULTI_NAMESPACE = "http://www.ehcache.org/v3/multi"; + private static final QName MULTI_CONFIGURATION_QNAME = new QName(MULTI_NAMESPACE, "configuration"); + + public static CompareMatcher isSameConfigurationAs(Object input, ElementSelector... extraElementSelectors) { + List elementSelectors = new ArrayList<>(asList(extraElementSelectors)); + elementSelectors.add(selectorForElementNamed(MULTI_CONFIGURATION_QNAME, byNameAndAttributes("identity"))); + elementSelectors.add(selectorForElementNamed(EVENTS_TO_FIRE_ON_QNAME, byNameAndText)); + elementSelectors.add(selectorForElementNamed(CACHE_QNAME, byNameAndAttributes("alias"))); + elementSelectors.add(conditionalSelector(element -> Nodes.getQName(element.getParentNode()).equals(RESOURCES_QNAME), byName)); + elementSelectors.add(Default); + + return CompareMatcher.isSimilarTo(input).ignoreComments().ignoreWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(elementSelectors.toArray(new ElementSelector[0]))); + } +} From b9ba6ba2a3271ae1ffbfa838f4720dfdcbf58934 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 13 Nov 2020 14:30:07 -0500 Subject: [PATCH 304/372] JAXB OSGi Version Ranges --- clustered/osgi-test/build.gradle | 65 ++++++---- ...OsgiTestUtils.java => ClusterSupport.java} | 70 +---------- .../org/ehcache/osgi/ClusteredOsgiTest.java | 25 ++-- dist/build.gradle | 2 +- gradle.properties | 2 +- osgi-test/build.gradle | 86 ++++++++----- .../java/org/ehcache/osgi/OsgiTestUtils.java | 115 ++++++++++++++++++ .../ehcache/osgi/ByteSizedOnHeapOsgiTest.java | 23 ++-- .../java/org/ehcache/osgi/Jsr107OsgiTest.java | 10 +- .../org/ehcache/osgi/OffHeapOsgiTest.java | 9 +- .../java/org/ehcache/osgi/OsgiTestUtils.java | 97 --------------- .../java/org/ehcache/osgi/SimpleOsgiTest.java | 9 +- .../ehcache/osgi/TransactionalOsgiTest.java | 9 +- xml/build.gradle | 27 ++++ 14 files changed, 277 insertions(+), 272 deletions(-) rename clustered/osgi-test/src/test/java/org/ehcache/osgi/{OsgiTestUtils.java => ClusterSupport.java} (54%) create mode 100644 osgi-test/src/main/java/org/ehcache/osgi/OsgiTestUtils.java delete mode 100644 osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java diff --git a/clustered/osgi-test/build.gradle b/clustered/osgi-test/build.gradle index 8399d48536..a14c90d4c0 100644 --- a/clustered/osgi-test/build.gradle +++ b/clustered/osgi-test/build.gradle @@ -16,6 +16,7 @@ configurations { osgiModule + lowerBoundOsgiModule.extendsFrom osgiModule testCompileOnly.extendsFrom osgiModule } @@ -38,29 +39,13 @@ dependencies { testCompileOnly project(':clustered:client') testCompileOnly project(':clustered:common') - testImplementation 'org.apache.felix:org.apache.felix.framework:6.0.3' - testImplementation ('org.ops4j.pax.exam:pax-exam-junit4:4.12.0') { - exclude group:'org.slf4j', module:'slf4j-api' - } - - testRuntimeOnly ('org.ops4j.pax.exam:pax-exam-container-native:4.12.0') { - exclude group:'org.slf4j', module:'slf4j-api' - } - testRuntimeOnly ('org.ops4j.pax.exam:pax-exam-link-mvn:4.12.0') { - exclude group:'org.slf4j', module:'slf4j-api' - } - testRuntimeOnly ("org.ops4j.pax.url:pax-url-wrap:2.6.1") { - exclude group:'org.slf4j', module:'slf4j-api' - } - + testImplementation project(':osgi-test') + testImplementation 'org.osgi:osgi.core:6.0.0' } configurations.all { resolutionStrategy { dependencySubstitution { - substitute(module('org.ops4j.pax.url:pax-url-aether:2.4.5')) - .because('https://ops4j1.jira.com/browse/PAXURL-341') - .with(module('org.ops4j.pax.url:pax-url-aether:2.6.1')) substitute(module('org.ops4j.pax.url:pax-url-classpath:2.4.5')) .because('https://ops4j1.jira.com/browse/PAXURL-341') .with(module('org.ops4j.pax.url:pax-url-classpath:2.6.1')) @@ -83,21 +68,47 @@ sourceSets { } } -configurations.osgiModule.dependencies.withType(ProjectDependency).forEach { - test.dependsOn it.dependencyProject.tasks.jar -} - task unzipKit(type: Copy) { dependsOn project(':clustered:clustered-dist').distZip from zipTree(project(':clustered:clustered-dist').distZip.archivePath) into 'build/ehcache-kit' } -test { +tasks.withType(Test) { dependsOn unzipKit systemProperty 'kitInstallationPath', "$unzipKit.destinationDir/${project(':clustered:clustered-dist').archivesBaseName}-$project.version-kit" -}.doFirst { - configurations.osgiModule.resolvedConfiguration.resolvedArtifacts.forEach({ - systemProperty "$it.moduleVersion.id.module:osgi-path", it.file - }) +} + +test { + dependsOn configurations.osgiModule + doFirst { + configurations.osgiModule.resolvedConfiguration.resolvedArtifacts.forEach({ + systemProperty "$it.moduleVersion.id.module:osgi-path", it.file + }) + } +} + +configurations { + lowerBoundOsgiModule { + resolutionStrategy.dependencySubstitution { + substitute module('org.glassfish.jaxb:jaxb-runtime') with module('com.sun.xml.bind:jaxb-osgi:2.2.8-b01') + } + } +} +dependencies { + lowerBoundOsgiModule 'javax.xml.bind:jaxb-api:2.2.9' +} + +tasks.register('lowerBoundTest', Test) { + group = JavaBasePlugin.VERIFICATION_GROUP + dependsOn configurations.lowerBoundOsgiModule + doFirst { + configurations.lowerBoundOsgiModule.resolvedConfiguration.resolvedArtifacts.forEach({ + systemProperty "$it.moduleVersion.id.module:osgi-path", it.file + }) + } +} + +tasks.named('check') { + dependsOn tasks.lowerBoundTest } diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusterSupport.java similarity index 54% rename from clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java rename to clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusterSupport.java index ed40975a01..7535bc2da4 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusterSupport.java @@ -16,12 +16,7 @@ package org.ehcache.osgi; -import org.ops4j.pax.exam.Option; -import org.ops4j.pax.exam.options.UrlProvisionOption; -import org.ops4j.pax.exam.options.WrappedUrlProvisionOption; - import java.io.Closeable; -import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; import java.net.URI; @@ -30,70 +25,9 @@ import java.nio.file.Paths; import java.util.concurrent.TimeUnit; -import static java.lang.Integer.parseInt; -import static java.lang.String.join; -import static java.lang.System.getProperty; -import static java.nio.file.Files.isRegularFile; import static java.util.Arrays.asList; -import static java.util.Objects.requireNonNull; -import static org.ops4j.pax.exam.CoreOptions.bundle; -import static org.ops4j.pax.exam.CoreOptions.cleanCaches; -import static org.ops4j.pax.exam.CoreOptions.composite; -import static org.ops4j.pax.exam.CoreOptions.junitBundles; -import static org.ops4j.pax.exam.CoreOptions.systemPackages; -import static org.ops4j.pax.exam.CoreOptions.systemProperty; -import static org.ops4j.pax.exam.CoreOptions.workingDirectory; -import static org.ops4j.pax.exam.CoreOptions.wrappedBundle; - -public class OsgiTestUtils { - - public static Option baseConfiguration(String... path) { - return composite( - wrappedGradleBundle("org.terracotta:terracotta-utilities-test-tools"), - gradleBundle("org.slf4j:slf4j-api"), - gradleBundle("org.slf4j:slf4j-simple").noStart(), - gradleBundle("org.apache.felix:org.apache.felix.scr"), - systemProperty("pax.exam.osgi.unresolved.fail").value("true"), - cleanCaches(true), - workingDirectory(join(File.separator, "build", "osgi-container", join(File.separator, path))), - junitBundles() - ); - } - - public static Option jaxbConfiguration() { - if (parseInt(getProperty("java.version").split("[^\\d]+")[0]) >= 9) { - return composite( - gradleBundle("org.glassfish.hk2:osgi-resource-locator"), - gradleBundle("javax.xml.bind:jaxb-api"), - gradleBundle("com.sun.activation:javax.activation"), - wrappedGradleBundle("org.glassfish.jaxb:jaxb-runtime"), - gradleBundle("com.sun.istack:istack-commons-runtime") - ); - } else { - return systemPackages( - "javax.xml.bind;version=2.3.0", - "javax.xml.bind.annotation;version=2.3.0", - "javax.xml.bind.annotation.adapters;version=2.3.0" - ); - } - } - public static UrlProvisionOption gradleBundle(String module) { - return bundle(artifact(module).toUri().toString()); - } - - public static WrappedUrlProvisionOption wrappedGradleBundle(String module) { - return wrappedBundle(artifact(module).toUri().toString()); - } - - private static Path artifact(String module) { - Path path = Paths.get(requireNonNull(getProperty(module + ":osgi-path"), module + " not available")); - if (isRegularFile(path)) { - return path; - } else { - throw new IllegalArgumentException("Module '" + module + "' not found at " + path); - } - } +public class ClusterSupport { public static Cluster startServer(Path serverDirectory) throws IOException { Path kitLocation = Paths.get(System.getProperty("kitInstallationPath")); @@ -151,7 +85,7 @@ public URI getConnectionUri() { } @Override - public void close() throws IOException { + public void close() { try { serverProcess.destroyForcibly(); } finally { diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java index b664b7e9b1..2bba55fd39 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java @@ -58,11 +58,10 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.ehcache.osgi.ClusterSupport.startServer; import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; -import static org.ehcache.osgi.OsgiTestUtils.startServer; -import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsCollectionContaining.hasItems; @@ -87,12 +86,13 @@ public Option[] individualModules() { gradleBundle("org.terracotta.management:management-model"), gradleBundle("org.terracotta.management:sequence-generator"), - wrappedGradleBundle("org.terracotta:statistics"), - wrappedGradleBundle("org.ehcache:sizeof"), - wrappedGradleBundle("org.terracotta:offheap-store"), - wrappedGradleBundle("org.terracotta:terracotta-utilities-tools"), + gradleBundle("org.terracotta:statistics"), + gradleBundle("org.ehcache:sizeof"), + gradleBundle("org.terracotta:offheap-store"), + gradleBundle("org.terracotta:terracotta-utilities-tools"), - baseConfiguration("ClusteredOsgiTest", "individualModules") + baseConfiguration("ClusteredOsgiTest", "individualModules"), + gradleBundle("org.terracotta:terracotta-utilities-test-tools") ); } @@ -102,20 +102,21 @@ public Option[] uberJar() { gradleBundle("org.ehcache:dist"), jaxbConfiguration(), gradleBundle("org.ehcache:clustered-dist"), - baseConfiguration("ClusteredOsgiTest", "uberJar") + baseConfiguration("ClusteredOsgiTest", "uberJar"), + gradleBundle("org.terracotta:terracotta-utilities-test-tools") ); } @Test public void testProgrammaticClusteredCache() throws Throwable { - try (OsgiTestUtils.Cluster cluster = startServer(serverLocation.newFolder().toPath())) { + try (ClusterSupport.Cluster cluster = startServer(serverLocation.newFolder().toPath())) { TestMethods.testProgrammaticClusteredCache(cluster); } } @Test public void testXmlClusteredCache() throws Throwable { - try (OsgiTestUtils.Cluster cluster = startServer(serverLocation.newFolder().toPath())) { + try (ClusterSupport.Cluster cluster = startServer(serverLocation.newFolder().toPath())) { TestMethods.testXmlClusteredCache(cluster); } } @@ -127,7 +128,7 @@ public void testAllServicesAreAvailable() { private static class TestMethods { - public static void testProgrammaticClusteredCache(OsgiTestUtils.Cluster cluster) throws Throwable { + public static void testProgrammaticClusteredCache(ClusterSupport.Cluster cluster) throws Throwable { try (PersistentCacheManager cacheManager = newCacheManagerBuilder() .with(cluster(cluster.getConnectionUri()).autoCreate(c -> c)) .withCache("clustered-cache", newCacheConfigurationBuilder(Long.class, String.class, @@ -141,7 +142,7 @@ public static void testProgrammaticClusteredCache(OsgiTestUtils.Cluster cluster) } } - public static void testXmlClusteredCache(OsgiTestUtils.Cluster cluster) throws Exception { + public static void testXmlClusteredCache(ClusterSupport.Cluster cluster) throws Exception { File config = cluster.getWorkingArea().resolve("ehcache.xml").toFile(); Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(TestMethods.class.getResourceAsStream("ehcache-clustered-osgi.xml")); diff --git a/dist/build.gradle b/dist/build.gradle index 9d7dcb397e..4b1038ab0f 100644 --- a/dist/build.gradle +++ b/dist/build.gradle @@ -43,6 +43,6 @@ jar { 'Bundle-Activator': 'org.ehcache.core.osgi.EhcacheActivator', 'Export-Package': '!org.ehcache.jsr107.tck, !org.ehcache.*.internal.*, org.ehcache.*, org.terracotta.statistics.*, org.terracotta.context', - 'Import-Package': 'javax.cache.*;resolution:=optional, !javax.annotation, !sun.misc, *' + 'Import-Package': "javax.cache.*;resolution:=optional, !javax.annotation, !sun.misc, javax.xml.bind*;version=\"${parent.jaxbVersion}\", *" ) } diff --git a/gradle.properties b/gradle.properties index 7422144cda..b089ed2176 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,7 +7,7 @@ statisticVersion = 2.1 jcacheVersion = 1.1.0 slf4jVersion = 1.7.25 sizeofVersion = 0.4.0 -jaxbVersion = 2.3.1 +jaxbVersion = [2.2,3) # Terracotta clustered terracottaPlatformVersion = 5.8.1-pre10 diff --git a/osgi-test/build.gradle b/osgi-test/build.gradle index 797569757d..501f4a00c6 100644 --- a/osgi-test/build.gradle +++ b/osgi-test/build.gradle @@ -16,10 +16,25 @@ configurations { osgiModule + lowerBoundOsgiModule.extendsFrom osgiModule testCompileOnly.extendsFrom osgiModule } dependencies { + api ('org.ops4j.pax.exam:pax-exam-junit4:4.12.0') { + exclude group:'org.slf4j', module:'slf4j-api' + } + implementation 'org.apache.felix:org.apache.felix.framework:6.0.3' + runtimeOnly ('org.ops4j.pax.exam:pax-exam-link-mvn:4.12.0') { + exclude group:'org.slf4j', module:'slf4j-api' + } + runtimeOnly ("org.ops4j.pax.url:pax-url-wrap:2.6.1") { + exclude group:'org.slf4j', module:'slf4j-api' + } + runtimeOnly ('org.ops4j.pax.exam:pax-exam-container-native:4.12.0') { + exclude group:'org.slf4j', module:'slf4j-api' + } + osgiModule project(':api') osgiModule project(':core') osgiModule project(':impl') @@ -39,30 +54,6 @@ dependencies { osgiModule 'com.sun.activation:javax.activation:1.2.0' osgiModule 'org.glassfish.hk2:osgi-resource-locator:1.0.2' - - testImplementation 'org.apache.felix:org.apache.felix.framework:6.0.3' - testImplementation ('org.ops4j.pax.exam:pax-exam-junit4:4.12.0') { - exclude group:'org.slf4j', module:'slf4j-api' - } - - testRuntimeOnly ('org.ops4j.pax.exam:pax-exam-container-native:4.12.0') { - exclude group:'org.slf4j', module:'slf4j-api' - } - testRuntimeOnly ('org.ops4j.pax.exam:pax-exam-link-mvn:4.12.0') { - exclude group:'org.slf4j', module:'slf4j-api' - } - testRuntimeOnly ("org.ops4j.pax.url:pax-url-wrap:2.6.1") { - exclude group:'org.slf4j', module:'slf4j-api' - } -} - -configurations.all { - resolutionStrategy { - force 'org.ops4j.base:ops4j-base-lang:1.5.0' - force 'org.ops4j.base:ops4j-base-net:1.5.0' - force 'org.ops4j.base:ops4j-base-util-property:1.5.0' - force 'org.ops4j.pax.url:pax-url-commons:2.6.1' - } } configurations.all { @@ -78,6 +69,9 @@ configurations.all { .because('https://ops4j1.jira.com/browse/PAXURL-341') .with(module('org.ops4j.pax.url:pax-url-link:2.6.1')) + substitute(module('biz.aQute.bnd:bndlib:2.4.0')) + .because('Java 9 Stuff') + .with(module('biz.aQute.bnd:biz.aQute.bndlib:5.2.0')) substitute(module('junit:junit:4.12')) .because('CVE-2020-15250') .with(module('junit:junit:4.13.1')) @@ -92,17 +86,43 @@ sourceSets { } } -configurations.osgiModule.dependencies.withType(ProjectDependency).forEach { - test.dependsOn it.dependencyProject.tasks.jar +if (testJava.javaVersion.isJava9Compatible()) { + tasks.withType(Test) { + //https://issues.apache.org/jira/browse/FELIX-5727 - framework extensions in Java 9 are ugly + jvmArgs += '--add-opens=java.base/jdk.internal.loader=ALL-UNNAMED' + } } test { - if (testJava.javaVersion.isJava9Compatible()) { - //https://issues.apache.org/jira/browse/FELIX-5727 - framework extensions in Java 9 are ugly - jvmArgs += ['--add-opens=java.base/jdk.internal.loader=ALL-UNNAMED'] + dependsOn configurations.osgiModule + doFirst { + configurations.osgiModule.resolvedConfiguration.resolvedArtifacts.forEach({ + systemProperty "$it.moduleVersion.id.module:osgi-path", it.file + }) } -}.doFirst { - configurations.osgiModule.resolvedConfiguration.resolvedArtifacts.forEach({ - systemProperty "$it.moduleVersion.id.module:osgi-path", it.file - }) +} + +configurations { + lowerBoundOsgiModule { + resolutionStrategy.dependencySubstitution { + substitute module('org.glassfish.jaxb:jaxb-runtime') with module('com.sun.xml.bind:jaxb-osgi:2.2.8-b01') + } + } +} +dependencies { + lowerBoundOsgiModule 'javax.xml.bind:jaxb-api:2.2.9' +} + +tasks.register('lowerBoundTest', Test) { + group = JavaBasePlugin.VERIFICATION_GROUP + dependsOn configurations.lowerBoundOsgiModule + doFirst { + configurations.lowerBoundOsgiModule.resolvedConfiguration.resolvedArtifacts.forEach { + systemProperty "$it.moduleVersion.id.module:osgi-path", it.file + } + } +} + +tasks.named('check') { + dependsOn tasks.lowerBoundTest } diff --git a/osgi-test/src/main/java/org/ehcache/osgi/OsgiTestUtils.java b/osgi-test/src/main/java/org/ehcache/osgi/OsgiTestUtils.java new file mode 100644 index 0000000000..90fc0623e5 --- /dev/null +++ b/osgi-test/src/main/java/org/ehcache/osgi/OsgiTestUtils.java @@ -0,0 +1,115 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.osgi; + +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.options.ProvisionOption; +import org.ops4j.pax.exam.options.WrappedUrlProvisionOption; +import org.osgi.framework.Constants; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Optional; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; + +import static java.lang.String.join; +import static java.lang.System.getProperty; +import static org.ops4j.pax.exam.CoreOptions.bundle; +import static org.ops4j.pax.exam.CoreOptions.cleanCaches; +import static org.ops4j.pax.exam.CoreOptions.composite; +import static org.ops4j.pax.exam.CoreOptions.junitBundles; +import static org.ops4j.pax.exam.CoreOptions.systemProperty; +import static org.ops4j.pax.exam.CoreOptions.workingDirectory; +import static org.ops4j.pax.exam.CoreOptions.wrappedBundle; +import static org.ops4j.pax.exam.options.WrappedUrlProvisionOption.OverwriteMode.MERGE; + +public class OsgiTestUtils { + + public static Option baseConfiguration(String ... path) { + return composite( + gradleBundle("org.slf4j:slf4j-api"), + gradleBundle("org.slf4j:slf4j-simple").noStart(), + gradleBundle("org.apache.felix:org.apache.felix.scr"), + systemProperty("pax.exam.osgi.unresolved.fail").value("true"), + cleanCaches(true), + workingDirectory(join(File.separator, "build", "osgi-container", join(File.separator, path))), + junitBundles() + ); + } + + public static Option jaxbConfiguration() { + return optionalGradleBundle("com.sun.xml.bind:jaxb-osgi") + .map(jaxb -> composite(jaxb, + gradleBundle("javax.xml.bind:jaxb-api"), + gradleBundle("com.sun.activation:javax.activation"), + gradleBundle("org.glassfish.hk2:osgi-resource-locator")) + ).orElseGet(() -> optionalGradleBundle("org.glassfish.jaxb:jaxb-runtime") + .map(jaxb -> composite(jaxb, + wrappedGradleBundle("javax.xml.bind:jaxb-api").instructions("-removeheaders=Require-Capability"), + gradleBundle("com.sun.istack:istack-commons-runtime"), + gradleBundle("com.sun.activation:javax.activation"), + gradleBundle("org.glassfish.hk2:osgi-resource-locator")) + ).orElseThrow(AssertionError::new)); + } + + public static Option jtaConfiguration() { + return composite( + wrappedGradleBundle("javax.transaction:jta").instructions("Fragment-Host=org.apache.felix.framework"), + gradleBundle("org.codehaus.btm:btm") + ); + } + + public static ProvisionOption gradleBundle(String module) { + return optionalGradleBundle(module).orElseThrow(() -> new IllegalArgumentException("Cannot find '" + module + "'")); + } + + private static final Attributes.Name BUNDLE_SYMBOLICNAME = new Attributes.Name(Constants.BUNDLE_SYMBOLICNAME); + + public static Optional> optionalGradleBundle(String module) { + return artifact(module).map(artifact -> { + try (JarFile jar = new JarFile(artifact.toFile())) { + Manifest manifest = jar.getManifest(); + if (manifest != null && manifest.getMainAttributes().containsKey(BUNDLE_SYMBOLICNAME)) { + return bundle(artifact.toUri().toString()); + } else { + return wrappedBundle(artifact.toUri().toString()); + } + } catch (IOException e) { + throw new IllegalArgumentException("Module '" + module + "' artifact " + artifact + " is broken?"); + } + }); + } + + public static WrappedUrlProvisionOption wrappedGradleBundle(String module) { + ProvisionOption provisionOption = gradleBundle(module); + if (provisionOption instanceof WrappedUrlProvisionOption) { + return (WrappedUrlProvisionOption) provisionOption; + } else { + return wrappedBundle(provisionOption.getURL()).overwriteManifest(MERGE); + } + } + + private static Optional artifact(String module) { + return Optional.ofNullable(getProperty(module + ":osgi-path")).map(Paths::get).filter(Files::isRegularFile); + } +} + diff --git a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java index 959a94960e..c96b24f5ec 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java @@ -16,14 +16,6 @@ package org.ehcache.osgi; -import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; -import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; -import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; -import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; -import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; -import static org.ops4j.pax.exam.CoreOptions.options; - import org.ehcache.Cache; import org.ehcache.CacheManager; import org.ehcache.config.builders.CacheManagerBuilder; @@ -36,6 +28,13 @@ import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerMethod; +import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; +import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; +import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; +import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; +import static org.ops4j.pax.exam.CoreOptions.options; + @RunWith(PaxExam.class) @ExamReactorStrategy(PerMethod.class) public class ByteSizedOnHeapOsgiTest { @@ -50,10 +49,10 @@ public Option[] individualModules() { gradleBundle("org.terracotta.management:management-model"), gradleBundle("org.terracotta.management:sequence-generator"), - wrappedGradleBundle("org.terracotta:statistics"), - wrappedGradleBundle("org.ehcache:sizeof"), - wrappedGradleBundle("org.terracotta:offheap-store"), - wrappedGradleBundle("org.terracotta:terracotta-utilities-tools"), + gradleBundle("org.terracotta:statistics"), + gradleBundle("org.ehcache:sizeof"), + gradleBundle("org.terracotta:offheap-store"), + gradleBundle("org.terracotta:terracotta-utilities-tools"), baseConfiguration("ByteSizedOnHeapOsgiTest", "individualModules") ); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java index fe466026a5..546291111f 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java @@ -32,7 +32,6 @@ import javax.cache.CacheManager; import javax.cache.Caching; import javax.cache.spi.CachingProvider; - import java.util.ServiceLoader; import java.util.Set; @@ -43,7 +42,6 @@ import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; -import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsCollectionContaining.hasItems; import static org.junit.Assert.assertEquals; @@ -69,10 +67,10 @@ public Option[] individualModules() { gradleBundle("org.terracotta.management:management-model"), gradleBundle("org.terracotta.management:sequence-generator"), - wrappedGradleBundle("org.terracotta:statistics"), - wrappedGradleBundle("org.ehcache:sizeof"), - wrappedGradleBundle("org.terracotta:offheap-store"), - wrappedGradleBundle("org.terracotta:terracotta-utilities-tools"), + gradleBundle("org.terracotta:statistics"), + gradleBundle("org.ehcache:sizeof"), + gradleBundle("org.terracotta:offheap-store"), + gradleBundle("org.terracotta:terracotta-utilities-tools"), baseConfiguration("Jsr107OsgiTest", "individualModules") ); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java index bd36d46737..81be27c82f 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java @@ -37,7 +37,6 @@ import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; -import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.ops4j.pax.exam.CoreOptions.frameworkProperty; @@ -57,10 +56,10 @@ public Option[] individualModules() { gradleBundle("org.terracotta.management:management-model"), gradleBundle("org.terracotta.management:sequence-generator"), - wrappedGradleBundle("org.terracotta:statistics"), - wrappedGradleBundle("org.ehcache:sizeof"), - wrappedGradleBundle("org.terracotta:offheap-store"), - wrappedGradleBundle("org.terracotta:terracotta-utilities-tools"), + gradleBundle("org.terracotta:statistics"), + gradleBundle("org.ehcache:sizeof"), + gradleBundle("org.terracotta:offheap-store"), + gradleBundle("org.terracotta:terracotta-utilities-tools"), baseConfiguration("OffHeapOsgiTest", "individualModules") ); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java deleted file mode 100644 index 9c2620b433..0000000000 --- a/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.ehcache.osgi; - -import org.ops4j.pax.exam.Option; -import org.ops4j.pax.exam.options.UrlProvisionOption; -import org.ops4j.pax.exam.options.WrappedUrlProvisionOption; - -import java.io.File; -import java.nio.file.Path; -import java.nio.file.Paths; - -import static java.lang.Integer.parseInt; -import static java.lang.String.join; -import static java.lang.System.getProperty; -import static java.nio.file.Files.isRegularFile; -import static java.util.Objects.requireNonNull; -import static org.ops4j.pax.exam.CoreOptions.bundle; -import static org.ops4j.pax.exam.CoreOptions.cleanCaches; -import static org.ops4j.pax.exam.CoreOptions.composite; -import static org.ops4j.pax.exam.CoreOptions.junitBundles; -import static org.ops4j.pax.exam.CoreOptions.systemPackages; -import static org.ops4j.pax.exam.CoreOptions.systemProperty; -import static org.ops4j.pax.exam.CoreOptions.workingDirectory; -import static org.ops4j.pax.exam.CoreOptions.wrappedBundle; - -public class OsgiTestUtils { - - public static Option baseConfiguration(String ... path) { - return composite( - gradleBundle("org.slf4j:slf4j-api"), - gradleBundle("org.slf4j:slf4j-simple").noStart(), - gradleBundle("org.apache.felix:org.apache.felix.scr"), - systemProperty("pax.exam.osgi.unresolved.fail").value("true"), - cleanCaches(true), - workingDirectory(join(File.separator, "build", "osgi-container", join(File.separator, path))), - junitBundles() - ); - } - - public static Option jaxbConfiguration() { - if (parseInt(getProperty("java.version").split("[^\\d]+")[0]) >= 9) { - return composite( - gradleBundle("org.glassfish.hk2:osgi-resource-locator"), - gradleBundle("javax.xml.bind:jaxb-api"), - gradleBundle("com.sun.activation:javax.activation"), - wrappedGradleBundle("org.glassfish.jaxb:jaxb-runtime"), - gradleBundle("com.sun.istack:istack-commons-runtime") - ); - } else { - return systemPackages( - "javax.xml.bind;version=2.3.0", - "javax.xml.bind.annotation;version=2.3.0", - "javax.xml.bind.annotation.adapters;version=2.3.0" - ); - } - } - - public static Option jtaConfiguration() { - return composite( - wrappedGradleBundle("javax.transaction:jta").instructions("Fragment-Host=org.apache.felix.framework"), - wrappedGradleBundle("org.codehaus.btm:btm") - ); - } - - public static UrlProvisionOption gradleBundle(String module) { - return bundle(artifact(module).toUri().toString()); - } - - public static WrappedUrlProvisionOption wrappedGradleBundle(String module) { - return wrappedBundle(artifact(module).toUri().toString()); - } - - private static Path artifact(String module) { - Path path = Paths.get(requireNonNull(getProperty(module + ":osgi-path"), module + " not available")); - if (isRegularFile(path)) { - return path; - } else { - throw new IllegalArgumentException("Module '" + module + "' not found at " + path); - } - } -} - diff --git a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java index cc072fefb7..329827f2bd 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java @@ -48,7 +48,6 @@ import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; -import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsCollectionContaining.hasItems; import static org.junit.Assert.assertEquals; @@ -71,10 +70,10 @@ public Option[] individualModules() { gradleBundle("org.terracotta.management:management-model"), gradleBundle("org.terracotta.management:sequence-generator"), - wrappedGradleBundle("org.terracotta:statistics"), - wrappedGradleBundle("org.ehcache:sizeof"), - wrappedGradleBundle("org.terracotta:offheap-store"), - wrappedGradleBundle("org.terracotta:terracotta-utilities-tools"), + gradleBundle("org.terracotta:statistics"), + gradleBundle("org.ehcache:sizeof"), + gradleBundle("org.terracotta:offheap-store"), + gradleBundle("org.terracotta:terracotta-utilities-tools"), baseConfiguration("SimpleOsgiTest", "individualModules") ); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java index 313d0cc39f..75b98ef167 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java @@ -43,7 +43,6 @@ import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; import static org.ehcache.osgi.OsgiTestUtils.jtaConfiguration; -import static org.ehcache.osgi.OsgiTestUtils.wrappedGradleBundle; import static org.ops4j.pax.exam.CoreOptions.options; @RunWith(PaxExam.class) @@ -62,10 +61,10 @@ public Option[] individualModules() { gradleBundle("org.terracotta.management:management-model"), gradleBundle("org.terracotta.management:sequence-generator"), - wrappedGradleBundle("org.terracotta:statistics"), - wrappedGradleBundle("org.ehcache:sizeof"), - wrappedGradleBundle("org.terracotta:offheap-store"), - wrappedGradleBundle("org.terracotta:terracotta-utilities-tools"), + gradleBundle("org.terracotta:statistics"), + gradleBundle("org.ehcache:sizeof"), + gradleBundle("org.terracotta:offheap-store"), + gradleBundle("org.terracotta:terracotta-utilities-tools"), baseConfiguration("TransactionalOsgiTest", "individualModules") ); diff --git a/xml/build.gradle b/xml/build.gradle index 6b5754b54e..6c6f076306 100644 --- a/xml/build.gradle +++ b/xml/build.gradle @@ -39,6 +39,7 @@ configurations.xjcClasspath.resolutionStrategy.dependencySubstitution { jar { bnd ( 'Export-Package': 'org.ehcache.xml, org.ehcache.xml.exceptions, org.ehcache.xml.model', + 'Import-Package': "javax.xml.bind*;version=\"${parent.jaxbVersion}\", *" ) } @@ -47,3 +48,29 @@ xjcGenerate { extension = true extraArgs = ['-Xfluent-api', '-Xannotate'] } + +configurations { + lowerBoundTestRuntime.extendsFrom testRuntimeClasspath +} +configurations { + lowerBoundTestRuntime { + resolutionStrategy.dependencySubstitution { + substitute module('org.glassfish.jaxb:jaxb-runtime') with module('com.sun.xml.bind:jaxb-impl:2.2.8-b01') + } + } +} +dependencies { + lowerBoundTestRuntime 'com.sun.activation:javax.activation:1.2.0' +} + +tasks.register('lowerBoundTest', Test) { + group = JavaBasePlugin.VERIFICATION_GROUP + //remove the original runtime classpath + classpath -= configurations.testRuntimeClasspath + //add the classpath we want + classpath += configurations.lowerBoundTestRuntime +} + +tasks.named('check') { + dependsOn tasks.lowerBoundTest +} From 250bb10c0bf8c6d4674ef04b870c97d30bbb9467 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 20 Nov 2020 12:00:47 -0500 Subject: [PATCH 305/372] Avoid security vulnerabilities in plexus-utils --- clustered/osgi-test/build.gradle | 4 ++++ osgi-test/build.gradle | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/clustered/osgi-test/build.gradle b/clustered/osgi-test/build.gradle index a14c90d4c0..2b4aa2e83c 100644 --- a/clustered/osgi-test/build.gradle +++ b/clustered/osgi-test/build.gradle @@ -46,6 +46,10 @@ dependencies { configurations.all { resolutionStrategy { dependencySubstitution { + substitute(module('org.ops4j.pax.url:pax-url-aether:2.4.5')) + .because('https://github.com/codehaus-plexus/plexus-utils/issues/3' + + ' and https://github.com/codehaus-plexus/plexus-utils/issues/4') + .with(module('org.ops4j.pax.url:pax-url-aether:2.6.3')) substitute(module('org.ops4j.pax.url:pax-url-classpath:2.4.5')) .because('https://ops4j1.jira.com/browse/PAXURL-341') .with(module('org.ops4j.pax.url:pax-url-classpath:2.6.1')) diff --git a/osgi-test/build.gradle b/osgi-test/build.gradle index 501f4a00c6..a2d9750f54 100644 --- a/osgi-test/build.gradle +++ b/osgi-test/build.gradle @@ -60,8 +60,9 @@ configurations.all { resolutionStrategy { dependencySubstitution { substitute(module('org.ops4j.pax.url:pax-url-aether:2.4.5')) - .because('https://ops4j1.jira.com/browse/PAXURL-341') - .with(module('org.ops4j.pax.url:pax-url-aether:2.6.1')) + .because('https://github.com/codehaus-plexus/plexus-utils/issues/3' + + ' and https://github.com/codehaus-plexus/plexus-utils/issues/4') + .with(module('org.ops4j.pax.url:pax-url-aether:2.6.3')) substitute(module('org.ops4j.pax.url:pax-url-classpath:2.4.5')) .because('https://ops4j1.jira.com/browse/PAXURL-341') .with(module('org.ops4j.pax.url:pax-url-classpath:2.6.1')) From 7fbb3fdeb12fc56f74525753f5b2d2a5984cc7fd Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Mon, 30 Nov 2020 13:08:50 -0800 Subject: [PATCH 306/372] bump platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index b089ed2176..d571264399 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre10 +terracottaPlatformVersion = 5.8.1-pre11 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.1-pre5 terracottaPassthroughTestingVersion = 1.7.0 From 8be15a15185bd53a106a9b7469722eb632540805 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 1 Dec 2020 17:07:51 -0500 Subject: [PATCH 307/372] Upgrade to new tc-platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d571264399..edc5f653c0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre11 +terracottaPlatformVersion = 5.8.1-pre12 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.1-pre5 terracottaPassthroughTestingVersion = 1.7.0 From cec4e74303928ba2bab866889501d28950a81917 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 2 Dec 2020 17:41:53 -0500 Subject: [PATCH 308/372] Upgrade to new tc-platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index edc5f653c0..797073c57d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre12 +terracottaPlatformVersion = 5.8.1-pre13 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.1-pre5 terracottaPassthroughTestingVersion = 1.7.0 From 36433caae5bf2967ef364c36397c799dbf2248dc Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 10 Dec 2018 10:09:22 -0500 Subject: [PATCH 309/372] Do property substitution using JAXB --- .../ClusteredResourceConfigurationParser.java | 17 +- ...acheManagerServiceConfigurationParser.java | 54 ++-- ...teringCacheServiceConfigurationParser.java | 2 +- .../main/resources/ehcache-clustered-ext.xsd | 54 ++-- ...steredResourceConfigurationParserTest.java | 60 ++++ ...ManagerServiceConfigurationParserTest.java | 238 ++++++++++++++- docs/src/docs/asciidoc/user/107.adoc | 1 + docs/src/docs/asciidoc/user/xml.adoc | 17 +- ...entRegistryServiceConfigurationParser.java | 9 +- .../main/resources/ehcache-management-ext.xsd | 2 +- ...egistryServiceConfigurationParserTest.java | 35 +++ ...acheManagerServiceConfigurationParser.java | 3 +- .../TxCacheServiceConfigurationParser.java | 3 +- .../src/main/resources/ehcache-tx-ext.xsd | 6 +- ...ManagerServiceConfigurationParserTest.java | 32 ++ ...TxCacheServiceConfigurationParserTest.java | 31 ++ .../org/ehcache/xml/ConfigurationParser.java | 59 +--- .../xml/CoreCacheConfigurationParser.java | 14 +- .../java/org/ehcache/xml/JaxbParsers.java | 83 ++++++ .../xml/ResourceConfigurationParser.java | 47 ++- .../java/org/ehcache/xml/model/Expiry.java | 4 +- .../xml/multi/XmlMultiConfiguration.java | 2 + ...DefaultWriteBehindConfigurationParser.java | 4 +- xml/src/main/resources/ehcache-core.xsd | 115 +++++-- .../xml/CoreCacheConfigurationParserTest.java | 6 +- .../java/org/ehcache/xml/JaxbParsersTest.java | 281 ++++++++++++++++++ .../ehcache/xml/PropertySubstitutionTest.java | 119 ++++++++ .../org/ehcache/xml/XmlConfigurationTest.java | 24 -- .../configs/ehcache-system-props.xml | 58 ++++ .../test/resources/configs/systemprops.xml | 35 --- 30 files changed, 1143 insertions(+), 272 deletions(-) create mode 100644 xml/src/main/java/org/ehcache/xml/JaxbParsers.java create mode 100644 xml/src/test/java/org/ehcache/xml/JaxbParsersTest.java create mode 100644 xml/src/test/java/org/ehcache/xml/PropertySubstitutionTest.java create mode 100644 xml/src/test/resources/configs/ehcache-system-props.xml delete mode 100644 xml/src/test/resources/configs/systemprops.xml diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java index 4478a5fbcd..321f8068ed 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java @@ -23,6 +23,7 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.xml.BaseConfigParser; import org.ehcache.xml.CacheResourceConfigurationParser; +import org.ehcache.xml.JaxbParsers; import org.ehcache.xml.exceptions.XmlConfigurationException; import org.osgi.service.component.annotations.Component; import org.w3c.dom.Attr; @@ -74,16 +75,16 @@ public URI getNamespace() { protected ResourcePool parseResourceConfig(final Element fragment) { final String elementName = fragment.getLocalName(); switch (elementName) { - case "clustered-shared": - final String sharing = fragment.getAttribute("sharing"); + case SHARED_ELEMENT_NAME: + final String sharing = JaxbParsers.parsePropertyOrString(fragment.getAttribute(SHARING_ELEMENT_NAME)); return new SharedClusteredResourcePoolImpl(sharing); - case "clustered-dedicated": + case DEDICATED_ELEMENT_NAME: // 'from' attribute is optional on 'clustered-dedicated' element - final Attr fromAttr = fragment.getAttributeNode("from"); - final String from = (fromAttr == null ? null : fromAttr.getValue()); + final Attr fromAttr = fragment.getAttributeNode(FROM_ELEMENT_NAME); + final String from = (fromAttr == null ? null : JaxbParsers.parsePropertyOrString(fromAttr.getValue())); - final String unitValue = fragment.getAttribute("unit").toUpperCase(); + final String unitValue = fragment.getAttribute(UNIT_ELEMENT_NAME).toUpperCase(); final MemoryUnit sizeUnits; try { sizeUnits = MemoryUnit.valueOf(unitValue); @@ -99,13 +100,13 @@ protected ResourcePool parseResourceConfig(final Element fragment) { } final long size; try { - size = Long.parseLong(sizeValue); + size = JaxbParsers.parsePropertyOrPositiveInteger(sizeValue).longValueExact(); } catch (NumberFormatException e) { throw new XmlConfigurationException(String.format("XML configuration element <%s> value '%s' is not valid", elementName, sizeValue), e); } return new DedicatedClusteredResourcePoolImpl(from, size, sizeUnits); - case "clustered": + case CLUSTERED_ELEMENT_NAME: return new ClusteredResourcePoolImpl(); } return null; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java index 73bc725f4d..16297a8a81 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java @@ -26,8 +26,9 @@ import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.xml.BaseConfigParser; import org.ehcache.xml.CacheManagerServiceConfigurationParser; +import org.ehcache.xml.JaxbParsers; import org.ehcache.xml.exceptions.XmlConfigurationException; -import org.ehcache.xml.model.TimeType; +import org.ehcache.xml.model.TimeTypeWithPropSubst; import org.osgi.service.component.annotations.Component; import org.w3c.dom.Attr; import org.w3c.dom.Document; @@ -53,6 +54,7 @@ import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; +import javax.xml.bind.helpers.DefaultValidationEventHandler; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; @@ -117,7 +119,7 @@ public URI getNamespace() { @Override public ServiceCreationConfiguration parseServiceCreationConfiguration(final Element fragment, ClassLoader classLoader) { - if ("cluster".equals(fragment.getLocalName())) { + if (CLUSTER_ELEMENT_NAME.equals(fragment.getLocalName())) { ClusteringCacheManagerServiceConfigurationParser.ServerSideConfig serverConfig = null; URI connectionUri = null; @@ -129,12 +131,12 @@ public URI getNamespace() { final Node item = childNodes.item(i); if (Node.ELEMENT_NODE == item.getNodeType()) { switch (item.getLocalName()) { - case "connection": + case CONNECTION_ELEMENT_NAME: /* * is a required element in the XSD */ - final Attr urlAttribute = ((Element)item).getAttributeNode("url"); - final String urlValue = urlAttribute.getValue(); + final Attr urlAttribute = ((Element)item).getAttributeNode(URL_ATTRIBUTE_NAME); + final String urlValue = JaxbParsers.parseStringWithProperties(urlAttribute.getValue()); try { connectionUri = new URI(urlValue); } catch (URISyntaxException e) { @@ -144,46 +146,46 @@ public URI getNamespace() { } break; - case "cluster-connection": - clusterTierManager = ((Element)item).getAttribute("cluster-tier-manager"); + case CLUSTER_CONNECTION_ELEMENT_NAME: + clusterTierManager = JaxbParsers.parsePropertyOrString(((Element)item).getAttribute(CLUSTER_TIER_MANAGER_ATTRIBUTE_NAME)); final NodeList serverNodes = item.getChildNodes(); for (int j = 0; j < serverNodes.getLength(); j++) { final Node serverNode = serverNodes.item(j); - final String host = ((Element)serverNode).getAttributeNode("host").getValue(); - final Attr port = ((Element)serverNode).getAttributeNode("port"); + final String host = JaxbParsers.parsePropertyOrString(((Element)serverNode).getAttributeNode(HOST_ATTRIBUTE_NAME).getValue()); + final Attr port = ((Element)serverNode).getAttributeNode(PORT_ATTRIBUTE_NAME); InetSocketAddress address; if (port == null) { address = InetSocketAddress.createUnresolved(host, 0); } else { - String portString = port.getValue(); + String portString = JaxbParsers.parsePropertyOrString(port.getValue()); address = InetSocketAddress.createUnresolved(host, Integer.parseInt(portString)); } serverAddresses.add(address); } break; - case "read-timeout": + case READ_TIMEOUT_ELEMENT_NAME: /* * is an optional element */ getTimeout = processTimeout(fragment, item); break; - case "write-timeout": + case WRITE_TIMEOUT_ELEMENT_NAME: /* * is an optional element */ putTimeout = processTimeout(fragment, item); break; - case "connection-timeout": + case CONNECTION_TIMEOUT_ELEMENT_NAME: /* * is an optional element */ connectionTimeout = processTimeout(fragment, item); break; - case "server-side-config": + case SERVER_SIDE_CONFIG: /* * is an optional element */ @@ -399,6 +401,7 @@ private ClusteringCacheManagerServiceConfigurationParser.ServerSideConfig proces serverSideConfig.clientMode = Boolean.parseBoolean(autoCreateAttr) ? ClientMode.AUTO_CREATE : ClientMode.EXPECTING; } } else if (autoCreateAttr.isEmpty()) { + clientModeAttr = JaxbParsers.parsePropertyOrString(clientModeAttr); serverSideConfig.clientMode = ClientMode.valueOf(clientModeAttr.toUpperCase(Locale.ROOT).replace('-', '_')); } else { throw new XmlConfigurationException("Cannot define both '" + AUTO_CREATE_ATTRIBUTE_NAME + "' and '" + CLIENT_MODE_ATTRIBUTE_NAME + "' attributes"); @@ -409,22 +412,22 @@ private ClusteringCacheManagerServiceConfigurationParser.ServerSideConfig proces final Node item = serverSideNodes.item(i); if (Node.ELEMENT_NODE == item.getNodeType()) { String nodeLocalName = item.getLocalName(); - if ("default-resource".equals(nodeLocalName)) { - serverSideConfig.defaultServerResource = ((Element)item).getAttribute("from"); + if (DEFAULT_RESOURCE_ELEMENT_NAME.equals(nodeLocalName)) { + serverSideConfig.defaultServerResource = JaxbParsers.parsePropertyOrString(((Element)item).getAttribute(FROM_ATTRIBUTE_NAME)); - } else if ("shared-pool".equals(nodeLocalName)) { + } else if (SHARED_POOL_ELEMENT_NAME.equals(nodeLocalName)) { Element sharedPoolElement = (Element)item; - String poolName = sharedPoolElement.getAttribute("name"); // required - Attr fromAttr = sharedPoolElement.getAttributeNode("from"); // optional + String poolName = sharedPoolElement.getAttribute(NAME_ATTRIBUTE_NAME); // required + Attr fromAttr = sharedPoolElement.getAttributeNode(FROM_ATTRIBUTE_NAME); // optional String fromResource = (fromAttr == null ? null : fromAttr.getValue()); - Attr unitAttr = sharedPoolElement.getAttributeNode("unit"); // optional - default 'B' + Attr unitAttr = sharedPoolElement.getAttributeNode(UNIT_ATTRIBUTE_NAME); // optional - default 'B' String unit = (unitAttr == null ? "B" : unitAttr.getValue()); MemoryUnit memoryUnit = MemoryUnit.valueOf(unit.toUpperCase(Locale.ENGLISH)); String quantityValue = sharedPoolElement.getFirstChild().getNodeValue(); long quantity; try { - quantity = Long.parseLong(quantityValue); + quantity = JaxbParsers.parsePropertyOrPositiveInteger(quantityValue).longValueExact(); } catch (NumberFormatException e) { throw new XmlConfigurationException("Magnitude of value specified for is too large"); @@ -434,7 +437,7 @@ private ClusteringCacheManagerServiceConfigurationParser.ServerSideConfig proces if (fromResource == null) { poolDefinition = new ServerSideConfiguration.Pool(memoryUnit.toBytes(quantity)); } else { - poolDefinition = new ServerSideConfiguration.Pool(memoryUnit.toBytes(quantity), fromResource); + poolDefinition = new ServerSideConfiguration.Pool(memoryUnit.toBytes(quantity), JaxbParsers.parsePropertyOrString(fromResource)); } if (serverSideConfig.pools.put(poolName, poolDefinition) != null) { @@ -449,11 +452,12 @@ private ClusteringCacheManagerServiceConfigurationParser.ServerSideConfig proces private Duration processTimeout(Element parentElement, Node timeoutNode) { try { // are direct subtype of ehcache:time-type; use JAXB to interpret it - JAXBContext context = JAXBContext.newInstance(TimeType.class); + JAXBContext context = JAXBContext.newInstance(TimeTypeWithPropSubst.class); Unmarshaller unmarshaller = context.createUnmarshaller(); - JAXBElement jaxbElement = unmarshaller.unmarshal(timeoutNode, TimeType.class); + unmarshaller.setEventHandler(new DefaultValidationEventHandler()); + JAXBElement jaxbElement = unmarshaller.unmarshal(timeoutNode, TimeTypeWithPropSubst.class); - TimeType timeType = jaxbElement.getValue(); + TimeTypeWithPropSubst timeType = jaxbElement.getValue(); BigInteger amount = timeType.getValue(); if (amount.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { throw new XmlConfigurationException( diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java index 35be7d00c4..67b7c4e7bf 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java @@ -65,7 +65,7 @@ public URI getNamespace() { public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { if (CLUSTERED_STORE_ELEMENT_NAME.equals(fragment.getLocalName())) { if (fragment.hasAttribute(CONSISTENCY_ATTRIBUTE_NAME)) { - return new ClusteredStoreConfiguration(Consistency.valueOf(fragment.getAttribute("consistency").toUpperCase())); + return new ClusteredStoreConfiguration(Consistency.valueOf(fragment.getAttribute(CONSISTENCY_ATTRIBUTE_NAME).toUpperCase())); } else { return new ClusteredStoreConfiguration(); } diff --git a/clustered/client/src/main/resources/ehcache-clustered-ext.xsd b/clustered/client/src/main/resources/ehcache-clustered-ext.xsd index f613874eb6..f42a6c5ff7 100644 --- a/clustered/client/src/main/resources/ehcache-clustered-ext.xsd +++ b/clustered/client/src/main/resources/ehcache-clustered-ext.xsd @@ -51,7 +51,7 @@ - + Specifies the amount of time a cache read operation will wait for a response from a cluster @@ -59,7 +59,7 @@ - + Specifies the amount of time a cache write operation will wait for a response from a cluster @@ -67,7 +67,7 @@ - + Specifies the amount of time a cache will wait to connect to a cluster @@ -90,9 +90,13 @@ - - - + + + + + + + @@ -100,7 +104,7 @@ - + Cluster Tier Manager identifier. @@ -116,14 +120,14 @@ - + The host that the server is running on. - + The port that the server is listening on. @@ -132,14 +136,6 @@ - - - - - - - - @@ -187,7 +183,7 @@ - + @@ -201,11 +197,15 @@ - - - - - + + + + + + + + + @@ -218,7 +218,7 @@ - + @@ -233,7 +233,7 @@ - + Name of the shared pool this resource uses. @@ -252,7 +252,7 @@ - + Optional reference to a server-side storage resource. @@ -262,7 +262,7 @@ - + Required reference to a server-side storage resource. diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java index 8eb8f5784f..70a0e69e9a 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java @@ -15,21 +15,81 @@ */ package org.ehcache.clustered.client.internal.config.xml; +import org.ehcache.clustered.client.config.DedicatedClusteredResourcePool; +import org.ehcache.clustered.client.config.SharedClusteredResourcePool; import org.ehcache.clustered.client.internal.config.ClusteredResourcePoolImpl; import org.ehcache.clustered.client.internal.config.DedicatedClusteredResourcePoolImpl; import org.ehcache.clustered.client.internal.config.SharedClusteredResourcePoolImpl; import org.ehcache.config.units.MemoryUnit; import org.junit.Test; +import org.w3c.dom.Element; import org.w3c.dom.Node; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.StringReader; import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; /** * ClusteredResourceConfigurationParserTest */ public class ClusteredResourceConfigurationParserTest { + @Test + public void testClusteredSharedUsingProperties() throws ParserConfigurationException, IOException, SAXException { + String property = ClusteredResourceConfigurationParserTest.class.getName() + ":sharing"; + String inputString = ""; + + ClusteredResourceConfigurationParser parser = new ClusteredResourceConfigurationParser(); + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + Element node = documentBuilderFactory.newDocumentBuilder() + .parse(new InputSource(new StringReader(inputString))).getDocumentElement(); + + System.setProperty(property, "foobar"); + try { + SharedClusteredResourcePool configuration = (SharedClusteredResourcePool) parser.parseResourceConfig(node); + + assertThat(configuration.getSharedResourcePool(), is("foobar")); + } finally { + System.clearProperty(property); + } + } + + @Test + public void testClusteredDedicatedUsingProperties() throws ParserConfigurationException, IOException, SAXException { + String fromProperty = ClusteredResourceConfigurationParserTest.class.getName() + ":from"; + String sizeProperty = ClusteredResourceConfigurationParserTest.class.getName() + ":size"; + String inputString = "" + + "${" + sizeProperty + "}"; + + ClusteredResourceConfigurationParser parser = new ClusteredResourceConfigurationParser(); + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + Element node = documentBuilderFactory.newDocumentBuilder() + .parse(new InputSource(new StringReader(inputString))).getDocumentElement(); + + System.setProperty(fromProperty, "foobar"); + System.setProperty(sizeProperty, "1024"); + try { + DedicatedClusteredResourcePool configuration = (DedicatedClusteredResourcePool) parser.parseResourceConfig(node); + + assertThat(configuration.getFromResource(), is("foobar")); + assertThat(configuration.getSize(), is(1024L)); + } finally { + System.clearProperty(fromProperty); + System.clearProperty(sizeProperty); + } + } + @Test public void testTranslateClusteredResourcePoolConfiguration() { ClusteredResourceConfigurationParser configTranslator = new ClusteredResourceConfigurationParser(); diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java index dc933e2b7f..1906861600 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java @@ -20,6 +20,7 @@ import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.config.builders.TimeoutsBuilder; import org.ehcache.clustered.client.internal.ConnectionSource; +import org.ehcache.clustered.common.ServerSideConfiguration; import org.ehcache.config.Configuration; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.util.ClassLoading; @@ -27,7 +28,7 @@ import org.ehcache.xml.CacheManagerServiceConfigurationParser; import org.ehcache.xml.XmlConfiguration; import org.ehcache.xml.exceptions.XmlConfigurationException; -import org.ehcache.xml.model.TimeType; +import org.ehcache.xml.model.TimeTypeWithPropSubst; import org.hamcrest.Matchers; import org.junit.ClassRule; import org.junit.Rule; @@ -50,7 +51,9 @@ import java.time.temporal.TemporalUnit; import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import javax.xml.parsers.DocumentBuilder; @@ -64,6 +67,7 @@ import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.ehcache.xml.XmlModel.convertToJavaTimeUnit; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; @@ -81,6 +85,8 @@ public class ClusteringCacheManagerServiceConfigurationParserTest { @Rule public final TestName testName = new TestName(); + private static final String PROPERTY_PREFIX = ClusteringCacheManagerServiceConfigurationParserTest.class.getName() + ":"; + /** * Ensures the {@link ClusteringCacheManagerServiceConfigurationParser} is locatable as a * {@link CacheManagerServiceConfigurationParser} instance. @@ -209,7 +215,7 @@ public void testGetTimeoutUnitDefault() throws Exception { findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); assertThat(clusteringServiceConfiguration, is(notNullValue())); - TemporalUnit defaultUnit = convertToJavaTimeUnit(new TimeType().getUnit()); + TemporalUnit defaultUnit = convertToJavaTimeUnit(new TimeTypeWithPropSubst().getUnit()); assertThat(clusteringServiceConfiguration.getTimeouts().getReadOperationTimeout(), is(equalTo(Duration.of(5, defaultUnit)))); } @@ -295,7 +301,90 @@ public void testGetTimeoutValueOmitted() throws Exception { fail("Expecting XmlConfigurationException"); } catch (XmlConfigurationException e) { assertThat(e.getMessage(), containsString("Error parsing XML configuration ")); - assertThat(e.getCause().getMessage(), containsString("'' is not a valid value for 'integer'")); + assertThat(e.getCause().getMessage(), containsString("'' is not a valid value of union type 'propertyOrPositiveInteger")); + } + } + + @Test + public void testGetTimeoutAsProperty() throws Exception { + String readTimeoutProperty = PROPERTY_PREFIX + testName.getMethodName() + ":read"; + String writeTimeoutProperty = PROPERTY_PREFIX + testName.getMethodName() + ":write"; + String connectTimeoutProperty = PROPERTY_PREFIX + testName.getMethodName() + ":connect"; + Map properties = new HashMap<>(); + properties.put(readTimeoutProperty, "5"); + properties.put(writeTimeoutProperty, "10"); + properties.put(connectTimeoutProperty, "15"); + + final String[] config = new String[] + { + "", + "", + " ", + " ", + " ", + " ${" + readTimeoutProperty + "}", + " ${" + writeTimeoutProperty + "}", + " ${" + connectTimeoutProperty + "}", + " ", + " ", + "", + "" + }; + + properties.forEach(System::setProperty); + try { + final Configuration configuration = new XmlConfiguration(makeConfig(config)); + + Collection> serviceCreationConfigurations = + configuration.getServiceCreationConfigurations(); + assertThat(serviceCreationConfigurations, is(not(Matchers.empty()))); + + ClusteringServiceConfiguration clusteringServiceConfiguration = + findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); + assertThat(clusteringServiceConfiguration, is(notNullValue())); + + Timeouts timeouts = clusteringServiceConfiguration.getTimeouts(); + assertThat(timeouts.getReadOperationTimeout(), is(Duration.of(5, MINUTES))); + assertThat(timeouts.getWriteOperationTimeout(), is(Duration.of(10, MINUTES))); + assertThat(timeouts.getConnectionTimeout(), is(Duration.of(15, MINUTES))); + } finally { + properties.keySet().forEach(System::clearProperty); + } + } + + @Test + public void testUrlWithProperty() throws Exception { + String serverProperty = PROPERTY_PREFIX + testName.getMethodName() + ":server"; + String portProperty = PROPERTY_PREFIX + testName.getMethodName() + ":port"; + Map properties = new HashMap<>(); + properties.put(serverProperty, "example.com"); + properties.put(portProperty, "9540"); + + final String[] config = new String[] + { + "", + "", + " ", + " ", + " ", + " ", + " ", + "", + "" + }; + + properties.forEach(System::setProperty); + try { + XmlConfiguration configuration = new XmlConfiguration(makeConfig(config)); + ClusteringServiceConfiguration clusteringConfig = findSingletonAmongst(ClusteringServiceConfiguration.class, configuration.getServiceCreationConfigurations()); + ConnectionSource.ClusterUri connectionSource = (ConnectionSource.ClusterUri) clusteringConfig.getConnectionSource(); + assertThat(connectionSource.getClusterUri(), is(URI.create("terracotta://example.com:9540/cachemanager"))); + } finally { + properties.keySet().forEach(System::clearProperty); } } @@ -418,6 +507,49 @@ public void testServersWithClusterTierManagerAndOptionalPorts() throws Exception assertThat(servers, is(expectedServers)); } + @Test + public void testServersWithClusterTierManagerAndOptionalPortsUsingProperties() throws Exception { + String hostProperty = PROPERTY_PREFIX + testName.getMethodName() + ":host"; + String portProperty = PROPERTY_PREFIX + testName.getMethodName() + ":port"; + String tierManagerProperty = PROPERTY_PREFIX + testName.getMethodName() + ":tierManager"; + Map properties = new HashMap<>(); + properties.put(hostProperty, "100.100.100.100"); + properties.put(portProperty, "9510"); + properties.put(tierManagerProperty, "george"); + + final String[] config = new String[] + { + "", + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "", + "" + }; + + properties.forEach(System::setProperty); + try { + final Configuration configuration = new XmlConfiguration(makeConfig(config)); + Collection> serviceCreationConfigurations = configuration.getServiceCreationConfigurations(); + ClusteringServiceConfiguration clusteringServiceConfiguration = + findSingletonAmongst(ClusteringServiceConfiguration.class, serviceCreationConfigurations); + ConnectionSource.ServerList connectionSource = (ConnectionSource.ServerList) clusteringServiceConfiguration.getConnectionSource(); + Iterable servers = connectionSource.getServers(); + + assertThat(connectionSource.getClusterTierManager(), is("george")); + assertThat(servers, contains(InetSocketAddress.createUnresolved("100.100.100.100", 9510))); + } finally { + properties.keySet().forEach(System::clearProperty); + } + } + @Test @SuppressWarnings("deprecation") public void testAutoCreateFalseMapsToExpecting() throws IOException { final String[] config = new String[] @@ -487,6 +619,106 @@ public void testBothAutoCreateAndClientModeIsDisallowed() throws IOException { } } + @Test + public void testClientModeAsAProperty() throws IOException { + String clientModeProperty = PROPERTY_PREFIX + testName.getMethodName() + ":client-mode"; + Map properties = new HashMap<>(); + properties.put(clientModeProperty, "auto-create"); + + final String[] config = new String[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + properties.forEach(System::setProperty); + try { + XmlConfiguration configuration = new XmlConfiguration(makeConfig(config)); + ClusteringServiceConfiguration clusterConfig = findSingletonAmongst(ClusteringServiceConfiguration.class, configuration.getServiceCreationConfigurations()); + assertThat(clusterConfig.getClientMode(), is(ClusteringServiceConfiguration.ClientMode.AUTO_CREATE)); + } finally { + properties.keySet().forEach(System::clearProperty); + } + } + + @Test + public void testSharedPoolUsingProperties() throws IOException { + String poolSizeProperty = PROPERTY_PREFIX + testName.getMethodName() + ":pool-size"; + String fromProperty = PROPERTY_PREFIX + testName.getMethodName() + ":from"; + Map properties = new HashMap<>(); + properties.put(poolSizeProperty, "1024"); + properties.put(fromProperty, "source"); + + final String[] config = new String[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ${" + poolSizeProperty + "}", + " ", + " ", + " ", + " ", + "" + }; + + properties.forEach(System::setProperty); + try { + XmlConfiguration configuration = new XmlConfiguration(makeConfig(config)); + ClusteringServiceConfiguration clusterConfig = findSingletonAmongst(ClusteringServiceConfiguration.class, configuration.getServiceCreationConfigurations()); + ServerSideConfiguration.Pool pool = clusterConfig.getServerConfiguration().getResourcePools().get("pool"); + assertThat(pool.getSize(), is(1024L)); + assertThat(pool.getServerResource(), is("source")); + } finally { + properties.keySet().forEach(System::clearProperty); + } + } + + @Test + public void testDefaultResourceAsAProperty() throws IOException { + String fromProperty = PROPERTY_PREFIX + testName.getMethodName() + ":from"; + Map properties = new HashMap<>(); + properties.put(fromProperty, "source"); + + final String[] config = new String[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + properties.forEach(System::setProperty); + try { + XmlConfiguration configuration = new XmlConfiguration(makeConfig(config)); + ClusteringServiceConfiguration clusterConfig = findSingletonAmongst(ClusteringServiceConfiguration.class, configuration.getServiceCreationConfigurations()); + assertThat(clusterConfig.getServerConfiguration().getDefaultServerResource(), is("source")); + } finally { + properties.keySet().forEach(System::clearProperty); + } + } + @Test public void testTranslateServiceCreationConfiguration() throws Exception { URI connectionUri = new URI("terracotta://localhost:9510/my-application"); diff --git a/docs/src/docs/asciidoc/user/107.adoc b/docs/src/docs/asciidoc/user/107.adoc index b419af0cb4..d4a471cba5 100644 --- a/docs/src/docs/asciidoc/user/107.adoc +++ b/docs/src/docs/asciidoc/user/107.adoc @@ -187,6 +187,7 @@ include::{sourcedir39}/107/src/test/resources/org/ehcache/docs/ehcache-107-mbean <3> The cache `overrideCache` will have both MBeans disabled, overriding the service configuration. <4> The cache `overrideOneCache` will have the statistics MBean disabled, whereas the management MBean will be enabled according to the service configuration. +[[supplement-jsr-107-configurations]] ==== Supplementing JCache cache configurations using Ehcache XML extensions You can also create `cache-templates`. diff --git a/docs/src/docs/asciidoc/user/xml.adoc b/docs/src/docs/asciidoc/user/xml.adoc index b16a16ba58..0ed5c10431 100644 --- a/docs/src/docs/asciidoc/user/xml.adoc +++ b/docs/src/docs/asciidoc/user/xml.adoc @@ -84,12 +84,8 @@ WARNING: Processing of cache template configurations can be triggered lazily by == Property replacement in XML configuration files -Java system properties can be referenced inside XML configuration files. -The property value will replace the property reference during the configuration parsing. - -This is done by using the `${prop.name}` syntax. -It is supported in all attributes and elements values that accept the `${}` characters as legal characters. -This currently rules out all numbers, mostly used in sizing things, and identifiers, such as cache and template names. +Certain elements inside XML configuration files can use `${property-name}` syntax. The value of the given +system-property will replace the property reference during the configuration parsing. WARNING: If the system property does not exist, this will make the configuration parsing fail. @@ -101,6 +97,15 @@ A classical use case for this feature is for disk files location inside the `dir ---- <1> Here `user.home` will be replaced by the value of the system property, something like `/home/user` +Attributes within the core configuration that can use system properties are: + + * Local persistence directory (supports substitution within a string). + * Thread pool minimum and maximum size attributes. + * Write-behind queue size, concurrency, batch size and maximum batch delay. + * Cache TTI and TTL + * Core resource sizes (heap, offheap and disk) + * Disk store writer concurrency and segment count + == XML programmatic parsing NOTE: If you are obtaining your `CacheManager` through the JSR-107 API, what follows is done automatically diff --git a/management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java b/management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java index d83c5bc5f6..12b3e412db 100644 --- a/management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java +++ b/management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java @@ -19,6 +19,7 @@ import org.ehcache.spi.service.ServiceCreationConfiguration; import org.ehcache.xml.BaseConfigParser; import org.ehcache.xml.CacheManagerServiceConfigurationParser; +import org.ehcache.xml.JaxbParsers; import org.ehcache.xml.exceptions.XmlConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -71,8 +72,8 @@ public URI getNamespace() { for (Element tags : NodeListIterable.elements(fragment, NAMESPACE, "tags")) { // tag for (Element tag : NodeListIterable.elements(tags, NAMESPACE, "tag")) { - String val = val(tag); - if (val != null && !val.isEmpty()) { + String val = JaxbParsers.parsePropertyOrString(tag.getTextContent()); + if (!val.isEmpty()) { registryConfiguration.addTag(val); } } @@ -92,10 +93,6 @@ private static String attr(Element element, String name) { return s == null || s.equals("") ? null : s; } - private static String val(Element element) { - return element.hasChildNodes() ? element.getFirstChild().getNodeValue() : null; - } - @Override public Class getServiceType() { return ManagementRegistryService.class; diff --git a/management/src/main/resources/ehcache-management-ext.xsd b/management/src/main/resources/ehcache-management-ext.xsd index 13d8130b11..927129c9c9 100644 --- a/management/src/main/resources/ehcache-management-ext.xsd +++ b/management/src/main/resources/ehcache-management-ext.xsd @@ -34,7 +34,7 @@ - + diff --git a/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java b/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java index 4e24db76f2..afb4751a85 100644 --- a/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java +++ b/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java @@ -15,8 +15,18 @@ */ package org.ehcache.management.registry; +import org.hamcrest.Matchers; import org.junit.Test; +import org.w3c.dom.Element; import org.w3c.dom.Node; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import java.io.IOException; +import java.io.StringReader; import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.hamcrest.MatcherAssert.assertThat; @@ -26,6 +36,31 @@ */ public class ManagementRegistryServiceConfigurationParserTest { + @Test + public void testParseTagInsideProperty() throws ParserConfigurationException, IOException, SAXException { + String property = ManagementRegistryServiceConfigurationParserTest.class.getName() + ":tag"; + String inputString = "" + + "tag1${" + property + "}"; + + ManagementRegistryServiceConfigurationParser configParser = new ManagementRegistryServiceConfigurationParser(); + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + Element node = documentBuilderFactory.newDocumentBuilder() + .parse(new InputSource(new StringReader(inputString))).getDocumentElement(); + + System.setProperty(property, "tag2"); + try { + DefaultManagementRegistryConfiguration configuration = + (DefaultManagementRegistryConfiguration) configParser.parseServiceCreationConfiguration(node, null); + + assertThat(configuration.getTags(), Matchers.hasItems("tag1", "tag2")); + } finally { + System.clearProperty(property); + } + } + @Test public void testTranslateServiceCreationConfiguration() { ManagementRegistryServiceConfigurationParser configTranslator = new ManagementRegistryServiceConfigurationParser(); diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java index d412299de9..1a58b26816 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java @@ -22,6 +22,7 @@ import org.ehcache.xml.BaseConfigParser; import org.ehcache.xml.CacheManagerServiceConfigurationParser; import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.ehcache.xml.JaxbParsers; import org.ehcache.xml.exceptions.XmlConfigurationException; import org.osgi.service.component.annotations.Component; import org.w3c.dom.Document; @@ -62,7 +63,7 @@ public URI getNamespace() { public ServiceCreationConfiguration parseServiceCreationConfiguration(Element fragment, ClassLoader classLoader) { String localName = fragment.getLocalName(); if ("jta-tm".equals(localName)) { - String transactionManagerProviderConfigurationClassName = fragment.getAttribute("transaction-manager-lookup-class"); + String transactionManagerProviderConfigurationClassName = JaxbParsers.parsePropertyOrString(fragment.getAttribute("transaction-manager-lookup-class")); try { Class aClass = Class.forName(transactionManagerProviderConfigurationClassName, true, delegationChain( () -> Thread.currentThread().getContextClassLoader(), diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java index a3a940631c..f5b5993385 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java @@ -21,6 +21,7 @@ import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.transactions.xa.internal.XAStore; import org.ehcache.transactions.xa.configuration.XAStoreConfiguration; +import org.ehcache.xml.JaxbParsers; import org.ehcache.xml.exceptions.XmlConfigurationException; import org.osgi.service.component.annotations.Component; import org.w3c.dom.Document; @@ -59,7 +60,7 @@ public URI getNamespace() { public ServiceConfiguration parseServiceConfiguration(Element fragment, ClassLoader classLoader) { String localName = fragment.getLocalName(); if ("xa-store".equals(localName)) { - String uniqueXAResourceId = fragment.getAttribute("unique-XAResource-id"); + String uniqueXAResourceId = JaxbParsers.parsePropertyOrString(fragment.getAttribute("unique-XAResource-id")); return new XAStoreConfiguration(uniqueXAResourceId); } else { throw new XmlConfigurationException(String.format("XML configuration element <%s> in <%s> is not supported", diff --git a/transactions/src/main/resources/ehcache-tx-ext.xsd b/transactions/src/main/resources/ehcache-tx-ext.xsd index 23f5bd6ab6..266c992aa5 100644 --- a/transactions/src/main/resources/ehcache-tx-ext.xsd +++ b/transactions/src/main/resources/ehcache-tx-ext.xsd @@ -28,11 +28,11 @@ - + - + - \ No newline at end of file + diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java index 7967d1791e..33bcbc3360 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java @@ -18,16 +18,48 @@ import org.ehcache.transactions.xa.txmgr.btm.BitronixTransactionManagerLookup; import org.ehcache.transactions.xa.txmgr.provider.LookupTransactionManagerProviderConfiguration; import org.junit.Test; +import org.w3c.dom.Element; import org.w3c.dom.Node; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.StringReader; import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.sameInstance; /** * TxCacheManagerServiceConfigurationParserTest */ public class TxCacheManagerServiceConfigurationParserTest { + @Test + public void testParseLookupInsideProperty() throws ParserConfigurationException, IOException, SAXException { + String property = TxCacheManagerServiceConfigurationParserTest.class.getName() + ":lookup"; + String inputString = ""; + + TxCacheManagerServiceConfigurationParser configParser = new TxCacheManagerServiceConfigurationParser(); + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + Element node = documentBuilderFactory.newDocumentBuilder() + .parse(new InputSource(new StringReader(inputString))).getDocumentElement(); + + System.setProperty(property, BitronixTransactionManagerLookup.class.getName()); + try { + LookupTransactionManagerProviderConfiguration configuration = + (LookupTransactionManagerProviderConfiguration) configParser.parseServiceCreationConfiguration(node, null); + + assertThat(configuration.getTransactionManagerLookup(), sameInstance(BitronixTransactionManagerLookup.class)); + } finally { + System.clearProperty(property); + } + } + @Test public void testTranslateServiceCreationConfiguration() { TxCacheManagerServiceConfigurationParser configTranslator = new TxCacheManagerServiceConfigurationParser(); diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java index c232c962c5..1e9b61c865 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java @@ -17,16 +17,47 @@ import org.ehcache.transactions.xa.configuration.XAStoreConfiguration; import org.junit.Test; +import org.w3c.dom.Element; import org.w3c.dom.Node; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.StringReader; import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; /** * TxCacheServiceConfigurationParserTest */ public class TxCacheServiceConfigurationParserTest { + @Test + public void testParseXaResourceIdInsideProperty() throws ParserConfigurationException, IOException, SAXException { + String property = TxCacheManagerServiceConfigurationParserTest.class.getName() + ":xaResourceId"; + String inputString = ""; + + TxCacheServiceConfigurationParser configParser = new TxCacheServiceConfigurationParser(); + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + Element node = documentBuilderFactory.newDocumentBuilder() + .parse(new InputSource(new StringReader(inputString))).getDocumentElement(); + + System.setProperty(property, "Brian"); + try { + XAStoreConfiguration configuration = (XAStoreConfiguration) configParser.parseServiceConfiguration(node, null); + + assertThat(configuration.getUniqueXAResourceId(), is("Brian")); + } finally { + System.clearProperty(property); + } + } + @Test public void testTranslateServiceConfiguration() { TxCacheServiceConfigurationParser configTranslator = new TxCacheServiceConfigurationParser(); diff --git a/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java index e2c73890fb..5325197c77 100644 --- a/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java @@ -33,9 +33,6 @@ import org.ehcache.xml.model.ObjectFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; @@ -46,6 +43,7 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; +import javax.xml.bind.helpers.DefaultValidationEventHandler; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -70,7 +68,6 @@ import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.security.PrivilegedAction; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collections; @@ -79,14 +76,11 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Stack; -import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; import java.util.stream.StreamSupport; import static java.lang.String.format; -import static java.security.AccessController.doPrivileged; import static java.util.Arrays.asList; import static java.util.Spliterators.spliterator; import static java.util.function.Function.identity; @@ -107,7 +101,6 @@ */ public class ConfigurationParser { - private static final Pattern SYSPROP = Pattern.compile("\\$\\{([^}]+)\\}"); private static final SchemaFactory XSD_SCHEMA_FACTORY = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); private static Schema newSchema(Source... schemas) throws SAXException { synchronized (XSD_SCHEMA_FACTORY) { @@ -132,23 +125,6 @@ private static Schema newSchema(Source... schemas) throws SAXException { private final ServiceConfigurationParser serviceConfigurationParser; private final ResourceConfigurationParser resourceConfigurationParser; - static String replaceProperties(String originalValue) { - Matcher matcher = SYSPROP.matcher(originalValue); - - StringBuffer sb = new StringBuffer(); - while (matcher.find()) { - final String property = matcher.group(1); - final String value = doPrivileged((PrivilegedAction) () -> System.getProperty(property)); - if (value == null) { - throw new IllegalStateException(String.format("Replacement for ${%s} not found!", property)); - } - matcher.appendReplacement(sb, Matcher.quoteReplacement(value)); - } - matcher.appendTail(sb); - final String resolvedValue = sb.toString(); - return resolvedValue.equals(originalValue) ? null : resolvedValue; - } - @SuppressWarnings("unchecked") private static Stream stream(Iterable iterable) { return StreamSupport.stream(spliterator((Iterator) iterable.iterator(), Long.MAX_VALUE, 0), false); @@ -181,36 +157,6 @@ CacheConfigurationBuilder parseServiceConfigurations(CacheConfigura return serviceConfigurationParser.parseConfiguration(cacheDefinition, cacheClassLoader, cacheBuilder); } - private static void substituteSystemProperties(Node node) { - Stack nodeLists = new Stack<>(); - nodeLists.push(node.getChildNodes()); - while (!nodeLists.isEmpty()) { - NodeList nodeList = nodeLists.pop(); - for (int i = 0; i < nodeList.getLength(); ++i) { - Node currentNode = nodeList.item(i); - if (currentNode.hasChildNodes()) { - nodeLists.push(currentNode.getChildNodes()); - } - final NamedNodeMap attributes = currentNode.getAttributes(); - if (attributes != null) { - for (int j = 0; j < attributes.getLength(); ++j) { - final Node attributeNode = attributes.item(j); - final String newValue = replaceProperties(attributeNode.getNodeValue()); - if (newValue != null) { - attributeNode.setNodeValue(newValue); - } - } - } - if (currentNode.getNodeType() == Node.TEXT_NODE) { - final String newValue = replaceProperties(currentNode.getNodeValue()); - if (newValue != null) { - currentNode.setNodeValue(newValue); - } - } - } - } - } - private static Iterable getCacheElements(ConfigType configType) { List cacheCfgs = new ArrayList<>(); final List cacheOrCacheTemplate = configType.getCacheOrCacheTemplate(); @@ -285,8 +231,6 @@ public Document uriToDocument(URI uri) throws IOException, SAXException { } public XmlConfigurationWrapper documentToConfig(Document document, ClassLoader classLoader, Map cacheClassLoaders) throws JAXBException, ClassNotFoundException, InstantiationException, IllegalAccessException { - substituteSystemProperties(document); - Element root = document.getDocumentElement(); QName rootName = new QName(root.getNamespaceURI(), root.getLocalName()); @@ -296,6 +240,7 @@ public XmlConfigurationWrapper documentToConfig(Document document, ClassLoader c Class configTypeClass = ConfigType.class; Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + unmarshaller.setEventHandler(new DefaultValidationEventHandler()); ConfigType jaxbModel = unmarshaller.unmarshal(document, configTypeClass).getValue(); FluentConfigurationBuilder managerBuilder = newConfigurationBuilder().withClassLoader(classLoader); diff --git a/xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java index 8c6b23963a..89681e3999 100644 --- a/xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java @@ -27,21 +27,15 @@ import org.ehcache.xml.model.CacheType; import org.ehcache.xml.model.Expiry; import org.ehcache.xml.model.ExpiryType; -import org.ehcache.xml.model.TimeType; -import org.ehcache.xml.model.TimeUnit; +import org.ehcache.xml.model.ObjectFactory; +import org.ehcache.xml.model.TimeTypeWithPropSubst; import java.math.BigInteger; import java.time.Duration; import java.util.stream.Stream; import static java.util.Comparator.comparing; -import static java.util.concurrent.TimeUnit.DAYS; -import static java.util.concurrent.TimeUnit.HOURS; -import static java.util.concurrent.TimeUnit.MICROSECONDS; -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.NANOSECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import static org.ehcache.core.config.ExpiryUtils.jucTimeUnitToTemporalUnit; import static org.ehcache.xml.XmlConfiguration.getClassForName; import static org.ehcache.xml.XmlModel.convertToXmlTimeUnit; @@ -113,12 +107,12 @@ public CacheType unparseConfiguration(CacheConfiguration cacheConfiguratio return cacheType; } - private static TimeType convertToTimeType(Duration duration) { + private static TimeTypeWithPropSubst convertToTimeType(Duration duration) { return Stream.of(java.util.concurrent.TimeUnit.values()) .sorted(comparing(unit -> unit.convert(duration.toNanos(), NANOSECONDS))) .filter(unit -> duration.equals(Duration.of(unit.convert(duration.toNanos(), NANOSECONDS), jucTimeUnitToTemporalUnit(unit)))) .findFirst() - .map(unit -> new TimeType() + .map(unit -> new ObjectFactory().createTimeTypeWithPropSubst() .withValue(BigInteger.valueOf(unit.convert(duration.toNanos(), NANOSECONDS))) .withUnit(convertToXmlTimeUnit(unit)) ).orElseThrow(AssertionError::new); diff --git a/xml/src/main/java/org/ehcache/xml/JaxbParsers.java b/xml/src/main/java/org/ehcache/xml/JaxbParsers.java new file mode 100644 index 0000000000..3d3e5acfca --- /dev/null +++ b/xml/src/main/java/org/ehcache/xml/JaxbParsers.java @@ -0,0 +1,83 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.xml; + +import java.math.BigInteger; +import java.security.PrivilegedAction; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.security.AccessController.doPrivileged; + +public class JaxbParsers { + + private static final Pattern SYSPROP = Pattern.compile("\\$\\{(?[^{}]+)}"); + private static final Pattern PADDED_SYSPROP = Pattern.compile("\\s*" + SYSPROP.pattern() + "\\s*"); + + public static String parsePropertyOrString(String s) { + Matcher matcher = PADDED_SYSPROP.matcher(s); + if (matcher.matches()) { + String property = matcher.group("property"); + String value = doPrivileged((PrivilegedAction) () -> System.getProperty(property)); + if (value == null) { + throw new IllegalStateException(String.format("Replacement for ${%s} not found!", property)); + } else { + return value; + } + } else { + return s; + } + } + + public static BigInteger parsePropertyOrInteger(String s) { + return new BigInteger(parsePropertyOrString(s)); + } + + public static BigInteger parsePropertyOrPositiveInteger(String s) { + BigInteger value = parsePropertyOrInteger(s); + if (value.compareTo(BigInteger.ZERO) > 0) { + return value; + } else { + throw new IllegalArgumentException("Value " + value + " is not a positive integer"); + } + } + + public static BigInteger parsePropertyOrNonNegativeInteger(String s) { + BigInteger value = parsePropertyOrInteger(s); + if (value.compareTo(BigInteger.ZERO) >= 0) { + return value; + } else { + throw new IllegalArgumentException("Value " + value + " is not a non-negative integer"); + } + } + + public static String parseStringWithProperties(String s) { + Matcher matcher = SYSPROP.matcher(s); + StringBuffer sb = new StringBuffer(); + while (matcher.find()) { + final String property = matcher.group("property"); + final String value = doPrivileged((PrivilegedAction) () -> System.getProperty(property)); + if (value == null) { + throw new IllegalStateException(String.format("Replacement for ${%s} not found!", property)); + } + matcher.appendReplacement(sb, Matcher.quoteReplacement(value)); + } + matcher.appendTail(sb); + return sb.toString(); + } + +} diff --git a/xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java index 94dacb3f23..97493718fd 100644 --- a/xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java @@ -29,11 +29,11 @@ import org.ehcache.xml.model.CacheType; import org.ehcache.xml.model.Disk; import org.ehcache.xml.model.Heap; -import org.ehcache.xml.model.MemoryType; +import org.ehcache.xml.model.MemoryTypeWithPropSubst; import org.ehcache.xml.model.ObjectFactory; import org.ehcache.xml.model.Offheap; -import org.ehcache.xml.model.PersistableMemoryType; -import org.ehcache.xml.model.ResourceType; +import org.ehcache.xml.model.PersistableMemoryTypeWithPropSubst; +import org.ehcache.xml.model.ResourceTypeWithPropSubst; import org.ehcache.xml.model.ResourcesType; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -52,6 +52,7 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; +import javax.xml.bind.helpers.DefaultValidationEventHandler; import javax.xml.parsers.ParserConfigurationException; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; @@ -60,6 +61,7 @@ public class ResourceConfigurationParser { + private static final ObjectFactory OBJECT_FACTORY = new ObjectFactory(); private static final Schema CORE_SCHEMA; static { SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); @@ -69,11 +71,7 @@ public class ResourceConfigurationParser { throw new AssertionError(e); } } - private static final String CORE_SCHEMA_NS; - static { - ObjectFactory factory = new ObjectFactory(); - CORE_SCHEMA_NS = factory.createResource(factory.createResourceType()).getName().getNamespaceURI(); - } + private static final String CORE_SCHEMA_NS = OBJECT_FACTORY.createResource(OBJECT_FACTORY.createResourceTypeWithPropSubst()).getName().getNamespaceURI(); private final JAXBContext jaxbContext; private final Set extensionParsers; @@ -99,16 +97,16 @@ public ResourcePools parseResourceConfiguration(CacheTemplate cacheTemplate, Res } else { try { Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - unmarshaller.setSchema(CORE_SCHEMA); + unmarshaller.setEventHandler(new DefaultValidationEventHandler()); Object resource = unmarshaller.unmarshal(element); if (resource instanceof Heap) { resourcePool = parseHeapConfiguration((Heap) resource); } else if (resource instanceof Offheap) { - MemoryType offheapResource = ((Offheap) resource).getValue(); + MemoryTypeWithPropSubst offheapResource = ((Offheap) resource).getValue(); resourcePool = new SizedResourcePoolImpl<>(org.ehcache.config.ResourceType.Core.OFFHEAP, offheapResource.getValue().longValue(), parseMemory(offheapResource), false); } else if (resource instanceof Disk) { - PersistableMemoryType diskResource = ((Disk) resource).getValue(); + PersistableMemoryTypeWithPropSubst diskResource = ((Disk) resource).getValue(); resourcePool = new SizedResourcePoolImpl<>(org.ehcache.config.ResourceType.Core.DISK, diskResource.getValue().longValue(), parseMemory(diskResource), diskResource.isPersistent()); } else { @@ -130,20 +128,20 @@ public ResourcePools parseResourceConfiguration(CacheTemplate cacheTemplate, Res } private ResourcePool parseHeapConfiguration(Heap heap) { - ResourceType heapResource = heap.getValue(); + ResourceTypeWithPropSubst heapResource = heap.getValue(); return new SizedResourcePoolImpl<>(org.ehcache.config.ResourceType.Core.HEAP, heapResource.getValue().longValue(), parseUnit(heapResource), false); } - private static ResourceUnit parseUnit(ResourceType resourceType) { - if (resourceType.getUnit().value().equalsIgnoreCase("entries")) { + private static ResourceUnit parseUnit(ResourceTypeWithPropSubst resourceType) { + if (resourceType.getUnit().equals(org.ehcache.xml.model.ResourceUnit.ENTRIES)) { return EntryUnit.ENTRIES; } else { return org.ehcache.config.units.MemoryUnit.valueOf(resourceType.getUnit().value().toUpperCase()); } } - private static org.ehcache.config.units.MemoryUnit parseMemory(MemoryType memoryType) { + private static org.ehcache.config.units.MemoryUnit parseMemory(MemoryTypeWithPropSubst memoryType) { return MemoryUnit.valueOf(memoryType.getUnit().value().toUpperCase()); } @@ -166,21 +164,12 @@ public CacheType unparseResourceConfiguration(ResourcePools resourcePools, Cache SizedResourcePool pool = (SizedResourcePool) resourcePool; Object resource; if (resourceType == org.ehcache.config.ResourceType.Core.HEAP) { - Heap heap = new Heap(); - ResourceType xmlResourceType = new ResourceType().withValue(BigInteger.valueOf(pool.getSize())).withUnit(unparseUnit(pool.getUnit())); - heap.setValue(xmlResourceType); - resource = heap; + resource = OBJECT_FACTORY.createHeap(OBJECT_FACTORY.createResourceTypeWithPropSubst().withValue(BigInteger.valueOf(pool.getSize())).withUnit(unparseUnit(pool.getUnit()))); } else if (resourceType == org.ehcache.config.ResourceType.Core.OFFHEAP) { - Offheap offheap = new Offheap(); - MemoryType memoryType = new MemoryType().withValue(BigInteger.valueOf(pool.getSize())).withUnit(unparseMemory((MemoryUnit) pool.getUnit())); - offheap.setValue(memoryType); - resource = offheap; + resource = OBJECT_FACTORY.createOffheap(OBJECT_FACTORY.createMemoryTypeWithPropSubst().withValue(BigInteger.valueOf(pool.getSize())).withUnit(unparseMemory((MemoryUnit) pool.getUnit()))); } else if (resourceType == org.ehcache.config.ResourceType.Core.DISK) { - Disk disk = new Disk(); - PersistableMemoryType memoryType = new PersistableMemoryType().withValue(BigInteger.valueOf(pool.getSize())) - .withUnit(unparseMemory((MemoryUnit) pool.getUnit())).withPersistent(pool.isPersistent()); - disk.setValue(memoryType); - resource = disk; + resource = OBJECT_FACTORY.createDisk(OBJECT_FACTORY.createPersistableMemoryTypeWithPropSubst().withValue(BigInteger.valueOf(pool.getSize())) + .withUnit(unparseMemory((MemoryUnit) pool.getUnit())).withPersistent(pool.isPersistent())); } else { throw new AssertionError("Unrecognized core resource type: " + resourceType); } @@ -207,7 +196,7 @@ public CacheType unparseResourceConfiguration(ResourcePools resourcePools, Cache resources.add(element); }); - return cacheType.withResources(new ResourcesType().withResource(resources)); + return cacheType.withResources(OBJECT_FACTORY.createResourcesType().withResource(resources)); } private static org.ehcache.xml.model.ResourceUnit unparseUnit(ResourceUnit resourceUnit) { diff --git a/xml/src/main/java/org/ehcache/xml/model/Expiry.java b/xml/src/main/java/org/ehcache/xml/model/Expiry.java index 9f7f0011dd..2307708328 100644 --- a/xml/src/main/java/org/ehcache/xml/model/Expiry.java +++ b/xml/src/main/java/org/ehcache/xml/model/Expiry.java @@ -45,7 +45,7 @@ public String type() { } public long value() { - final TimeType time; + final TimeTypeWithPropSubst time; if(isTTI()) { time = type.getTti(); } else { @@ -55,7 +55,7 @@ public long value() { } public TemporalUnit unit() { - final TimeType time; + final TimeTypeWithPropSubst time; if(isTTI()) { time = type.getTti(); } else { diff --git a/xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java b/xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java index 2e3de99e2e..c87789b5ce 100644 --- a/xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java +++ b/xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java @@ -31,6 +31,7 @@ import javax.xml.bind.Unmarshaller; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.helpers.DefaultValidationEventHandler; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; @@ -87,6 +88,7 @@ private XmlMultiConfiguration(URL url, BiFunction { diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParser.java index daa0a5ed4b..a42f0f4da2 100644 --- a/xml/src/main/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParser.java @@ -23,7 +23,7 @@ import org.ehcache.xml.model.BaseCacheType; import org.ehcache.xml.model.CacheLoaderWriterType; import org.ehcache.xml.model.CacheTemplate; -import org.ehcache.xml.model.TimeType; +import org.ehcache.xml.model.TimeTypeWithPropSubst; import java.math.BigInteger; @@ -62,7 +62,7 @@ public DefaultWriteBehindConfigurationParser() { writeBehind.withBatching(new CacheLoaderWriterType.WriteBehind.Batching() .withBatchSize(BigInteger.valueOf(batchingConfiguration.getBatchSize())) .withCoalesce(batchingConfiguration.isCoalescing()) - .withMaxWriteDelay(new TimeType() + .withMaxWriteDelay(new TimeTypeWithPropSubst() .withValue(BigInteger.valueOf(batchingConfiguration.getMaxDelay())) .withUnit(convertToXmlTimeUnit(batchingConfiguration.getMaxDelayUnit())) ) diff --git a/xml/src/main/resources/ehcache-core.xsd b/xml/src/main/resources/ehcache-core.xsd index 721126fef5..7cd287bc2b 100644 --- a/xml/src/main/resources/ehcache-core.xsd +++ b/xml/src/main/resources/ehcache-core.xsd @@ -134,7 +134,7 @@ - + @@ -171,8 +171,8 @@ - - + + @@ -385,9 +385,9 @@ - + - + @@ -396,8 +396,8 @@ - - + + @@ -435,14 +435,14 @@ - + Entries in the cache should expire if not accessed for the defined time. - + Entries in the cache should expire after the defined time. @@ -460,9 +460,9 @@ - + - + @@ -477,20 +477,32 @@ - - - - The memory unit (see org.ehcache.config.units.MemoryUnit) this value is expressed in. - - - + - + - + + + + + + + + + + + The memory unit (see org.ehcache.config.units.MemoryUnit) this value is expressed in. + + + + + + + + @@ -502,9 +514,9 @@ - + - + @@ -518,7 +530,7 @@ - + @@ -528,7 +540,7 @@ - + @@ -538,7 +550,7 @@ - + @@ -557,8 +569,8 @@ - - + + @@ -617,7 +629,54 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/src/test/java/org/ehcache/xml/CoreCacheConfigurationParserTest.java b/xml/src/test/java/org/ehcache/xml/CoreCacheConfigurationParserTest.java index 5768e79f10..0befa07036 100644 --- a/xml/src/test/java/org/ehcache/xml/CoreCacheConfigurationParserTest.java +++ b/xml/src/test/java/org/ehcache/xml/CoreCacheConfigurationParserTest.java @@ -24,7 +24,7 @@ import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.xml.exceptions.XmlConfigurationException; import org.ehcache.xml.model.CacheType; -import org.ehcache.xml.model.TimeType; +import org.ehcache.xml.model.TimeTypeWithPropSubst; import org.ehcache.xml.model.TimeUnit; import org.hamcrest.CoreMatchers; import org.junit.Test; @@ -93,7 +93,7 @@ public void unparseConfigurationCustomExpiry() { public void unparseConfigurationTtiExpiry() { CacheConfiguration cacheConfiguration = buildCacheConfigWith(ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofMillis(2500))); CacheType cacheType = parser.unparseConfiguration(cacheConfiguration, new CacheType()); - TimeType tti = cacheType.getExpiry().getTti(); + TimeTypeWithPropSubst tti = cacheType.getExpiry().getTti(); assertThat(tti, notNullValue()); assertThat(tti.getValue(), is(BigInteger.valueOf(2500))); assertThat(tti.getUnit(), is(TimeUnit.MILLIS)); @@ -103,7 +103,7 @@ public void unparseConfigurationTtiExpiry() { public void unparseConfigurationTtlExpiry() { CacheConfiguration cacheConfiguration = buildCacheConfigWith(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(60))); CacheType cacheType = parser.unparseConfiguration(cacheConfiguration, new CacheType()); - TimeType ttl = cacheType.getExpiry().getTtl(); + TimeTypeWithPropSubst ttl = cacheType.getExpiry().getTtl(); assertThat(ttl, notNullValue()); assertThat(ttl.getValue(), is(BigInteger.valueOf(1))); assertThat(ttl.getUnit(), is(TimeUnit.HOURS)); diff --git a/xml/src/test/java/org/ehcache/xml/JaxbParsersTest.java b/xml/src/test/java/org/ehcache/xml/JaxbParsersTest.java new file mode 100644 index 0000000000..a23d1ffe62 --- /dev/null +++ b/xml/src/test/java/org/ehcache/xml/JaxbParsersTest.java @@ -0,0 +1,281 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.xml; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import java.math.BigInteger; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThrows; + +public class JaxbParsersTest { + + private static final String PROPERTY_PREFIX = JaxbParsersTest.class.getName() + ":"; + @Rule public final TestName testName = new TestName(); + + @Test + public void testParsePropertyOrStringFromNullString() { + assertThrows(NullPointerException.class, () -> JaxbParsers.parsePropertyOrString(null)); + } + + @Test + public void testParsePropertyOrStringWithoutProperty() { + assertThat(JaxbParsers.parsePropertyOrString("${foobar"), is("${foobar")); + assertThat(JaxbParsers.parsePropertyOrString("foobar"), is("foobar")); + assertThat(JaxbParsers.parsePropertyOrString("foobar}"), is("foobar}")); + assertThat(JaxbParsers.parsePropertyOrString("$foobar"), is("$foobar")); + } + + @Test + public void testParsePropertyOrStringWithProperty() { + String property = PROPERTY_PREFIX + testName.getMethodName(); + System.setProperty(property, "barfoo"); + try { + assertThat(JaxbParsers.parsePropertyOrString("${" + property + "}"), is("barfoo")); + } finally { + System.clearProperty(property); + } + } + + @Test + public void testParsePropertyOrStringWithMissingProperty() { + String property = PROPERTY_PREFIX + testName.getMethodName(); + assertThrows(IllegalStateException.class, () -> JaxbParsers.parsePropertyOrString("${" + property + "}")); + } + + @Test + public void testParsePropertyOrIntegerFromNullString() { + assertThrows(NullPointerException.class, () -> JaxbParsers.parsePropertyOrInteger(null)); + } + + @Test + public void testParsePropertyOrIntegerValidWithoutProperty() { + assertThat(JaxbParsers.parsePropertyOrInteger("123"), is(BigInteger.valueOf(123))); + assertThat(JaxbParsers.parsePropertyOrInteger("-123"), is(BigInteger.valueOf(-123))); + } + + @Test + public void testParsePropertyOrIntegerInvalidWithoutProperty() { + assertThrows(NumberFormatException.class, () -> JaxbParsers.parsePropertyOrInteger("foobar")); + } + + @Test + public void testParsePropertyOrIntegerValidWithProperty() { + String property = PROPERTY_PREFIX + testName.getMethodName(); + System.setProperty(property, "123"); + try { + assertThat(JaxbParsers.parsePropertyOrInteger("${" + property + "}"), is(BigInteger.valueOf(123))); + } finally { + System.clearProperty(property); + } + System.setProperty(property, "-123"); + try { + assertThat(JaxbParsers.parsePropertyOrInteger("${" + property + "}"), is(BigInteger.valueOf(-123))); + } finally { + System.clearProperty(property); + } + } + + @Test + public void testParsePropertyOrIntegerInvalidWithProperty() { + String property = PROPERTY_PREFIX + testName.getMethodName(); + System.setProperty(property, "barfoo"); + try { + assertThrows(NumberFormatException.class, () -> JaxbParsers.parsePropertyOrInteger("${" + property + "}")); + } finally { + System.clearProperty(property); + } + } + + @Test + public void testParsePropertyOrIntegerWithMissingProperty() { + String property = PROPERTY_PREFIX + testName.getMethodName(); + assertThrows(IllegalStateException.class, () -> JaxbParsers.parsePropertyOrInteger("${" + property + "}")); + } + + + @Test + public void testParsePropertyOrPositiveIntegerFromNullString() { + assertThrows(NullPointerException.class, () -> JaxbParsers.parsePropertyOrPositiveInteger(null)); + } + + @Test + public void testParsePropertyOrPositiveIntegerValidWithoutProperty() { + assertThat(JaxbParsers.parsePropertyOrPositiveInteger("123"), is(BigInteger.valueOf(123))); + } + + @Test + public void testParsePropertyOrPositiveIntegerInvalidWithoutProperty() { + assertThrows(NumberFormatException.class, () -> JaxbParsers.parsePropertyOrPositiveInteger("foobar")); + } + + @Test + public void testParsePropertyOrPositiveIntegerOutOfRangeWithoutProperty() { + assertThrows(IllegalArgumentException.class, () -> JaxbParsers.parsePropertyOrPositiveInteger("0")); + } + + @Test + public void testParsePropertyOrPositiveIntegerValidWithProperty() { + String property = PROPERTY_PREFIX + testName.getMethodName(); + System.setProperty(property, "123"); + try { + assertThat(JaxbParsers.parsePropertyOrPositiveInteger("${" + property + "}"), is(BigInteger.valueOf(123))); + } finally { + System.clearProperty(property); + } + } + + @Test + public void testParsePropertyOrPositiveIntegerInvalidWithProperty() { + String property = PROPERTY_PREFIX + testName.getMethodName(); + System.setProperty(property, "barfoo"); + try { + assertThrows(NumberFormatException.class, () -> JaxbParsers.parsePropertyOrPositiveInteger("${" + property + "}")); + } finally { + System.clearProperty(property); + } + } + + @Test + public void testParsePropertyOrPositiveIntegerOutOfRangeWithProperty() { + String property = PROPERTY_PREFIX + testName.getMethodName(); + System.setProperty(property, "0"); + try { + assertThrows(IllegalArgumentException.class, () -> JaxbParsers.parsePropertyOrPositiveInteger("${" + property + "}")); + } finally { + System.clearProperty(property); + } + } + + @Test + public void testParsePropertyOrPositiveIntegerWithMissingProperty() { + String property = PROPERTY_PREFIX + testName.getMethodName(); + assertThrows(IllegalStateException.class, () -> JaxbParsers.parsePropertyOrPositiveInteger("${" + property + "}")); + } + + @Test + public void parsePropertyOrNonNegativeInteger() { + } + + @Test + public void testParsePropertyOrNonNegativeIntegerFromNullString() { + assertThrows(NullPointerException.class, () -> JaxbParsers.parsePropertyOrNonNegativeInteger(null)); + } + + @Test + public void testParsePropertyOrNonNegativeIntegerValidWithoutProperty() { + assertThat(JaxbParsers.parsePropertyOrNonNegativeInteger("123"), is(BigInteger.valueOf(123))); + } + + @Test + public void testParsePropertyOrNonNegativeIntegerInvalidWithoutProperty() { + assertThrows(NumberFormatException.class, () -> JaxbParsers.parsePropertyOrNonNegativeInteger("foobar")); + } + + @Test + public void testParsePropertyOrNonNegativeIntegerOutOfRangeWithoutProperty() { + assertThrows(IllegalArgumentException.class, () -> JaxbParsers.parsePropertyOrNonNegativeInteger("-1")); + } + + @Test + public void testParsePropertyOrNonNegativeIntegerValidWithProperty() { + String property = PROPERTY_PREFIX + testName.getMethodName(); + System.setProperty(property, "123"); + try { + assertThat(JaxbParsers.parsePropertyOrNonNegativeInteger("${" + property + "}"), is(BigInteger.valueOf(123))); + } finally { + System.clearProperty(property); + } + } + + @Test + public void testParsePropertyOrNonNegativeIntegerInvalidWithProperty() { + String property = PROPERTY_PREFIX + testName.getMethodName(); + System.setProperty(property, "barfoo"); + try { + assertThrows(NumberFormatException.class, () -> JaxbParsers.parsePropertyOrNonNegativeInteger("${" + property + "}")); + } finally { + System.clearProperty(property); + } + } + + @Test + public void testParsePropertyOrNonNegativeIntegerOutOfRangeWithProperty() { + String property = PROPERTY_PREFIX + testName.getMethodName(); + System.setProperty(property, "-1"); + try { + assertThrows(IllegalArgumentException.class, () -> JaxbParsers.parsePropertyOrNonNegativeInteger("${" + property + "}")); + } finally { + System.clearProperty(property); + } + } + + @Test + public void testParsePropertyOrNonNegativeIntegerWithMissingProperty() { + String property = PROPERTY_PREFIX + testName.getMethodName(); + assertThrows(IllegalStateException.class, () -> JaxbParsers.parsePropertyOrNonNegativeInteger("${" + property + "}")); + } + + @Test + public void parseStringWithProperties() { + } + + @Test + public void testParseStringWithPropertiesFromNullString() { + assertThrows(NullPointerException.class, () -> JaxbParsers.parseStringWithProperties(null)); + } + + @Test + public void testParseStringWithPropertiesWithoutProperties() { + assertThat(JaxbParsers.parseStringWithProperties("foo${bar"), is("foo${bar")); + assertThat(JaxbParsers.parseStringWithProperties("foobar"), is("foobar")); + assertThat(JaxbParsers.parseStringWithProperties("foo}bar"), is("foo}bar")); + assertThat(JaxbParsers.parseStringWithProperties("foo$bar"), is("foo$bar")); + } + + @Test + public void testParseStringWithPropertiesWithProperties() { + String foo = PROPERTY_PREFIX + testName.getMethodName() + ":foo"; + String bar = PROPERTY_PREFIX + testName.getMethodName() + ":bar"; + System.setProperty(foo, "foo"); + System.setProperty(bar, "bar"); + try { + assertThat(JaxbParsers.parseStringWithProperties("start:${" + foo + "}:middle:${" + bar + "}:end"), is("start:foo:middle:bar:end")); + } finally { + System.clearProperty(foo); + System.clearProperty(bar); + } + } + + @Test + public void testParseStringWithPropertiesWithMissingProperty() { + String foo = PROPERTY_PREFIX + testName.getMethodName() + ":foo"; + String bar = PROPERTY_PREFIX + testName.getMethodName() + ":bar"; + assertThat(System.getProperty(bar), is(nullValue())); + System.setProperty(foo, "foo"); + try { + assertThrows(IllegalStateException.class, () -> JaxbParsers.parseStringWithProperties("start:${" + foo + "}:middle:${" + bar + "}:end")); + } finally { + System.clearProperty(foo); + } + } +} diff --git a/xml/src/test/java/org/ehcache/xml/PropertySubstitutionTest.java b/xml/src/test/java/org/ehcache/xml/PropertySubstitutionTest.java new file mode 100644 index 0000000000..6993783696 --- /dev/null +++ b/xml/src/test/java/org/ehcache/xml/PropertySubstitutionTest.java @@ -0,0 +1,119 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.xml; + +import org.ehcache.config.CacheConfiguration; +import org.ehcache.config.ResourceType; +import org.ehcache.impl.config.executor.PooledExecutionServiceConfiguration; +import org.ehcache.impl.config.loaderwriter.writebehind.DefaultWriteBehindConfiguration; +import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; +import org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration; +import org.ehcache.spi.service.ServiceCreationConfiguration; +import org.ehcache.xml.exceptions.XmlConfigurationException; +import org.hamcrest.CustomMatcher; +import org.hamcrest.CustomTypeSafeMatcher; +import org.junit.Test; + +import javax.xml.bind.UnmarshalException; +import java.net.URL; +import java.time.Duration; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.either; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThrows; +import static org.terracotta.utilities.test.matchers.Matchers.causedBy; + +public class PropertySubstitutionTest { + + @Test + public void testMissingProperties() { + final URL resource = PropertySubstitutionTest.class.getResource("/configs/ehcache-system-props.xml"); + XmlConfigurationException failure = assertThrows(XmlConfigurationException.class, () -> new XmlConfiguration(resource)); + assertThat(failure, causedBy(instanceOf(UnmarshalException.class))); + } + + @Test + public void testSubstitutions() { + Map neededProperties = new HashMap<>(); + neededProperties.put("ehcache.persistence.directory", "foobar"); + neededProperties.put("ehcache.thread-pools.min-size", "0"); + neededProperties.put("ehcache.thread-pools.max-size", "4"); + neededProperties.put("ehcache.expiry.ttl", "10"); + neededProperties.put("ehcache.expiry.tti", "20"); + neededProperties.put("ehcache.loader-writer.write-behind.size", "1000"); + neededProperties.put("ehcache.loader-writer.write-behind.concurrency", "4"); + neededProperties.put("ehcache.loader-writer.write-behind.batching.batch-size", "100"); + neededProperties.put("ehcache.loader-writer.write-behind.batching.max-write-delay", "10"); + neededProperties.put("ehcache.disk-store-settings.writer-concurrency", "8"); + neededProperties.put("ehcache.disk-store-settings.disk-segments", "16"); + neededProperties.put("ehcache.resources.heap", "1024"); + neededProperties.put("ehcache.resources.offheap", "2048"); + neededProperties.put("ehcache.resources.disk", "4096"); + + System.getProperties().putAll(neededProperties); + try { + final URL resource = PropertySubstitutionTest.class.getResource("/configs/ehcache-system-props.xml"); + XmlConfiguration xmlConfig = new XmlConfiguration(new XmlConfiguration(resource)); + + Collection> serviceCreationConfigurations = xmlConfig.getServiceCreationConfigurations(); + + assertThat(findSingletonAmongst(DefaultPersistenceConfiguration.class, serviceCreationConfigurations).getRootDirectory().getAbsolutePath(), either( + is("/dir/path/foobar/tail")).or(new CustomTypeSafeMatcher("matches pattern [A-Z]:\\dir\\path\\foobar\\tail") { + @Override + protected boolean matchesSafely(String item) { + return item.matches("[A-Z]:\\\\dir\\\\path\\\\foobar\\\\tail"); + } + })); + PooledExecutionServiceConfiguration.PoolConfiguration poolConfiguration = findSingletonAmongst(PooledExecutionServiceConfiguration.class, serviceCreationConfigurations).getPoolConfigurations().get("theone"); + assertThat(poolConfiguration.minSize(), is(0)); + assertThat(poolConfiguration.maxSize(), is(4)); + + CacheConfiguration testCacheConfig = xmlConfig.getCacheConfigurations().get("test"); + assertThat(testCacheConfig.getExpiryPolicy().getExpiryForCreation(null, null), is(Duration.ofHours(10))); + assertThat(testCacheConfig.getExpiryPolicy().getExpiryForAccess(null, null), is(nullValue())); + assertThat(testCacheConfig.getExpiryPolicy().getExpiryForUpdate(null, null, null), is(Duration.ofHours(10))); + + DefaultWriteBehindConfiguration writeBehindConfiguration = findSingletonAmongst(DefaultWriteBehindConfiguration.class, testCacheConfig.getServiceConfigurations()); + assertThat(writeBehindConfiguration.getConcurrency(), is(4)); + assertThat(writeBehindConfiguration.getMaxQueueSize(), is(1000)); + assertThat(writeBehindConfiguration.getBatchingConfiguration().getBatchSize(), is(100)); + assertThat(writeBehindConfiguration.getBatchingConfiguration().getMaxDelay(), is(10L)); + + OffHeapDiskStoreConfiguration diskStoreConfiguration = findSingletonAmongst(OffHeapDiskStoreConfiguration.class, testCacheConfig.getServiceConfigurations()); + assertThat(diskStoreConfiguration.getDiskSegments(), is(16)); + assertThat(diskStoreConfiguration.getWriterConcurrency(), is(8)); + + assertThat(testCacheConfig.getResourcePools().getPoolForResource(ResourceType.Core.HEAP).getSize(), is(1024L)); + assertThat(testCacheConfig.getResourcePools().getPoolForResource(ResourceType.Core.OFFHEAP).getSize(), is(2048L)); + assertThat(testCacheConfig.getResourcePools().getPoolForResource(ResourceType.Core.DISK).getSize(), is(4096L)); + + CacheConfiguration anotherTestCacheConfig = xmlConfig.getCacheConfigurations().get("another-test"); + assertThat(anotherTestCacheConfig.getExpiryPolicy().getExpiryForCreation(null, null), is(Duration.ofMillis(20))); + assertThat(anotherTestCacheConfig.getExpiryPolicy().getExpiryForAccess(null, null), is(Duration.ofMillis(20))); + assertThat(anotherTestCacheConfig.getExpiryPolicy().getExpiryForUpdate(null, null, null), is(Duration.ofMillis(20))); + } finally { + neededProperties.keySet().forEach(System::clearProperty); + } + } +} diff --git a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java index 49ca059aa9..698e5a9be4 100644 --- a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java @@ -723,30 +723,6 @@ public void testResilienceStrategyFromTemplate() throws Exception { assertThat(resilienceStrategyConfiguration.getClazz(), sameInstance(ShrubberyResilience.class)); } - @Test - public void testSysPropReplace() { - System.getProperties().setProperty("ehcache.match", Number.class.getName()); - XmlConfiguration xmlConfig = new XmlConfiguration(XmlConfigurationTest.class.getResource("/configs/systemprops.xml")); - - assertThat(xmlConfig.getCacheConfigurations().get("bar").getKeyType(), sameInstance((Class)Number.class)); - - DefaultPersistenceConfiguration persistenceConfiguration = (DefaultPersistenceConfiguration)xmlConfig.getServiceCreationConfigurations().iterator().next(); - assertThat(persistenceConfiguration.getRootDirectory(), is(new File(System.getProperty("user.home") + "/ehcache"))); - } - - @Test - public void testSysPropReplaceRegExp() { - assertThat(ConfigurationParser.replaceProperties("foo${file.separator}"), equalTo("foo" + File.separator)); - assertThat(ConfigurationParser.replaceProperties("${file.separator}foo${file.separator}"), equalTo(File.separator + "foo" + File.separator)); - try { - ConfigurationParser.replaceProperties("${bar}foo"); - fail("Should have thrown!"); - } catch (IllegalStateException e) { - assertThat(e.getMessage().contains("${bar}"), is(true)); - } - assertThat(ConfigurationParser.replaceProperties("foo"), nullValue()); - } - @Test public void testMultithreadedXmlParsing() throws InterruptedException, ExecutionException { Callable parserTask = () -> new XmlConfiguration(XmlConfigurationTest.class.getResource("/configs/one-cache.xml")); diff --git a/xml/src/test/resources/configs/ehcache-system-props.xml b/xml/src/test/resources/configs/ehcache-system-props.xml new file mode 100644 index 0000000000..f9a9474fad --- /dev/null +++ b/xml/src/test/resources/configs/ehcache-system-props.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + com.pany.ehcache.copier.Description + com.pany.ehcache.copier.Person + + ${ehcache.expiry.ttl} + + + com.pany.ehcache.integration.TestCacheLoaderWriter + + + ${ehcache.loader-writer.write-behind.batching.max-write-delay} + + + + + ${ehcache.resources.heap} + ${ehcache.resources.offheap} + ${ehcache.resources.disk} + + + + + + java.lang.Long + java.lang.String + + ${ehcache.expiry.tti} + + 4096 + + diff --git a/xml/src/test/resources/configs/systemprops.xml b/xml/src/test/resources/configs/systemprops.xml deleted file mode 100644 index bf18c771d0..0000000000 --- a/xml/src/test/resources/configs/systemprops.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - 5 - - - - ${ehcache.match} - 5 - - From 3cc59e76087c3af807561df4cb6e775b2edfdfad Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 15 Dec 2020 13:06:41 -0500 Subject: [PATCH 310/372] Update to Terracotta Platform 5.8.1-pre14 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 797073c57d..fc8a9b1a9c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre13 +terracottaPlatformVersion = 5.8.1-pre14 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.1-pre5 terracottaPassthroughTestingVersion = 1.7.0 From e46c3e19d3ec1728d969ad38dd64447b35fc33af Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 10 Jul 2019 13:58:04 -0400 Subject: [PATCH 311/372] BND directive cleanup --- core/build.gradle | 2 +- dist/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index 782444732a..59d62566b1 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -34,6 +34,6 @@ jar { bnd ( 'Bundle-Activator': 'org.ehcache.core.osgi.EhcacheActivator', 'Import-Package': '!javax.annotation, *', - 'Export-Package': '!org.ehcache.core.internal.*, org.ehcache.core.*, org.ehcache.config.builders.*' + 'Export-Package': '!org.ehcache.core.internal.*, org.ehcache.core.*' ) } diff --git a/dist/build.gradle b/dist/build.gradle index 4b1038ab0f..4f784a54a2 100644 --- a/dist/build.gradle +++ b/dist/build.gradle @@ -42,7 +42,7 @@ jar { 'Bundle-Description': 'Ehcache is an open-source caching library, compliant with the JSR-107 standard.', 'Bundle-Activator': 'org.ehcache.core.osgi.EhcacheActivator', - 'Export-Package': '!org.ehcache.jsr107.tck, !org.ehcache.*.internal.*, org.ehcache.*, org.terracotta.statistics.*, org.terracotta.context', + 'Export-Package': '!org.ehcache.jsr107.tck, !org.ehcache.*.internal.*, org.ehcache.*', 'Import-Package': "javax.cache.*;resolution:=optional, !javax.annotation, !sun.misc, javax.xml.bind*;version=\"${parent.jaxbVersion}\", *" ) } From 4a83b27c47ec6ec6f34789300352ae996e32e6ab Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 10 Jul 2019 14:33:33 -0400 Subject: [PATCH 312/372] Remove core dependency on management-model --- .../clustered/BasicEntityInteractionTest.java | 6 +- .../org/ehcache/osgi/ClusteredOsgiTest.java | 3 - core/build.gradle | 3 - .../core/spi/service/StatisticsService.java | 53 +--- .../statistics/DefaultStatisticsService.java | 59 +---- .../core/statistics/StatisticType.java | 22 ++ .../statistics/SuppliedValueStatistic.java | 2 - .../core/statistics/ValueStatistic.java | 2 - ...rg.ehcache.core.spi.service.ServiceFactory | 1 + .../impl/internal/store/heap/OnHeapStore.java | 2 +- .../store/offheap/AbstractOffHeapStore.java | 4 +- .../org/ehcache/impl/store/BaseStore.java | 2 +- ...rg.ehcache.core.spi.service.ServiceFactory | 1 - management/build.gradle | 1 + .../management/ExtendedStatisticsService.java | 74 ++++++ .../statistics/EhcacheStatisticsProvider.java | 5 +- .../statistics/StandardEhcacheStatistics.java | 6 +- .../DefaultExtendedStatisticsService.java | 250 ++++++++++++++++++ ...faultExtendedStatisticsServiceFactory.java | 39 +++ .../DefaultManagementRegistryService.java | 8 +- ...rg.ehcache.core.spi.service.ServiceFactory | 3 +- .../EhcacheStatisticsProviderTest.java | 6 +- .../ehcache/osgi/ByteSizedOnHeapOsgiTest.java | 3 - .../java/org/ehcache/osgi/Jsr107OsgiTest.java | 3 - .../org/ehcache/osgi/OffHeapOsgiTest.java | 3 - .../java/org/ehcache/osgi/SimpleOsgiTest.java | 3 - .../ehcache/osgi/TransactionalOsgiTest.java | 3 - 27 files changed, 423 insertions(+), 144 deletions(-) create mode 100644 core/src/main/java/org/ehcache/core/statistics/StatisticType.java create mode 100644 core/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory create mode 100644 management/src/main/java/org/ehcache/management/ExtendedStatisticsService.java create mode 100644 management/src/main/java/org/ehcache/management/registry/DefaultExtendedStatisticsService.java create mode 100644 management/src/main/java/org/ehcache/management/registry/DefaultExtendedStatisticsServiceFactory.java diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java index 1a446f7c27..de021034cd 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java @@ -28,8 +28,8 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; import org.ehcache.management.cluster.DefaultClusteringManagementService; +import org.ehcache.management.registry.DefaultExtendedStatisticsService; import org.hamcrest.Matchers; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -85,7 +85,7 @@ public void testClusteringServiceConfigurationBuilderThrowsNPE() throws Exceptio .with(clusteredDedicated(offheap, 2, MemoryUnit.MB)) ) ).with(ClusteringServiceConfigurationBuilder.cluster(tsaUri) - ).using(new DefaultStatisticsService() + ).using(new DefaultExtendedStatisticsService() ).using(new DefaultClusteringManagementService() ).build(true)) { Cache cache = cacheManager.getCache(cacheName, Long.class, String.class); @@ -107,7 +107,7 @@ public void testServicesStoppedTwice() throws Exception { ).with(ClusteringServiceConfigurationBuilder.cluster(tsaUri) .autoCreate(server -> server.defaultServerResource(offheap)) // manually adding the following two services should work - ).using(new DefaultStatisticsService() + ).using(new DefaultExtendedStatisticsService() ).using(new DefaultClusteringManagementService() ).build(true)) { Cache cache = cacheManager.getCache(cacheName, Long.class, String.class); diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java index 2bba55fd39..5350076eee 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java @@ -83,9 +83,6 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:xml"), jaxbConfiguration(), gradleBundle("org.ehcache:clustered-dist"), - gradleBundle("org.terracotta.management:management-model"), - gradleBundle("org.terracotta.management:sequence-generator"), - gradleBundle("org.terracotta:statistics"), gradleBundle("org.ehcache:sizeof"), gradleBundle("org.terracotta:offheap-store"), diff --git a/core/build.gradle b/core/build.gradle index 59d62566b1..d342e3d9fa 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -22,9 +22,6 @@ plugins { dependencies { api project(':api') implementation "org.terracotta:statistics:$parent.statisticVersion" - api ("org.terracotta.management:management-model:$terracottaPlatformVersion") { - exclude group:'org.terracotta', module:'statistics' - } compileOnly 'org.osgi:osgi.core:6.0.0' compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':spi-tester') diff --git a/core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java b/core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java index 3cb0166c4d..720edee96f 100644 --- a/core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java +++ b/core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java @@ -16,21 +16,16 @@ package org.ehcache.core.spi.service; -import org.ehcache.Cache; import org.ehcache.core.spi.store.Store; import org.ehcache.core.statistics.CacheStatistics; -import org.ehcache.core.statistics.LatencyHistogramConfiguration; import org.ehcache.core.statistics.OperationObserver; +import org.ehcache.core.statistics.OperationStatistic; +import org.ehcache.core.statistics.StatisticType; import org.ehcache.spi.service.Service; -import org.terracotta.management.model.capabilities.descriptors.StatisticDescriptor; -import org.terracotta.management.model.stats.Statistic; -import org.terracotta.management.model.stats.StatisticType; import java.io.Serializable; -import java.util.Collection; import java.util.Map; import java.util.Set; -import java.util.function.LongSupplier; import java.util.function.Supplier; /** @@ -46,48 +41,6 @@ public interface StatisticsService extends Service { */ CacheStatistics getCacheStatistics(String cacheName); - /** - * Create statistics registry - * @param cacheName name (alias) of the cache - * @param cache the {@link Cache} associated with the given alias - * @param timeSource source of time for statistics maintenance - */ - void createCacheRegistry(String cacheName, Cache cache, LongSupplier timeSource); - - /** - * Registers a cache for statistics - * @param cacheName name (alias) of the cache - */ - void registerCacheStatistics(String cacheName); - - /** - * Returns the Statistics descriptor for the cache with the given alias - * @param cacheName name (alias) of the cache - * @return the collection of {@link StatisticDescriptor}s of the cache - */ - Collection getCacheDescriptors(String cacheName); - - /** - * Registers derived statistics for the cache - * @param the generic type of statistics - * @param cacheName name (alias) of the cache - * @param cache the cache associated with the given alias - * @param statName name of the statistic - * @param outcome Class of the type of statistics - * @param derivedName visible name of the statistics - * @param configuration the histogram configuration for statistics - */ - , K, V> void registerDerivedStatistics(String cacheName, Cache cache, String statName, T outcome, String derivedName, LatencyHistogramConfiguration configuration); - - /** - * Returns the statistics for the cache - * @param cacheName name (alias) of the cache - * @param statisticNames names of the statistics - * @param since time since statistics needs to be collected - * @return map of statisticNames and statistics - */ - Map> collectStatistics(String cacheName, Collection statisticNames, long since); - /** * Registers the object to parent * @param toAssociate object to associate @@ -105,7 +58,7 @@ public interface StatisticsService extends Service { * @param statisticName name of the statistic * @return statistics for the store */ - , T extends Enum> org.ehcache.core.statistics.OperationStatistic registerStoreStatistics(Store store, String targetName, int tierHeight, String tag, Map> translation, String statisticName); + , T extends Enum> OperationStatistic registerStoreStatistics(Store store, String targetName, int tierHeight, String tag, Map> translation, String statisticName); /** * De-registers object from the parent diff --git a/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java b/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java index 6c0d202c49..7a93a756bf 100644 --- a/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java +++ b/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java @@ -30,27 +30,16 @@ import org.ehcache.spi.service.ServiceProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.terracotta.management.model.capabilities.descriptors.StatisticDescriptor; -import org.terracotta.management.model.stats.Statistic; -import org.terracotta.management.model.stats.StatisticRegistry; -import org.terracotta.management.model.stats.StatisticType; import org.terracotta.statistics.MappedOperationStatistic; -import org.terracotta.statistics.OperationStatistic; import org.terracotta.statistics.StatisticsManager; -import org.terracotta.statistics.derived.OperationResultFilter; -import org.terracotta.statistics.derived.latency.DefaultLatencyHistogramStatistic; import java.io.Serializable; -import java.util.Collection; -import java.util.EnumSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.function.LongSupplier; import java.util.function.Supplier; -import static org.ehcache.core.statistics.StatsUtils.findOperationStatisticOnChildren; import static org.terracotta.statistics.StatisticBuilder.operation; /** @@ -62,7 +51,6 @@ public class DefaultStatisticsService implements StatisticsService, CacheManager private static final Logger LOGGER = LoggerFactory.getLogger(DefaultStatisticsService.class); private final ConcurrentMap cacheStatistics = new ConcurrentHashMap<>(); - private final ConcurrentMap statisticRegistries = new ConcurrentHashMap<>(); private volatile InternalCacheManager cacheManager; private volatile boolean started = false; @@ -120,44 +108,9 @@ public void cleanForNode(Object node) { StatisticsManager.nodeFor(node).clean(); } - @Override - public void createCacheRegistry(String cacheName, Cache cache, LongSupplier timeSource) { - statisticRegistries.put(cacheName, new StatisticRegistry(cache, timeSource)); - } - - @Override - public void registerCacheStatistics(String cacheName) { - cacheStatistics.get(cacheName).getKnownStatistics().forEach(statisticRegistries.get(cacheName)::registerStatistic); - } - - @Override - public Collection getCacheDescriptors(String cacheName) { - return statisticRegistries.get(cacheName).getDescriptors(); - } - - @Override - public , K, V> void registerDerivedStatistics(String cacheName, Cache cache, String statName, T outcome, String derivedName, LatencyHistogramConfiguration configuration) { - DefaultLatencyHistogramStatistic histogram = new DefaultLatencyHistogramStatistic(configuration.getPhi(), configuration.getBucketCount(), configuration.getWindow()); - - @SuppressWarnings("unchecked") - Class outcomeClass = (Class) outcome.getClass(); - OperationStatistic stat = findOperationStatisticOnChildren(cache, outcomeClass, statName); - stat.addDerivedStatistic(new OperationResultFilter<>(EnumSet.of(outcome), histogram)); - - statisticRegistries.get(cacheName).registerStatistic(derivedName + "#50", histogram.medianStatistic()); - statisticRegistries.get(cacheName).registerStatistic(derivedName + "#95", histogram.percentileStatistic(0.95)); - statisticRegistries.get(cacheName).registerStatistic(derivedName + "#99", histogram.percentileStatistic(0.99)); - statisticRegistries.get(cacheName).registerStatistic(derivedName + "#100", histogram.maximumStatistic()); - } - - @Override - public Map> collectStatistics(String cacheName, Collection statisticNames, long since) { - return StatisticRegistry.collect(statisticRegistries.get(cacheName), statisticNames, since); - } - @Override public void registerStatistic(Object context, String name, StatisticType type, Set tags, Supplier valueSupplier) { - StatisticsManager.createPassThroughStatistic(context, name, tags, StatisticType.convert(type), valueSupplier); + StatisticsManager.createPassThroughStatistic(context, name, tags, convert(type), valueSupplier); } @Override @@ -229,4 +182,14 @@ public void cacheRemoved(String alias, Cache cache) { cacheStatistics.remove(alias); } + private static org.terracotta.statistics.StatisticType convert(StatisticType type) { + switch (type) { + case COUNTER: + return org.terracotta.statistics.StatisticType.COUNTER; + case GAUGE: + return org.terracotta.statistics.StatisticType.GAUGE; + default: + throw new IllegalArgumentException("Untranslatable statistic type : " + type); + } + } } diff --git a/core/src/main/java/org/ehcache/core/statistics/StatisticType.java b/core/src/main/java/org/ehcache/core/statistics/StatisticType.java new file mode 100644 index 0000000000..f24336185a --- /dev/null +++ b/core/src/main/java/org/ehcache/core/statistics/StatisticType.java @@ -0,0 +1,22 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.core.statistics; + +public enum StatisticType { + COUNTER, + GAUGE +} diff --git a/core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java b/core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java index feb2d57680..1a806fc4aa 100644 --- a/core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java +++ b/core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java @@ -16,8 +16,6 @@ package org.ehcache.core.statistics; -import org.terracotta.management.model.stats.StatisticType; - import java.io.Serializable; import java.util.Objects; import java.util.function.Supplier; diff --git a/core/src/main/java/org/ehcache/core/statistics/ValueStatistic.java b/core/src/main/java/org/ehcache/core/statistics/ValueStatistic.java index 51101ae11d..885e03de62 100644 --- a/core/src/main/java/org/ehcache/core/statistics/ValueStatistic.java +++ b/core/src/main/java/org/ehcache/core/statistics/ValueStatistic.java @@ -16,8 +16,6 @@ package org.ehcache.core.statistics; -import org.terracotta.management.model.stats.StatisticType; - import java.io.Serializable; public interface ValueStatistic { diff --git a/core/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory b/core/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory new file mode 100644 index 0000000000..2e4732b8a1 --- /dev/null +++ b/core/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory @@ -0,0 +1 @@ +org.ehcache.core.statistics.DefaultStatisticsServiceFactory diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index f8dba08972..47888a8b18 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -30,6 +30,7 @@ import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.core.events.StoreEventSink; import org.ehcache.core.spi.service.StatisticsService; +import org.ehcache.core.statistics.StatisticType; import org.ehcache.core.statistics.OperationObserver; import org.ehcache.core.statistics.OperationStatistic; import org.ehcache.impl.internal.concurrent.EvictingConcurrentMap; @@ -71,7 +72,6 @@ import org.ehcache.core.statistics.TierOperationOutcomes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.terracotta.management.model.stats.StatisticType; import java.time.Duration; import java.util.ArrayList; diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java index b38d4aad6e..fda2c6cb8a 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java @@ -38,6 +38,7 @@ import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.core.events.StoreEventSink; import org.ehcache.core.spi.service.StatisticsService; +import org.ehcache.core.statistics.StatisticType; import org.ehcache.core.statistics.OperationObserver; import org.ehcache.impl.store.BaseStore; import org.ehcache.spi.resilience.StoreAccessException; @@ -58,12 +59,11 @@ import org.ehcache.spi.serialization.Serializer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.terracotta.management.model.stats.StatisticType; import org.terracotta.offheapstore.exceptions.OversizeMappingException; import static org.ehcache.core.config.ExpiryUtils.isExpiryDurationInfinite; import static org.ehcache.core.exceptions.StorePassThroughException.handleException; -import static org.terracotta.management.model.stats.StatisticType.GAUGE; +import static org.ehcache.core.statistics.StatisticType.GAUGE; public abstract class AbstractOffHeapStore extends BaseStore implements AuthoritativeTier, LowerCachingTier { diff --git a/impl/src/main/java/org/ehcache/impl/store/BaseStore.java b/impl/src/main/java/org/ehcache/impl/store/BaseStore.java index 9bb1229995..8c698aa4f2 100644 --- a/impl/src/main/java/org/ehcache/impl/store/BaseStore.java +++ b/impl/src/main/java/org/ehcache/impl/store/BaseStore.java @@ -19,6 +19,7 @@ import org.ehcache.config.ResourceType; import org.ehcache.core.config.store.StoreStatisticsConfiguration; import org.ehcache.core.spi.service.StatisticsService; +import org.ehcache.core.statistics.StatisticType; import org.ehcache.core.spi.store.Store; import org.ehcache.core.statistics.OperationObserver; import org.ehcache.core.statistics.OperationStatistic; @@ -26,7 +27,6 @@ import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.spi.service.ServiceProvider; -import org.terracotta.management.model.stats.StatisticType; import java.io.Serializable; import java.util.Map; diff --git a/impl/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory b/impl/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory index cd8eb5c2ec..c2cf30fb9a 100644 --- a/impl/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory +++ b/impl/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory @@ -16,5 +16,4 @@ org.ehcache.impl.internal.loaderwriter.writebehind.WriteBehindProviderFactory org.ehcache.impl.internal.events.CacheEventNotificationListenerServiceProviderFactory org.ehcache.impl.internal.spi.copy.DefaultCopyProviderFactory org.ehcache.impl.internal.sizeof.DefaultSizeOfEngineProviderFactory -org.ehcache.core.statistics.DefaultStatisticsServiceFactory org.ehcache.impl.internal.spi.resilience.DefaultResilienceStrategyProviderFactory diff --git a/management/build.gradle b/management/build.gradle index dcff645726..b3417cad71 100644 --- a/management/build.gradle +++ b/management/build.gradle @@ -19,6 +19,7 @@ plugins { } dependencies { + implementation "org.terracotta:statistics:$statisticVersion" // optional: if we want xml config compileOnly project(':xml') diff --git a/management/src/main/java/org/ehcache/management/ExtendedStatisticsService.java b/management/src/main/java/org/ehcache/management/ExtendedStatisticsService.java new file mode 100644 index 0000000000..a6fde2e119 --- /dev/null +++ b/management/src/main/java/org/ehcache/management/ExtendedStatisticsService.java @@ -0,0 +1,74 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.management; + +import org.ehcache.Cache; +import org.ehcache.core.spi.service.StatisticsService; +import org.ehcache.core.statistics.LatencyHistogramConfiguration; +import org.terracotta.management.model.capabilities.descriptors.StatisticDescriptor; +import org.terracotta.management.model.stats.Statistic; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Map; +import java.util.function.LongSupplier; + +public interface ExtendedStatisticsService extends StatisticsService { + + /** + * Create statistics registry + * @param cacheName name (alias) of the cache + * @param cache the {@link Cache} associated with the given alias + * @param timeSource source of time for statistics maintenance + */ + void createCacheRegistry(String cacheName, Cache cache, LongSupplier timeSource); + + /** + * Registers a cache for statistics + * @param cacheName name (alias) of the cache + */ + void registerCacheStatistics(String cacheName); + + /** + * Returns the Statistics descriptor for the cache with the given alias + * @param cacheName name (alias) of the cache + * @return the collection of {@link StatisticDescriptor}s of the cache + */ + Collection getCacheDescriptors(String cacheName); + + /** + * Registers derived statistics for the cache + * @param the generic type of statistics + * @param cacheName name (alias) of the cache + * @param cache the cache associated with the given alias + * @param statName name of the statistic + * @param outcome Class of the type of statistics + * @param derivedName visible name of the statistics + * @param configuration the histogram configuration for statistics + */ + , K, V> void registerDerivedStatistics(String cacheName, Cache cache, String statName, T outcome, String derivedName, LatencyHistogramConfiguration configuration); + + /** + * Returns the statistics for the cache + * @param cacheName name (alias) of the cache + * @param statisticNames names of the statistics + * @param since time since statistics needs to be collected + * @return map of statisticNames and statistics + */ + Map> collectStatistics(String cacheName, Collection statisticNames, long since); + +} diff --git a/management/src/main/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProvider.java b/management/src/main/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProvider.java index e4b1793eb0..561df8f700 100644 --- a/management/src/main/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProvider.java +++ b/management/src/main/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProvider.java @@ -17,6 +17,7 @@ import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.time.TimeSource; +import org.ehcache.management.ExtendedStatisticsService; import org.ehcache.management.ManagementRegistryServiceConfiguration; import org.ehcache.management.providers.CacheBinding; import org.ehcache.management.providers.CacheBindingManagementProvider; @@ -40,10 +41,10 @@ @StatisticProvider public class EhcacheStatisticsProvider extends CacheBindingManagementProvider { - private final StatisticsService statisticsService; + private final ExtendedStatisticsService statisticsService; private final TimeSource timeSource; - public EhcacheStatisticsProvider(ManagementRegistryServiceConfiguration configuration, StatisticsService statisticsService, TimeSource timeSource) { + public EhcacheStatisticsProvider(ManagementRegistryServiceConfiguration configuration, ExtendedStatisticsService statisticsService, TimeSource timeSource) { super(configuration); this.statisticsService = Objects.requireNonNull(statisticsService); this.timeSource = Objects.requireNonNull(timeSource); diff --git a/management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java b/management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java index 88875ad9c4..ff728ea7c8 100644 --- a/management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java +++ b/management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java @@ -16,10 +16,10 @@ package org.ehcache.management.providers.statistics; import org.ehcache.Cache; -import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.core.statistics.CacheOperationOutcomes; import org.ehcache.core.statistics.LatencyHistogramConfiguration; +import org.ehcache.management.ExtendedStatisticsService; import org.ehcache.management.ManagementRegistryServiceConfiguration; import org.ehcache.management.providers.CacheBinding; import org.ehcache.management.providers.ExposedCacheBinding; @@ -33,9 +33,9 @@ public class StandardEhcacheStatistics extends ExposedCacheBinding { private final String cacheAlias; - private final StatisticsService statisticsService; + private final ExtendedStatisticsService statisticsService; - StandardEhcacheStatistics(ManagementRegistryServiceConfiguration registryConfiguration, CacheBinding cacheBinding, StatisticsService statisticsService, TimeSource timeSource) { + StandardEhcacheStatistics(ManagementRegistryServiceConfiguration registryConfiguration, CacheBinding cacheBinding, ExtendedStatisticsService statisticsService, TimeSource timeSource) { super(registryConfiguration, cacheBinding); this.cacheAlias = cacheBinding.getAlias(); this.statisticsService = statisticsService; diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultExtendedStatisticsService.java b/management/src/main/java/org/ehcache/management/registry/DefaultExtendedStatisticsService.java new file mode 100644 index 0000000000..c2f66cbc77 --- /dev/null +++ b/management/src/main/java/org/ehcache/management/registry/DefaultExtendedStatisticsService.java @@ -0,0 +1,250 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.management.registry; + +import org.ehcache.Cache; +import org.ehcache.Status; +import org.ehcache.config.CacheConfiguration; +import org.ehcache.core.InternalCache; +import org.ehcache.core.events.CacheManagerListener; +import org.ehcache.core.spi.service.CacheManagerProviderService; +import org.ehcache.core.spi.store.InternalCacheManager; +import org.ehcache.core.spi.store.Store; +import org.ehcache.core.statistics.CacheStatistics; +import org.ehcache.core.statistics.DefaultCacheStatistics; +import org.ehcache.core.statistics.DelegatedMappedOperationStatistics; +import org.ehcache.core.statistics.DelegatingOperationObserver; +import org.ehcache.core.statistics.LatencyHistogramConfiguration; +import org.ehcache.core.statistics.StatisticType; +import org.ehcache.core.statistics.OperationObserver; +import org.ehcache.core.statistics.StatsUtils; +import org.ehcache.core.statistics.ZeroOperationStatistic; +import org.ehcache.management.ExtendedStatisticsService; +import org.ehcache.spi.service.OptionalServiceDependencies; +import org.ehcache.spi.service.Service; +import org.ehcache.spi.service.ServiceProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.terracotta.management.model.capabilities.descriptors.StatisticDescriptor; +import org.terracotta.management.model.stats.Statistic; +import org.terracotta.management.model.stats.StatisticRegistry; +import org.terracotta.statistics.MappedOperationStatistic; +import org.terracotta.statistics.OperationStatistic; +import org.terracotta.statistics.StatisticsManager; +import org.terracotta.statistics.derived.OperationResultFilter; +import org.terracotta.statistics.derived.latency.DefaultLatencyHistogramStatistic; + +import java.io.Serializable; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.function.LongSupplier; +import java.util.function.Supplier; + +import static org.ehcache.core.statistics.StatsUtils.findOperationStatisticOnChildren; +import static org.terracotta.statistics.StatisticBuilder.operation; + +/** + * Default implementation using the statistics calculated by the observers set on the caches. + */ +@OptionalServiceDependencies({"org.ehcache.core.spi.service.CacheManagerProviderService"}) +public class DefaultExtendedStatisticsService implements ExtendedStatisticsService, CacheManagerListener { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultExtendedStatisticsService.class); + + private final ConcurrentMap cacheStatistics = new ConcurrentHashMap<>(); + private final ConcurrentMap statisticRegistries = new ConcurrentHashMap<>(); + + private volatile InternalCacheManager cacheManager; + private volatile boolean started = false; + + public CacheStatistics getCacheStatistics(String cacheName) { + CacheStatistics stats = cacheStatistics.get(cacheName); + if (stats == null) { + throw new IllegalArgumentException("Unknown cache: " + cacheName); + } + return stats; + } + + @Override + public void registerWithParent(Object toAssociate, Object parent) { + StatisticsManager.associate(toAssociate).withParent(parent); + } + + @Override + public , T extends Enum> org.ehcache.core.statistics.OperationStatistic registerStoreStatistics(Store store, String targetName, int tierHeight, String tag, Map> translation, String statisticName) { + + Class outcomeType = getOutcomeType(translation); + + // If the original stat doesn't exist, we do not need to translate it + if (StatsUtils.hasOperationStat(store, outcomeType, targetName)) { + + MappedOperationStatistic operationStatistic = new MappedOperationStatistic<>(store, translation, statisticName, tierHeight, targetName, tag); + StatisticsManager.associate(operationStatistic).withParent(store); + org.ehcache.core.statistics.OperationStatistic stat = new DelegatedMappedOperationStatistics<>(operationStatistic); + return stat; + } + return ZeroOperationStatistic.get(); + } + + /** + * From the Map of translation, we extract one of the items to get the declaring class of the enum. + * + * @param translation translation map + * @param type of the outcome + * @param type of the possible translations + * @return the outcome type + */ + private static , T extends Enum> Class getOutcomeType(Map> translation) { + Map.Entry> first = translation.entrySet().iterator().next(); + Class outcomeType = first.getValue().iterator().next().getDeclaringClass(); + return outcomeType; + } + + @Override + public void deRegisterFromParent(Object toDeassociate, Object parent) { + StatisticsManager.dissociate(toDeassociate).fromParent(parent); + } + + @Override + public void cleanForNode(Object node) { + StatisticsManager.nodeFor(node).clean(); + } + + @Override + public void createCacheRegistry(String cacheName, Cache cache, LongSupplier timeSource) { + statisticRegistries.put(cacheName, new StatisticRegistry(cache, timeSource)); + } + + @Override + public void registerCacheStatistics(String cacheName) { + cacheStatistics.get(cacheName).getKnownStatistics().forEach(statisticRegistries.get(cacheName)::registerStatistic); + } + + @Override + public Collection getCacheDescriptors(String cacheName) { + return statisticRegistries.get(cacheName).getDescriptors(); + } + + @Override + public , K, V> void registerDerivedStatistics(String cacheName, Cache cache, String statName, T outcome, String derivedName, LatencyHistogramConfiguration configuration) { + DefaultLatencyHistogramStatistic histogram = new DefaultLatencyHistogramStatistic(configuration.getPhi(), configuration.getBucketCount(), configuration.getWindow()); + + @SuppressWarnings("unchecked") + Class outcomeClass = (Class) outcome.getClass(); + OperationStatistic stat = findOperationStatisticOnChildren(cache, outcomeClass, statName); + stat.addDerivedStatistic(new OperationResultFilter<>(EnumSet.of(outcome), histogram)); + + statisticRegistries.get(cacheName).registerStatistic(derivedName + "#50", histogram.medianStatistic()); + statisticRegistries.get(cacheName).registerStatistic(derivedName + "#95", histogram.percentileStatistic(0.95)); + statisticRegistries.get(cacheName).registerStatistic(derivedName + "#99", histogram.percentileStatistic(0.99)); + statisticRegistries.get(cacheName).registerStatistic(derivedName + "#100", histogram.maximumStatistic()); + } + + @Override + public Map> collectStatistics(String cacheName, Collection statisticNames, long since) { + return StatisticRegistry.collect(statisticRegistries.get(cacheName), statisticNames, since); + } + + @Override + public void registerStatistic(Object context, String name, StatisticType type, Set tags, Supplier valueSupplier) { + StatisticsManager.createPassThroughStatistic(context, name, tags, convert(type), valueSupplier); + } + + @Override + public > OperationObserver createOperationStatistics(String name, Class outcome, String tag, Object context) { + return new DelegatingOperationObserver<>(operation(outcome).named(name).of(context).tag(tag).build()); + } + + public boolean isStarted() { + return started; + } + + @Override + public void start(ServiceProvider serviceProvider) { + LOGGER.debug("Starting service"); + + CacheManagerProviderService cacheManagerProviderService = serviceProvider.getService(CacheManagerProviderService.class); + if (cacheManagerProviderService != null) { + cacheManager = cacheManagerProviderService.getCacheManager(); + cacheManager.registerListener(this); + } + + started = true; + } + + @Override + public void stop() { + LOGGER.debug("Stopping service"); + cacheManager.deregisterListener(this); + cacheStatistics.clear(); + started = false; + } + + @Override + public void stateTransition(Status from, Status to) { + LOGGER.debug("Moving from " + from + " to " + to); + switch (to) { + case AVAILABLE: + registerAllCaches(); + break; + case UNINITIALIZED: + cacheManager.deregisterListener(this); + cacheStatistics.clear(); + break; + case MAINTENANCE: + throw new IllegalStateException("Should not be started in maintenance mode"); + default: + throw new AssertionError("Unsupported state: " + to); + } + } + + private void registerAllCaches() { + for (Map.Entry> entry : cacheManager.getRuntimeConfiguration().getCacheConfigurations().entrySet()) { + String alias = entry.getKey(); + CacheConfiguration configuration = entry.getValue(); + Cache cache = cacheManager.getCache(alias, configuration.getKeyType(), configuration.getValueType()); + cacheAdded(alias, cache); + } + } + + @Override + public void cacheAdded(String alias, Cache cache) { + LOGGER.debug("Cache added " + alias); + cacheStatistics.put(alias, new DefaultCacheStatistics((InternalCache) cache)); + } + + @Override + public void cacheRemoved(String alias, Cache cache) { + LOGGER.debug("Cache removed " + alias); + cacheStatistics.remove(alias); + } + + private static org.terracotta.statistics.StatisticType convert(StatisticType type) { + switch (type) { + case COUNTER: + return org.terracotta.statistics.StatisticType.COUNTER; + case GAUGE: + return org.terracotta.statistics.StatisticType.GAUGE; + default: + throw new IllegalArgumentException("Untranslatable statistic type : " + type); + } + } +} diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultExtendedStatisticsServiceFactory.java b/management/src/main/java/org/ehcache/management/registry/DefaultExtendedStatisticsServiceFactory.java new file mode 100644 index 0000000000..5c6bf126b2 --- /dev/null +++ b/management/src/main/java/org/ehcache/management/registry/DefaultExtendedStatisticsServiceFactory.java @@ -0,0 +1,39 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.management.registry; + +import org.ehcache.core.spi.service.ServiceFactory; +import org.ehcache.management.ExtendedStatisticsService; +import org.ehcache.spi.service.ServiceCreationConfiguration; + +public class DefaultExtendedStatisticsServiceFactory implements ServiceFactory { + + @Override + public int rank() { + return 10; + } + + @Override + public ExtendedStatisticsService create(ServiceCreationConfiguration configuration) { + return new DefaultExtendedStatisticsService(); + } + + @Override + public Class getServiceType() { + return DefaultExtendedStatisticsService.class; + } +} diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java index 8343daf225..53d7fc5513 100644 --- a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java +++ b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java @@ -21,9 +21,9 @@ import org.ehcache.core.events.CacheManagerListener; import org.ehcache.core.spi.service.CacheManagerProviderService; import org.ehcache.core.spi.service.ExecutionService; -import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.InternalCacheManager; import org.ehcache.core.spi.time.TimeSourceService; +import org.ehcache.management.ExtendedStatisticsService; import org.ehcache.management.ManagementRegistryService; import org.ehcache.management.ManagementRegistryServiceConfiguration; import org.ehcache.management.cluster.Clustering; @@ -45,7 +45,7 @@ import java.util.Collection; import java.util.Map; -@ServiceDependencies({CacheManagerProviderService.class, StatisticsService.class, TimeSourceService.class, ExecutionService.class}) +@ServiceDependencies({CacheManagerProviderService.class, ExtendedStatisticsService.class, TimeSourceService.class, ExecutionService.class}) @OptionalServiceDependencies({ "org.ehcache.clustered.client.service.EntityService", "org.ehcache.clustered.client.service.ClusteringService"}) @@ -55,7 +55,7 @@ public class DefaultManagementRegistryService extends DefaultManagementRegistry private volatile InternalCacheManager cacheManager; private volatile ClusteringManagementService clusteringManagementService; private volatile boolean clusteringManagementServiceAutoStarted; - private volatile StatisticsService statisticsService; + private volatile ExtendedStatisticsService statisticsService; public DefaultManagementRegistryService() { this(new DefaultManagementRegistryConfiguration()); @@ -70,7 +70,7 @@ public DefaultManagementRegistryService(ManagementRegistryServiceConfiguration c public void start(final ServiceProvider serviceProvider) { this.cacheManager = serviceProvider.getService(CacheManagerProviderService.class).getCacheManager(); - this.statisticsService = serviceProvider.getService(StatisticsService.class); + this.statisticsService = serviceProvider.getService(ExtendedStatisticsService.class); TimeSourceService timeSourceService = serviceProvider.getService(TimeSourceService.class); // initialize management capabilities (stats, action calls, etc) diff --git a/management/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory b/management/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory index e014208625..80723caaa6 100644 --- a/management/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory +++ b/management/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory @@ -1 +1,2 @@ -org.ehcache.management.registry.DefaultManagementRegistryFactory \ No newline at end of file +org.ehcache.management.registry.DefaultManagementRegistryFactory +org.ehcache.management.registry.DefaultExtendedStatisticsServiceFactory diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java index d396f031cc..488afc5331 100644 --- a/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java @@ -16,13 +16,13 @@ package org.ehcache.management.providers.statistics; import org.ehcache.core.Ehcache; -import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.time.SystemTimeSource; import org.ehcache.core.spi.time.TimeSource; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.management.ExtendedStatisticsService; import org.ehcache.management.ManagementRegistryServiceConfiguration; import org.ehcache.management.providers.CacheBinding; import org.ehcache.management.providers.ExposedCacheBinding; +import org.ehcache.management.registry.DefaultExtendedStatisticsService; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; import org.hamcrest.Matcher; import org.junit.After; @@ -49,7 +49,7 @@ public class EhcacheStatisticsProviderTest { ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); - StatisticsService statisticsService = new DefaultStatisticsService(); + ExtendedStatisticsService statisticsService = new DefaultExtendedStatisticsService(); Context cmContext_0 = Context.create("cacheManagerName", "cache-manager-0"); ManagementRegistryServiceConfiguration cmConfig_0 = new DefaultManagementRegistryConfiguration() .setContext(cmContext_0); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java index c96b24f5ec..251078b307 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java @@ -46,9 +46,6 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:core"), gradleBundle("org.ehcache.modules:api"), - gradleBundle("org.terracotta.management:management-model"), - gradleBundle("org.terracotta.management:sequence-generator"), - gradleBundle("org.terracotta:statistics"), gradleBundle("org.ehcache:sizeof"), gradleBundle("org.terracotta:offheap-store"), diff --git a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java index 546291111f..47495dd6c6 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java @@ -64,9 +64,6 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:api"), gradleBundle("javax.cache:cache-api"), - gradleBundle("org.terracotta.management:management-model"), - gradleBundle("org.terracotta.management:sequence-generator"), - gradleBundle("org.terracotta:statistics"), gradleBundle("org.ehcache:sizeof"), gradleBundle("org.terracotta:offheap-store"), diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java index 81be27c82f..157297ab03 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java @@ -53,9 +53,6 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:core"), gradleBundle("org.ehcache.modules:impl"), - gradleBundle("org.terracotta.management:management-model"), - gradleBundle("org.terracotta.management:sequence-generator"), - gradleBundle("org.terracotta:statistics"), gradleBundle("org.ehcache:sizeof"), gradleBundle("org.terracotta:offheap-store"), diff --git a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java index 329827f2bd..b3f64d9cfe 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java @@ -67,9 +67,6 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:impl"), gradleBundle("org.ehcache.modules:xml"), jaxbConfiguration(), - gradleBundle("org.terracotta.management:management-model"), - gradleBundle("org.terracotta.management:sequence-generator"), - gradleBundle("org.terracotta:statistics"), gradleBundle("org.ehcache:sizeof"), gradleBundle("org.terracotta:offheap-store"), diff --git a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java index 75b98ef167..856cf49646 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java @@ -58,9 +58,6 @@ public Option[] individualModules() { gradleBundle("org.ehcache.modules:xml"), jaxbConfiguration(), gradleBundle("org.ehcache:transactions"), jtaConfiguration(), - gradleBundle("org.terracotta.management:management-model"), - gradleBundle("org.terracotta.management:sequence-generator"), - gradleBundle("org.terracotta:statistics"), gradleBundle("org.ehcache:sizeof"), gradleBundle("org.terracotta:offheap-store"), From ace6aabe7d9c79d6bd992dc8747b2b5d3acebe56 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 10 Jul 2019 17:35:16 -0400 Subject: [PATCH 313/372] Move things around to truly hide the statistics library uses --- 107/build.gradle | 1 + .../jsr107/Eh107CacheStatisticsMXBean.java | 2 +- .../internal}/Jsr107LatencyMonitor.java | 4 +- .../client/BasicClusteredCacheTest.java | 2 +- .../client/ClusteredCacheExpirationTest.java | 2 +- .../ClusteredLoaderWriterStoreTest.java | 2 +- .../store/ClusteredStoreEventsTest.java | 2 +- .../internal/store/ClusteredStoreTest.java | 2 +- .../clustered/BasicEntityInteractionTest.java | 2 +- .../clustered/TerminatedServerTest.java | 2 +- .../statistics/DefaultCacheStatistics.java | 44 +-- .../statistics/DefaultStatisticsService.java | 6 +- .../DefaultStatisticsServiceFactory.java | 2 +- .../statistics/DefaultTierStatistics.java | 246 ++++++++++++++++ .../DelegatedMappedOperationStatistics.java | 109 +++++++ .../DelegatingOperationObserver.java | 37 +++ .../DelegatingOperationStatistic.java | 5 +- .../{ => internal}/statistics/StatsUtils.java | 4 +- .../statistics/SuppliedValueStatistic.java | 4 + .../core/statistics/TierStatistics.java | 9 - ...rg.ehcache.core.spi.service.ServiceFactory | 2 +- .../DefaultCacheStatisticsTest.java | 2 +- .../DefaultStatisticsServiceTest.java | 2 +- .../DefaultTierStatisticsDisabledTest.java | 2 +- .../statistics/DefaultTierStatisticsTest.java | 2 +- .../internal/statistics/StatsUtilsTest.java | 8 +- .../disk/OffHeapDiskStoreProviderTest.java | 2 +- .../store/disk/OffHeapDiskStoreSPITest.java | 2 +- .../store/disk/OffHeapDiskStoreTest.java | 2 +- .../ByteSizedOnHeapStoreByRefSPITest.java | 2 +- .../ByteSizedOnHeapStoreByValueSPITest.java | 2 +- .../heap/CountSizedOnHeapStoreByRefTest.java | 2 +- .../CountSizedOnHeapStoreByValueTest.java | 2 +- .../heap/OnHeapStoreBulkMethodsTest.java | 2 +- .../store/heap/OnHeapStoreByRefSPITest.java | 2 +- .../store/heap/OnHeapStoreByValueSPITest.java | 2 +- .../OnHeapStoreCachingTierByRefSPITest.java | 2 +- .../OnHeapStoreCachingTierByValueSPITest.java | 2 +- .../store/heap/OnHeapStoreEvictionTest.java | 2 +- .../store/heap/OnHeapStoreKeyCopierTest.java | 2 +- .../heap/OnHeapStoreValueCopierTest.java | 2 +- .../heap/bytesized/ByteAccountingTest.java | 2 +- .../ByteSizedOnHeapStoreByRefTest.java | 2 +- .../ByteSizedOnHeapStoreByValueTest.java | 2 +- .../bytesized/OnHeapStoreBulkMethodsTest.java | 2 +- .../OnHeapStoreCachingTierByRefSPITest.java | 2 +- .../OnHeapStoreCachingTierByValueSPITest.java | 2 +- .../store/offheap/OffHeapStoreSPITest.java | 2 +- .../store/offheap/OffHeapStoreTest.java | 2 +- .../tiering/CompoundCachingTierSPITest.java | 2 +- .../store/tiering/TieredStoreMutatorTest.java | 2 +- .../store/tiering/TieredStoreSPITest.java | 2 +- .../store/tiering/TieredStoreTest.java | 2 +- .../tiering/TieredStoreWith3TiersSPITest.java | 2 +- .../ehcache/integration/EhcacheBaseTest.java | 2 +- .../integration/EhcacheBulkMethodsITest.java | 2 +- .../statistics/CacheCalculationTest.java | 2 +- .../statistics/TierCalculationTest.java | 2 +- .../management/ExtendedStatisticsService.java | 2 +- ...anagementRegistryServiceConfiguration.java | 2 +- .../statistics/StandardEhcacheStatistics.java | 2 +- .../registry/DefaultCollectorService.java | 2 +- ...efaultManagementRegistryConfiguration.java | 1 - .../LatencyHistogramConfiguration.java | 2 +- .../statistics/DefaultCacheStatistics.java | 247 ++++++++++++++++ .../DefaultExtendedStatisticsService.java | 10 +- ...faultExtendedStatisticsServiceFactory.java | 2 +- .../statistics/DefaultTierStatistics.java | 40 +-- .../DelegatedMappedOperationStatistics.java | 4 +- .../DelegatingOperationObserver.java | 4 +- .../management/statistics/StatsUtils.java | 270 ++++++++++++++++++ ...rg.ehcache.core.spi.service.ServiceFactory | 2 +- .../EhcacheStatisticsProviderTest.java | 2 +- .../LatencyHistogramConfigurationTest.java | 2 +- .../StandardEhcacheStatisticsTest.java | 4 +- .../xa/internal/XAStoreProviderTest.java | 2 +- .../transactions/xa/internal/XAStoreTest.java | 2 +- 77 files changed, 1049 insertions(+), 122 deletions(-) rename {core/src/main/java/org/ehcache/core/statistics => 107/src/main/java/org/ehcache/jsr107/internal}/Jsr107LatencyMonitor.java (92%) rename core/src/main/java/org/ehcache/core/{ => internal}/statistics/DefaultCacheStatistics.java (82%) rename core/src/main/java/org/ehcache/core/{ => internal}/statistics/DefaultStatisticsService.java (96%) rename core/src/main/java/org/ehcache/core/{ => internal}/statistics/DefaultStatisticsServiceFactory.java (96%) create mode 100755 core/src/main/java/org/ehcache/core/internal/statistics/DefaultTierStatistics.java create mode 100644 core/src/main/java/org/ehcache/core/internal/statistics/DelegatedMappedOperationStatistics.java create mode 100644 core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationObserver.java rename core/src/main/java/org/ehcache/core/{ => internal}/statistics/DelegatingOperationStatistic.java (94%) rename core/src/main/java/org/ehcache/core/{ => internal}/statistics/StatsUtils.java (98%) rename {core/src/main/java/org/ehcache/core/statistics => management/src/main/java/org/ehcache/management/registry}/LatencyHistogramConfiguration.java (98%) create mode 100644 management/src/main/java/org/ehcache/management/statistics/DefaultCacheStatistics.java rename management/src/main/java/org/ehcache/management/{registry => statistics}/DefaultExtendedStatisticsService.java (95%) rename management/src/main/java/org/ehcache/management/{registry => statistics}/DefaultExtendedStatisticsServiceFactory.java (96%) rename {core/src/main/java/org/ehcache/core => management/src/main/java/org/ehcache/management}/statistics/DefaultTierStatistics.java (84%) rename {core/src/main/java/org/ehcache/core => management/src/main/java/org/ehcache/management}/statistics/DelegatedMappedOperationStatistics.java (94%) rename {core/src/main/java/org/ehcache/core => management/src/main/java/org/ehcache/management}/statistics/DelegatingOperationObserver.java (91%) create mode 100644 management/src/main/java/org/ehcache/management/statistics/StatsUtils.java diff --git a/107/build.gradle b/107/build.gradle index a710808ce7..a976458daa 100644 --- a/107/build.gradle +++ b/107/build.gradle @@ -49,6 +49,7 @@ dependencies { implementation project(':impl') implementation project(':xml') + implementation "org.terracotta:statistics:$statisticVersion" compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java b/107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java index 55ba63389e..a2d94cd83b 100644 --- a/107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java +++ b/107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java @@ -18,7 +18,7 @@ import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.statistics.CacheOperationOutcomes; import org.ehcache.core.statistics.CacheStatistics; -import org.ehcache.core.statistics.Jsr107LatencyMonitor; +import org.ehcache.jsr107.internal.Jsr107LatencyMonitor; import java.net.URI; diff --git a/core/src/main/java/org/ehcache/core/statistics/Jsr107LatencyMonitor.java b/107/src/main/java/org/ehcache/jsr107/internal/Jsr107LatencyMonitor.java similarity index 92% rename from core/src/main/java/org/ehcache/core/statistics/Jsr107LatencyMonitor.java rename to 107/src/main/java/org/ehcache/jsr107/internal/Jsr107LatencyMonitor.java index 30366c1f34..5c03ae35da 100644 --- a/core/src/main/java/org/ehcache/core/statistics/Jsr107LatencyMonitor.java +++ b/107/src/main/java/org/ehcache/jsr107/internal/Jsr107LatencyMonitor.java @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.statistics; +package org.ehcache.jsr107.internal; + +import org.ehcache.core.statistics.ChainedOperationObserver; import java.util.EnumSet; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java index 60988f2363..3f29a53628 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java @@ -26,7 +26,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java index 3ebe5fb4cf..a8a2a8164e 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java @@ -32,7 +32,7 @@ import org.ehcache.core.statistics.TierStatistics; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.TimeSourceConfiguration; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java index 477d6dcb9a..b7ee9e0c2d 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java @@ -25,7 +25,7 @@ import org.ehcache.clustered.loaderWriter.TestCacheLoaderWriter; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.time.TimeSource; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.impl.serialization.LongSerializer; import org.ehcache.impl.serialization.StringSerializer; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java index afd1f8b62f..9751829dc9 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java @@ -45,7 +45,7 @@ import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.core.events.StoreEventSink; import org.ehcache.core.spi.store.Store; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.serialization.LongSerializer; import org.ehcache.impl.serialization.StringSerializer; diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java index 143a87c28f..0ce631c4a9 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java @@ -35,7 +35,7 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.Ehcache; import org.ehcache.core.spi.store.Store; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.store.DefaultStoreEventDispatcher; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java index de021034cd..c12c700858 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java @@ -29,7 +29,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.cluster.DefaultClusteringManagementService; -import org.ehcache.management.registry.DefaultExtendedStatisticsService; +import org.ehcache.management.statistics.DefaultExtendedStatisticsService; import org.hamcrest.Matchers; import org.junit.BeforeClass; import org.junit.ClassRule; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java index a67b1abb3c..9bc57f8034 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java @@ -32,7 +32,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.spi.service.StatisticsService; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; diff --git a/core/src/main/java/org/ehcache/core/statistics/DefaultCacheStatistics.java b/core/src/main/java/org/ehcache/core/internal/statistics/DefaultCacheStatistics.java similarity index 82% rename from core/src/main/java/org/ehcache/core/statistics/DefaultCacheStatistics.java rename to core/src/main/java/org/ehcache/core/internal/statistics/DefaultCacheStatistics.java index 288c021d01..294d8c81f2 100644 --- a/core/src/main/java/org/ehcache/core/statistics/DefaultCacheStatistics.java +++ b/core/src/main/java/org/ehcache/core/internal/statistics/DefaultCacheStatistics.java @@ -14,13 +14,18 @@ * limitations under the License. */ -package org.ehcache.core.statistics; +package org.ehcache.core.internal.statistics; import org.ehcache.core.InternalCache; +import org.ehcache.core.statistics.BulkOps; import org.ehcache.core.statistics.CacheOperationOutcomes.GetOutcome; import org.ehcache.core.statistics.CacheOperationOutcomes.PutOutcome; -import org.terracotta.statistics.ValueStatistic; -import org.terracotta.statistics.derived.OperationResultFilter; +import org.ehcache.core.statistics.CacheStatistics; +import org.ehcache.core.statistics.ChainedOperationObserver; +import org.ehcache.core.statistics.OperationStatistic; +import org.ehcache.core.statistics.TierStatistics; +import org.ehcache.core.statistics.ValueStatistic; +import org.terracotta.statistics.ValueStatistics; import java.util.Collections; import java.util.EnumSet; @@ -31,10 +36,10 @@ import static org.ehcache.core.statistics.CacheOperationOutcomes.PutIfAbsentOutcome; import static org.ehcache.core.statistics.CacheOperationOutcomes.RemoveOutcome; import static org.ehcache.core.statistics.CacheOperationOutcomes.ReplaceOutcome; -import static org.ehcache.core.statistics.StatsUtils.findLowestTier; -import static org.ehcache.core.statistics.StatsUtils.findOperationStatisticOnChildren; -import static org.ehcache.core.statistics.StatsUtils.findTiers; -import static org.terracotta.statistics.ValueStatistics.counter; +import static org.ehcache.core.internal.statistics.StatsUtils.findLowestTier; +import static org.ehcache.core.internal.statistics.StatsUtils.findOperationStatisticOnChildren; +import static org.ehcache.core.internal.statistics.StatsUtils.findTiers; +import static org.ehcache.core.statistics.SuppliedValueStatistic.counter; /** * Contains usage statistics relative to a given cache. @@ -52,7 +57,7 @@ public class DefaultCacheStatistics implements CacheStatistics { private final InternalCache cache; - private final Map tierStatistics; + private final Map tierStatistics; private final TierStatistics lowestTier; private final Map> knownStatistics; @@ -74,7 +79,7 @@ public DefaultCacheStatistics(InternalCache cache) { tierStatistics = new HashMap<>(tierNames.length); for (String tierName : tierNames) { - TierStatistics tierStatistics = new DefaultTierStatistics(cache, tierName); + DefaultTierStatistics tierStatistics = new DefaultTierStatistics(cache, tierName); this.tierStatistics.put(tierName, tierStatistics); if (lowestTierName.equals(tierName)) { lowestTier = tierStatistics; @@ -91,16 +96,16 @@ public , S extends ChainedOperationObserver> void r stat.addDerivedStatistic(derivedStatistic); } - private Map> createKnownStatistics() { + private Map> createKnownStatistics() { Map> knownStatistics = new HashMap<>(30); - knownStatistics.put("Cache:HitCount", counter(this::getCacheHits)); - knownStatistics.put("Cache:MissCount", counter(this::getCacheMisses)); - knownStatistics.put("Cache:PutCount", counter(this::getCachePuts)); - knownStatistics.put("Cache:RemovalCount", counter(this::getCacheRemovals)); - knownStatistics.put("Cache:EvictionCount", counter(this::getCacheEvictions)); - knownStatistics.put("Cache:ExpirationCount", counter(this::getCacheExpirations)); - - for (TierStatistics tier : tierStatistics.values()) { + knownStatistics.put("Cache:HitCount", ValueStatistics.counter(this::getCacheHits)); + knownStatistics.put("Cache:MissCount", ValueStatistics.counter(this::getCacheMisses)); + knownStatistics.put("Cache:PutCount", ValueStatistics.counter(this::getCachePuts)); + knownStatistics.put("Cache:RemovalCount", ValueStatistics.counter(this::getCacheRemovals)); + knownStatistics.put("Cache:EvictionCount", ValueStatistics.counter(this::getCacheEvictions)); + knownStatistics.put("Cache:ExpirationCount", ValueStatistics.counter(this::getCacheExpirations)); + + for (DefaultTierStatistics tier : tierStatistics.values()) { knownStatistics.putAll(tier.getKnownStatistics()); } @@ -119,9 +124,6 @@ public Map getTierStatistics() { @Override public void clear() { compensatingCounters = compensatingCounters.snapshot(this); - for (TierStatistics t : tierStatistics.values()) { - t.clear(); - } } @Override diff --git a/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java b/core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsService.java similarity index 96% rename from core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java rename to core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsService.java index 7a93a756bf..8267c2db8b 100644 --- a/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsService.java +++ b/core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.statistics; +package org.ehcache.core.internal.statistics; import org.ehcache.Cache; import org.ehcache.Status; @@ -25,6 +25,10 @@ import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.InternalCacheManager; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.statistics.CacheStatistics; +import org.ehcache.core.statistics.OperationObserver; +import org.ehcache.core.statistics.StatisticType; +import org.ehcache.core.statistics.ZeroOperationStatistic; import org.ehcache.spi.service.OptionalServiceDependencies; import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceProvider; diff --git a/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsServiceFactory.java b/core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsServiceFactory.java similarity index 96% rename from core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsServiceFactory.java rename to core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsServiceFactory.java index b0aa724f19..905d154157 100644 --- a/core/src/main/java/org/ehcache/core/statistics/DefaultStatisticsServiceFactory.java +++ b/core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsServiceFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.statistics; +package org.ehcache.core.internal.statistics; import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.core.spi.service.StatisticsService; diff --git a/core/src/main/java/org/ehcache/core/internal/statistics/DefaultTierStatistics.java b/core/src/main/java/org/ehcache/core/internal/statistics/DefaultTierStatistics.java new file mode 100755 index 0000000000..3a5bcf2c84 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/internal/statistics/DefaultTierStatistics.java @@ -0,0 +1,246 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.core.internal.statistics; + +import org.ehcache.Cache; +import org.ehcache.core.statistics.StoreOperationOutcomes; +import org.ehcache.core.statistics.TierOperationOutcomes; +import org.ehcache.core.statistics.TierStatistics; +import org.ehcache.core.statistics.ValueStatistic; +import org.terracotta.statistics.OperationStatistic; +import org.terracotta.statistics.ValueStatistics; +import org.terracotta.statistics.ZeroOperationStatistic; + +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.function.Supplier; + +import static org.ehcache.core.internal.statistics.StatsUtils.findStatisticOnDescendants; +import static org.ehcache.core.statistics.SuppliedValueStatistic.counter; +import static org.ehcache.core.statistics.SuppliedValueStatistic.gauge; + +/** + * Contains usage statistics relative to a given tier. + */ +public class DefaultTierStatistics implements TierStatistics { + + private volatile CompensatingCounters compensatingCounters = CompensatingCounters.empty(); + + private final Map> knownStatistics; + + private final OperationStatistic get; + private final OperationStatistic put; + private final OperationStatistic putIfAbsent; + private final OperationStatistic replace; + private final OperationStatistic conditionalReplace; + private final OperationStatistic remove; + private final OperationStatistic conditionalRemove; + private final OperationStatistic eviction; + private final OperationStatistic expiration; + private final OperationStatistic compute; + private final OperationStatistic computeIfAbsent; + + //Ehcache default to -1 if unavailable, but the management layer needs optional or null + // (since -1 can be a normal value for a stat). + private final Optional> mapping; + private final Optional> allocatedMemory; + private final Optional> occupiedMemory; + + public DefaultTierStatistics(Cache cache, String tierName) { + + get = findOperationStatistic(cache, tierName, "tier", "get"); + put = findOperationStatistic(cache, tierName, "put"); + putIfAbsent = findOperationStatistic(cache, tierName, "putIfAbsent"); + replace = findOperationStatistic(cache, tierName, "replace"); + conditionalReplace = findOperationStatistic(cache, tierName, "conditionalReplace"); + remove = findOperationStatistic(cache, tierName, "remove"); + conditionalRemove = findOperationStatistic(cache, tierName, "conditionalRemove"); + eviction = findOperationStatistic(cache, tierName, "tier", "eviction"); + expiration = findOperationStatistic(cache, tierName, "expiration"); + compute = findOperationStatistic(cache, tierName, "compute"); + computeIfAbsent = findOperationStatistic(cache, tierName, "computeIfAbsent"); + + mapping = findValueStatistics(cache, tierName, "mappings"); + allocatedMemory = findValueStatistics(cache, tierName, "allocatedMemory"); + occupiedMemory = findValueStatistics(cache, tierName, "occupiedMemory"); + + Map> knownStatistics = createKnownStatistics(tierName); + this.knownStatistics = Collections.unmodifiableMap(knownStatistics); + } + + private Map> createKnownStatistics(String tierName) { + Map> knownStatistics = new HashMap<>(7); + addIfPresent(knownStatistics, tierName + ":HitCount", get, this::getHits); + addIfPresent(knownStatistics, tierName + ":MissCount", get, this::getMisses); + addIfPresent(knownStatistics, tierName + ":PutCount", put, this::getPuts); + addIfPresent(knownStatistics, tierName + ":RemovalCount", remove, this::getRemovals); + + // These two a special because they are used by the cache so they should always be there + knownStatistics.put(tierName + ":EvictionCount", ValueStatistics.counter(this::getEvictions)); + knownStatistics.put(tierName + ":ExpirationCount", ValueStatistics.counter(this::getExpirations)); + + mapping.ifPresent(longValueStatistic -> knownStatistics.put(tierName + ":MappingCount", ValueStatistics.gauge(this::getMappings))); + allocatedMemory.ifPresent(longValueStatistic -> knownStatistics.put(tierName + ":AllocatedByteSize", ValueStatistics.gauge(this::getAllocatedByteSize))); + occupiedMemory.ifPresent(longValueStatistic -> knownStatistics.put(tierName + ":OccupiedByteSize", ValueStatistics.gauge(this::getOccupiedByteSize))); + return knownStatistics; + } + + /** + * Add the statistic as a known statistic only if the reference statistic is available. We consider that the reference statistic can only be + * an instance of {@code ZeroOperationStatistic} when statistics are disabled. + * + * @param knownStatistics map of known statistics + * @param name the name of the statistic to add + * @param reference the reference statistic that should be available for the statistic to be added + * @param valueSupplier the supplier that will provide the current value for the statistic + * @param type of the supplied value + */ + private static void addIfPresent(Map> knownStatistics, String name, OperationStatistic reference, Supplier valueSupplier) { + if(!(reference instanceof ZeroOperationStatistic)) { + knownStatistics.put(name, ValueStatistics.counter(valueSupplier)); + } + } + + public Map> getKnownStatistics() { + return knownStatistics; + } + + private > OperationStatistic findOperationStatistic(Cache cache, String tierName, String tag, String stat) { + return StatsUtils.>findStatisticOnDescendants(cache, tierName, tag, stat).orElse(ZeroOperationStatistic.get()); + } + + private > OperationStatistic findOperationStatistic(Cache cache, String tierName, String stat) { + return StatsUtils.>findStatisticOnDescendants(cache, tierName, stat).orElse(ZeroOperationStatistic.get()); + } + + private Optional> findValueStatistics(Cache cache, String tierName, String statName) { + return findStatisticOnDescendants(cache, tierName, statName); + } + + /** + * Reset the values for this tier. However, note that {@code mapping, allocatedMemory, occupiedMemory} + * but be reset since it doesn't make sense. + */ + @Override + public void clear() { + compensatingCounters = compensatingCounters.snapshot(this); + } + + @Override + public long getHits() { + return get.sum(EnumSet.of(TierOperationOutcomes.GetOutcome.HIT)) + + putIfAbsent.sum(EnumSet.of(StoreOperationOutcomes.PutIfAbsentOutcome.HIT)) + + replace.sum(EnumSet.of(StoreOperationOutcomes.ReplaceOutcome.REPLACED)) + + compute.sum(EnumSet.of(StoreOperationOutcomes.ComputeOutcome.HIT)) + + computeIfAbsent.sum(EnumSet.of(StoreOperationOutcomes.ComputeIfAbsentOutcome.HIT)) + + conditionalReplace.sum(EnumSet.of(StoreOperationOutcomes.ConditionalReplaceOutcome.REPLACED)) + + conditionalRemove.sum(EnumSet.of(StoreOperationOutcomes.ConditionalRemoveOutcome.REMOVED)) - + compensatingCounters.hits; + } + + @Override + public long getMisses() { + return get.sum(EnumSet.of(TierOperationOutcomes.GetOutcome.MISS)) + + putIfAbsent.sum(EnumSet.of(StoreOperationOutcomes.PutIfAbsentOutcome.PUT)) + + replace.sum(EnumSet.of(StoreOperationOutcomes.ReplaceOutcome.MISS)) + + computeIfAbsent.sum(EnumSet.of(StoreOperationOutcomes.ComputeIfAbsentOutcome.NOOP)) + + conditionalReplace.sum(EnumSet.of(StoreOperationOutcomes.ConditionalReplaceOutcome.MISS)) + + conditionalRemove.sum(EnumSet.of(StoreOperationOutcomes.ConditionalRemoveOutcome.MISS)) - + compensatingCounters.misses; + } + + @Override + public long getPuts() { + return put.sum(EnumSet.of(StoreOperationOutcomes.PutOutcome.PUT)) + + putIfAbsent.sum(EnumSet.of(StoreOperationOutcomes.PutIfAbsentOutcome.PUT)) + + compute.sum(EnumSet.of(StoreOperationOutcomes.ComputeOutcome.PUT)) + + computeIfAbsent.sum(EnumSet.of(StoreOperationOutcomes.ComputeIfAbsentOutcome.PUT)) + + replace.sum(EnumSet.of(StoreOperationOutcomes.ReplaceOutcome.REPLACED)) + + conditionalReplace.sum(EnumSet.of(StoreOperationOutcomes.ConditionalReplaceOutcome.REPLACED)) - + compensatingCounters.puts; + } + + @Override + public long getRemovals() { + return remove.sum(EnumSet.of(StoreOperationOutcomes.RemoveOutcome.REMOVED)) + + compute.sum(EnumSet.of(StoreOperationOutcomes.ComputeOutcome.REMOVED)) + + conditionalRemove.sum(EnumSet.of(StoreOperationOutcomes.ConditionalRemoveOutcome.REMOVED)) - + compensatingCounters.removals; + } + + @Override + public long getEvictions() { + return eviction.sum(EnumSet.of(TierOperationOutcomes.EvictionOutcome.SUCCESS)) - + compensatingCounters.evictions; + } + + @Override + public long getExpirations() { + return expiration.sum() - compensatingCounters.expirations; + } + + @Override + public long getMappings() { + return mapping.map(org.terracotta.statistics.ValueStatistic::value).orElse(-1L); + } + + @Override + public long getAllocatedByteSize() { + return allocatedMemory.map(org.terracotta.statistics.ValueStatistic::value).orElse(-1L); + } + + @Override + public long getOccupiedByteSize() { + return occupiedMemory.map(org.terracotta.statistics.ValueStatistic::value).orElse(-1L); + } + + private static class CompensatingCounters { + final long hits; + final long misses; + final long puts; + final long removals; + final long evictions; + final long expirations; + + private CompensatingCounters(long hits, long misses, long puts, long removals, long evictions, long expirations) { + this.hits = hits; + this.misses = misses; + this.puts = puts; + this.removals = removals; + this.evictions = evictions; + this.expirations = expirations; + } + + static CompensatingCounters empty() { + return new CompensatingCounters(0, 0, 0, 0, 0, 0); + } + + CompensatingCounters snapshot(DefaultTierStatistics statistics) { + return new CompensatingCounters( + statistics.getHits() + hits, + statistics.getMisses() + misses, + statistics.getPuts() + puts, + statistics.getRemovals() + removals, + statistics.getEvictions() + evictions, + statistics.getExpirations() + expirations + ); + } + } +} diff --git a/core/src/main/java/org/ehcache/core/internal/statistics/DelegatedMappedOperationStatistics.java b/core/src/main/java/org/ehcache/core/internal/statistics/DelegatedMappedOperationStatistics.java new file mode 100644 index 0000000000..65e8c624f2 --- /dev/null +++ b/core/src/main/java/org/ehcache/core/internal/statistics/DelegatedMappedOperationStatistics.java @@ -0,0 +1,109 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.internal.statistics; + +import org.ehcache.core.statistics.ChainedOperationObserver; +import org.ehcache.core.statistics.OperationStatistic; +import org.terracotta.statistics.MappedOperationStatistic; + +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collectors; + +public class DelegatedMappedOperationStatistics, D extends Enum> implements OperationStatistic { + + private final MappedOperationStatistic delegate; + + public DelegatedMappedOperationStatistics(MappedOperationStatistic operationStatistic) { + this.delegate = operationStatistic; + } + + @Override + public Class type() { + return delegate.type(); + } + + @Override + public long count(D type) { + return delegate.count(type); + } + + @Override + public long sum(Set types) { + return delegate.sum(types); + } + + @Override + public long sum() { + return delegate.sum(); + } + + @Override + public void begin() { + delegate.begin(); + } + + @Override + public void end(D result) { + delegate.end(result); + } + + @Override + public void addDerivedStatistic(ChainedOperationObserver derived) { + delegate.addDerivedStatistic(convert(derived)); + } + + @Override + public void removeDerivedStatistic(ChainedOperationObserver derived) { + delegate.removeDerivedStatistic(convert(derived)); + } + + @Override + public Collection> getDerivedStatistics() { + Collection> derivedStatistics = delegate.getDerivedStatistics(); + return derivedStatistics.stream().map(this::revert).collect(Collectors.toSet()); + } + + private ChainedOperationObserver revert(org.terracotta.statistics.observer.ChainedOperationObserver observer) { + return new ChainedOperationObserver() { + @Override + public void begin(long time) { + observer.begin(time); + } + + @Override + public void end(long time, long latency, D result) { + observer.end(time, latency, result); + } + }; + } + + private org.terracotta.statistics.observer.ChainedOperationObserver convert(ChainedOperationObserver observer) { + return new org.terracotta.statistics.observer.ChainedOperationObserver() { + @Override + public void begin(long time) { + observer.begin(time); + } + + @Override + public void end(long time, long latency, D result) { + observer.end(time, latency, result); + } + }; + } + + +} diff --git a/core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationObserver.java b/core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationObserver.java new file mode 100644 index 0000000000..a6b8e9223f --- /dev/null +++ b/core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationObserver.java @@ -0,0 +1,37 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.core.internal.statistics; + +import org.ehcache.core.statistics.OperationObserver; + +public class DelegatingOperationObserver> implements OperationObserver { + + private final org.terracotta.statistics.observer.OperationObserver observer; + + public DelegatingOperationObserver(org.terracotta.statistics.observer.OperationObserver operationObserver) { + this.observer = operationObserver; + } + + @Override + public void begin() { + this.observer.begin(); + } + + @Override + public void end(T result) { + this.observer.end(result); + } +} diff --git a/core/src/main/java/org/ehcache/core/statistics/DelegatingOperationStatistic.java b/core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationStatistic.java similarity index 94% rename from core/src/main/java/org/ehcache/core/statistics/DelegatingOperationStatistic.java rename to core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationStatistic.java index c79d379755..0eb00e07df 100644 --- a/core/src/main/java/org/ehcache/core/statistics/DelegatingOperationStatistic.java +++ b/core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationStatistic.java @@ -13,7 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.statistics; +package org.ehcache.core.internal.statistics; + +import org.ehcache.core.statistics.ChainedOperationObserver; +import org.ehcache.core.statistics.OperationStatistic; import java.util.Collection; import java.util.Set; diff --git a/core/src/main/java/org/ehcache/core/statistics/StatsUtils.java b/core/src/main/java/org/ehcache/core/internal/statistics/StatsUtils.java similarity index 98% rename from core/src/main/java/org/ehcache/core/statistics/StatsUtils.java rename to core/src/main/java/org/ehcache/core/internal/statistics/StatsUtils.java index 12dc4bcbee..ed0a424911 100644 --- a/core/src/main/java/org/ehcache/core/statistics/StatsUtils.java +++ b/core/src/main/java/org/ehcache/core/internal/statistics/StatsUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.core.statistics; +package org.ehcache.core.internal.statistics; import java.util.Collections; import java.util.EnumSet; @@ -24,6 +24,8 @@ import java.util.function.Consumer; import org.ehcache.Cache; +import org.ehcache.core.statistics.CacheOperationOutcomes; +import org.ehcache.core.statistics.StoreOperationOutcomes; import org.terracotta.context.ContextManager; import org.terracotta.context.TreeNode; import org.terracotta.context.query.Matcher; diff --git a/core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java b/core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java index 1a806fc4aa..2ac1974951 100644 --- a/core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java +++ b/core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java @@ -51,6 +51,10 @@ public static ValueStatistic counter(Supplier supplier) return supply(StatisticType.COUNTER, supplier); } + public static ValueStatistic gauge(Supplier supplier) { + return supply(StatisticType.GAUGE, supplier); + } + public static ValueStatistic supply(StatisticType type, Supplier supplier) { return new SuppliedValueStatistic<>(type, supplier); } diff --git a/core/src/main/java/org/ehcache/core/statistics/TierStatistics.java b/core/src/main/java/org/ehcache/core/statistics/TierStatistics.java index a86946cb55..1335148bd2 100644 --- a/core/src/main/java/org/ehcache/core/statistics/TierStatistics.java +++ b/core/src/main/java/org/ehcache/core/statistics/TierStatistics.java @@ -16,8 +16,6 @@ package org.ehcache.core.statistics; -import org.terracotta.statistics.ValueStatistic; - import java.util.Map; /** @@ -25,13 +23,6 @@ */ public interface TierStatistics { - /** - * List of statistics tracked on this cache - * - * @return a map of statistics per name - */ - Map> getKnownStatistics(); - /** * Reset the values for this tier. However, note that {@code mapping, allocatedMemory, occupiedMemory} * won't be reset since it doesn't make sense. diff --git a/core/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory b/core/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory index 2e4732b8a1..7bcce30799 100644 --- a/core/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory +++ b/core/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory @@ -1 +1 @@ -org.ehcache.core.statistics.DefaultStatisticsServiceFactory +org.ehcache.core.internal.statistics.DefaultStatisticsServiceFactory diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java index 5ba0e4406f..b804590eb4 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java @@ -27,7 +27,7 @@ import org.ehcache.core.config.store.StoreStatisticsConfiguration; import org.ehcache.core.statistics.CacheOperationOutcomes; import org.ehcache.core.statistics.ChainedOperationObserver; -import org.ehcache.core.statistics.DefaultCacheStatistics; +import org.ehcache.core.internal.statistics.DefaultCacheStatistics; import org.ehcache.event.CacheEvent; import org.ehcache.event.CacheEventListener; import org.ehcache.event.EventType; diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java index cca3470c3d..09fa539c49 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java @@ -22,7 +22,7 @@ import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.spi.test.After; import org.junit.Before; import org.junit.Test; diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsDisabledTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsDisabledTest.java index 1eebd1e1b9..a29ddd23b5 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsDisabledTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsDisabledTest.java @@ -23,7 +23,7 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; -import org.ehcache.core.statistics.DefaultTierStatistics; +import org.ehcache.core.internal.statistics.DefaultTierStatistics; import org.ehcache.impl.internal.TimeSourceConfiguration; import org.ehcache.internal.TestTimeSource; import org.junit.After; diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java index cf12e539fb..e4bb37aed7 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java @@ -25,7 +25,7 @@ import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.core.config.store.StoreStatisticsConfiguration; -import org.ehcache.core.statistics.DefaultTierStatistics; +import org.ehcache.core.internal.statistics.DefaultTierStatistics; import org.ehcache.impl.internal.TimeSourceConfiguration; import org.ehcache.internal.TestTimeSource; import org.junit.After; diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java index 661bb436d7..6a356d89a6 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java @@ -43,7 +43,13 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.ehcache.config.builders.ResourcePoolsBuilder.heap; -import static org.ehcache.core.statistics.StatsUtils.*; +import static org.ehcache.core.internal.statistics.StatsUtils.findLowestTier; +import static org.ehcache.core.internal.statistics.StatsUtils.findOperationStatisticOnChildren; +import static org.ehcache.core.internal.statistics.StatsUtils.findStatisticOnDescendants; +import static org.ehcache.core.internal.statistics.StatsUtils.findTiers; +import static org.ehcache.core.internal.statistics.StatsUtils.hasOperationStat; +import static org.ehcache.core.internal.statistics.StatsUtils.hasProperty; +import static org.ehcache.core.internal.statistics.StatsUtils.hasTag; import static org.junit.Assert.assertThrows; import static org.terracotta.context.query.Matchers.attributes; import static org.terracotta.context.query.Matchers.context; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java index 4d129bdc96..5d3b36b429 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java @@ -29,7 +29,7 @@ import org.ehcache.core.spi.service.CacheManagerProviderService; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.store.Store; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.DefaultTimeSourceService; import org.ehcache.impl.serialization.LongSerializer; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java index c855aa6a77..755d7d2c51 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java @@ -23,7 +23,7 @@ import org.ehcache.config.SizedResourcePool; import org.ehcache.config.units.MemoryUnit; import org.ehcache.CachePersistenceException; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java index eeea3f8a10..5cc5fd54b0 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java @@ -26,7 +26,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.spi.service.CacheManagerProviderService; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.statistics.LowerCachingTierOperationsOutcome; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java index 5844075517..14af067cb2 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java @@ -20,7 +20,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.IdentityCopier; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java index 6d6506a67c..772e2ce7e4 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java @@ -20,7 +20,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.SerializingCopier; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByRefTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByRefTest.java index 2367f15248..4a97fddd52 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByRefTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByRefTest.java @@ -22,7 +22,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.units.EntryUnit; import org.ehcache.core.events.StoreEventDispatcher; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.impl.internal.sizeof.NoopSizeOfEngine; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByValueTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByValueTest.java index 7d032735c4..b3cfaca03f 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByValueTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByValueTest.java @@ -22,7 +22,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.units.EntryUnit; import org.ehcache.core.events.StoreEventDispatcher; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.sizeof.NoopSizeOfEngine; import org.ehcache.core.spi.time.TimeSource; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java index 3d88baa429..b065a01694 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java @@ -18,7 +18,7 @@ import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.core.events.NullStoreEventDispatcher; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java index 232056b134..dc7f61bea3 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java @@ -20,7 +20,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.IdentityCopier; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java index 78253ed98d..96b8443734 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java @@ -20,7 +20,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.SerializingCopier; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java index a137d0c675..765cd2291d 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java @@ -19,7 +19,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.core.events.NullStoreEventDispatcher; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java index 493f267c51..fd1dba84e4 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java @@ -19,7 +19,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.SerializingCopier; import org.ehcache.core.events.NullStoreEventDispatcher; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java index a2be9cdb12..3e951670ba 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java @@ -19,7 +19,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.spi.resilience.StoreAccessException; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java index 49d336c9d1..fbe6a7b7da 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java @@ -19,7 +19,7 @@ import org.ehcache.Cache; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.impl.copy.IdentityCopier; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java index 5ce6156922..28566f5bdb 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java @@ -19,7 +19,7 @@ import org.ehcache.Cache; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.EntryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.impl.copy.IdentityCopier; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java index 8c4b652c66..88f678b4ed 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java @@ -20,7 +20,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.event.EventType; import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByRefTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByRefTest.java index b6feb1e813..7f5bcf62c8 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByRefTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByRefTest.java @@ -23,7 +23,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.events.StoreEventDispatcher; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.impl.internal.sizeof.DefaultSizeOfEngine; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByValueTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByValueTest.java index c9119f5605..04e8218465 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByValueTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByValueTest.java @@ -22,7 +22,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.events.StoreEventDispatcher; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.sizeof.DefaultSizeOfEngine; import org.ehcache.impl.internal.store.heap.OnHeapStore; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java index 7381b2299e..e0421375a0 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java @@ -18,7 +18,7 @@ import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; import org.ehcache.core.events.NullStoreEventDispatcher; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java index 95d160874c..70d2b5beea 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java @@ -19,7 +19,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.core.events.NullStoreEventDispatcher; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java index 1351e71396..7b9caa6ec6 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java @@ -19,7 +19,7 @@ import org.ehcache.config.ResourcePools; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.SerializingCopier; import org.ehcache.core.events.NullStoreEventDispatcher; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java index df502f9ffc..60bb1ca087 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java @@ -22,7 +22,7 @@ import org.ehcache.config.SizedResourcePool; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.events.TestStoreEventDispatcher; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java index e29a216dbe..20b2449444 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java @@ -20,7 +20,7 @@ import org.ehcache.config.ResourceType; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.spi.store.Store; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.events.TestStoreEventDispatcher; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java index 5ee162a2ce..fe073da77f 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java @@ -21,7 +21,7 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.events.StoreEventDispatcher; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.impl.copy.IdentityCopier; import org.ehcache.core.events.NullStoreEventDispatcher; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java index 39d93f1025..bc3245bbfe 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java @@ -20,7 +20,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.spi.store.Store; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java index e51e7f849f..f3605deb02 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java @@ -26,7 +26,7 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.CachePersistenceException; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java index f7f601e626..63b1601e33 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java @@ -27,7 +27,7 @@ import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.Store.RemoveStatus; import org.ehcache.core.spi.store.Store.ReplaceStatus; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; import org.ehcache.core.spi.store.tiering.CachingTier; diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java index 6474aef6cc..6d556d805f 100755 --- a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java @@ -27,7 +27,7 @@ import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.events.StoreEventDispatcher; import org.ehcache.CachePersistenceException; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; diff --git a/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java b/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java index f317efd20b..829ffaec15 100644 --- a/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/EhcacheBaseTest.java @@ -28,7 +28,7 @@ import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; import org.ehcache.impl.internal.TimeSourceConfiguration; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.integration.statistics.AbstractCacheCalculationTest; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.ehcache.spi.service.Service; diff --git a/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java b/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java index 3416a33869..5784f64acf 100644 --- a/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java +++ b/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java @@ -21,7 +21,7 @@ import org.ehcache.config.ResourceType; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.spi.loaderwriter.BulkCacheLoadingException; import org.ehcache.spi.loaderwriter.BulkCacheWritingException; import org.ehcache.spi.resilience.StoreAccessException; diff --git a/integration-test/src/test/java/org/ehcache/integration/statistics/CacheCalculationTest.java b/integration-test/src/test/java/org/ehcache/integration/statistics/CacheCalculationTest.java index c0999c7790..be63a91bb2 100644 --- a/integration-test/src/test/java/org/ehcache/integration/statistics/CacheCalculationTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/statistics/CacheCalculationTest.java @@ -30,7 +30,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java b/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java index 4c97c4a5fc..c590a6096d 100644 --- a/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/statistics/TierCalculationTest.java @@ -33,7 +33,7 @@ import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration; import org.ehcache.impl.internal.TimeSourceConfiguration; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.integration.TestTimeSource; import org.junit.After; import org.junit.Before; diff --git a/management/src/main/java/org/ehcache/management/ExtendedStatisticsService.java b/management/src/main/java/org/ehcache/management/ExtendedStatisticsService.java index a6fde2e119..b0441c075c 100644 --- a/management/src/main/java/org/ehcache/management/ExtendedStatisticsService.java +++ b/management/src/main/java/org/ehcache/management/ExtendedStatisticsService.java @@ -18,7 +18,7 @@ import org.ehcache.Cache; import org.ehcache.core.spi.service.StatisticsService; -import org.ehcache.core.statistics.LatencyHistogramConfiguration; +import org.ehcache.management.registry.LatencyHistogramConfiguration; import org.terracotta.management.model.capabilities.descriptors.StatisticDescriptor; import org.terracotta.management.model.stats.Statistic; diff --git a/management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java b/management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java index a6552dc361..3a98419716 100644 --- a/management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java +++ b/management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java @@ -15,7 +15,7 @@ */ package org.ehcache.management; -import org.ehcache.core.statistics.LatencyHistogramConfiguration; +import org.ehcache.management.registry.LatencyHistogramConfiguration; import org.ehcache.spi.service.ServiceCreationConfiguration; import org.terracotta.management.model.context.Context; diff --git a/management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java b/management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java index ff728ea7c8..ac27889b52 100644 --- a/management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java +++ b/management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java @@ -18,7 +18,7 @@ import org.ehcache.Cache; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.core.statistics.CacheOperationOutcomes; -import org.ehcache.core.statistics.LatencyHistogramConfiguration; +import org.ehcache.management.registry.LatencyHistogramConfiguration; import org.ehcache.management.ExtendedStatisticsService; import org.ehcache.management.ManagementRegistryServiceConfiguration; import org.ehcache.management.providers.CacheBinding; diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultCollectorService.java b/management/src/main/java/org/ehcache/management/registry/DefaultCollectorService.java index 633f11356e..8444d78192 100644 --- a/management/src/main/java/org/ehcache/management/registry/DefaultCollectorService.java +++ b/management/src/main/java/org/ehcache/management/registry/DefaultCollectorService.java @@ -23,7 +23,7 @@ import org.ehcache.core.spi.store.InternalCacheManager; import org.ehcache.core.spi.time.TimeSource; import org.ehcache.core.spi.time.TimeSourceService; -import org.ehcache.core.statistics.StatsUtils; +import org.ehcache.core.internal.statistics.StatsUtils; import org.ehcache.management.CollectorService; import org.ehcache.management.ManagementRegistryService; import org.ehcache.management.ManagementRegistryServiceConfiguration; diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java index 26c515c315..e7dc7a3629 100644 --- a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java +++ b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java @@ -17,7 +17,6 @@ import org.ehcache.management.ManagementRegistryService; import org.ehcache.management.ManagementRegistryServiceConfiguration; -import org.ehcache.core.statistics.LatencyHistogramConfiguration; import org.terracotta.management.model.context.Context; import java.util.Arrays; diff --git a/core/src/main/java/org/ehcache/core/statistics/LatencyHistogramConfiguration.java b/management/src/main/java/org/ehcache/management/registry/LatencyHistogramConfiguration.java similarity index 98% rename from core/src/main/java/org/ehcache/core/statistics/LatencyHistogramConfiguration.java rename to management/src/main/java/org/ehcache/management/registry/LatencyHistogramConfiguration.java index 85b9d9eda4..687660173b 100644 --- a/core/src/main/java/org/ehcache/core/statistics/LatencyHistogramConfiguration.java +++ b/management/src/main/java/org/ehcache/management/registry/LatencyHistogramConfiguration.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.statistics; +package org.ehcache.management.registry; import java.time.Duration; import java.util.Objects; diff --git a/management/src/main/java/org/ehcache/management/statistics/DefaultCacheStatistics.java b/management/src/main/java/org/ehcache/management/statistics/DefaultCacheStatistics.java new file mode 100644 index 0000000000..6ebb39b9d2 --- /dev/null +++ b/management/src/main/java/org/ehcache/management/statistics/DefaultCacheStatistics.java @@ -0,0 +1,247 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.management.statistics; + +import org.ehcache.core.InternalCache; +import org.ehcache.core.internal.statistics.DefaultTierStatistics; +import org.ehcache.core.internal.statistics.DelegatingOperationStatistic; +import org.ehcache.core.statistics.BulkOps; +import org.ehcache.core.statistics.CacheOperationOutcomes.GetOutcome; +import org.ehcache.core.statistics.CacheOperationOutcomes.PutOutcome; +import org.ehcache.core.statistics.CacheStatistics; +import org.ehcache.core.statistics.ChainedOperationObserver; +import org.ehcache.core.statistics.OperationStatistic; +import org.ehcache.core.statistics.TierStatistics; +import org.ehcache.core.statistics.ValueStatistic; +import org.terracotta.statistics.ValueStatistics; + +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +import static org.ehcache.core.internal.statistics.StatsUtils.findLowestTier; +import static org.ehcache.core.internal.statistics.StatsUtils.findOperationStatisticOnChildren; +import static org.ehcache.core.internal.statistics.StatsUtils.findTiers; +import static org.ehcache.core.statistics.CacheOperationOutcomes.ConditionalRemoveOutcome; +import static org.ehcache.core.statistics.CacheOperationOutcomes.PutIfAbsentOutcome; +import static org.ehcache.core.statistics.CacheOperationOutcomes.RemoveOutcome; +import static org.ehcache.core.statistics.CacheOperationOutcomes.ReplaceOutcome; +import static org.ehcache.core.statistics.SuppliedValueStatistic.counter; + +/** + * Contains usage statistics relative to a given cache. + */ +public class DefaultCacheStatistics implements CacheStatistics { + + private volatile CompensatingCounters compensatingCounters = CompensatingCounters.empty(); + + private final org.terracotta.statistics.OperationStatistic get; + private final org.terracotta.statistics.OperationStatistic put; + private final org.terracotta.statistics.OperationStatistic remove; + private final org.terracotta.statistics.OperationStatistic putIfAbsent; + private final org.terracotta.statistics.OperationStatistic replace; + private final org.terracotta.statistics.OperationStatistic conditionalRemove; + + private final InternalCache cache; + + private final Map tierStatistics; + private final TierStatistics lowestTier; + + private final Map> knownStatistics; + + public DefaultCacheStatistics(InternalCache cache) { + this.cache = cache; + + get = findOperationStatisticOnChildren(cache, GetOutcome.class, "get"); + put = findOperationStatisticOnChildren(cache, PutOutcome.class, "put"); + remove = findOperationStatisticOnChildren(cache, RemoveOutcome.class, "remove"); + putIfAbsent = findOperationStatisticOnChildren(cache, PutIfAbsentOutcome.class, "putIfAbsent"); + replace = findOperationStatisticOnChildren(cache, ReplaceOutcome.class, "replace"); + conditionalRemove = findOperationStatisticOnChildren(cache, ConditionalRemoveOutcome.class, "conditionalRemove"); + + String[] tierNames = findTiers(cache); + + String lowestTierName = findLowestTier(tierNames); + TierStatistics lowestTier = null; + + tierStatistics = new HashMap<>(tierNames.length); + for (String tierName : tierNames) { + DefaultTierStatistics tierStatistics = new DefaultTierStatistics(cache, tierName); + this.tierStatistics.put(tierName, tierStatistics); + if (lowestTierName.equals(tierName)) { + lowestTier = tierStatistics; + } + } + this.lowestTier = lowestTier; + + knownStatistics = createKnownStatistics(); + } + + @Override + public , S extends ChainedOperationObserver> void registerDerivedStatistic(Class outcomeClass, String statName, S derivedStatistic) { + OperationStatistic stat = new DelegatingOperationStatistic<>(findOperationStatisticOnChildren(cache, outcomeClass, statName)); + stat.addDerivedStatistic(derivedStatistic); + } + + private Map> createKnownStatistics() { + Map> knownStatistics = new HashMap<>(30); + knownStatistics.put("Cache:HitCount", ValueStatistics.counter(this::getCacheHits)); + knownStatistics.put("Cache:MissCount", ValueStatistics.counter(this::getCacheMisses)); + knownStatistics.put("Cache:PutCount", ValueStatistics.counter(this::getCachePuts)); + knownStatistics.put("Cache:RemovalCount", ValueStatistics.counter(this::getCacheRemovals)); + knownStatistics.put("Cache:EvictionCount", ValueStatistics.counter(this::getCacheEvictions)); + knownStatistics.put("Cache:ExpirationCount", ValueStatistics.counter(this::getCacheExpirations)); + + for (DefaultTierStatistics tier : tierStatistics.values()) { + knownStatistics.putAll(tier.getKnownStatistics()); + } + + return Collections.unmodifiableMap(knownStatistics); + } + + public Map> getKnownStatistics() { + return knownStatistics; + } + + public Map getTierStatistics() { + return Collections.unmodifiableMap(tierStatistics); + } + + @Override + public void clear() { + compensatingCounters = compensatingCounters.snapshot(this); + for (TierStatistics t : tierStatistics.values()) { + t.clear(); + } + } + + @Override + public long getCacheHits() { + return normalize(getHits() - compensatingCounters.cacheHits); + } + + @Override + public float getCacheHitPercentage() { + long cacheHits = getCacheHits(); + return normalize((float) cacheHits / (cacheHits + getCacheMisses())) * 100.0f; + } + + @Override + public long getCacheMisses() { + return normalize(getMisses() - compensatingCounters.cacheMisses); + } + + @Override + public float getCacheMissPercentage() { + long cacheMisses = getCacheMisses(); + return normalize((float) cacheMisses / (getCacheHits() + cacheMisses)) * 100.0f; + } + + @Override + public long getCacheGets() { + return normalize(getHits() + getMisses() - compensatingCounters.cacheGets); + } + + @Override + public long getCachePuts() { + return normalize(getBulkCount(BulkOps.PUT_ALL) + + put.sum(EnumSet.of(PutOutcome.PUT)) + + putIfAbsent.sum(EnumSet.of(PutIfAbsentOutcome.PUT)) + + replace.sum(EnumSet.of(ReplaceOutcome.HIT)) - + compensatingCounters.cachePuts); + } + + @Override + public long getCacheRemovals() { + return normalize(getBulkCount(BulkOps.REMOVE_ALL) + + remove.sum(EnumSet.of(RemoveOutcome.SUCCESS)) + + conditionalRemove.sum(EnumSet.of(ConditionalRemoveOutcome.SUCCESS)) - + compensatingCounters.cacheRemovals); + } + + @Override + public long getCacheEvictions() { + return normalize(lowestTier.getEvictions()); + } + + @Override + public long getCacheExpirations() { + return normalize(lowestTier.getExpirations()); + } + + private long getMisses() { + return getBulkCount(BulkOps.GET_ALL_MISS) + + get.sum(EnumSet.of(GetOutcome.MISS)) + + putIfAbsent.sum(EnumSet.of(PutIfAbsentOutcome.PUT)) + + replace.sum(EnumSet.of(ReplaceOutcome.MISS_NOT_PRESENT)) + + conditionalRemove.sum(EnumSet.of(ConditionalRemoveOutcome.FAILURE_KEY_MISSING)); + } + + private long getHits() { + return getBulkCount(BulkOps.GET_ALL_HITS) + + get.sum(EnumSet.of(GetOutcome.HIT)) + + putIfAbsent.sum(EnumSet.of(PutIfAbsentOutcome.HIT)) + + replace.sum(EnumSet.of(ReplaceOutcome.HIT, ReplaceOutcome.MISS_PRESENT)) + + conditionalRemove.sum(EnumSet.of(ConditionalRemoveOutcome.SUCCESS, ConditionalRemoveOutcome.FAILURE_KEY_PRESENT)); + } + + private long getBulkCount(BulkOps bulkOps) { + return cache.getBulkMethodEntries().get(bulkOps).longValue(); + } + + private static long normalize(long value) { + return Math.max(0, value); + } + + private static float normalize(float value) { + if (Float.isNaN(value)) { + return 0.0f; + } + return Math.min(1.0f, Math.max(0.0f, value)); + } + + private static class CompensatingCounters { + final long cacheHits; + final long cacheMisses; + final long cacheGets; + final long cachePuts; + final long cacheRemovals; + + private CompensatingCounters(long cacheHits, long cacheMisses, long cacheGets, long cachePuts, long cacheRemovals) { + this.cacheHits = cacheHits; + this.cacheMisses = cacheMisses; + this.cacheGets = cacheGets; + this.cachePuts = cachePuts; + this.cacheRemovals = cacheRemovals; + } + + static CompensatingCounters empty() { + return new CompensatingCounters(0, 0, 0, 0, 0); + } + + CompensatingCounters snapshot(DefaultCacheStatistics statistics) { + return new CompensatingCounters( + cacheHits + statistics.getHits(), + cacheMisses + statistics.getMisses(), + cacheGets + statistics.getCacheGets(), + cachePuts + statistics.getCachePuts(), + cacheRemovals + statistics.getCacheRemovals()); + } + } + +} diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultExtendedStatisticsService.java b/management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsService.java similarity index 95% rename from management/src/main/java/org/ehcache/management/registry/DefaultExtendedStatisticsService.java rename to management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsService.java index c2f66cbc77..13d21e5b26 100644 --- a/management/src/main/java/org/ehcache/management/registry/DefaultExtendedStatisticsService.java +++ b/management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.management.registry; +package org.ehcache.management.statistics; import org.ehcache.Cache; import org.ehcache.Status; @@ -25,15 +25,11 @@ import org.ehcache.core.spi.store.InternalCacheManager; import org.ehcache.core.spi.store.Store; import org.ehcache.core.statistics.CacheStatistics; -import org.ehcache.core.statistics.DefaultCacheStatistics; -import org.ehcache.core.statistics.DelegatedMappedOperationStatistics; -import org.ehcache.core.statistics.DelegatingOperationObserver; -import org.ehcache.core.statistics.LatencyHistogramConfiguration; import org.ehcache.core.statistics.StatisticType; import org.ehcache.core.statistics.OperationObserver; -import org.ehcache.core.statistics.StatsUtils; import org.ehcache.core.statistics.ZeroOperationStatistic; import org.ehcache.management.ExtendedStatisticsService; +import org.ehcache.management.registry.LatencyHistogramConfiguration; import org.ehcache.spi.service.OptionalServiceDependencies; import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceProvider; @@ -58,7 +54,7 @@ import java.util.function.LongSupplier; import java.util.function.Supplier; -import static org.ehcache.core.statistics.StatsUtils.findOperationStatisticOnChildren; +import static org.ehcache.core.internal.statistics.StatsUtils.findOperationStatisticOnChildren; import static org.terracotta.statistics.StatisticBuilder.operation; /** diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultExtendedStatisticsServiceFactory.java b/management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsServiceFactory.java similarity index 96% rename from management/src/main/java/org/ehcache/management/registry/DefaultExtendedStatisticsServiceFactory.java rename to management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsServiceFactory.java index 5c6bf126b2..ae43c72ffb 100644 --- a/management/src/main/java/org/ehcache/management/registry/DefaultExtendedStatisticsServiceFactory.java +++ b/management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsServiceFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.ehcache.management.registry; +package org.ehcache.management.statistics; import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.management.ExtendedStatisticsService; diff --git a/core/src/main/java/org/ehcache/core/statistics/DefaultTierStatistics.java b/management/src/main/java/org/ehcache/management/statistics/DefaultTierStatistics.java similarity index 84% rename from core/src/main/java/org/ehcache/core/statistics/DefaultTierStatistics.java rename to management/src/main/java/org/ehcache/management/statistics/DefaultTierStatistics.java index 5bd4431e92..742ee19cd6 100755 --- a/core/src/main/java/org/ehcache/core/statistics/DefaultTierStatistics.java +++ b/management/src/main/java/org/ehcache/management/statistics/DefaultTierStatistics.java @@ -14,11 +14,16 @@ * limitations under the License. */ -package org.ehcache.core.statistics; +package org.ehcache.management.statistics; import org.ehcache.Cache; +import org.ehcache.core.internal.statistics.StatsUtils; +import org.ehcache.core.statistics.StoreOperationOutcomes; +import org.ehcache.core.statistics.TierOperationOutcomes; +import org.ehcache.core.statistics.TierStatistics; +import org.ehcache.core.statistics.ValueStatistic; import org.terracotta.statistics.OperationStatistic; -import org.terracotta.statistics.ValueStatistic; +import org.terracotta.statistics.ValueStatistics; import org.terracotta.statistics.ZeroOperationStatistic; import java.util.Collections; @@ -28,9 +33,9 @@ import java.util.Optional; import java.util.function.Supplier; -import static org.ehcache.core.statistics.StatsUtils.findStatisticOnDescendants; -import static org.terracotta.statistics.ValueStatistics.counter; -import static org.terracotta.statistics.ValueStatistics.gauge; +import static org.ehcache.core.internal.statistics.StatsUtils.findStatisticOnDescendants; +import static org.ehcache.core.statistics.SuppliedValueStatistic.counter; +import static org.ehcache.core.statistics.SuppliedValueStatistic.gauge; /** * Contains usage statistics relative to a given tier. @@ -39,7 +44,7 @@ public class DefaultTierStatistics implements TierStatistics { private volatile CompensatingCounters compensatingCounters = CompensatingCounters.empty(); - private final Map> knownStatistics; + private final Map> knownStatistics; private final OperationStatistic get; private final OperationStatistic put; @@ -77,24 +82,24 @@ public DefaultTierStatistics(Cache cache, String tierName) { allocatedMemory = findValueStatistics(cache, tierName, "allocatedMemory"); occupiedMemory = findValueStatistics(cache, tierName, "occupiedMemory"); - Map> knownStatistics = createKnownStatistics(tierName); + Map> knownStatistics = createKnownStatistics(tierName); this.knownStatistics = Collections.unmodifiableMap(knownStatistics); } - private Map> createKnownStatistics(String tierName) { - Map> knownStatistics = new HashMap<>(7); + private Map> createKnownStatistics(String tierName) { + Map> knownStatistics = new HashMap<>(7); addIfPresent(knownStatistics, tierName + ":HitCount", get, this::getHits); addIfPresent(knownStatistics, tierName + ":MissCount", get, this::getMisses); addIfPresent(knownStatistics, tierName + ":PutCount", put, this::getPuts); addIfPresent(knownStatistics, tierName + ":RemovalCount", remove, this::getRemovals); // These two a special because they are used by the cache so they should always be there - knownStatistics.put(tierName + ":EvictionCount", counter(this::getEvictions)); - knownStatistics.put(tierName + ":ExpirationCount", counter(this::getExpirations)); + knownStatistics.put(tierName + ":EvictionCount", ValueStatistics.counter(this::getEvictions)); + knownStatistics.put(tierName + ":ExpirationCount", ValueStatistics.counter(this::getExpirations)); - mapping.ifPresent(longValueStatistic -> knownStatistics.put(tierName + ":MappingCount", gauge(this::getMappings))); - allocatedMemory.ifPresent(longValueStatistic -> knownStatistics.put(tierName + ":AllocatedByteSize", gauge(this::getAllocatedByteSize))); - occupiedMemory.ifPresent(longValueStatistic -> knownStatistics.put(tierName + ":OccupiedByteSize", gauge(this::getOccupiedByteSize))); + mapping.ifPresent(longValueStatistic -> knownStatistics.put(tierName + ":MappingCount", ValueStatistics.gauge(this::getMappings))); + allocatedMemory.ifPresent(longValueStatistic -> knownStatistics.put(tierName + ":AllocatedByteSize", ValueStatistics.gauge(this::getAllocatedByteSize))); + occupiedMemory.ifPresent(longValueStatistic -> knownStatistics.put(tierName + ":OccupiedByteSize", ValueStatistics.gauge(this::getOccupiedByteSize))); return knownStatistics; } @@ -108,14 +113,13 @@ private Map> createKnownStatistics(String tierName) { * @param valueSupplier the supplier that will provide the current value for the statistic * @param type of the supplied value */ - private static void addIfPresent(Map> knownStatistics, String name, OperationStatistic reference, Supplier valueSupplier) { + private static void addIfPresent(Map> knownStatistics, String name, OperationStatistic reference, Supplier valueSupplier) { if(!(reference instanceof ZeroOperationStatistic)) { - knownStatistics.put(name, counter(valueSupplier)); + knownStatistics.put(name, ValueStatistics.counter(valueSupplier)); } } - @Override - public Map> getKnownStatistics() { + public Map> getKnownStatistics() { return knownStatistics; } diff --git a/core/src/main/java/org/ehcache/core/statistics/DelegatedMappedOperationStatistics.java b/management/src/main/java/org/ehcache/management/statistics/DelegatedMappedOperationStatistics.java similarity index 94% rename from core/src/main/java/org/ehcache/core/statistics/DelegatedMappedOperationStatistics.java rename to management/src/main/java/org/ehcache/management/statistics/DelegatedMappedOperationStatistics.java index 3b4ff273f2..cfbb3be33d 100644 --- a/core/src/main/java/org/ehcache/core/statistics/DelegatedMappedOperationStatistics.java +++ b/management/src/main/java/org/ehcache/management/statistics/DelegatedMappedOperationStatistics.java @@ -13,8 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.statistics; +package org.ehcache.management.statistics; +import org.ehcache.core.statistics.ChainedOperationObserver; +import org.ehcache.core.statistics.OperationStatistic; import org.terracotta.statistics.MappedOperationStatistic; import java.util.Collection; diff --git a/core/src/main/java/org/ehcache/core/statistics/DelegatingOperationObserver.java b/management/src/main/java/org/ehcache/management/statistics/DelegatingOperationObserver.java similarity index 91% rename from core/src/main/java/org/ehcache/core/statistics/DelegatingOperationObserver.java rename to management/src/main/java/org/ehcache/management/statistics/DelegatingOperationObserver.java index 1ec14b5e40..773b28d11a 100644 --- a/core/src/main/java/org/ehcache/core/statistics/DelegatingOperationObserver.java +++ b/management/src/main/java/org/ehcache/management/statistics/DelegatingOperationObserver.java @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.ehcache.core.statistics; +package org.ehcache.management.statistics; + +import org.ehcache.core.statistics.OperationObserver; public class DelegatingOperationObserver> implements OperationObserver { diff --git a/management/src/main/java/org/ehcache/management/statistics/StatsUtils.java b/management/src/main/java/org/ehcache/management/statistics/StatsUtils.java new file mode 100644 index 0000000000..39f313ce5f --- /dev/null +++ b/management/src/main/java/org/ehcache/management/statistics/StatsUtils.java @@ -0,0 +1,270 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.management.statistics; + +import org.ehcache.Cache; +import org.ehcache.core.statistics.CacheOperationOutcomes; +import org.ehcache.core.statistics.StoreOperationOutcomes; +import org.terracotta.context.ContextManager; +import org.terracotta.context.TreeNode; +import org.terracotta.context.query.Matcher; +import org.terracotta.context.query.Matchers; +import org.terracotta.context.query.Query; +import org.terracotta.statistics.OperationStatistic; +import org.terracotta.statistics.derived.OperationResultFilter; + +import java.util.Collections; +import java.util.EnumSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Consumer; + +import static org.terracotta.context.query.Matchers.attributes; +import static org.terracotta.context.query.Matchers.context; +import static org.terracotta.context.query.Matchers.hasAttribute; +import static org.terracotta.context.query.Matchers.identifier; +import static org.terracotta.context.query.Matchers.subclassOf; +import static org.terracotta.context.query.QueryBuilder.queryBuilder; + +/** + * Class allowing to query cache and tier statistics + */ +public final class StatsUtils { + + private StatsUtils() {} + + public static Matcher> hasTag(final String tag) { + return hasAttribute("tags", new Matcher>() { + @Override + protected boolean matchesSafely(Set object) { + return object.contains(tag); + } + }); + } + + public static Matcher> hasProperty(final String key, final String value) { + return hasAttribute("properties", new Matcher>() { + @Override + protected boolean matchesSafely(Map properties) { + Object val = properties.get(key); + return val != null && value.equals(val); + } + }); + } + + /** + * Search for a statistic on the descendant of the context that matches the tag and statistic name. + * + * @param context the context of the query + * @param discriminator a filter on the discriminator property + * @param tag the tag we are looking for + * @param statName statistic name + * @param type of the statistic that will be returned + * @return the wanted statistic or null if no such statistic is found + * @throws RuntimeException when more than one matching statistic is found + */ + public static Optional findStatisticOnDescendants(Object context, String discriminator, String tag, String statName) { + + @SuppressWarnings("unchecked") + Set statResult = queryBuilder() + .descendants() + .filter(context(attributes(Matchers.allOf( + hasAttribute("name", statName), + hasProperty("discriminator", discriminator), + hasTag(tag))))) + .build().execute(Collections.singleton(ContextManager.nodeFor(context))); + + if (statResult.size() > 1) { + throw new RuntimeException("One stat expected for " + statName + " but found " + statResult.size()); + } + + if (statResult.size() == 1) { + @SuppressWarnings("unchecked") + T result = (T) statResult.iterator().next().getContext().attributes().get("this"); + return Optional.ofNullable(result); + } + + // No such stat in this context + return Optional.empty(); + } + + /** + * Search for a statistic on the descendant of the context that matches the tag and statistic name. + * + * @param context the context of the query + * @param tag the tag we are looking for + * @param statName statistic name + * @param type of the statistic that will be returned + * @return the wanted statistic or null if no such statistic is found + * @throws RuntimeException when more than one matching statistic is found + */ + public static Optional findStatisticOnDescendants(Object context, String tag, String statName) { + + @SuppressWarnings("unchecked") + Set statResult = queryBuilder() + .descendants() + .filter(context(attributes(Matchers.allOf( + hasAttribute("name", statName), + hasTag(tag))))) + .build().execute(Collections.singleton(ContextManager.nodeFor(context))); + + if (statResult.size() > 1) { + throw new RuntimeException("One stat expected for " + statName + " but found " + statResult.size()); + } + + if (statResult.size() == 1) { + @SuppressWarnings("unchecked") + T result = (T) statResult.iterator().next().getContext().attributes().get("this"); + return Optional.ofNullable(result); + } + + // No such stat in this context + return Optional.empty(); + } + + /** + * Find an operation statistic attached (as a children) to this context that matches the statistic name and type + * + * @param context the context of the query + * @param type type of the operation statistic + * @param statName statistic name + * @param type of the operation statistic content + * @return the operation statistic searched for + * @throws RuntimeException if 0 or more than 1 result is found + */ + public static > OperationStatistic findOperationStatisticOnChildren(Object context, Class type, String statName) { + @SuppressWarnings("unchecked") + Query query = queryBuilder() + .children() + .filter(context(attributes(Matchers.allOf(hasAttribute("name", statName), hasAttribute("type", type))))) + .build(); + + Set result = query.execute(Collections.singleton(ContextManager.nodeFor(context))); + if (result.size() > 1) { + throw new RuntimeException("result must be unique"); + } + if (result.isEmpty()) { + throw new RuntimeException("result must not be null"); + } + @SuppressWarnings("unchecked") + OperationStatistic statistic = (OperationStatistic) result.iterator().next().getContext().attributes().get("this"); + return statistic; + } + + /** + * Find the list of tiers of a cache. We assume a lot of things here. + *
    + *
  • The "eviction" statistic is available on the tier
  • + *
  • That the tiers have only one tag attribute
  • + *
  • That this tag contains the tier name
  • + *
  • That the only descendants having an "eviction" statistic are the tiers
  • + *
+ * + * @param cache the context for looking for tiers + * @return an array of tier names + * @throws RuntimeException if not tiers are found or if tiers have multiple tags + */ + public static String[] findTiers(Cache cache) { + // Here I'm randomly taking the eviction observer because it exists on all tiers + @SuppressWarnings("unchecked") + Query statQuery = queryBuilder() + .descendants() + .filter(context(attributes(Matchers.allOf(hasAttribute("name", "eviction"), hasAttribute("type", StoreOperationOutcomes.EvictionOutcome.class))))) + .build(); + + Set statResult = statQuery.execute(Collections.singleton(ContextManager.nodeFor(cache))); + + if (statResult.isEmpty()) { + throw new RuntimeException("Failed to find tiers using the eviction observer, valid result Set sizes must 1 or more"); + } + + String[] tiers = new String[statResult.size()]; + + int i = 0; + for (TreeNode treeNode : statResult) { + Set tags = (Set) treeNode.getContext().attributes().get("tags"); + if (tags.size() != 1) { + throw new RuntimeException("We expect tiers to have only one tag"); + } + + String storeType = tags.iterator().next().toString(); + tiers[i++] = storeType; + } + return tiers; + } + + /** + * Find the lowest tier from a list of tier. We assume a lot of things here that the tiers depth + * magically matches the alphabetical order. + * + * @param tiers all tiers + * @return the lowest tier + */ + public static String findLowestTier(String[] tiers) { + //if only 1 store then you don't need to find the lowest tier + if (tiers.length == 1) { + return tiers[0]; + } + + //we expect at least one tier + if (tiers.length == 0) { + throw new RuntimeException("No existing tier"); + } + + // We rely here on the alphabetical order matching the depth order so from highest to lowest we have + // OnHeap, OffHeap, Disk, Clustered + String lowestTier = tiers[0]; + for (int i = 1; i < tiers.length; i++) { + if (tiers[i].compareTo(lowestTier) < 0) { + lowestTier = tiers[i]; + } + } + + return lowestTier; + } + + public static > boolean hasOperationStat(Object rootNode, Class statisticType, String statName) { + Query q = queryBuilder().descendants() + .filter(context(identifier(subclassOf(OperationStatistic.class)))) + .filter(context(attributes(Matchers.allOf( + hasAttribute("name", statName), + hasAttribute("this", new Matcher>() { + @Override + protected boolean matchesSafely(OperationStatistic object) { + return object.type().equals(statisticType); + } + }) + )))) + .build(); + + Set result = q.execute(Collections.singleton(ContextManager.nodeFor(rootNode))); + + if (result.size() > 1) { + throw new RuntimeException("a zero or a single stat was expected; found " + result.size()); + } + + return !result.isEmpty(); + } + + public static void registerClearNotification(String alias, Cache cache, Consumer cacheClear) { + OperationStatistic clear = StatsUtils.findOperationStatisticOnChildren(cache, + CacheOperationOutcomes.ClearOutcome.class, "clear"); + clear.addDerivedStatistic(new OperationResultFilter<>(EnumSet.of(CacheOperationOutcomes.ClearOutcome.SUCCESS), + (time, latency) -> cacheClear.accept(alias))); + } +} diff --git a/management/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory b/management/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory index 80723caaa6..fb6fb41c9f 100644 --- a/management/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory +++ b/management/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory @@ -1,2 +1,2 @@ org.ehcache.management.registry.DefaultManagementRegistryFactory -org.ehcache.management.registry.DefaultExtendedStatisticsServiceFactory +org.ehcache.management.statistics.DefaultExtendedStatisticsServiceFactory diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java index 488afc5331..659ff56f4a 100644 --- a/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java @@ -22,7 +22,7 @@ import org.ehcache.management.ManagementRegistryServiceConfiguration; import org.ehcache.management.providers.CacheBinding; import org.ehcache.management.providers.ExposedCacheBinding; -import org.ehcache.management.registry.DefaultExtendedStatisticsService; +import org.ehcache.management.statistics.DefaultExtendedStatisticsService; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; import org.hamcrest.Matcher; import org.junit.After; diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/LatencyHistogramConfigurationTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/LatencyHistogramConfigurationTest.java index ccd906ef38..75c97ea12e 100644 --- a/management/src/test/java/org/ehcache/management/providers/statistics/LatencyHistogramConfigurationTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/LatencyHistogramConfigurationTest.java @@ -15,7 +15,7 @@ */ package org.ehcache.management.providers.statistics; -import org.ehcache.core.statistics.LatencyHistogramConfiguration; +import org.ehcache.management.registry.LatencyHistogramConfiguration; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java index 989d38415a..ce8d1749ae 100755 --- a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java @@ -24,7 +24,7 @@ import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.statistics.CacheOperationOutcomes; -import org.ehcache.core.statistics.LatencyHistogramConfiguration; +import org.ehcache.management.registry.LatencyHistogramConfiguration; import org.ehcache.management.ManagementRegistryService; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; import org.ehcache.management.registry.DefaultManagementRegistryService; @@ -53,7 +53,7 @@ import static java.time.Duration.ofMillis; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; -import static org.ehcache.core.statistics.StatsUtils.findOperationStatisticOnChildren; +import static org.ehcache.core.internal.statistics.StatsUtils.findOperationStatisticOnChildren; import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; public class StandardEhcacheStatisticsTest { diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreProviderTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreProviderTest.java index aabb0494f0..e6546f7f83 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreProviderTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreProviderTest.java @@ -21,7 +21,7 @@ import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.time.TimeSourceService; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.impl.internal.DefaultTimeSourceService; import org.ehcache.impl.internal.store.offheap.OffHeapStore; import org.ehcache.spi.persistence.StateRepository; diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java index be637928f8..dc2c0c2e8d 100644 --- a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java @@ -27,7 +27,7 @@ import org.ehcache.core.spi.service.CacheManagerProviderService; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.store.Store; -import org.ehcache.core.statistics.DefaultStatisticsService; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.config.copy.DefaultCopyProviderConfiguration; From 8b97020023bbc2f16477beecc22151b15c90fd30 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 16 Dec 2020 10:40:57 -0500 Subject: [PATCH 314/372] Correct a bunch of long term service dependency mistakes --- .../service/OptionalServiceDependencies.java | 2 ++ .../spi/service/ServiceDependencies.java | 2 ++ .../ehcache/spi/service/ServiceProvider.java | 1 + .../service/ClusteringServiceFactory.java | 4 +-- .../service/DefaultClusteringService.java | 2 +- .../client/internal/store/ClusteredStore.java | 4 ++- .../store/ClusteredStoreProviderFactory.java | 2 +- .../client/NonClusteredCacheTest.java | 3 +- .../statistics/DefaultStatisticsService.java | 35 +++++++------------ .../DefaultStatisticsServiceFactory.java | 4 +-- .../core/spi/service/ServiceFactory.java | 4 +-- .../store/AbstractWrapperStoreProvider.java | 9 +++-- .../services/FancyCacheProviderFactory.java | 2 +- .../services/TestProvidedServiceFactory.java | 2 +- .../core/spi/services/TestServiceFactory.java | 4 +-- .../internal/TimeSourceServiceFactory.java | 4 +-- .../DefaultExecutionServiceFactory.java | 7 +++- .../WriteBehindProviderFactory.java | 4 +-- .../DefaultDiskResourceServiceFactory.java | 2 +- ...DefaultLocalPersistenceServiceFactory.java | 4 +-- .../DefaultSizeOfEngineProviderFactory.java | 4 +-- .../spi/copy/DefaultCopyProviderFactory.java | 4 +-- ...aultCacheEventListenerProviderFactory.java | 6 ++-- ...faultCacheLoaderWriterProviderFactory.java | 6 ++-- ...aultResilienceStrategyProviderFactory.java | 4 +-- .../DefaultSerializationProviderFactory.java | 4 +-- .../internal/store/disk/OffHeapDiskStore.java | 3 +- .../disk/OffHeapDiskStoreProviderFactory.java | 2 +- .../impl/internal/store/heap/OnHeapStore.java | 5 ++- .../heap/OnHeapStoreProviderFactory.java | 2 +- .../internal/store/offheap/OffHeapStore.java | 2 +- .../offheap/OffHeapStoreProviderFactory.java | 2 +- .../store/tiering/CompoundCachingTier.java | 11 ++++-- .../CompoundCachingTierProviderFactory.java | 2 +- .../internal/store/tiering/TieredStore.java | 11 ++++-- .../tiering/TieredStoreProviderFactory.java | 2 +- .../org/ehcache/impl/store/BaseStore.java | 25 +++++++++---- .../DefaultStatisticsServiceTest.java | 7 ---- .../store/heap/OnHeapStoreProviderTest.java | 4 +++ .../DefaultManagementRegistryFactory.java | 4 +-- .../DefaultExtendedStatisticsService.java | 21 +++++------ .../transactions/xa/internal/XAStore.java | 9 +++-- .../configuration/XAStoreProviderFactory.java | 2 +- .../journal/DefaultJournalProvider.java | 21 ++++++----- .../DefaultJournalProviderFactory.java | 4 +-- ...aultTransactionManagerProviderFactory.java | 4 +-- .../ehcache/transactions/NonXACacheTest.java | 4 +-- 47 files changed, 154 insertions(+), 122 deletions(-) diff --git a/api/src/main/java/org/ehcache/spi/service/OptionalServiceDependencies.java b/api/src/main/java/org/ehcache/spi/service/OptionalServiceDependencies.java index bb73063c4d..1bfbb528f2 100644 --- a/api/src/main/java/org/ehcache/spi/service/OptionalServiceDependencies.java +++ b/api/src/main/java/org/ehcache/spi/service/OptionalServiceDependencies.java @@ -17,6 +17,7 @@ package org.ehcache.spi.service; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -26,6 +27,7 @@ */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) +@Inherited public @interface OptionalServiceDependencies { /** diff --git a/api/src/main/java/org/ehcache/spi/service/ServiceDependencies.java b/api/src/main/java/org/ehcache/spi/service/ServiceDependencies.java index a09ba1e71a..8e582d38bd 100644 --- a/api/src/main/java/org/ehcache/spi/service/ServiceDependencies.java +++ b/api/src/main/java/org/ehcache/spi/service/ServiceDependencies.java @@ -17,6 +17,7 @@ package org.ehcache.spi.service; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -26,6 +27,7 @@ */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) +@Inherited public @interface ServiceDependencies { /** diff --git a/api/src/main/java/org/ehcache/spi/service/ServiceProvider.java b/api/src/main/java/org/ehcache/spi/service/ServiceProvider.java index ffc4a8d9d3..d1f2b0c2d1 100644 --- a/api/src/main/java/org/ehcache/spi/service/ServiceProvider.java +++ b/api/src/main/java/org/ehcache/spi/service/ServiceProvider.java @@ -17,6 +17,7 @@ package org.ehcache.spi.service; import java.util.Collection; +import java.util.Optional; /** * A repository of {@link Service} instances that can be used to look them up by type. diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java index 6592f75702..c02c4bdc99 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java @@ -37,7 +37,7 @@ public ClusteringService create(final ServiceCreationConfiguration getServiceType() { - return ClusteringService.class; + public Class getServiceType() { + return DefaultClusteringService.class; } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java index 0692c26c58..efb548a59d 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java @@ -60,7 +60,7 @@ /** * Provides support for accessing server-based cluster services. */ -class DefaultClusteringService implements ClusteringService, EntityService { +public class DefaultClusteringService implements ClusteringService, EntityService { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultClusteringService.class); diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index 67b5e6be3a..7e79077aa4 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -69,6 +69,7 @@ import org.ehcache.spi.persistence.StateRepository; import org.ehcache.spi.serialization.Serializer; import org.ehcache.spi.serialization.StatefulSerializer; +import org.ehcache.spi.service.OptionalServiceDependencies; import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.spi.service.ServiceDependencies; @@ -598,6 +599,7 @@ public void setInvalidationValve(InvalidationValve valve) { * Provider of {@link ClusteredStore} instances. */ @ServiceDependencies({TimeSourceService.class, ClusteringService.class}) + @OptionalServiceDependencies("org.ehcache.core.spi.service.StatisticsService") public static class Provider extends BaseStoreProvider implements AuthoritativeTier.Provider { private static final Logger LOGGER = LoggerFactory.getLogger(Provider.class); @@ -698,7 +700,7 @@ public void releaseStore(Store resource) { } ClusteredStore clusteredStore = (ClusteredStore) resource; this.clusteringService.releaseServerStoreProxy(clusteredStore.storeProxy, false); - getServiceProvider().getService(StatisticsService.class).cleanForNode(clusteredStore); + getStatisticsService().ifPresent(s -> s.cleanForNode(clusteredStore)); tierOperationStatistics.remove(clusteredStore); } finally { connectLock.unlock(); diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java index aef0dc5113..a141224543 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java @@ -31,7 +31,7 @@ public ClusteredStore.Provider create(final ServiceCreationConfiguration getServiceType() { + public Class getServiceType() { return ClusteredStore.Provider.class; } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java index 21653b939a..51350722c3 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java @@ -17,6 +17,7 @@ package org.ehcache.clustered.client; import org.ehcache.CacheManager; +import org.ehcache.clustered.client.internal.service.DefaultClusteringService; import org.ehcache.clustered.client.internal.store.ClusteredStore; import org.ehcache.clustered.client.service.ClusteringService; import org.ehcache.config.CacheConfiguration; @@ -49,7 +50,7 @@ public void testNonClustered() throws Exception { * Ensure the cluster provider classes are loadable through the ServiceLoader mechanism. */ assertThat(stream(spliterator(ClassLoading.servicesOfType(ServiceFactory.class).iterator(), Long.MAX_VALUE, 0), false).map(f -> f.getServiceType()).collect(Collectors.toList()), - hasItems(ClusteredStore.Provider.class, ClusteringService.class)); + hasItems(ClusteredStore.Provider.class, DefaultClusteringService.class)); CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder( String.class, diff --git a/core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsService.java b/core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsService.java index 8267c2db8b..45c5edcd38 100644 --- a/core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsService.java +++ b/core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsService.java @@ -27,10 +27,11 @@ import org.ehcache.core.spi.store.Store; import org.ehcache.core.statistics.CacheStatistics; import org.ehcache.core.statistics.OperationObserver; +import org.ehcache.core.statistics.OperationStatistic; import org.ehcache.core.statistics.StatisticType; import org.ehcache.core.statistics.ZeroOperationStatistic; -import org.ehcache.spi.service.OptionalServiceDependencies; import org.ehcache.spi.service.Service; +import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.spi.service.ServiceProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,7 +50,7 @@ /** * Default implementation using the statistics calculated by the observers set on the caches. */ -@OptionalServiceDependencies({"org.ehcache.core.spi.service.CacheManagerProviderService"}) +@ServiceDependencies(CacheManagerProviderService.class) public class DefaultStatisticsService implements StatisticsService, CacheManagerListener { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultStatisticsService.class); @@ -57,8 +58,8 @@ public class DefaultStatisticsService implements StatisticsService, CacheManager private final ConcurrentMap cacheStatistics = new ConcurrentHashMap<>(); private volatile InternalCacheManager cacheManager; - private volatile boolean started = false; + @Override public CacheStatistics getCacheStatistics(String cacheName) { CacheStatistics stats = cacheStatistics.get(cacheName); if (stats == null) { @@ -73,7 +74,7 @@ public void registerWithParent(Object toAssociate, Object parent) { } @Override - public , T extends Enum> org.ehcache.core.statistics.OperationStatistic registerStoreStatistics(Store store, String targetName, int tierHeight, String tag, Map> translation, String statisticName) { + public , T extends Enum> OperationStatistic registerStoreStatistics(Store store, String targetName, int tierHeight, String tag, Map> translation, String statisticName) { Class outcomeType = getOutcomeType(translation); @@ -82,10 +83,10 @@ public , T extends Enum> org.ehcache.core.statistics. MappedOperationStatistic operationStatistic = new MappedOperationStatistic<>(store, translation, statisticName, tierHeight, targetName, tag); StatisticsManager.associate(operationStatistic).withParent(store); - org.ehcache.core.statistics.OperationStatistic stat = new DelegatedMappedOperationStatistics<>(operationStatistic); - return stat; + return new DelegatedMappedOperationStatistics<>(operationStatistic); + } else { + return ZeroOperationStatistic.get(); } - return ZeroOperationStatistic.get(); } /** @@ -98,13 +99,12 @@ public , T extends Enum> org.ehcache.core.statistics. */ private static , T extends Enum> Class getOutcomeType(Map> translation) { Map.Entry> first = translation.entrySet().iterator().next(); - Class outcomeType = first.getValue().iterator().next().getDeclaringClass(); - return outcomeType; + return first.getValue().iterator().next().getDeclaringClass(); } @Override - public void deRegisterFromParent(Object toDeassociate, Object parent) { - StatisticsManager.dissociate(toDeassociate).fromParent(parent); + public void deRegisterFromParent(Object toDisassociate, Object parent) { + StatisticsManager.dissociate(toDisassociate).fromParent(parent); } @Override @@ -122,21 +122,13 @@ public > OperationObserver createOperationStatistics(String return new DelegatingOperationObserver<>(operation(outcome).named(name).of(context).tag(tag).build()); } - public boolean isStarted() { - return started; - } - @Override public void start(ServiceProvider serviceProvider) { LOGGER.debug("Starting service"); CacheManagerProviderService cacheManagerProviderService = serviceProvider.getService(CacheManagerProviderService.class); - if (cacheManagerProviderService != null) { - cacheManager = cacheManagerProviderService.getCacheManager(); - cacheManager.registerListener(this); - } - - started = true; + cacheManager = cacheManagerProviderService.getCacheManager(); + cacheManager.registerListener(this); } @Override @@ -144,7 +136,6 @@ public void stop() { LOGGER.debug("Stopping service"); cacheManager.deregisterListener(this); cacheStatistics.clear(); - started = false; } @Override diff --git a/core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsServiceFactory.java b/core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsServiceFactory.java index 905d154157..c88dbdd6c9 100644 --- a/core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsServiceFactory.java +++ b/core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsServiceFactory.java @@ -30,7 +30,7 @@ public StatisticsService create(ServiceCreationConfiguration getServiceType() { - return StatisticsService.class; + public Class getServiceType() { + return DefaultStatisticsService.class; } } diff --git a/core/src/main/java/org/ehcache/core/spi/service/ServiceFactory.java b/core/src/main/java/org/ehcache/core/spi/service/ServiceFactory.java index ae9c873a91..54c1688e3e 100644 --- a/core/src/main/java/org/ehcache/core/spi/service/ServiceFactory.java +++ b/core/src/main/java/org/ehcache/core/spi/service/ServiceFactory.java @@ -61,9 +61,9 @@ default int rank() { T create(ServiceCreationConfiguration configuration); /** - * Queries a {@code ServiceFactory} to know which {@link Service} type it produces. + * Queries a {@code ServiceFactory} to know which concrete {@link Service} type it produces. * - * @return the class of the produced service. + * @return the concrete class of the produced service. */ Class getServiceType(); diff --git a/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java b/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java index 44f630fd7c..63e21e0b75 100644 --- a/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java +++ b/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java @@ -17,9 +17,9 @@ import org.ehcache.core.collections.ConcurrentWeakIdentityHashMap; import org.ehcache.core.spi.service.StatisticsService; +import org.ehcache.spi.service.OptionalServiceDependencies; import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceConfiguration; -import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.spi.service.ServiceProvider; import java.util.Arrays; @@ -27,7 +27,7 @@ import static org.ehcache.core.store.StoreSupport.selectStoreProvider; -@ServiceDependencies({StatisticsService.class}) +@OptionalServiceDependencies("org.ehcache.core.spi.service.StatisticsService") public abstract class AbstractWrapperStoreProvider implements WrapperStore.Provider { private volatile ServiceProvider serviceProvider; @@ -43,7 +43,10 @@ public Store createStore(Store.Configuration storeConfig, Ser Store store = underlyingStoreProvider.createStore(storeConfig, serviceConfigs); Store wrappedStore = wrap(store, storeConfig, serviceConfigs); - serviceProvider.getService(StatisticsService.class).registerWithParent(store, wrappedStore); + StatisticsService statisticsService = serviceProvider.getService(StatisticsService.class); + if (statisticsService != null) { + statisticsService.registerWithParent(store, wrappedStore); + } createdStores.put(wrappedStore, new StoreReference<>(store, underlyingStoreProvider)); return wrappedStore; } diff --git a/core/src/test/java/org/ehcache/core/spi/services/FancyCacheProviderFactory.java b/core/src/test/java/org/ehcache/core/spi/services/FancyCacheProviderFactory.java index e790e16f70..baf0e949ce 100644 --- a/core/src/test/java/org/ehcache/core/spi/services/FancyCacheProviderFactory.java +++ b/core/src/test/java/org/ehcache/core/spi/services/FancyCacheProviderFactory.java @@ -29,7 +29,7 @@ public FancyCacheProvider create(ServiceCreationConfiguration getServiceType() { + public Class getServiceType() { return FancyCacheProvider.class; } } diff --git a/core/src/test/java/org/ehcache/core/spi/services/TestProvidedServiceFactory.java b/core/src/test/java/org/ehcache/core/spi/services/TestProvidedServiceFactory.java index 9b463bbe39..064bd04320 100644 --- a/core/src/test/java/org/ehcache/core/spi/services/TestProvidedServiceFactory.java +++ b/core/src/test/java/org/ehcache/core/spi/services/TestProvidedServiceFactory.java @@ -29,7 +29,7 @@ public TestProvidedService create(ServiceCreationConfiguration getServiceType() { + public Class getServiceType() { return TestProvidedService.class; } } diff --git a/core/src/test/java/org/ehcache/core/spi/services/TestServiceFactory.java b/core/src/test/java/org/ehcache/core/spi/services/TestServiceFactory.java index 386b73c222..df85d34e81 100644 --- a/core/src/test/java/org/ehcache/core/spi/services/TestServiceFactory.java +++ b/core/src/test/java/org/ehcache/core/spi/services/TestServiceFactory.java @@ -29,7 +29,7 @@ public TestService create(ServiceCreationConfiguration configura } @Override - public Class getServiceType() { - return TestService.class; + public Class getServiceType() { + return DefaultTestService.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java b/impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java index 4e5523c33a..add65271c6 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java @@ -32,7 +32,7 @@ public TimeSourceService create(ServiceCreationConfiguration getServiceType() { - return TimeSourceService.class; + public Class getServiceType() { + return DefaultTimeSourceService.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java b/impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java index bb7ca8f6fb..a1eaa43e2f 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java @@ -42,7 +42,12 @@ public ExecutionService create(ServiceCreationConfiguration } @Override - public Class getServiceType() { + public Class getServiceType() { + /* + * XXX : There isn't a unique concrete type returned by this factory + * Currently this isn't a problem since neither of the concrete types + * returned have service depencies. + */ return ExecutionService.class; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java index f39185c277..f70df30c7d 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java @@ -87,8 +87,8 @@ public void releaseWriteBehindLoaderWriter(CacheLoaderWriter cacheLoaderWr } @Override - public Class getServiceType() { - return WriteBehindProvider.class; + public Class getServiceType() { + return Provider.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java b/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java index 222706b55b..bc142ee477 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java @@ -30,7 +30,7 @@ public DefaultDiskResourceService create(final ServiceCreationConfiguration getServiceType() { + public Class getServiceType() { return DefaultDiskResourceService.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java b/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java index 2b3082fe82..dfc91f30b3 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java @@ -36,7 +36,7 @@ public DefaultLocalPersistenceService create(final ServiceCreationConfiguration< } @Override - public Class getServiceType() { - return LocalPersistenceService.class; + public Class getServiceType() { + return DefaultLocalPersistenceService.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java index 1cb0d1d1bc..7f03033ba6 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java @@ -43,8 +43,8 @@ public SizeOfEngineProvider create(ServiceCreationConfiguration getServiceType() { - return SizeOfEngineProvider.class; + public Class getServiceType() { + return DefaultSizeOfEngineProvider.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java index 8e6be51e45..3616eab932 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java @@ -39,7 +39,7 @@ public CopyProvider create(final ServiceCreationConfiguration c } @Override - public Class getServiceType() { - return CopyProvider.class; + public Class getServiceType() { + return DefaultCopyProvider.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java index eaef9911a2..6545a34b7a 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java @@ -28,12 +28,12 @@ public class DefaultCacheEventListenerProviderFactory implements ServiceFactory { @Override - public DefaultCacheEventListenerProvider create(ServiceCreationConfiguration configuration) { + public CacheEventListenerProvider create(ServiceCreationConfiguration configuration) { return new DefaultCacheEventListenerProvider(); } @Override - public Class getServiceType() { - return CacheEventListenerProvider.class; + public Class getServiceType() { + return DefaultCacheEventListenerProvider.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java index b420322cc1..475c7df4a3 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java @@ -29,7 +29,7 @@ public class DefaultCacheLoaderWriterProviderFactory implements ServiceFactory { @Override - public DefaultCacheLoaderWriterProvider create(ServiceCreationConfiguration configuration) { + public CacheLoaderWriterProvider create(ServiceCreationConfiguration configuration) { if (configuration != null && !(configuration instanceof DefaultCacheLoaderWriterProviderConfiguration)) { throw new IllegalArgumentException("Expected a configuration of type DefaultCacheLoaderWriterProviderConfiguration but got " + configuration .getClass() @@ -39,7 +39,7 @@ public DefaultCacheLoaderWriterProvider create(ServiceCreationConfiguration getServiceType() { - return CacheLoaderWriterProvider.class; + public Class getServiceType() { + return DefaultCacheLoaderWriterProvider.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java index a53b27f5bf..e0f74d0bdb 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java @@ -37,8 +37,8 @@ public ResilienceStrategyProvider create(ServiceCreationConfiguration getServiceType() { - return ResilienceStrategyProvider.class; + public Class getServiceType() { + return DefaultResilienceStrategyProvider.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java index fc1a3cd499..19f85eb43a 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java @@ -39,7 +39,7 @@ public DefaultSerializationProvider create(ServiceCreationConfiguration getServiceType() { - return SerializationProvider.class; + public Class getServiceType() { + return DefaultSerializationProvider.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java index 7d23042e2c..d1f91c5681 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java @@ -40,6 +40,7 @@ import org.ehcache.spi.persistence.PersistableResourceService.PersistenceSpaceIdentifier; import org.ehcache.spi.persistence.StateRepository; import org.ehcache.spi.serialization.StatefulSerializer; +import org.ehcache.spi.service.OptionalServiceDependencies; import org.ehcache.spi.service.ServiceProvider; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; @@ -385,7 +386,7 @@ public void releaseStore(Store resource) { try { OffHeapDiskStore offHeapDiskStore = (OffHeapDiskStore)resource; close(offHeapDiskStore); - getServiceProvider().getService(StatisticsService.class).cleanForNode(offHeapDiskStore); + getStatisticsService().ifPresent(s -> s.cleanForNode(offHeapDiskStore)); tierOperationStatistics.remove(offHeapDiskStore); } catch (IOException e) { throw new RuntimeException(e); diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java index 9172596cfb..b7d4d4b8ca 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java @@ -39,7 +39,7 @@ public OffHeapDiskStore.Provider create(ServiceCreationConfiguration getServiceType() { + public Class getServiceType() { return OffHeapDiskStore.Provider.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index 47888a8b18..a1a6423b09 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -61,6 +61,7 @@ import org.ehcache.impl.internal.store.BinaryValueHolder; import org.ehcache.spi.copy.Copier; import org.ehcache.spi.copy.CopyProvider; +import org.ehcache.spi.service.OptionalServiceDependencies; import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.core.spi.store.heap.SizeOfEngine; @@ -1616,6 +1617,8 @@ void fireOnExpirationEvent(K mappedKey, ValueHolder mappedValue, StoreEventSi } @ServiceDependencies({TimeSourceService.class, CopyProvider.class, SizeOfEngineProvider.class}) + @OptionalServiceDependencies("org.ehcache.core.spi.service.Statis" + + "ticsService") public static class Provider extends BaseStoreProvider implements CachingTier.Provider, HigherCachingTier.Provider { private final Map, List>> createdStores = new ConcurrentWeakIdentityHashMap<>(); @@ -1672,7 +1675,7 @@ public void releaseStore(Store resource) { } OnHeapStore onHeapStore = (OnHeapStore)resource; close(onHeapStore); - getServiceProvider().getService(StatisticsService.class).cleanForNode(onHeapStore); + getStatisticsService().ifPresent(s -> s.cleanForNode(onHeapStore)); tierOperationStatistics.remove(onHeapStore); CopyProvider copyProvider = getServiceProvider().getService(CopyProvider.class); diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java index 3a6229396e..bb1fe01943 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java @@ -32,7 +32,7 @@ public OnHeapStore.Provider create(ServiceCreationConfiguration getServiceType() { + public Class getServiceType() { return OnHeapStore.Provider.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java index 0e153e1ddc..acaf26bc75 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java @@ -187,7 +187,7 @@ public void releaseStore(Store resource) { } OffHeapStore offHeapStore = (OffHeapStore) resource; close(offHeapStore); - getServiceProvider().getService(StatisticsService.class).cleanForNode(offHeapStore); + getStatisticsService().ifPresent(s -> s.cleanForNode(offHeapStore)); tierOperationStatistics.remove(offHeapStore); } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java index 800c82a35b..8619fd8a13 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java @@ -32,7 +32,7 @@ public OffHeapStore.Provider create(ServiceCreationConfiguration getServiceType() { + public Class getServiceType() { return OffHeapStore.Provider.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java index 16bb266442..1883026f03 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java @@ -24,6 +24,7 @@ import org.ehcache.core.spi.store.tiering.CachingTier; import org.ehcache.core.spi.store.tiering.HigherCachingTier; import org.ehcache.core.spi.store.tiering.LowerCachingTier; +import org.ehcache.spi.service.OptionalServiceDependencies; import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.spi.service.ServiceDependencies; @@ -208,7 +209,8 @@ public List getConfigurationChangeListeners() } - @ServiceDependencies({HigherCachingTier.Provider.class, LowerCachingTier.Provider.class, StatisticsService.class}) + @ServiceDependencies({HigherCachingTier.Provider.class, LowerCachingTier.Provider.class}) + @OptionalServiceDependencies("org.ehcache.core.spi.service.StatisticsService") public static class Provider implements CachingTier.Provider { private volatile ServiceProvider serviceProvider; private final ConcurrentMap, Map.Entry> providersMap = new ConcurrentWeakIdentityHashMap<>(); @@ -234,8 +236,11 @@ public CachingTier createCachingTier(Store.Configuration stor LowerCachingTier lowerCachingTier = lowerProvider.createCachingTier(storeConfig, serviceConfigs); CompoundCachingTier compoundCachingTier = new CompoundCachingTier<>(higherCachingTier, lowerCachingTier); - serviceProvider.getService(StatisticsService.class).registerWithParent(higherCachingTier, compoundCachingTier); - serviceProvider.getService(StatisticsService.class).registerWithParent(lowerCachingTier, compoundCachingTier); + StatisticsService statisticsService = serviceProvider.getService(StatisticsService.class); + if (statisticsService != null) { + statisticsService.registerWithParent(higherCachingTier, compoundCachingTier); + statisticsService.registerWithParent(lowerCachingTier, compoundCachingTier); + } providersMap.put(compoundCachingTier, new AbstractMap.SimpleEntry<>(higherProvider, lowerProvider)); return compoundCachingTier; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java index b7e33273ec..7fd64e0d3e 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java @@ -30,7 +30,7 @@ public CompoundCachingTier.Provider create(ServiceCreationConfiguration getServiceType() { + public Class getServiceType() { return CompoundCachingTier.Provider.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java index 8f29f4c488..c2b3c0bbe2 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java @@ -27,6 +27,7 @@ import org.ehcache.core.spi.store.events.StoreEventSource; import org.ehcache.core.spi.store.tiering.AuthoritativeTier; import org.ehcache.core.spi.store.tiering.CachingTier; +import org.ehcache.spi.service.OptionalServiceDependencies; import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.spi.service.ServiceDependencies; @@ -392,7 +393,8 @@ private ValueHolder handleStoreAccessException(StoreAccessException ce) throw throw new RuntimeException("Unexpected checked exception wrapped in StoreAccessException", cause); } - @ServiceDependencies({CachingTier.Provider.class, AuthoritativeTier.Provider.class, StatisticsService.class}) + @ServiceDependencies({CachingTier.Provider.class, AuthoritativeTier.Provider.class}) + @OptionalServiceDependencies("org.ehcache.core.spi.service.StatisticsService") public static class Provider implements Store.Provider { private volatile ServiceProvider serviceProvider; @@ -465,8 +467,11 @@ public Store createStore(Configuration storeConfig, ServiceCo AuthoritativeTier authoritativeTier = authoritativeTierProvider.createAuthoritativeTier(storeConfig, configurations); TieredStore store = new TieredStore<>(cachingTier, authoritativeTier); - serviceProvider.getService(StatisticsService.class).registerWithParent(cachingTier, store); - serviceProvider.getService(StatisticsService.class).registerWithParent(authoritativeTier, store); + StatisticsService statisticsService = serviceProvider.getService(StatisticsService.class); + if (statisticsService != null) { + statisticsService.registerWithParent(cachingTier, store); + statisticsService.registerWithParent(authoritativeTier, store); + } registerStore(store, cachingTierProvider, authoritativeTierProvider); return store; } diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java index e009aac754..17bb23a501 100644 --- a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java +++ b/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java @@ -32,7 +32,7 @@ public TieredStore.Provider create(ServiceCreationConfiguration getServiceType() { + public Class getServiceType() { return TieredStore.Provider.class; } } diff --git a/impl/src/main/java/org/ehcache/impl/store/BaseStore.java b/impl/src/main/java/org/ehcache/impl/store/BaseStore.java index 8c698aa4f2..d3971a68d1 100644 --- a/impl/src/main/java/org/ehcache/impl/store/BaseStore.java +++ b/impl/src/main/java/org/ehcache/impl/store/BaseStore.java @@ -24,16 +24,19 @@ import org.ehcache.core.statistics.OperationObserver; import org.ehcache.core.statistics.OperationStatistic; import org.ehcache.core.statistics.ZeroOperationStatistic; +import org.ehcache.spi.service.OptionalServiceDependencies; import org.ehcache.spi.service.Service; -import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.spi.service.ServiceProvider; import java.io.Serializable; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.function.Supplier; +import static java.util.Optional.ofNullable; + /** * Base class to most stores. It provides functionality common to stores in general. A given store implementation is not required to extend * it but the implementor might find it easier to do so. @@ -81,27 +84,31 @@ protected void checkValue(V valueObject) { * @return the created observer */ protected > OperationObserver createObserver(String name, Class outcome, boolean canBeDisabled) { - if(!operationStatisticsEnabled && canBeDisabled) { + if (statisticsService == null || !operationStatisticsEnabled && canBeDisabled) { return ZeroOperationStatistic.get(); + } else { + return statisticsService.createOperationStatistics(name, outcome, getStatisticsTag(), this); } - return statisticsService.createOperationStatistics(name, outcome, getStatisticsTag(), this); } protected void registerStatistic(String name, StatisticType type, Set tags, Supplier valueSupplier) { - statisticsService.registerStatistic(this, name, type, tags, valueSupplier); + if (statisticsService != null) { + statisticsService.registerStatistic(this, name, type, tags, valueSupplier); + } } protected abstract String getStatisticsTag(); - @ServiceDependencies({StatisticsService.class}) + @OptionalServiceDependencies("org.ehcache.core.spi.service.StatisticsService") protected static abstract class BaseStoreProvider implements Store.Provider { private volatile ServiceProvider serviceProvider; protected , T extends Enum> OperationStatistic createTranslatedStatistic(BaseStore store, String statisticName, Map> translation, String targetName) { - StatisticsService statisticsService = serviceProvider.getService(StatisticsService.class); - return statisticsService.registerStoreStatistics(store, targetName, getResourceType().getTierHeight(), store.getStatisticsTag(), translation, statisticName); + return getStatisticsService() + .map(s -> s.registerStoreStatistics(store, targetName, getResourceType().getTierHeight(), store.getStatisticsTag(), translation, statisticName)) + .orElse(ZeroOperationStatistic.get()); } @Override @@ -119,5 +126,9 @@ protected ServiceProvider getServiceProvider() { } protected abstract ResourceType getResourceType(); + + protected Optional getStatisticsService() { + return ofNullable(serviceProvider.getService(StatisticsService.class)); + } } } diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java index 09fa539c49..7c516027cf 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java @@ -62,20 +62,13 @@ public void after() { public void startStopStart() throws Exception { cacheManager.init(); - assertThat(service.isStarted()).isTrue(); - Cache cache = cacheManager.getCache(CACHE, Long.class, String.class); cache.get(2L); assertThat(service.getCacheStatistics(CACHE).getCacheMisses()).isEqualTo(1); cacheManager.close(); - - assertThat(service.isStarted()).isFalse(); - cacheManager.init(); - assertThat(service.isStarted()).isTrue(); - // We expect the stats to be reinitialized after a stop start assertThat(service.getCacheStatistics(CACHE).getCacheMisses()).isEqualTo(0); cache = cacheManager.getCache(CACHE, Long.class, String.class); diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderTest.java b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderTest.java index 99a82a24bb..ebfae715fc 100644 --- a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderTest.java +++ b/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderTest.java @@ -18,17 +18,21 @@ import org.ehcache.config.ResourcePool; import org.ehcache.config.ResourceType; +import org.ehcache.core.internal.statistics.DefaultStatisticsService; +import org.ehcache.core.spi.ServiceLocator; import org.ehcache.core.spi.store.Store; import org.ehcache.impl.internal.util.UnmatchedResourceType; import org.ehcache.spi.service.ServiceConfiguration; import org.junit.Test; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; import static java.util.Collections.EMPTY_LIST; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; /** diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryFactory.java b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryFactory.java index 81256a7c2f..8f2ca11868 100644 --- a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryFactory.java +++ b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryFactory.java @@ -30,8 +30,8 @@ public ManagementRegistryService create(ServiceCreationConfiguration getServiceType() { - return ManagementRegistryService.class; + public Class getServiceType() { + return DefaultManagementRegistryService.class; } } diff --git a/management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsService.java b/management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsService.java index 13d21e5b26..a42566a425 100644 --- a/management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsService.java +++ b/management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsService.java @@ -30,8 +30,8 @@ import org.ehcache.core.statistics.ZeroOperationStatistic; import org.ehcache.management.ExtendedStatisticsService; import org.ehcache.management.registry.LatencyHistogramConfiguration; -import org.ehcache.spi.service.OptionalServiceDependencies; import org.ehcache.spi.service.Service; +import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.spi.service.ServiceProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,7 +60,7 @@ /** * Default implementation using the statistics calculated by the observers set on the caches. */ -@OptionalServiceDependencies({"org.ehcache.core.spi.service.CacheManagerProviderService"}) +@ServiceDependencies(CacheManagerProviderService.class) public class DefaultExtendedStatisticsService implements ExtendedStatisticsService, CacheManagerListener { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultExtendedStatisticsService.class); @@ -94,8 +94,7 @@ public , T extends Enum> org.ehcache.core.statistics. MappedOperationStatistic operationStatistic = new MappedOperationStatistic<>(store, translation, statisticName, tierHeight, targetName, tag); StatisticsManager.associate(operationStatistic).withParent(store); - org.ehcache.core.statistics.OperationStatistic stat = new DelegatedMappedOperationStatistics<>(operationStatistic); - return stat; + return new DelegatedMappedOperationStatistics<>(operationStatistic); } return ZeroOperationStatistic.get(); } @@ -110,13 +109,12 @@ public , T extends Enum> org.ehcache.core.statistics. */ private static , T extends Enum> Class getOutcomeType(Map> translation) { Map.Entry> first = translation.entrySet().iterator().next(); - Class outcomeType = first.getValue().iterator().next().getDeclaringClass(); - return outcomeType; + return first.getValue().iterator().next().getDeclaringClass(); } @Override - public void deRegisterFromParent(Object toDeassociate, Object parent) { - StatisticsManager.dissociate(toDeassociate).fromParent(parent); + public void deRegisterFromParent(Object toDisassociate, Object parent) { + StatisticsManager.dissociate(toDisassociate).fromParent(parent); } @Override @@ -178,11 +176,8 @@ public void start(ServiceProvider serviceProvider) { LOGGER.debug("Starting service"); CacheManagerProviderService cacheManagerProviderService = serviceProvider.getService(CacheManagerProviderService.class); - if (cacheManagerProviderService != null) { - cacheManager = cacheManagerProviderService.getCacheManager(); - cacheManager.registerListener(this); - } - + cacheManager = cacheManagerProviderService.getCacheManager(); + cacheManager.registerListener(this); started = true; } diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java index f6d86c3ce3..a9c506820a 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java @@ -33,6 +33,7 @@ import org.ehcache.core.spi.time.TimeSource; import org.ehcache.core.spi.time.TimeSourceService; import org.ehcache.spi.serialization.StatefulSerializer; +import org.ehcache.spi.service.OptionalServiceDependencies; import org.ehcache.spi.service.ServiceProvider; import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.events.StoreEventSource; @@ -760,6 +761,7 @@ public CreatedStoreRef(final Store.Provider storeProvider, final SoftLockValueCo } @ServiceDependencies({TimeSourceService.class, JournalProvider.class, CopyProvider.class, TransactionManagerProvider.class}) + @OptionalServiceDependencies("org.ehcache.core.spi.service.StatisticsService") public static class Provider implements WrapperStore.Provider { private volatile ServiceProvider serviceProvider; @@ -936,11 +938,14 @@ public Duration getExpiryForUpdate(K key, Supplier> oldSof Store> underlyingStore = underlyingStoreProvider.createStore(underlyingStoreConfig, underlyingServiceConfigs.toArray(new ServiceConfiguration[0])); // create the XA store + StatisticsService statisticsService = serviceProvider.getService(StatisticsService.class); TransactionManagerWrapper transactionManagerWrapper = transactionManagerProvider.getTransactionManagerWrapper(); Store store = new XAStore<>(storeConfig.getKeyType(), storeConfig.getValueType(), underlyingStore, - transactionManagerWrapper, timeSource, journal, uniqueXAResourceId, serviceProvider.getService(StatisticsService.class)); + transactionManagerWrapper, timeSource, journal, uniqueXAResourceId, statisticsService); - serviceProvider.getService(StatisticsService.class).registerWithParent(underlyingStore, store); + if (statisticsService != null) { + statisticsService.registerWithParent(underlyingStore, store); + } // create the softLockSerializer lifecycle helper SoftLockValueCombinedSerializerLifecycleHelper helper = diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java index 42d2eaf1f9..dfd7b9ba2a 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java @@ -32,7 +32,7 @@ public XAStore.Provider create(ServiceCreationConfiguration } @Override - public Class getServiceType() { + public Class getServiceType() { return XAStore.Provider.class; } } diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProvider.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProvider.java index 8024a7b418..9b75bf375b 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProvider.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProvider.java @@ -19,6 +19,7 @@ import org.ehcache.CachePersistenceException; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.spi.persistence.PersistableResourceService; +import org.ehcache.spi.service.OptionalServiceDependencies; import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.spi.service.ServiceProvider; import org.ehcache.spi.serialization.Serializer; @@ -30,7 +31,7 @@ /** * @author Ludovic Orban */ -@ServiceDependencies(DiskResourceService.class) +@OptionalServiceDependencies("org.ehcache.core.spi.service.DiskResourceService") public class DefaultJournalProvider implements JournalProvider { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultJournalProvider.class); @@ -52,14 +53,16 @@ public Journal getJournal(PersistableResourceService.PersistenceSpaceIden if (persistentSpaceId == null) { LOGGER.info("Using transient XAStore journal"); return new TransientJournal<>(); - } - - try { - LOGGER.info("Using persistent XAStore journal"); - FileBasedPersistenceContext persistenceContext = diskResourceService.createPersistenceContextWithin(persistentSpaceId, "XAJournal"); - return new PersistentJournal<>(persistenceContext.getDirectory(), keySerializer); - } catch (CachePersistenceException cpe) { - throw new RuntimeException(cpe); + } else if (diskResourceService == null) { + throw new AssertionError("Null diskResourceService with non-null persistentSpaceId [" + persistentSpaceId + "]"); + } else { + try { + LOGGER.info("Using persistent XAStore journal"); + FileBasedPersistenceContext persistenceContext = diskResourceService.createPersistenceContextWithin(persistentSpaceId, "XAJournal"); + return new PersistentJournal<>(persistenceContext.getDirectory(), keySerializer); + } catch (CachePersistenceException cpe) { + throw new RuntimeException(cpe); + } } } } diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java index 1371fe0cf7..15f777336c 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java @@ -32,7 +32,7 @@ public JournalProvider create(ServiceCreationConfiguration c } @Override - public Class getServiceType() { - return JournalProvider.class; + public Class getServiceType() { + return DefaultJournalProvider.class; } } diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java b/transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java index 27176ae91d..2cbf253513 100644 --- a/transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java +++ b/transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java @@ -44,7 +44,7 @@ public TransactionManagerProvider create(ServiceCreationConfiguration getServiceType() { - return TransactionManagerProvider.class; + public Class getServiceType() { + return LookupTransactionManagerProvider.class; } } diff --git a/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java b/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java index c662f32ab7..81bcae99fb 100644 --- a/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java +++ b/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java @@ -26,7 +26,7 @@ import org.ehcache.core.spi.service.ServiceFactory; import org.ehcache.core.util.ClassLoading; import org.ehcache.transactions.xa.internal.XAStore; -import org.ehcache.transactions.xa.txmgr.provider.TransactionManagerProvider; +import org.ehcache.transactions.xa.txmgr.provider.LookupTransactionManagerProvider; import org.junit.Test; import static java.util.Spliterators.spliterator; @@ -48,7 +48,7 @@ public void testNonXA() throws Exception { * Ensure the XA provider classes are loadable through the ServiceLoader mechanism. */ assertThat(stream(spliterator(ClassLoading.servicesOfType(ServiceFactory.class).iterator(), Long.MAX_VALUE, 0), false).map(s -> s.getServiceType()).collect(toList()), - hasItems(XAStore.Provider.class, TransactionManagerProvider.class)); + hasItems(XAStore.Provider.class, LookupTransactionManagerProvider.class)); CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder( String.class, From 866e8a5855e09a21af2b3e13d1950bdafd2ccdc0 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 8 Jan 2021 14:53:15 -0500 Subject: [PATCH 315/372] Suppress CVE-2020-13956 for pax-url-aether --- config/owasp-supressions.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/config/owasp-supressions.xml b/config/owasp-supressions.xml index 19b18f49f3..5718b311b8 100644 --- a/config/owasp-supressions.xml +++ b/config/owasp-supressions.xml @@ -30,4 +30,10 @@ pkg:maven/junit/junit@4.13.1 CVE-2020-15250 + + + PAX URL Aether repackages httpclient and isn't (yet) fixed + db40edda8b95d880d2a810560fd5e46eb4fa6909 + CVE-2020-13956 + From 5b4c9000bdf635052eef376787f4d1e006b535e4 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 7 Dec 2020 14:29:07 -0500 Subject: [PATCH 316/372] Send server keys with iterator batches --- .../client/internal/store/ClusteredStore.java | 4 +- .../store/CommonServerStoreProxy.java | 9 +- .../store/EventualServerStoreProxy.java | 3 +- .../store/FailedReconnectStoreProxy.java | 4 +- .../store/ReconnectingServerStoreProxy.java | 11 ++- .../store/StrongServerStoreProxy.java | 3 +- .../lock/LockingServerStoreProxyImpl.java | 3 +- .../store/CommonServerStoreProxyTest.java | 23 +++-- .../messages/EhcacheEntityResponse.java | 9 +- .../common/internal/store/ServerStore.java | 3 +- .../common/internal/messages/ChainCodec.java | 30 ++++-- .../internal/messages/ResponseCodec.java | 32 ++++--- .../internal/messages/ServerStoreOpCodec.java | 8 +- .../internal/messages/ChainCodecTest.java | 91 ++++++++++++++++++- .../internal/messages/ResponseCodecTest.java | 18 ++-- .../messages/EhcacheSyncMessageCodec.java | 4 +- .../PassiveReplicationMessageCodec.java | 4 +- .../server/store/ClusterTierActiveEntity.java | 23 ++--- .../store/ClusterTierActiveEntityTest.java | 14 ++- .../clustered/server/ServerStoreImpl.java | 3 +- .../server/offheap/OffHeapChainMap.java | 16 ++-- .../server/offheap/OffHeapServerStore.java | 7 +- .../server/store/ServerStoreTest.java | 15 +-- .../server/store/impl/ReferenceStoreImpl.java | 9 +- .../java/org/ehcache/clustered/Matchers.java | 15 +++ 25 files changed, 248 insertions(+), 113 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index 7e79077aa4..e722a4edcb 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -407,7 +407,7 @@ public StoreEventSource getStoreEventSource() { @Override public Iterator>> iterator() { try { - java.util.Iterator chainIterator = storeProxy.iterator(); + java.util.Iterator> chainIterator = storeProxy.iterator(); return new Iterator>>() { @@ -429,7 +429,7 @@ public Cache.Entry> next() { private java.util.Iterator>> nextChain() { while (chainIterator.hasNext()) { - Map> chainContents = resolver.resolveAll(chainIterator.next(), timeSource.getTimeMillis()); + Map> chainContents = resolver.resolveAll(chainIterator.next().getValue(), timeSource.getTimeMillis()); if (!chainContents.isEmpty()) { return chainContents.entrySet().stream().map(entry -> { K key = entry.getKey(); diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java index 97d519346b..81ef2c294c 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java @@ -39,6 +39,7 @@ import java.nio.ByteBuffer; import java.util.Iterator; +import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeoutException; @@ -198,16 +199,16 @@ public void clear() throws TimeoutException { } @Override - public Iterator iterator() throws TimeoutException { + public Iterator> iterator() throws TimeoutException { EhcacheEntityResponse.IteratorBatch iteratorBatch = openIterator(); if (iteratorBatch.isLast()) { return iteratorBatch.getChains().iterator(); } else { UUID iteratorId = iteratorBatch.getIdentity(); - return new Iterator() { + return new Iterator>() { private boolean lastBatch = false; - private Iterator batch = iteratorBatch.getChains().iterator(); + private Iterator> batch = iteratorBatch.getChains().iterator(); @Override public boolean hasNext() { @@ -215,7 +216,7 @@ public boolean hasNext() { } @Override - public Chain next() { + public Map.Entry next() { if (lastBatch || batch.hasNext()) { return batch.next(); } else { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java index 093cf1aa6e..f5c46b05e3 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java @@ -19,6 +19,7 @@ import java.nio.ByteBuffer; import java.util.Iterator; +import java.util.Map; import java.util.concurrent.TimeoutException; public class EventualServerStoreProxy implements ServerStoreProxy { @@ -70,7 +71,7 @@ public void clear() throws TimeoutException { } @Override - public Iterator iterator() throws TimeoutException { + public Iterator> iterator() throws TimeoutException { return delegate.iterator(); } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/FailedReconnectStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/FailedReconnectStoreProxy.java index 48a70066d3..430ef8a71b 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/FailedReconnectStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/FailedReconnectStoreProxy.java @@ -21,7 +21,7 @@ import java.nio.ByteBuffer; import java.util.Iterator; -import java.util.concurrent.TimeoutException; +import java.util.Map; public class FailedReconnectStoreProxy implements LockingServerStoreProxy { private final Throwable failure; @@ -63,7 +63,7 @@ public void clear() { } @Override - public Iterator iterator() { + public Iterator> iterator() { throw new RuntimeException("Cache " + getCacheId() + " failed reconnecting to cluster", failure); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java index 7c1819df4d..27e19cadac 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java @@ -25,6 +25,7 @@ import java.nio.ByteBuffer; import java.util.Iterator; +import java.util.Map; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; @@ -105,7 +106,7 @@ public void clear() throws TimeoutException { } @Override - public Iterator iterator() throws TimeoutException { + public Iterator> iterator() throws TimeoutException { return onStoreProxy(LockingServerStoreProxy::iterator); } @@ -192,7 +193,7 @@ public void clear() { } @Override - public Iterator iterator() { + public Iterator> iterator() { throw new ReconnectInProgressException(); } @@ -210,12 +211,12 @@ public void unlock(long key, boolean localonly) { private LockingServerStoreProxy unsupportedLocking(ServerStoreProxy serverStoreProxy) { return new LockingServerStoreProxy() { @Override - public ChainEntry lock(long hash) throws TimeoutException { + public ChainEntry lock(long hash) { throw new UnsupportedOperationException("Lock ops are not supported"); } @Override - public void unlock(long hash, boolean localonly) throws TimeoutException { + public void unlock(long hash, boolean localonly) { throw new UnsupportedOperationException("Lock ops are not supported"); } @@ -260,7 +261,7 @@ public void clear() throws TimeoutException { } @Override - public Iterator iterator() throws TimeoutException { + public Iterator> iterator() throws TimeoutException { return serverStoreProxy.iterator(); } }; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java index a98735b31b..571ce56c6f 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java @@ -24,6 +24,7 @@ import java.nio.ByteBuffer; import java.time.Duration; import java.util.Iterator; +import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; @@ -240,7 +241,7 @@ public void clear() throws TimeoutException { } @Override - public Iterator iterator() throws TimeoutException { + public Iterator> iterator() throws TimeoutException { return delegate.iterator(); } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java index df8130aee7..923d4926e3 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java @@ -21,6 +21,7 @@ import java.nio.ByteBuffer; import java.util.Iterator; +import java.util.Map; import java.util.concurrent.TimeoutException; public class LockingServerStoreProxyImpl implements LockingServerStoreProxy { @@ -110,7 +111,7 @@ public void clear() throws TimeoutException { } @Override - public Iterator iterator() throws TimeoutException { + public Iterator> iterator() throws TimeoutException { return storeProxy.iterator(); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java index ecf7984dad..3677e8781c 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java @@ -29,6 +29,7 @@ import java.nio.ByteBuffer; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.NoSuchElementException; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; @@ -398,7 +399,7 @@ public void testEmptyStoreIteratorIsEmpty() throws Exception { ClusterTierClientEntity clientEntity = createClientEntity("testEmptyStoreIteratorIsEmpty", Consistency.EVENTUAL, true); CommonServerStoreProxy serverStoreProxy = new CommonServerStoreProxy("testEmptyStoreIteratorIsEmpty", clientEntity, mock(ServerCallback.class)); - Iterator iterator = serverStoreProxy.iterator(); + Iterator> iterator = serverStoreProxy.iterator(); assertThat(iterator.hasNext(), is(false)); try { @@ -416,10 +417,12 @@ public void testSingleChainIterator() throws Exception { serverStoreProxy.append(1L, createPayload(42L)); - Iterator iterator = serverStoreProxy.iterator(); + Iterator> iterator = serverStoreProxy.iterator(); assertThat(iterator.hasNext(), is(true)); - assertThat(iterator.next(), hasPayloads(42L)); + Map.Entry next = iterator.next(); + assertThat(next.getKey(), is(1L)); + assertThat(next.getValue(), hasPayloads(42L)); assertThat(iterator.hasNext(), is(false)); try { iterator.next(); @@ -437,10 +440,12 @@ public void testSingleChainMultipleElements() throws Exception { serverStoreProxy.append(1L, createPayload(42L)); serverStoreProxy.append(1L, createPayload(43L)); - Iterator iterator = serverStoreProxy.iterator(); + Iterator> iterator = serverStoreProxy.iterator(); assertThat(iterator.hasNext(), is(true)); - assertThat(iterator.next(), hasPayloads(42L, 43L)); + Map.Entry next = iterator.next(); + assertThat(next.getKey(), is(1L)); + assertThat(next.getValue(), hasPayloads(42L, 43L)); assertThat(iterator.hasNext(), CoreMatchers.is(false)); try { iterator.next(); @@ -458,23 +463,23 @@ public void testMultipleChains() throws Exception { serverStoreProxy.append(1L, createPayload(42L)); serverStoreProxy.append(2L, createPayload(43L)); - Iterator iterator = serverStoreProxy.iterator(); + Iterator> iterator = serverStoreProxy.iterator(); Matcher chainOne = hasPayloads(42L); Matcher chainTwo = hasPayloads(43L); assertThat(iterator.hasNext(), CoreMatchers.is(true)); - Chain next = iterator.next(); + Chain next = iterator.next().getValue(); assertThat(next, either(chainOne).or(chainTwo)); if (chainOne.matches(next)) { assertThat(iterator.hasNext(), is(true)); - assertThat(iterator.next(), is(chainTwo)); + assertThat(iterator.next().getValue(), is(chainTwo)); assertThat(iterator.hasNext(), is(false)); } else { assertThat(iterator.hasNext(), is(true)); - assertThat(iterator.next(), is(chainOne)); + assertThat(iterator.next().getValue(), is(chainOne)); assertThat(iterator.hasNext(), is(false)); } diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java index 08653adfca..61dbfcb597 100644 --- a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java +++ b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java @@ -23,6 +23,7 @@ import java.nio.ByteBuffer; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; @@ -342,17 +343,17 @@ public EhcacheResponseType getResponseType() { } } - public static IteratorBatch iteratorBatchResponse(UUID id, List chains, boolean last) { + public static IteratorBatch iteratorBatchResponse(UUID id, List> chains, boolean last) { return new IteratorBatch(id, chains, last); } public static class IteratorBatch extends EhcacheEntityResponse { private final UUID id; - private final List chains; + private final List> chains; private final boolean last; - public IteratorBatch(UUID id, List chains, boolean last) { + private IteratorBatch(UUID id, List> chains, boolean last) { this.id = id; this.chains = chains; this.last = last; @@ -367,7 +368,7 @@ public boolean isLast() { return last; } - public List getChains() { + public List> getChains() { return chains; } diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java index 5e232bca9a..ab62818b89 100644 --- a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java +++ b/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java @@ -18,6 +18,7 @@ import java.nio.ByteBuffer; import java.util.Iterator; +import java.util.Map; import java.util.concurrent.TimeoutException; /** @@ -135,5 +136,5 @@ public interface ServerStore { * * @return an chain iterator. */ - Iterator iterator() throws TimeoutException; + Iterator> iterator() throws TimeoutException; } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java index 606ec6e41a..b66ba41de7 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java @@ -27,8 +27,10 @@ import org.terracotta.runnel.encoding.StructEncoder; import java.nio.ByteBuffer; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.List; +import java.util.Map; import static org.ehcache.clustered.common.internal.util.ChainBuilder.chainFromList; @@ -47,16 +49,21 @@ private ChainCodec() { .structs("elements", 10, ELEMENT_STRUCT) .build(); - public static byte[] encode(Chain chain) { + public static final Struct CHAIN_ENTRY_STRUCT = StructBuilder.newStructBuilder() + .int64("key", 5) + .structs("elements", 10, ELEMENT_STRUCT) + .build(); + + public static byte[] encodeChain(Chain chain) { StructEncoder encoder = CHAIN_STRUCT.encoder(); - encode(encoder, chain); + encodeChain(encoder, chain); ByteBuffer byteBuffer = encoder.encode(); return byteBuffer.array(); } - public static void encode(StructEncoder encoder, Chain chain) { + public static void encodeChain(StructEncoder encoder, Chain chain) { StructArrayEncoder> elementsEncoder = encoder.structs("elements"); for (Element element : chain) { StructEncoder elementEncoder = elementsEncoder.add(); @@ -69,12 +76,17 @@ public static void encode(StructEncoder encoder, Chain chain) { elementsEncoder.end(); } - public static Chain decode(byte[] payload) { + public static void encodeChainEntry(StructEncoder encoder, Map.Entry chain) { + encoder.int64("key", chain.getKey()); + encodeChain(encoder, chain.getValue()); + } + + public static Chain decodeChain(byte[] payload) { StructDecoder decoder = CHAIN_STRUCT.decoder(ByteBuffer.wrap(payload)); - return decode(decoder); + return decodeChain(decoder); } - public static Chain decode(StructDecoder decoder) { + public static Chain decodeChain(StructDecoder decoder) { StructArrayDecoder> elementsDecoder = decoder.structs("elements"); final List elements = new ArrayList<>(); @@ -110,4 +122,10 @@ public String toString() { return chainFromList(elements); } + + public static Map.Entry decodeChainEntry(StructDecoder decoder) { + Long key = decoder.int64("key"); + Chain elements = decodeChain(decoder); + return new AbstractMap.SimpleImmutableEntry<>(key, elements); + } } diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java index dce4f73493..d082a095c6 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; @@ -41,6 +42,7 @@ import static org.ehcache.clustered.common.internal.messages.BaseCodec.EHCACHE_RESPONSE_TYPES_ENUM_MAPPING; import static org.ehcache.clustered.common.internal.messages.BaseCodec.RESPONSE_TYPE_FIELD_INDEX; import static org.ehcache.clustered.common.internal.messages.BaseCodec.RESPONSE_TYPE_FIELD_NAME; +import static org.ehcache.clustered.common.internal.messages.ChainCodec.CHAIN_ENTRY_STRUCT; import static org.ehcache.clustered.common.internal.messages.ChainCodec.CHAIN_STRUCT; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.allInvalidationDone; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.clientInvalidateAll; @@ -125,7 +127,7 @@ public class ResponseCodec { private static final Struct ITERATOR_BATCH_STRUCT = newStructBuilder() .enm(RESPONSE_TYPE_FIELD_NAME, RESPONSE_TYPE_FIELD_INDEX, EHCACHE_RESPONSE_TYPES_ENUM_MAPPING) .string("id", 20) - .structs("chains", 30, CHAIN_STRUCT) + .structs("chains", 30, CHAIN_ENTRY_STRUCT) .bool("last", 40) .build(); @@ -145,7 +147,7 @@ public byte[] encode(EhcacheEntityResponse response) { final EhcacheEntityResponse.GetResponse getResponse = (EhcacheEntityResponse.GetResponse)response; return GET_RESPONSE_STRUCT.encoder() .enm(RESPONSE_TYPE_FIELD_NAME, getResponse.getResponseType()) - .struct(CHAIN_FIELD, getResponse.getChain(), ChainCodec::encode) + .struct(CHAIN_FIELD, getResponse.getChain(), ChainCodec::encodeChain) .encode().array(); case HASH_INVALIDATION_DONE: { EhcacheEntityResponse.HashInvalidationDone hashInvalidationDone = (EhcacheEntityResponse.HashInvalidationDone) response; @@ -180,7 +182,7 @@ public byte[] encode(EhcacheEntityResponse response) { return SERVER_APPEND_RESPONSE_STRUCT.encoder() .enm(RESPONSE_TYPE_FIELD_NAME, serverAppend.getResponseType()) .byteBuffer(APPENDED_FIELD, serverAppend.getAppended()) - .struct(CHAIN_FIELD, serverAppend.getBeforeAppend(), ChainCodec::encode) + .struct(CHAIN_FIELD, serverAppend.getBeforeAppend(), ChainCodec::encodeChain) .encode().array(); } case SERVER_INVALIDATE_HASH: { @@ -189,7 +191,7 @@ public byte[] encode(EhcacheEntityResponse response) { .enm(RESPONSE_TYPE_FIELD_NAME, serverInvalidateHash.getResponseType()) .int64(KEY_FIELD, serverInvalidateHash.getKey()); if (serverInvalidateHash.getEvictedChain() != null) { - encoder.struct(CHAIN_FIELD, serverInvalidateHash.getEvictedChain(), ChainCodec::encode); + encoder.struct(CHAIN_FIELD, serverInvalidateHash.getEvictedChain(), ChainCodec::encodeChain); } return encoder.encode().array(); } @@ -217,14 +219,14 @@ public byte[] encode(EhcacheEntityResponse response) { return RESOLVE_REQUEST_RESPONSE_STRUCT.encoder() .enm(RESPONSE_TYPE_FIELD_NAME, resolve.getResponseType()) .int64(KEY_FIELD, resolve.getKey()) - .struct(CHAIN_FIELD, resolve.getChain(), ChainCodec::encode) + .struct(CHAIN_FIELD, resolve.getChain(), ChainCodec::encodeChain) .encode().array(); } case LOCK_SUCCESS: { EhcacheEntityResponse.LockSuccess lockSuccess = (EhcacheEntityResponse.LockSuccess) response; return LOCK_RESPONSE_STRUCT.encoder() .enm(RESPONSE_TYPE_FIELD_NAME, lockSuccess.getResponseType()) - .struct(CHAIN_FIELD, lockSuccess.getChain(), ChainCodec::encode) + .struct(CHAIN_FIELD, lockSuccess.getChain(), ChainCodec::encodeChain) .encode().array(); } case LOCK_FAILURE: { @@ -238,7 +240,7 @@ public byte[] encode(EhcacheEntityResponse response) { return ITERATOR_BATCH_STRUCT.encoder() .enm(RESPONSE_TYPE_FIELD_NAME, iteratorBatch.getResponseType()) .string("id", iteratorBatch.getIdentity().toString()) - .structs("chains", iteratorBatch.getChains(), ChainCodec::encode) + .structs("chains", iteratorBatch.getChains(), ChainCodec::encodeChainEntry) .bool("last", iteratorBatch.isLast()) .encode().array(); } @@ -271,7 +273,7 @@ public EhcacheEntityResponse decode(byte[] payload) { return failure(exception.withClientStackTrace()); case GET_RESPONSE: decoder = GET_RESPONSE_STRUCT.decoder(buffer); - return getResponse(ChainCodec.decode(decoder.struct(CHAIN_FIELD))); + return getResponse(ChainCodec.decodeChain(decoder.struct(CHAIN_FIELD))); case HASH_INVALIDATION_DONE: { decoder = HASH_INVALIDATION_DONE_RESPONSE_STRUCT.decoder(buffer); long key = decoder.int64(KEY_FIELD); @@ -284,7 +286,7 @@ public EhcacheEntityResponse decode(byte[] payload) { decoder = SERVER_APPEND_RESPONSE_STRUCT.decoder(buffer); ByteBuffer appended = decoder.byteBuffer(APPENDED_FIELD); StructDecoder> chainDecoder = decoder.struct(CHAIN_FIELD); - Chain chain = chainDecoder == null ? null : ChainCodec.decode(chainDecoder); + Chain chain = chainDecoder == null ? null : ChainCodec.decodeChain(chainDecoder); return serverAppend(appended, chain); } case CLIENT_INVALIDATE_HASH: { @@ -302,7 +304,7 @@ public EhcacheEntityResponse decode(byte[] payload) { decoder = SERVER_INVALIDATE_HASH_RESPONSE_STRUCT.decoder(buffer); long key = decoder.int64(KEY_FIELD); StructDecoder> chainDecoder = decoder.struct(CHAIN_FIELD); - Chain evictedChain = chainDecoder == null ? null : ChainCodec.decode(chainDecoder); + Chain evictedChain = chainDecoder == null ? null : ChainCodec.decodeChain(chainDecoder); return serverInvalidateHash(key, evictedChain); } case MAP_VALUE: { @@ -322,12 +324,12 @@ public EhcacheEntityResponse decode(byte[] payload) { case RESOLVE_REQUEST: { decoder = RESOLVE_REQUEST_RESPONSE_STRUCT.decoder(buffer); long key = decoder.int64(KEY_FIELD); - Chain chain = ChainCodec.decode(decoder.struct(CHAIN_FIELD)); + Chain chain = ChainCodec.decodeChain(decoder.struct(CHAIN_FIELD)); return resolveRequest(key, chain); } case LOCK_SUCCESS: { decoder = LOCK_RESPONSE_STRUCT.decoder(buffer); - Chain chain = ChainCodec.decode(decoder.struct(CHAIN_FIELD)); + Chain chain = ChainCodec.decodeChain(decoder.struct(CHAIN_FIELD)); return new EhcacheEntityResponse.LockSuccess(chain); } case LOCK_FAILURE: { @@ -337,12 +339,12 @@ public EhcacheEntityResponse decode(byte[] payload) { decoder = ITERATOR_BATCH_STRUCT.decoder(buffer); UUID id = UUID.fromString(decoder.string("id")); StructArrayDecoder> chainsDecoder = decoder.structs("chains"); - List chains = new ArrayList<>(chainsDecoder.length()); + List> chains = new ArrayList<>(chainsDecoder.length()); while (chainsDecoder.hasNext()) { - chains.add(ChainCodec.decode(chainsDecoder.next())); + chains.add(ChainCodec.decodeChainEntry(chainsDecoder.next())); } boolean last = decoder.bool("last"); - return new EhcacheEntityResponse.IteratorBatch(id, chains, last); + return EhcacheEntityResponse.iteratorBatchResponse(id, chains, last); } default: diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java index ca5b0ae9ff..cd38dc0310 100644 --- a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java +++ b/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java @@ -128,8 +128,8 @@ public byte[] encode(ServerStoreOpMessage message) { final ReplaceAtHeadMessage replaceAtHeadMessage = (ReplaceAtHeadMessage) message; return encodeMandatoryFields(REPLACE_MESSAGE_STRUCT, message) .int64(KEY_FIELD, replaceAtHeadMessage.getKey()) - .struct("expect", replaceAtHeadMessage.getExpect(), ChainCodec::encode) - .struct("update", replaceAtHeadMessage.getUpdate(), ChainCodec::encode) + .struct("expect", replaceAtHeadMessage.getExpect(), ChainCodec::encodeChain) + .struct("update", replaceAtHeadMessage.getUpdate(), ChainCodec::encodeChain) .encode().array(); case CLIENT_INVALIDATION_ACK: ClientInvalidationAck clientInvalidationAckMessage = (ClientInvalidationAck) message; @@ -199,8 +199,8 @@ public EhcacheEntityMessage decode(EhcacheMessageType opCode, ByteBuffer message case REPLACE: { StructDecoder decoder = REPLACE_MESSAGE_STRUCT.decoder(messageBuffer); Long key = decoder.int64(KEY_FIELD); - Chain expect = ChainCodec.decode(decoder.struct("expect")); - Chain update = ChainCodec.decode(decoder.struct("update")); + Chain expect = ChainCodec.decodeChain(decoder.struct("expect")); + Chain update = ChainCodec.decodeChain(decoder.struct("update")); return new ReplaceAtHeadMessage(key, expect, update); } case CLIENT_INVALIDATION_ACK: { diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java index 8021e729e5..7fa0a7b0ba 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java @@ -19,8 +19,12 @@ import org.ehcache.clustered.common.internal.store.Chain; import org.ehcache.clustered.common.internal.store.Element; import org.junit.Test; +import org.terracotta.runnel.encoding.StructEncoder; +import java.nio.ByteBuffer; +import java.util.AbstractMap.SimpleImmutableEntry; import java.util.Iterator; +import java.util.Map; import static org.ehcache.clustered.ChainUtils.chainOf; import static org.ehcache.clustered.ChainUtils.createPayload; @@ -42,7 +46,7 @@ public void testChainWithSingleElement() { assertThat(readPayload(chainIterator.next().getPayload()), is(1L)); assertThat(chainIterator.hasNext(), is(false)); - Chain decoded = ChainCodec.decode(ChainCodec.encode(chain)); + Chain decoded = ChainCodec.decodeChain(ChainCodec.encodeChain(chain)); assertThat(decoded.isEmpty(), is(false)); chainIterator = decoded.iterator(); @@ -59,7 +63,7 @@ public void testChainWithSingleSequencedElement() { assertThat(readPayload(chainIterator.next().getPayload()), is(1L)); assertThat(chainIterator.hasNext(), is(false)); - Chain decoded = ChainCodec.decode(ChainCodec.encode(chain)); + Chain decoded = ChainCodec.decodeChain(ChainCodec.encodeChain(chain)); assertThat(decoded.isEmpty(), is(false)); chainIterator = decoded.iterator(); @@ -76,7 +80,7 @@ public void testChainWithMultipleElements() { assertThat(chain.isEmpty(), is(false)); assertThat(chain, hasPayloads(1L, 2L, 3L)); - Chain decoded = ChainCodec.decode(ChainCodec.encode(chain)); + Chain decoded = ChainCodec.decodeChain(ChainCodec.encodeChain(chain)); assertThat(decoded.isEmpty(), is(false)); assertThat(decoded, hasPayloads(1L, 2L, 3L)); @@ -89,7 +93,7 @@ public void testChainWithMultipleSequencedElements() { assertThat(chain.isEmpty(), is(false)); assertThat(chain, hasPayloads(1L, 2L, 3L)); - Chain decoded = ChainCodec.decode(ChainCodec.encode(chain)); + Chain decoded = ChainCodec.decodeChain(ChainCodec.encodeChain(chain)); assertThat(decoded.isEmpty(), is(false)); assertThat(decoded, hasPayloads(1L, 2L, 3L)); @@ -99,8 +103,85 @@ public void testChainWithMultipleSequencedElements() { @Test public void testEmptyChain() { - Chain decoded = ChainCodec.decode(ChainCodec.encode(chainOf())); + Chain decoded = ChainCodec.decodeChain(ChainCodec.encodeChain(chainOf())); assertThat(decoded.isEmpty(), is(true)); } + + @Test + public void testChainEntryWithSingleElement() { + SimpleImmutableEntry entry = new SimpleImmutableEntry<>(42L, chainOf(createPayload(1L))); + StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); + ChainCodec.encodeChainEntry(encoder, entry); + + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); + + + assertThat(decoded.getKey(), is(42L)); + assertThat(decoded.getValue().isEmpty(), is(false)); + Iterator chainIterator = decoded.getValue().iterator(); + assertThat(readPayload(chainIterator.next().getPayload()), is(1L)); + assertThat(chainIterator.hasNext(), is(false)); + } + + @Test + public void testChainEntryWithSingleSequencedElement() { + Chain chain = sequencedChainOf(createPayload(1L)); + SimpleImmutableEntry entry = new SimpleImmutableEntry<>(43L, chain); + StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); + ChainCodec.encodeChainEntry(encoder, entry); + + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); + + assertThat(decoded.getKey(), is(43L)); + assertThat(decoded.getValue().isEmpty(), is(false)); + Iterator chainIterator = decoded.getValue().iterator(); + assertThat(readPayload(chainIterator.next().getPayload()), is(1L)); + assertThat(chainIterator.hasNext(), is(false)); + + assertThat(decoded.getValue(), sameSequenceAs(chain)); + } + + @Test + public void testChainEntryWithMultipleElements() { + Chain chain = chainOf(createPayload(1L), createPayload(2L), createPayload(3L)); + SimpleImmutableEntry entry = new SimpleImmutableEntry<>(44L, chain); + StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); + ChainCodec.encodeChainEntry(encoder, entry); + + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); + + assertThat(decoded.getKey(), is(44L)); + assertThat(decoded.getValue().isEmpty(), is(false)); + assertThat(decoded.getValue(), hasPayloads(1L, 2L, 3L)); + } + + @Test + public void testChainEntryWithMultipleSequencedElements() { + Chain chain = sequencedChainOf(createPayload(1L), createPayload(2L), createPayload(3L)); + SimpleImmutableEntry entry = new SimpleImmutableEntry<>(45L, chain); + StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); + ChainCodec.encodeChainEntry(encoder, entry); + + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); + + assertThat(decoded.getKey(), is(45L)); + assertThat(decoded.getValue().isEmpty(), is(false)); + assertThat(decoded.getValue(), hasPayloads(1L, 2L, 3L)); + + assertThat(decoded.getValue(), sameSequenceAs(chain)); + } + + @Test + public void testEmptyChainEntry() { + Chain chain = chainOf(); + SimpleImmutableEntry entry = new SimpleImmutableEntry<>(46L, chain); + StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); + ChainCodec.encodeChainEntry(encoder, entry); + + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); + + assertThat(decoded.getKey(), is(46L)); + assertThat(decoded.getValue().isEmpty(), is(true)); + } } diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java index f983e37faf..967a263def 100644 --- a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java +++ b/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java @@ -21,16 +21,17 @@ import org.hamcrest.Matchers; import org.junit.Test; +import java.util.AbstractMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; +import static java.util.Arrays.asList; import static org.ehcache.clustered.ChainUtils.chainOf; import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.Matchers.hasPayloads; -import static java.util.Arrays.asList; -import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.allInvalidationDone; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.clientInvalidateAll; import static org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse.clientInvalidateHash; @@ -200,19 +201,18 @@ public void testLockResponse() { @Test public void testIteratorBatchResponse() { UUID uuid = UUID.randomUUID(); - List chains = asList( - chainOf(createPayload(1L), createPayload(10L)), - chainOf(createPayload(2L), createPayload(20L)) - ); - EhcacheEntityResponse.IteratorBatch iteratorBatch = new EhcacheEntityResponse.IteratorBatch(uuid, chains, true); + List> chains = asList( + new AbstractMap.SimpleImmutableEntry<>(1L, chainOf(createPayload(1L), createPayload(10L))), + new AbstractMap.SimpleImmutableEntry<>(2L, chainOf(createPayload(2L), createPayload(20L)))); + EhcacheEntityResponse.IteratorBatch iteratorBatch = EhcacheEntityResponse.iteratorBatchResponse(uuid, chains, true); byte[] encoded = RESPONSE_CODEC.encode(iteratorBatch); EhcacheEntityResponse.IteratorBatch batchDecoded = (EhcacheEntityResponse.IteratorBatch) RESPONSE_CODEC.decode(encoded); assertThat(batchDecoded.getResponseType(), is(EhcacheResponseType.ITERATOR_BATCH)); assertThat(batchDecoded.getIdentity(), is(uuid)); - assertThat(batchDecoded.getChains().get(0), hasPayloads(1L, 10L)); - assertThat(batchDecoded.getChains().get(1), hasPayloads(2L, 20L)); + assertThat(batchDecoded.getChains().get(0).getValue(), hasPayloads(1L, 10L)); + assertThat(batchDecoded.getChains().get(1).getValue(), hasPayloads(2L, 20L)); assertThat(batchDecoded.isLast(), is(true)); } diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java index efdaa00555..dd4d260f83 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java @@ -180,7 +180,7 @@ private byte[] encodeDataSync(EhcacheDataSyncMessage syncMessage) { encoder.structs(CHAIN_MAP_ENTRIES_SUB_STRUCT, syncMessage.getChainMap().entrySet(), (entryEncoder, entry) -> { entryEncoder.int64(KEY_FIELD, entry.getKey()); - entryEncoder.struct(CHAIN_FIELD, entry.getValue(), ChainCodec::encode); + entryEncoder.struct(CHAIN_FIELD, entry.getValue(), ChainCodec::encodeChain); }); return encoder.encode().array(); } @@ -273,7 +273,7 @@ private Map decodeChainMapEntries(StructDecoder decoder) { StructDecoder entryDecoder = entriesDecoder.next(); Long key = entryDecoder.int64(KEY_FIELD); StructDecoder chainDecoder = entryDecoder.struct(CHAIN_FIELD); - Chain chain = ChainCodec.decode(chainDecoder); + Chain chain = ChainCodec.decodeChain(chainDecoder); chainMap.put(key, chain); entryDecoder.end(); } diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java index b8f49381c9..4099ea4ddb 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java @@ -89,7 +89,7 @@ private byte[] encodeChainReplicationMessage(PassiveReplicationMessage.ChainRepl .int64(CLIENT_ID_FIELD, message.getClientId()) .int64(OLDEST_TRANSACTION_ID_FIELD, message.getOldestTransactionId()) .int64(KEY_FIELD, message.getKey()) - .struct(CHAIN_FIELD, message.getChain(), ChainCodec::encode) + .struct(CHAIN_FIELD, message.getChain(), ChainCodec::encodeChain) .encode().array(); } @@ -128,7 +128,7 @@ private PassiveReplicationMessage.ChainReplicationMessage decodeChainReplication Long oldestTransactionId = decoder.int64(OLDEST_TRANSACTION_ID_FIELD); Long key = decoder.int64(KEY_FIELD); - Chain chain = ChainCodec.decode(decoder.struct(CHAIN_FIELD)); + Chain chain = ChainCodec.decodeChain(decoder.struct(CHAIN_FIELD)); return new PassiveReplicationMessage.ChainReplicationMessage(key, chain, currentTransactionId, oldestTransactionId, clientId); } diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java index 97d19f8746..e37db805cd 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java @@ -85,6 +85,7 @@ import org.terracotta.entity.StateDumpCollector; import java.nio.ByteBuffer; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -168,7 +169,7 @@ public class ClusterTierActiveEntity implements ActiveServerEntity inflightInvalidations; private final Set eventListeners = new HashSet<>(); // accesses are synchronized on eventListeners itself private final Map connectedClients = new ConcurrentHashMap<>(); - private final Map>> liveIterators = new ConcurrentHashMap<>(); + private final Map>>> liveIterators = new ConcurrentHashMap<>(); private final int chainCompactionLimit; private final ServerLockManager lockManager; @@ -516,11 +517,11 @@ private EhcacheEntityResponse invokeServerStoreOperation(InvokeContext context, case ITERATOR_OPEN: { IteratorOpenMessage iteratorOpenMessage = (IteratorOpenMessage) message; try { - Iterator iterator = cacheStore.iterator(); - List batch = iteratorBatch(iterator, iteratorOpenMessage.getBatchSize()); + Iterator> iterator = cacheStore.iterator(); + List> batch = iteratorBatch(iterator, iteratorOpenMessage.getBatchSize()); if (iterator.hasNext()) { - Map> liveIterators = this.liveIterators.computeIfAbsent(clientDescriptor, client -> new ConcurrentHashMap<>()); + Map>> liveIterators = this.liveIterators.computeIfAbsent(clientDescriptor, client -> new ConcurrentHashMap<>()); UUID id; do { id = UUID.randomUUID(); @@ -549,11 +550,11 @@ private EhcacheEntityResponse invokeServerStoreOperation(InvokeContext context, IteratorAdvanceMessage iteratorAdvanceMessage = (IteratorAdvanceMessage) message; UUID id = iteratorAdvanceMessage.getIdentity(); - Iterator iterator = liveIterators.getOrDefault(clientDescriptor, emptyMap()).get(id); + Iterator> iterator = liveIterators.getOrDefault(clientDescriptor, emptyMap()).get(id); if (iterator == null) { return failure(new InvalidOperationException("Referenced iterator is already closed (or never existed)")); } else { - List batch = iteratorBatch(iterator, iteratorAdvanceMessage.getBatchSize()); + List> batch = iteratorBatch(iterator, iteratorAdvanceMessage.getBatchSize()); if (iterator.hasNext()) { return iteratorBatchResponse(id, batch, false); } else { @@ -612,13 +613,13 @@ Set getEventListeners() { } } - private List iteratorBatch(Iterator iterator, int batchSize) { - List chains = new ArrayList<>(); + private List> iteratorBatch(Iterator> iterator, int batchSize) { + List> chains = new ArrayList<>(); int size = 0; while (iterator.hasNext() && size < batchSize && size >= 0) { - Chain nextChain = iterator.next(); - chains.add(nextChain); - for (Element e: nextChain) { + Map.Entry nextChain = iterator.next(); + chains.add(new AbstractMap.SimpleImmutableEntry<>(nextChain.getKey(), nextChain.getValue())); + for (Element e: nextChain.getValue()) { size += e.getPayload().remaining(); } } diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index d10a141ad6..fe08159b4d 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -84,6 +84,7 @@ import java.util.function.BiConsumer; import static org.ehcache.clustered.ChainUtils.createPayload; +import static org.ehcache.clustered.Matchers.entry; import static org.ehcache.clustered.Matchers.hasPayloads; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; @@ -1018,7 +1019,10 @@ public void testShortIterationIsNotTracked() throws Exception { EhcacheEntityResponse.IteratorBatch iteratorBatch = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.IteratorOpenMessage(Integer.MAX_VALUE)); assertThat(iteratorBatch.isLast(), is(true)); - assertThat(iteratorBatch.getChains(), containsInAnyOrder(hasPayloads(1L, 2L), hasPayloads(3L, 4L))); + assertThat(iteratorBatch.getChains(), containsInAnyOrder( + entry(is(1L), hasPayloads(1L, 2L)), + entry(is(2L), hasPayloads(3L, 4L)) + )); assertThat(activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.IteratorAdvanceMessage(iteratorBatch.getIdentity(), Integer.MAX_VALUE)), failsWith(instanceOf(InvalidOperationException.class))); } @@ -1041,8 +1045,8 @@ public void testLongIteration() throws Exception { EhcacheEntityResponse.IteratorBatch batchOne = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.IteratorOpenMessage(1)); - Matcher chainOne = hasPayloads(1L, 2L); - Matcher chainTwo = hasPayloads(3L, 4L); + Matcher> chainOne = entry(is(1L), hasPayloads(1L, 2L)); + Matcher> chainTwo = entry(is(2L), hasPayloads(3L, 4L)); assertThat(batchOne.isLast(), is(false)); assertThat(batchOne.getChains(), either(contains(chainOne)).or(contains(chainTwo))); @@ -1076,8 +1080,8 @@ public void testExplicitIteratorClose() throws Exception { EhcacheEntityResponse.IteratorBatch batchOne = (EhcacheEntityResponse.IteratorBatch) activeEntity.invokeActive(client.invokeContext(), new ServerStoreOpMessage.IteratorOpenMessage(1)); - Matcher chainOne = hasPayloads(1L, 2L); - Matcher chainTwo = hasPayloads(3L, 4L); + Matcher> chainOne = entry(is(1L), hasPayloads(1L, 2L)); + Matcher> chainTwo = entry(is(2L), hasPayloads(3L, 4L)); assertThat(batchOne.isLast(), is(false)); assertThat(batchOne.getChains(), either(contains(chainOne)).or(contains(chainTwo))); diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java index ed11ea7b2b..f96b1928ef 100644 --- a/clustered/server/service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java +++ b/clustered/server/service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java @@ -29,6 +29,7 @@ import java.util.AbstractList; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; public class ServerStoreImpl implements ServerSideServerStore, MapInternals { @@ -205,7 +206,7 @@ private void checkPayLoadSize(ByteBuffer payLoad) { } @Override - public Iterator iterator() { + public Iterator> iterator() { return store.iterator(); } } diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java index 64ffb354e4..4bed35acdb 100644 --- a/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java +++ b/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java @@ -17,6 +17,7 @@ import java.nio.ByteBuffer; import java.nio.IntBuffer; +import java.util.AbstractMap; import java.util.Collections; import java.util.Iterator; import java.util.Map; @@ -35,7 +36,7 @@ import static org.ehcache.clustered.common.internal.util.ChainBuilder.chainFromList; -public class OffHeapChainMap implements MapInternals, Iterable { +public class OffHeapChainMap implements MapInternals, Iterable> { interface ChainMapEvictionListener { void onEviction(K key, InternalChain evictedChain); @@ -239,26 +240,27 @@ public Set keySet() { } @Override - public Iterator iterator() { + public Iterator> iterator() { Iterator> headsIterator = heads.detachedEntryIterator(); - return new Iterator() { + return new Iterator>() { @Override public boolean hasNext() { return headsIterator.hasNext(); } @Override - public Chain next() { + public Map.Entry next() { final Lock lock = heads.readLock(); lock.lock(); try { - InternalChain chain = headsIterator.next().getValue(); + Map.Entry entry = headsIterator.next(); + InternalChain chain = entry.getValue(); if (chain == null) { - return EMPTY_CHAIN; + return new AbstractMap.SimpleImmutableEntry<>(entry.getKey(), EMPTY_CHAIN); } else { try { - return chain.detach(); + return new AbstractMap.SimpleImmutableEntry<>(entry.getKey(), chain.detach()); } finally { chain.close(); } diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java index d0bc197351..f3bed5513e 100644 --- a/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java +++ b/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.NoSuchElementException; import java.util.function.LongConsumer; import java.util.function.LongFunction; @@ -367,10 +368,10 @@ public long getDataVitalMemory() { } @Override - public Iterator iterator() { - return new AggregateIterator() { + public Iterator> iterator() { + return new AggregateIterator>() { @Override - protected Iterator getNextIterator() { + protected Iterator> getNextIterator() { return listIterator.next().iterator(); } }; diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java index 20247cd95b..7450450670 100644 --- a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java +++ b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java @@ -25,6 +25,7 @@ import java.nio.ByteBuffer; import java.util.HashSet; import java.util.Iterator; +import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.concurrent.TimeoutException; @@ -219,7 +220,7 @@ public void test_replaceAtHead_doesNotConsumeBuffer() { public void testEmptyIterator() throws TimeoutException { ServerStore store = newStore(); - Iterator chainIterator = store.iterator(); + Iterator> chainIterator = store.iterator(); assertThat(chainIterator.hasNext(), Is.is(false)); try { @@ -235,10 +236,12 @@ public void testSingleElementIterator() throws TimeoutException { ServerStore store = newStore(); store.append(1L, createPayload(42L)); - Iterator chainIterator = store.iterator(); + Iterator> chainIterator = store.iterator(); assertThat(chainIterator.hasNext(), is(true)); - assertThat(chainIterator.next(), hasPayloads(42L)); + Map.Entry next = chainIterator.next(); + assertThat(next.getKey(), is(1L)); + assertThat(next.getValue(), hasPayloads(42L)); assertThat(chainIterator.hasNext(), is(false)); try { chainIterator.next(); @@ -260,12 +263,12 @@ public void testHeavilyPopulatedIterator() throws TimeoutException { } }); - Iterator chainIterator = store.iterator(); + Iterator> chainIterator = store.iterator(); Set longs = new HashSet<>(); while (chainIterator.hasNext()) { - Chain chain = chainIterator.next(); - for (Element e: chain) { + Map.Entry chain = chainIterator.next(); + for (Element e: chain.getValue()) { long l = readPayload(e.getPayload()); assertThat(longs, not(hasItem(l))); longs.add(l); diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java index 18cec76fdc..8a63f587bd 100644 --- a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java +++ b/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java @@ -20,8 +20,6 @@ import org.ehcache.clustered.common.internal.store.ServerStore; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -29,9 +27,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; /** * Implements {@link ServerStore} @@ -100,8 +95,8 @@ public void clear() { } @Override - public Iterator iterator() { - return map.values().iterator(); + public Iterator> iterator() { + return map.entrySet().iterator(); } private HeapChainImpl cast(Chain chain) { diff --git a/clustered/test-utils/src/main/java/org/ehcache/clustered/Matchers.java b/clustered/test-utils/src/main/java/org/ehcache/clustered/Matchers.java index a1d034446f..344af5e0b3 100644 --- a/clustered/test-utils/src/main/java/org/ehcache/clustered/Matchers.java +++ b/clustered/test-utils/src/main/java/org/ehcache/clustered/Matchers.java @@ -26,11 +26,26 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Map; import static org.ehcache.clustered.ChainUtils.readPayload; public class Matchers { + public static Matcher> entry(Matcher key, Matcher value) { + return new TypeSafeMatcher>() { + @Override + protected boolean matchesSafely(Map.Entry item) { + return key.matches(item.getKey()) && value.matches(item.getValue()); + } + + @Override + public void describeTo(Description description) { + description.appendText("an entry with key ").appendDescriptionOf(key).appendText(" and value ").appendDescriptionOf(value); + } + }; + } + public static Matcher matchesChain(Chain expected) { return new TypeSafeMatcher() { @Override From ece9a067432a1817c418cc6b4f9ba51de70997d8 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 25 Jan 2021 16:36:47 -0500 Subject: [PATCH 317/372] Upgrade to new tc-platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index fc8a9b1a9c..928d46b9e7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre14 +terracottaPlatformVersion = 5.8.1-pre15 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.1-pre5 terracottaPassthroughTestingVersion = 1.7.0 From 2ee876ca45677072d8afcb6bff26df794b8355ca Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 26 Jan 2021 11:25:08 -0500 Subject: [PATCH 318/372] Upgrade to new core version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 928d46b9e7..e0622bd3d6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ jaxbVersion = [2.2,3) # Terracotta clustered terracottaPlatformVersion = 5.8.1-pre15 terracottaApisVersion = 1.7.0 -terracottaCoreVersion = 5.7.1-pre5 +terracottaCoreVersion = 5.7.1-pre9 terracottaPassthroughTestingVersion = 1.7.0 terracottaUtilitiesVersion = 0.0.6 From 4880bfe01a4bfe8a17fea1e17492f769797729c1 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 2 Feb 2021 15:15:05 -0500 Subject: [PATCH 319/372] Version upgrade --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e0622bd3d6..cbe2a956b1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre15 +terracottaPlatformVersion = 5.8.1-pre16 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.1-pre9 terracottaPassthroughTestingVersion = 1.7.0 From 3ed9a1755cebcfc007d6bda828812b92bb1bc1db Mon Sep 17 00:00:00 2001 From: mobasherul Date: Wed, 3 Feb 2021 20:05:58 +0530 Subject: [PATCH 320/372] Bump up platform version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index cbe2a956b1..e51704be40 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre16 +terracottaPlatformVersion = 5.8.1-pre17 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.1-pre9 terracottaPassthroughTestingVersion = 1.7.0 From db860d3bea7e54b80d068f99b2da57c05e95b5a7 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 5 Feb 2021 14:27:16 -0500 Subject: [PATCH 321/372] Update gradle.properties --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e51704be40..c1f226c6a7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre17 +terracottaPlatformVersion = 5.8.1-pre18 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.1-pre9 terracottaPassthroughTestingVersion = 1.7.0 From 09a344dcf0be86715a1f9eea94de084b25fa1b57 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 12 Feb 2021 19:40:46 -0500 Subject: [PATCH 322/372] Version upgrade --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index c1f226c6a7..eeec3bf233 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre18 +terracottaPlatformVersion = 5.8.1-pre19 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.1-pre9 terracottaPassthroughTestingVersion = 1.7.0 From 7e72a7014317c759a4a38d643986c00996f2e764 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 17 Feb 2021 22:06:22 -0500 Subject: [PATCH 323/372] Version upgrade --- gradle.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index eeec3bf233..65d71fe35d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,10 +10,10 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.1-pre19 +terracottaPlatformVersion = 5.8.1 terracottaApisVersion = 1.7.0 -terracottaCoreVersion = 5.7.1-pre9 -terracottaPassthroughTestingVersion = 1.7.0 +terracottaCoreVersion = 5.7.1 +terracottaPassthroughTestingVersion = 1.7.1 terracottaUtilitiesVersion = 0.0.6 # Test lib versions From 23ec44bc57b04cfa39ee8fe35ae05398670ddbba Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 23 Feb 2021 21:08:26 -0500 Subject: [PATCH 324/372] Version upgrade --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 65d71fe35d..6e710bb59b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.1 +terracottaPlatformVersion = 5.8.3 terracottaApisVersion = 1.7.0 terracottaCoreVersion = 5.7.1 terracottaPassthroughTestingVersion = 1.7.1 From ec6fb752d82310cdb35334757630687fccf21db6 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 24 Feb 2021 09:12:59 -0500 Subject: [PATCH 325/372] Make the Glassfish JAXB Runtime provided scope --- dist/build.gradle | 2 +- xml/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/build.gradle b/dist/build.gradle index 4f784a54a2..732bfe9955 100644 --- a/dist/build.gradle +++ b/dist/build.gradle @@ -31,7 +31,7 @@ dependencies { dependencies { shadowCompile "org.slf4j:slf4j-api:$parent.slf4jVersion" - shadowCompile "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" + shadowProvided "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" shadowProvided "javax.cache:cache-api:$parent.jcacheVersion" } diff --git a/xml/build.gradle b/xml/build.gradle index 6c6f076306..39c0afbdd5 100644 --- a/xml/build.gradle +++ b/xml/build.gradle @@ -25,7 +25,7 @@ dependencies { api project(':api') implementation project(':core') implementation project(':impl') - implementation "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" + providedImplementation "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" testFixturesApi 'org.xmlunit:xmlunit-core:2.6.0', 'org.xmlunit:xmlunit-matchers:2.6.0' xjcClasspath 'org.jvnet.jaxb2_commons:jaxb2-fluent-api:3.0' From b82f46672fb9613d2204876e86cc6e6d225c83bf Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 5 Mar 2021 11:40:32 -0500 Subject: [PATCH 326/372] Fixes #2885 : Refetch manager entity on reconnect when appropriate --- .../internal/service/ConnectionState.java | 27 ++++++++++++------- .../internal/service/ConnectionStateTest.java | 3 ++- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java index abf9ad7c5d..3c5bcfd83f 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java @@ -91,6 +91,10 @@ public ClusterTierManagerClientEntityFactory getEntityFactory() { return entityFactory; } + public ClusterTierManagerClientEntity getEntity() { + return entity; + } + public ClusterTierClientEntity createClusterTierClientEntity(String cacheId, ServerStoreConfiguration clientStoreConfiguration, boolean isReconnect) throws CachePersistenceException { @@ -109,7 +113,7 @@ public ClusterTierClientEntity createClusterTierClientEntity(String cacheId, throw new CachePersistenceException("Cluster tier proxy '" + cacheId + "' for entity '" + entityIdentifier + "' does not exist.", e); } catch (ConnectionClosedException | ConnectionShutdownException e) { LOGGER.info("Disconnected from the server", e); - handleConnectionClosedException(); + handleConnectionClosedException(true); } } @@ -129,10 +133,13 @@ public void initClusterConnection() { } } - private void reconnect() { + private void reconnect(boolean retrieve) { while (true) { try { connect(); + if (retrieve) { + retrieveEntity(); + } LOGGER.info("New connection to server is established, reconnect count is {}", reconnectCounter.incrementAndGet()); break; } catch (ConnectionException e) { @@ -164,7 +171,7 @@ private boolean silentDestroyUtil() { return true; } catch (ConnectionClosedException | ConnectionShutdownException e) { LOGGER.info("Disconnected from the server", e); - reconnect(); + reconnect(false); return false; } } @@ -240,7 +247,7 @@ public void destroyAll() throws CachePersistenceException { } catch (EntityBusyException e) { throw new CachePersistenceException("Cannot delete cluster tiers on " + connectionSource, e); } catch (ConnectionClosedException | ConnectionShutdownException e) { - handleConnectionClosedException(); + handleConnectionClosedException(false); } } } @@ -263,7 +270,7 @@ public void destroy(String name) throws CachePersistenceException { break; } } catch (ConnectionClosedException | ConnectionShutdownException e) { - reconnect(); + reconnect(false); } } @@ -277,7 +284,7 @@ public void destroy(String name) throws CachePersistenceException { LOGGER.debug("Destruction of cluster tier {} failed as it does not exist", name); break; } catch (ConnectionClosedException | ConnectionShutdownException e) { - handleConnectionClosedException(); + handleConnectionClosedException(false); } } } @@ -292,7 +299,7 @@ private void autoCreateEntity() throws ClusterTierManagerValidationException, Il //ignore - entity already exists - try to retrieve } catch (ConnectionClosedException | ConnectionShutdownException e) { LOGGER.info("Disconnected from the server", e); - reconnect(); + reconnect(false); continue; } @@ -308,17 +315,17 @@ private void autoCreateEntity() throws ClusterTierManagerValidationException, Il + "'; retrieve operation timed out", e); } catch (ConnectionClosedException | ConnectionShutdownException e) { LOGGER.info("Disconnected from the server", e); - reconnect(); + reconnect(false); } } } - private void handleConnectionClosedException() { + private void handleConnectionClosedException(boolean retrieve) { while (true) { try { destroyState(false); - reconnect(); + reconnect(retrieve); connectionRecoveryListener.run(); break; } catch (ConnectionClosedException | ConnectionShutdownException e) { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java index e2a12e8793..0d0941462d 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java @@ -84,6 +84,7 @@ public void testInitializeStateAfterConnectionCloses() throws Exception { assertThat(connectionState.getConnection(), notNullValue()); assertThat(connectionState.getEntityFactory(), notNullValue()); + assertThat(connectionState.getEntity(), notNullValue()); connectionState.getConnection().close(); @@ -105,7 +106,7 @@ public void testCreateClusterTierEntityAfterConnectionCloses() throws Exception ClusterTierClientEntity clientEntity = connectionState.createClusterTierClientEntity("cache1", serverStoreConfiguration, false); assertThat(clientEntity, notNullValue()); - + assertThat(connectionState.getEntity(), notNullValue()); } //For test to simulate connection close as result of lease expiry From b200f9cc10f599f97696bb42c6f9217cf899ed03 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 9 Mar 2021 14:18:39 -0500 Subject: [PATCH 327/372] Resources sizes are not important when validating --- .../service/DefaultClusteringServiceTest.java | 8 ++------ .../clustered/common/PoolAllocation.java | 4 ++-- .../ClusterTierManagerActiveEntityTest.java | 4 ++-- .../server/ServerStoreCompatibilityTest.java | 18 ++++-------------- .../store/ClusterTierActiveEntityTest.java | 4 ++-- .../server/EhcacheStateServiceImpl.java | 14 -------------- 6 files changed, 12 insertions(+), 40 deletions(-) diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java index 5a6be4db87..8100a13bb4 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java @@ -20,8 +20,6 @@ import org.ehcache.clustered.client.config.ClusteredResourcePool; import org.ehcache.clustered.client.config.ClusteredResourceType; import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; -import org.ehcache.clustered.client.config.ClusteringServiceConfiguration.ClientMode; -import org.ehcache.clustered.client.config.Timeouts; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.client.internal.ClusterTierManagerClientEntityFactory; @@ -38,8 +36,6 @@ import org.ehcache.clustered.client.service.ClusteringService; import org.ehcache.clustered.client.service.ClusteringService.ClusteredCacheIdentifier; import org.ehcache.clustered.common.Consistency; -import org.ehcache.clustered.common.ServerSideConfiguration; -import org.ehcache.clustered.common.ServerSideConfiguration.Pool; import org.ehcache.clustered.common.internal.exceptions.InvalidServerStoreConfigurationException; import org.ehcache.clustered.lock.server.VoltronReadWriteLockServerEntityService; import org.ehcache.clustered.server.ObservableEhcacheServerEntityService; @@ -1941,7 +1937,7 @@ public void testGetServerStoreProxyFailureClearsEntityListeners() throws Excepti // Initial setup end service.start(null); - when(resourcePools.getPoolForResource(eq(DEDICATED))).thenReturn(new DedicatedClusteredResourcePoolImpl("serverResource1", 2L, MemoryUnit.MB)); + when(resourcePools.getPoolForResource(eq(DEDICATED))).thenReturn(new DedicatedClusteredResourcePoolImpl("serverResource2", 1L, MemoryUnit.MB)); try { service.getServerStoreProxy(cacheIdentifier, storeConfig, Consistency.STRONG, mock(ServerCallback.class)); fail("Server store proxy creation should have failed"); @@ -1980,7 +1976,7 @@ public void testGetServerStoreProxyFailureDoesNotClearOtherStoreEntityListeners( ClusteringService.ClusteredCacheIdentifier otherCacheIdentifier = (ClusteredCacheIdentifier) service.getPersistenceSpaceIdentifier("my-other-cache", null); service.getServerStoreProxy(otherCacheIdentifier, storeConfig, Consistency.STRONG, mock(ServerCallback.class)); // Creates one more store - when(resourcePools.getPoolForResource(eq(DEDICATED))).thenReturn(new DedicatedClusteredResourcePoolImpl("serverResource1", 2L, MemoryUnit.MB)); + when(resourcePools.getPoolForResource(eq(DEDICATED))).thenReturn(new DedicatedClusteredResourcePoolImpl("serverResource2", 1L, MemoryUnit.MB)); try { service.getServerStoreProxy(cacheIdentifier, storeConfig, Consistency.STRONG, mock(ServerCallback.class)); fail("Server store proxy creation should have failed"); diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/PoolAllocation.java b/clustered/common-api/src/main/java/org/ehcache/clustered/common/PoolAllocation.java index 6917c5b099..c8250fd31a 100644 --- a/clustered/common-api/src/main/java/org/ehcache/clustered/common/PoolAllocation.java +++ b/clustered/common-api/src/main/java/org/ehcache/clustered/common/PoolAllocation.java @@ -17,6 +17,7 @@ package org.ehcache.clustered.common; import java.io.Serializable; +import java.util.Objects; /** * PoolAllocation @@ -86,8 +87,7 @@ public boolean isCompatible(PoolAllocation other) { final Dedicated dedicated = (Dedicated)other; - if (size != dedicated.size) return false; - return resourceName != null ? resourceName.equals(dedicated.resourceName) : dedicated.resourceName == null; + return Objects.equals(resourceName, dedicated.resourceName); } @Override diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java index 77632737f2..017c0fd4a6 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java @@ -400,7 +400,7 @@ public void testValidateDefaultResourceNameDifferent() throws Exception { } @Test - public void testValidateClientSharedPoolSizeTooBig() throws Exception { + public void testValidateClientSharedPoolSizeDifferent() throws Exception { OffHeapIdentifierRegistry registry = new OffHeapIdentifierRegistry(); registry.addResource("defaultServerResource1", 8, MemoryUnit.MEGABYTES); registry.addResource("serverResource1", 8, MemoryUnit.MEGABYTES); @@ -422,7 +422,7 @@ public void testValidateClientSharedPoolSizeTooBig() throws Exception { .sharedPool("primary", "serverResource1", 4, MemoryUnit.MEGABYTES) .sharedPool("secondary", "serverResource2", 36, MemoryUnit.MEGABYTES) .build(); - assertFailure(activeEntity.invokeActive(client.invokeContext(), MESSAGE_FACTORY.validateStoreManager(validate)),InvalidServerSideConfigurationException.class, "Pool 'secondary' not equal."); + assertSuccess(activeEntity.invokeActive(client.invokeContext(), MESSAGE_FACTORY.validateStoreManager(validate))); } @Test diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java index 19e81870e4..a4e2709666 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java @@ -176,7 +176,7 @@ public void testConsitencyMismatch() { } @Test - public void testDedicatedPoolResourceTooBig() { + public void testDedicatedPoolResourceTooBig() throws InvalidServerStoreConfigurationException { ServerStoreConfiguration serverConfiguration = new ServerStoreConfiguration(DEDICATED_POOL_ALLOCATION, STORED_KEY_TYPE, STORED_VALUE_TYPE, @@ -193,16 +193,11 @@ public void testDedicatedPoolResourceTooBig() { ServerStoreCompatibility serverStoreCompatibility = new ServerStoreCompatibility(); - try { - serverStoreCompatibility.verify(serverConfiguration, clientConfiguration); - fail("Expected InvalidServerStoreConfigurationException"); - } catch(InvalidServerStoreConfigurationException e) { - assertThat(e.getMessage(), containsString("resourcePoolType")); - } + serverStoreCompatibility.verify(serverConfiguration, clientConfiguration); } @Test - public void testDedicatedPoolResourceTooSmall() { + public void testDedicatedPoolResourceTooSmall() throws InvalidServerStoreConfigurationException { ServerStoreConfiguration serverConfiguration = new ServerStoreConfiguration(DEDICATED_POOL_ALLOCATION, STORED_KEY_TYPE, STORED_VALUE_TYPE, @@ -219,12 +214,7 @@ public void testDedicatedPoolResourceTooSmall() { ServerStoreCompatibility serverStoreCompatibility = new ServerStoreCompatibility(); - try { - serverStoreCompatibility.verify(serverConfiguration, clientConfiguration); - fail("Expected InvalidServerStoreConfigurationException"); - } catch(InvalidServerStoreConfigurationException e) { - assertThat(e.getMessage(), containsString("resourcePoolType")); - } + serverStoreCompatibility.verify(serverConfiguration, clientConfiguration); } @Test diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index fe08159b4d..151f77dbb2 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -618,7 +618,7 @@ public void testValidateDedicatedServerStoreBad() throws Exception { assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, new ServerStoreConfigBuilder() - .dedicated(defaultResource, 8, MemoryUnit.MEGABYTES) + .dedicated("banana", 1024, MemoryUnit.KILOBYTES) .build())), failsWith(instanceOf(InvalidServerStoreConfigurationException.class))); } @@ -713,7 +713,7 @@ public void testValidateServerStore_DedicatedStoresDifferentSizes() throws Excep storeConfiguration.getPoolAllocation(); assertThat(activeEntity.invokeActive(client.invokeContext(), new LifecycleMessage.ValidateServerStore(defaultStoreName, storeConfiguration)), - failsWith(both(IsInstanceOf.any(InvalidServerStoreConfigurationException.class)).and(withMessage(containsString(expectedMessageContent))))); + succeeds()); } @Test diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/EhcacheStateServiceImpl.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/EhcacheStateServiceImpl.java index a31a00289f..c8f58d50a6 100644 --- a/clustered/server/service/src/main/java/org/ehcache/clustered/server/EhcacheStateServiceImpl.java +++ b/clustered/server/service/src/main/java/org/ehcache/clustered/server/EhcacheStateServiceImpl.java @@ -211,20 +211,6 @@ private void checkConfigurationCompatibility(ServerSideConfiguration incomingCon + "Client: " + incomingConfig.getResourcePools().keySet() + " " + "Server: " + sharedResourcePools.keySet().toString()); } - - try { - for (Map.Entry pool : resolveResourcePools(incomingConfig).entrySet()) { - ServerSideConfiguration.Pool serverPool = this.sharedResourcePools.get(pool.getKey()).getPool(); - - if (!serverPool.equals(pool.getValue())) { - throw new InvalidServerSideConfigurationException("Pool '" + pool.getKey() + "' not equal. " - + "Client: " + pool.getValue() + " " - + "Server: " + serverPool); - } - } - } catch (ConfigurationException e) { - throw new InvalidServerSideConfigurationException(e.getMessage()); - } } private static Map resolveResourcePools(ServerSideConfiguration configuration) throws ConfigurationException { From 628a858dfd6adbcbdfced9eac352d91ffce23e8c Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 9 Mar 2021 17:32:49 -0500 Subject: [PATCH 328/372] Treat ClusterTierManagerValidationException as a PerpetualCachePersistenceException --- ...ClusterTierManagerValidationException.java | 6 +--- .../internal/service/ConnectionState.java | 36 +++++++++---------- .../service/DefaultClusteringService.java | 11 ++++-- ...rTierManagerClientEntityExceptionTest.java | 3 +- .../internal/service/ReconnectTest.java | 9 ++++- 5 files changed, 37 insertions(+), 28 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerValidationException.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerValidationException.java index 27c793b278..e0aac0f71d 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerValidationException.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerValidationException.java @@ -19,7 +19,7 @@ /** * Thrown to indicate a failure in validating an {@code Entity} supporting clustered operations. */ -public class ClusterTierManagerValidationException extends RuntimeException { +public class ClusterTierManagerValidationException extends PerpetualCachePersistenceException { private static final long serialVersionUID = -428725072152588216L; @@ -30,8 +30,4 @@ public ClusterTierManagerValidationException(String message) { public ClusterTierManagerValidationException(String message, Throwable cause) { super(message, cause); } - - public ClusterTierManagerValidationException(Throwable cause) { - super(cause); - } } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java index 2231312f3e..0fccac4e77 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java @@ -136,17 +136,10 @@ public void initClusterConnection(Executor asyncWorker) { } } - private void reconnect(boolean retrieve) { + private void reconnect() { while (true) { try { connect(); - if (retrieve) { - if (serviceConfiguration.getClientMode().equals(ClientMode.AUTO_CREATE_ON_RECONNECT)) { - autoCreateEntity(); - } else { - retrieveEntity(); - } - } LOGGER.info("New connection to server is established, reconnect count is {}", reconnectCounter.incrementAndGet()); break; } catch (ConnectionException e) { @@ -178,7 +171,7 @@ private boolean silentDestroyUtil() { return true; } catch (ConnectionClosedException | ConnectionShutdownException e) { LOGGER.info("Disconnected from the server", e); - reconnect(false); + reconnect(); return false; } } @@ -207,7 +200,7 @@ public void acquireLeadership() { } } - public void initializeState() { + public void initializeState() throws ClusterTierManagerValidationException { try { switch (serviceConfiguration.getClientMode()) { case CONNECT: @@ -221,14 +214,14 @@ public void initializeState() { default: throw new AssertionError(serviceConfiguration.getClientMode()); } - } catch (RuntimeException e) { + } catch (Throwable t) { entityFactory = null; closeConnection(); - throw e; + throw t; } } - private void retrieveEntity() { + private void retrieveEntity() throws ClusterTierManagerValidationException { try { entity = entityFactory.retrieve(entityIdentifier, serviceConfiguration.getServerConfiguration()); } catch (DestroyInProgressException | EntityNotFoundException e) { @@ -284,7 +277,7 @@ public void destroy(String name) throws CachePersistenceException { break; } } catch (ConnectionClosedException | ConnectionShutdownException e) { - reconnect(false); + reconnect(); } } @@ -313,7 +306,7 @@ private void autoCreateEntity() throws ClusterTierManagerValidationException, Il //ignore - entity already exists - try to retrieve } catch (ConnectionClosedException | ConnectionShutdownException e) { LOGGER.info("Disconnected from the server", e); - reconnect(false); + reconnect(); continue; } @@ -329,17 +322,24 @@ private void autoCreateEntity() throws ClusterTierManagerValidationException, Il + "'; retrieve operation timed out", e); } catch (ConnectionClosedException | ConnectionShutdownException e) { LOGGER.info("Disconnected from the server", e); - reconnect(false); + reconnect(); } } } - private void handleConnectionClosedException(boolean retrieve) { + private void handleConnectionClosedException(boolean retrieve) throws ClusterTierManagerValidationException { while (true) { try { destroyState(false); - reconnect(retrieve); + reconnect(); + if (retrieve) { + if (serviceConfiguration.getClientMode().equals(ClientMode.AUTO_CREATE_ON_RECONNECT)) { + autoCreateEntity(); + } else { + retrieveEntity(); + } + } connectionRecoveryListener.run(); break; } catch (ConnectionClosedException | ConnectionShutdownException e) { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java index efb548a59d..a884883e88 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java @@ -17,6 +17,7 @@ package org.ehcache.clustered.client.internal.service; import org.ehcache.CachePersistenceException; +import org.ehcache.clustered.client.internal.ClusterTierManagerValidationException; import org.ehcache.clustered.client.internal.PerpetualCachePersistenceException; import org.ehcache.clustered.client.config.ClusteredResourcePool; import org.ehcache.clustered.client.config.ClusteredResourceType; @@ -118,9 +119,13 @@ public boolean isConnected() { @Override public void start(final ServiceProvider serviceProvider) { - asyncExecutor = createAsyncWorker(); - connectionState.initClusterConnection(asyncExecutor); - connectionState.initializeState(); + try { + asyncExecutor = createAsyncWorker(); + connectionState.initClusterConnection(asyncExecutor); + connectionState.initializeState(); + } catch (ClusterTierManagerValidationException e) { + throw new RuntimeException(e); + } } @Override diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java index 7c5901aed4..82ecc988d2 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java @@ -99,7 +99,8 @@ public void testServerExceptionPassThrough() throws Exception { accessService.start(null); fail("Expecting ClusterTierManagerValidationException"); - } catch (ClusterTierManagerValidationException e) { + } catch (RuntimeException e) { + assertThat(e.getCause(), is(instanceOf(ClusterTierManagerValidationException.class))); /* * Find the last ClusterTierManagerClientEntity involved exception in the causal chain. This diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java index 3e78662c29..dbcf495614 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java @@ -18,6 +18,7 @@ import org.ehcache.clustered.client.config.ClusteringServiceConfiguration; import org.ehcache.clustered.client.config.Timeouts; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; +import org.ehcache.clustered.client.internal.ClusterTierManagerValidationException; import org.ehcache.clustered.client.internal.MockConnectionService; import org.hamcrest.Matchers; import org.junit.Test; @@ -62,7 +63,13 @@ public void testAfterConnectionReconnectHappensEvenAfterConnectionException() th connectionState.initClusterConnection(Runnable::run); - CompletableFuture future = CompletableFuture.runAsync(() -> connectionState.initializeState()); + CompletableFuture future = CompletableFuture.runAsync(() -> { + try { + connectionState.initializeState(); + } catch (ClusterTierManagerValidationException e) { + throw new AssertionError(e); + } + }); MockConnectionService.mockConnection = null; From 634ca613e416b8366a237b67350adcaaaa45151a Mon Sep 17 00:00:00 2001 From: "House, James" Date: Mon, 15 Mar 2021 17:32:19 -0400 Subject: [PATCH 329/372] upgrade to latest jackson-databind (2.12.2 from 2.12.1) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 6e710bb59b..26153f74bb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,7 +21,7 @@ junitVersion = 4.13.1 assertjVersion = 3.9.0 hamcrestVersion = 1.3 mockitoVersion = 2.23.4 -jacksonVersion = 2.10.1 +jacksonVersion = 2.12.2 jcacheTckVersion = 1.1.0 # Tools From 870c225d0763931ae1635b5185694a1655693acb Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 24 Mar 2021 15:48:58 -0400 Subject: [PATCH 330/372] Fixes #2892 : Capture the ThreadGroup of the starting thread and use it for async workers --- .../internal/service/DefaultClusteringService.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java index a1a5978cef..b10cef2c52 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java @@ -337,8 +337,19 @@ private static class ClusteredSpace { } private static ExecutorService createAsyncWorker() { + SecurityManager s = System.getSecurityManager(); + ThreadGroup initialGroup = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); return Executors.newSingleThreadExecutor(r -> { - Thread t = new Thread(r, "Async DefaultClusteringService Worker"); + ThreadGroup group = initialGroup; + while (group != null && group.isDestroyed()) { + ThreadGroup parent = group.getParent(); + if (parent == null) { + break; + } else { + group = parent; + } + } + Thread t = new Thread(group, r, "Async DefaultClusteringService Worker"); t.setDaemon(true); return t; }); From 73e0f0e9decdce416281b43bd56d260ff501cb4c Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Wed, 24 Mar 2021 14:24:22 -0700 Subject: [PATCH 331/372] move integrated tests to inline testing --- azure-pipelines.yml | 3 +- build.gradle | 2 +- .../client/internal/ConnectionSource.java | 7 ++ .../internal/service/ConnectionState.java | 4 +- clustered/integration-test/build.gradle | 2 + .../BasicCacheOpsMultiThreadedTest.java | 2 +- .../clustered/BasicClusteredCacheOpsTest.java | 2 +- .../clustered/BasicEntityInteractionTest.java | 2 +- ...anagerLifecycleEhcacheIntegrationTest.java | 6 +- ...gerClientEntityFactoryIntegrationTest.java | 2 +- .../clustered/ClusteredIterationTest.java | 2 +- .../clustered/ClusteredLoaderWriterTest.java | 2 +- .../org/ehcache/clustered/ClusteredTests.java | 10 ++ .../ehcache/clustered/DestroyLoopTest.java | 2 +- .../clustered/EventsFailureBehaviorTest.java | 2 +- .../IterationFailureBehaviorTest.java | 2 +- .../clustered/JCacheClusteredTest.java | 2 +- .../java/org/ehcache/clustered/LeaseTest.java | 2 +- .../clustered/OversizedCacheOpsTest.java | 2 +- .../clustered/ReconnectDuringDestroyTest.java | 2 +- .../ResourcePoolAllocationFailureTest.java | 2 +- .../clustered/TerminatedServerTest.java | 2 +- .../VoltronReadWriteLockIntegrationTest.java | 2 +- ...onReadWriteLockPassiveIntegrationTest.java | 2 +- .../AbstractClusteringManagementTest.java | 2 +- .../management/CMClosedEventSentTest.java | 2 +- .../EhcacheConfigWithManagementTest.java | 2 +- .../ManagementClusterConnectionTest.java | 2 +- .../reconnect/AutoCreateOnReconnectTest.java | 2 +- .../reconnect/BasicCacheReconnectTest.java | 2 +- .../CacheManagerDestroyReconnectTest.java | 2 +- .../reconnect/EventsReconnectTest.java | 2 +- ...dCacheOpsReplicationMultiThreadedTest.java | 2 +- ...BasicClusteredCacheOpsReplicationTest.java | 2 +- ...OpsReplicationWithMultipleClientsTest.java | 2 +- ...CacheOpsReplicationWithServersApiTest.java | 2 +- .../BasicLifeCyclePassiveReplicationTest.java | 2 +- .../clustered/replication/DuplicateTest.java | 2 +- .../OversizedCacheOpsPassiveTest.java | 7 +- .../clustered/sync/PassiveSyncTest.java | 2 +- ...icClusteredWriteBehindMultiClientTest.java | 2 +- .../BasicClusteredWriteBehindTest.java | 2 +- ...WriteBehindWithPassiveMultiClientTest.java | 2 +- ...icClusteredWriteBehindWithPassiveTest.java | 2 +- .../src/test/resources/tc-logback.xml | 32 +++++++ .../internal/messages/EhcacheServerCodec.java | 5 + .../server/store/ClusterTierActiveEntity.java | 9 +- .../store/ClusterTierServerEntityService.java | 18 +++- .../VoltronReadWriteLockActiveEntityTest.java | 4 +- .../server/TestClientDescriptor.java | 5 + .../clustered/server/TestClientSourceId.java | 5 + .../store/ClusterTierActiveEntityTest.java | 95 ++++++++++--------- gradle.properties | 10 +- 53 files changed, 193 insertions(+), 103 deletions(-) create mode 100644 clustered/integration-test/src/test/resources/tc-logback.xml diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 3d05a082e6..590980b08b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -40,11 +40,10 @@ jobs: vmImage: 'windows-latest' jdkVersion: '1.8' jobName: 'WindowsJava8' - options: '--max-workers=1' - template: build-templates/gradle-common.yml@templates parameters: vmImage: 'windows-latest' jdkVersion: '1.8' - options: '-PtestVM=java11Home --max-workers=1' + options: '-PtestVM=java11Home' jobName: 'WindowsJava11' diff --git a/build.gradle b/build.gradle index 1d6fa0fc5e..1a6bd85609 100644 --- a/build.gradle +++ b/build.gradle @@ -221,7 +221,7 @@ subprojects { tasks.withType(Test) { executable = testJava.javaExecutable maxHeapSize = "256m" - maxParallelForks 64 + maxParallelForks 16 systemProperty 'java.awt.headless', 'true' } tasks.withType(Javadoc) { diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java index ffb5f8a00a..cfeb60e9e0 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java @@ -159,6 +159,13 @@ public void close() throws IOException { connection.close(); } } + + @Override + public boolean isValid() { + return connection.isValid(); + } + + }; } catch (EntityNotProvidedException | EntityVersionMismatchException | EntityNotFoundException e) { throw new AssertionError(e); diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java index 0fccac4e77..16dfcfb517 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java @@ -130,7 +130,7 @@ public void initClusterConnection(Executor asyncWorker) { this.asyncWorker = requireNonNull(asyncWorker); try { connect(); - } catch (ConnectionException ex) { + } catch (ConnectionClosedException | ConnectionException ex) { LOGGER.error("Initial connection failed due to", ex); throw new RuntimeException(ex); } @@ -142,7 +142,7 @@ private void reconnect() { connect(); LOGGER.info("New connection to server is established, reconnect count is {}", reconnectCounter.incrementAndGet()); break; - } catch (ConnectionException e) { + } catch (ConnectionClosedException | ConnectionException e) { LOGGER.error("Re-connection to server failed, trying again", e); } } diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index 68d9e3207a..055dd129de 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -59,6 +59,8 @@ task copyServerLibs(type: Copy) { } test { + maxHeapSize = '512m' + maxParallelForks = 8 dependsOn copyServerLibs environment 'JAVA_HOME', testJava.javaHome //If this directory does not exist, tests will fail with a cryptic assert failure diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java index 62aa35b1ab..e0593eafc8 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicCacheOpsMultiThreadedTest.java @@ -48,7 +48,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + /** * Simulate multiple clients starting up the same cache manager simultaneously and ensure that puts and gets works just diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java index e5bfc5a8e9..173def759b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java @@ -48,7 +48,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.collection.IsIterableWithSize.iterableWithSize; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class BasicClusteredCacheOpsTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java index c12c700858..89c622f5ed 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java @@ -50,7 +50,7 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.fail; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class BasicEntityInteractionTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java index 15056b0a16..38bd261e11 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java @@ -56,7 +56,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.junit.Assert.fail; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class CacheManagerLifecycleEhcacheIntegrationTest extends ClusteredTests { @@ -179,6 +179,10 @@ public EntityRef getEntityRef(Class cls, lo public void close() throws IOException { //no-op } + + public boolean isValid() { + return true; + } }; } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java index 7e22bf2561..3c492969c3 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java @@ -39,7 +39,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class ClusterTierManagerClientEntityFactoryIntegrationTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java index 03ad8d85a5..9f83679ebf 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredIterationTest.java @@ -45,7 +45,7 @@ import static org.hamcrest.core.IsInstanceOf.any; import static org.hamcrest.core.IsNull.notNullValue; import static org.junit.Assert.fail; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class ClusteredIterationTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java index 1fff9ad9ef..cd8a699701 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredLoaderWriterTest.java @@ -53,7 +53,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + @RunWith(Parameterized.class) public class ClusteredLoaderWriterTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java index 7fb2cea56c..87f885586d 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java @@ -28,6 +28,8 @@ import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; +import org.terracotta.testing.config.ConfigRepoStartupBuilder; +import org.terracotta.testing.rules.BasicExternalClusterBuilder; /** * Base class for all clustered tests. It makes sure the environment is correctly configured to launch the servers. Especially @@ -118,6 +120,14 @@ protected static String offheapResources(Map resources) { return sb.append("\n").toString(); } + protected static BasicExternalClusterBuilder newCluster() { + return BasicExternalClusterBuilder.newCluster().startupBuilder(ConfigRepoStartupBuilder::new); + } + + protected static BasicExternalClusterBuilder newCluster(int size) { + return BasicExternalClusterBuilder.newCluster(size).startupBuilder(ConfigRepoStartupBuilder::new); + } + protected static String leaseLength(Duration leaseLength) { return "" + "" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java index e6e44313d1..65f78e3d1b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/DestroyLoopTest.java @@ -42,7 +42,7 @@ import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class DestroyLoopTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java index c7554e84a9..30917b7429 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/EventsFailureBehaviorTest.java @@ -67,7 +67,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isOneOf; import static org.hamcrest.Matchers.nullValue; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + /* * Eventing behavior is broken across a failover due to actives and passives diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java index e2e05a6f68..0ef99480fe 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/IterationFailureBehaviorTest.java @@ -52,7 +52,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.core.IsNull.notNullValue; import static org.junit.Assert.fail; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; public class IterationFailureBehaviorTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java index 84c03a9300..8eb99192c2 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java @@ -31,7 +31,7 @@ import java.util.Properties; import static org.ehcache.clustered.CacheManagerLifecycleEhcacheIntegrationTest.substitute; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + /** * JCacheClusteredTest - runs the TCK test suite using clustered caches diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java index be29ddd8f7..a6dd37b680 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/LeaseTest.java @@ -43,7 +43,7 @@ import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java index a1ad5c458e..e4cdeb9493 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/OversizedCacheOpsTest.java @@ -35,7 +35,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class OversizedCacheOpsTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java index e8ca590987..041fcfa63c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ReconnectDuringDestroyTest.java @@ -54,7 +54,7 @@ import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java index 7cb99a9fb4..14b6140e57 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java @@ -37,7 +37,7 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.fail; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class ResourcePoolAllocationFailureTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java index 9bc57f8034..e95fc343c8 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/TerminatedServerTest.java @@ -63,7 +63,7 @@ import static java.time.Duration.ofSeconds; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.RULE; import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java index 854ccaf030..aa4d914b7f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java @@ -37,7 +37,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.junit.Assert.fail; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class VoltronReadWriteLockIntegrationTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java index a297868c94..f892a67cdf 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java @@ -34,7 +34,7 @@ import static org.ehcache.clustered.lock.VoltronReadWriteLockIntegrationTest.async; import static org.junit.Assert.fail; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + @RunWith(Parallel.class) public class VoltronReadWriteLockPassiveIntegrationTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 8f277b768c..24c694e7ae 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -64,7 +64,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.rules.RuleChain.outerRule; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + @SuppressWarnings("rawtypes") // Need to suppress because of a Javac bug giving a rawtype on AbstractManageableNode::isManageable. public abstract class AbstractClusteringManagementTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java index c4b682ec1c..e9c81f1a2f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/CMClosedEventSentTest.java @@ -38,7 +38,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertFalse; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class CMClosedEventSentTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java index 4793b5ad80..5a06d00806 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java @@ -35,7 +35,7 @@ import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class EhcacheConfigWithManagementTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index 1e93df16d7..571a92f921 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -51,7 +51,7 @@ import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java index c6802cb6de..5a310c78b5 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/AutoCreateOnReconnectTest.java @@ -32,7 +32,7 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.MatcherAssert.assertThat; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class AutoCreateOnReconnectTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java index 2c5d6464a4..c675ee7885 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/BasicCacheReconnectTest.java @@ -48,7 +48,7 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.fail; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java index 7e838b7dd5..8bde8b8927 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/CacheManagerDestroyReconnectTest.java @@ -32,7 +32,7 @@ import java.time.Duration; import static java.time.Duration.ofSeconds; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java index f2bcecfd42..0b0c5ab51a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/reconnect/EventsReconnectTest.java @@ -57,7 +57,7 @@ import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.junit.Assert.fail; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index c686cc61da..e8fe76b259 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -69,7 +69,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.fail; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + /** * This test asserts Active-Passive fail-over with diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java index 5d2ebec90b..9de6e0bd41 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java @@ -53,7 +53,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + @RunWith(ParallelParameterized.class) public class BasicClusteredCacheOpsReplicationTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java index 5240038ea3..77648fbc4c 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java @@ -58,7 +58,7 @@ import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + /** * The point of this test is to assert proper data read after fail-over handling. diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java index 4c168fa527..c8a9628963 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithServersApiTest.java @@ -42,7 +42,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.nullValue; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class BasicClusteredCacheOpsReplicationWithServersApiTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java index b98f2adcb8..98e2703ba0 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java @@ -38,7 +38,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.fail; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + @RunWith(Parallel.class) public class BasicLifeCyclePassiveReplicationTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java index 6e2081daa4..fa3a988e01 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java @@ -49,7 +49,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assume.assumeThat; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class DuplicateTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java index d3411d9ffe..10e14a1620 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/OversizedCacheOpsPassiveTest.java @@ -26,7 +26,6 @@ import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.terracotta.testing.rules.Cluster; @@ -34,12 +33,14 @@ import java.util.Arrays; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; +import org.junit.Ignore; + -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; /** * Test the effect of cache eviction during passive sync. */ +@Ignore("OOME on build slaves due to high memory requirements") public class OversizedCacheOpsPassiveTest extends ClusteredTests { private static final int MAX_PUTS = 3000; private static final int MAX_SWITCH_OVER = 3; @@ -52,7 +53,7 @@ public class OversizedCacheOpsPassiveTest extends ClusteredTests { newCluster(2).in(clusterPath()) .withSystemProperty("ehcache.sync.data.gets.threshold", "2") .withServiceFragment(offheapResource("primary-server-resource", 2)) - .withSystemProperty("JAVA_OPTS", "-Xms1024m -Xmx8192m") + .withServerHeap(2048) .build(); @Test diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java index af5ef41aee..eea6d9af54 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java @@ -39,7 +39,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class PassiveSyncTest extends ClusteredTests { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java index 4ed3264dc8..a83b9f6c93 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindMultiClientTest.java @@ -24,7 +24,7 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class BasicClusteredWriteBehindMultiClientTest extends WriteBehindTestBase { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java index c31652c89d..ac19b72fcc 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java @@ -34,7 +34,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.notNullValue; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class BasicClusteredWriteBehindTest extends WriteBehindTestBase { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java index 64f25d21df..d2c14c28d7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveMultiClientTest.java @@ -24,7 +24,7 @@ import org.junit.Test; import org.terracotta.testing.rules.Cluster; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + public class BasicClusteredWriteBehindWithPassiveMultiClientTest extends WriteBehindTestBase { diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java index 58026e6df5..072f5cd8bf 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindWithPassiveTest.java @@ -27,7 +27,7 @@ import org.junit.Test; import org.junit.runner.RunWith; -import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; + @RunWith(Parallel.class) public class BasicClusteredWriteBehindWithPassiveTest extends WriteBehindTestBase { diff --git a/clustered/integration-test/src/test/resources/tc-logback.xml b/clustered/integration-test/src/test/resources/tc-logback.xml new file mode 100644 index 0000000000..4208262b28 --- /dev/null +++ b/clustered/integration-test/src/test/resources/tc-logback.xml @@ -0,0 +1,32 @@ + + + + + %d [%t] %p %c - %m%n + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java index 42001e7fc1..bd30f8ccff 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java @@ -149,6 +149,11 @@ public long toLong() { return cid; } + @Override + public boolean isValidClient() { + return true; + } + @Override public boolean matches(ClientDescriptor cd) { return cd.getSourceId().toLong() == cid; diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java index e37db805cd..5d583ce3b5 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java @@ -148,9 +148,7 @@ public class ClusterTierActiveEntity implements ActiveServerEntity()); + private final Executor syncGetsExecutor; private final String storeIdentifier; private final ServerStoreConfiguration configuration; @@ -178,7 +176,7 @@ public class ClusterTierActiveEntity implements ActiveServerEntity asyncGet = CompletableFuture.runAsync( - () -> doGetsForSync(segmentId, messageQ, syncChannel, thisThread), SYNC_GETS_EXECUTOR); + () -> doGetsForSync(segmentId, messageQ, syncChannel, thisThread), syncGetsExecutor); try { try { while (messageQ.take().execute()) ; diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java index 0e6fff599c..b5a1ebd576 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java @@ -16,6 +16,12 @@ package org.ehcache.clustered.server.store; +import java.io.Closeable; +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import org.ehcache.clustered.common.internal.messages.CommonConfigCodec; import org.ehcache.clustered.common.internal.messages.ConfigCodec; import org.ehcache.clustered.common.internal.messages.EhcacheCodec; @@ -46,12 +52,15 @@ /** * ClusterTierServerEntityService */ -public class ClusterTierServerEntityService implements EntityServerService { +public class ClusterTierServerEntityService implements EntityServerService, Closeable { private static final long ENTITY_VERSION = 10L; private static final int DEFAULT_CONCURRENCY = 16; private static final KeySegmentMapper DEFAULT_MAPPER = new KeySegmentMapper(DEFAULT_CONCURRENCY); private static final ConfigCodec CONFIG_CODEC = new CommonConfigCodec(); + private static final int MAX_SYNC_CONCURRENCY = 1; + private final ExecutorService syncGets = new ThreadPoolExecutor(0, MAX_SYNC_CONCURRENCY, + 20, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); private final EntityConfigurationCodec configCodec = new EntityConfigurationCodec(CONFIG_CODEC); @@ -65,10 +74,15 @@ public boolean handlesEntityType(String typeName) { return typeName.equals("org.ehcache.clustered.client.internal.store.InternalClusterTierClientEntity"); } + @Override + public void close() throws IOException { + syncGets.shutdownNow(); + } + @Override public ClusterTierActiveEntity createActiveEntity(ServiceRegistry registry, byte[] configuration) throws ConfigurationException { ClusterTierEntityConfiguration clusterTierEntityConfiguration = configCodec.decodeClusteredStoreConfiguration(configuration); - return new ClusterTierActiveEntity(registry, clusterTierEntityConfiguration, DEFAULT_MAPPER); + return new ClusterTierActiveEntity(registry, clusterTierEntityConfiguration, DEFAULT_MAPPER, syncGets); } @Override diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java index da9ed5beb1..4f6112cbd5 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java @@ -133,7 +133,7 @@ public void testWriteUnlockNotifiesListeners() throws MessageCodecException { ActiveInvokeContext locker = newContext(); ActiveInvokeContext waiter = newContext(); - ClientDescriptor waiterDescriptor = () -> null; + ClientDescriptor waiterDescriptor = mock(ClientDescriptor.class); when(waiter.getClientDescriptor()).thenReturn(waiterDescriptor); entity.invokeActive(locker, LockMessaging.lock(WRITE)); @@ -149,7 +149,7 @@ public void testReadUnlockNotifiesListeners() throws MessageCodecException { ActiveInvokeContext locker = newContext(); ActiveInvokeContext waiter = newContext(); - ClientDescriptor waiterDescriptor = () -> null; + ClientDescriptor waiterDescriptor = mock(ClientDescriptor.class); when(waiter.getClientDescriptor()).thenReturn(waiterDescriptor); entity.invokeActive(locker, LockMessaging.lock(READ)); diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java index bbe1e12bb1..dd0dfdbc3e 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java @@ -45,6 +45,11 @@ public ClientSourceId getSourceId() { return new TestClientSourceId(clientId); } + @Override + public boolean isValidClient() { + return true; + } + @Override public String toString() { return "TestClientDescriptor[" + clientId + "]"; diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientSourceId.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientSourceId.java index 9624e3815d..4b287cd07d 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientSourceId.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientSourceId.java @@ -32,6 +32,11 @@ public long toLong() { return id; } + @Override + public boolean isValidClient() { + return true; + } + @Override public boolean matches(ClientDescriptor clientDescriptor) { return clientDescriptor.getSourceId().toLong() == id; diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index 151f77dbb2..4c1ad89cc1 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -81,6 +81,10 @@ import java.util.Random; import java.util.Set; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import static org.ehcache.clustered.ChainUtils.createPayload; @@ -113,6 +117,9 @@ public class ClusterTierActiveEntityTest { private static final KeySegmentMapper DEFAULT_MAPPER = new KeySegmentMapper(16); + private static final int MAX_SYNC_CONCURRENCY = 1; + private static final ExecutorService SYNC_GETS_EXECUTOR = new ThreadPoolExecutor(0, MAX_SYNC_CONCURRENCY, + 20, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); private String defaultStoreName = "store"; private String defaultResource = "default"; @@ -133,12 +140,12 @@ public void setUp() { @Test(expected = ConfigurationException.class) public void testConfigNull() throws Exception { - new ClusterTierActiveEntity(mock(ServiceRegistry.class), null, DEFAULT_MAPPER); + new ClusterTierActiveEntity(mock(ServiceRegistry.class), null, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); } @Test public void testConnected() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); ClientDescriptor client = TestClientDescriptor.newClient(); activeEntity.connected(client); @@ -150,7 +157,7 @@ public void testConnected() throws Exception { @Test public void testConnectedAgain() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); ClientDescriptor client = TestClientDescriptor.newClient(); activeEntity.connected(client); @@ -163,7 +170,7 @@ public void testConnectedAgain() throws Exception { @Test public void testConnectedSecond() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); ClientDescriptor client1 = TestClientDescriptor.newClient(); activeEntity.connected(client1); @@ -178,7 +185,7 @@ public void testConnectedSecond() throws Exception { @Test public void testDisconnectedNotConnected() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); ClientDescriptor client1 = TestClientDescriptor.newClient(); activeEntity.disconnected(client1); @@ -190,7 +197,7 @@ public void testDisconnectedNotConnected() throws Exception { */ @Test public void testDisconnected() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); ClientDescriptor client1 = TestClientDescriptor.newClient(); activeEntity.connected(client1); @@ -201,7 +208,7 @@ public void testDisconnected() throws Exception { @Test public void testEventListenerEnabledTracking() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client1 = TestClientDescriptor.newClient(); @@ -237,7 +244,7 @@ public void testEventListenerEnabledTracking() throws Exception { */ @Test public void testDisconnectedSecond() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); ClientDescriptor client1 = TestClientDescriptor.newClient(); activeEntity.connected(client1); @@ -263,7 +270,7 @@ public void testLoadExistingRegistersEvictionListener() throws Exception { IEntityMessenger entityMessenger = mock(IEntityMessenger.class); ServiceRegistry registry = getCustomMockedServiceRegistry(stateService, null, entityMessenger, null, null); - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(registry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(registry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.loadExisting(); verify(store).setEventListener(any(ServerStoreEventListener.class)); } @@ -279,7 +286,7 @@ public void testEnableEventListenerMessageEnablesOrDisablesEventsOnStore() throw IEntityMessenger entityMessenger = mock(IEntityMessenger.class); ServiceRegistry registry = getCustomMockedServiceRegistry(stateService, null, entityMessenger, null, null); - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(registry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(registry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client = TestClientDescriptor.newClient(); @@ -297,7 +304,7 @@ public void testEnableEventListenerMessageEnablesOrDisablesEventsOnStore() throw @Test public void testAppendInvalidationAcksTakenIntoAccount() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client1 = TestClientDescriptor.newClient(); @@ -342,7 +349,7 @@ public void testAppendInvalidationAcksTakenIntoAccount() throws Exception { @Test public void testClearInvalidationAcksTakenIntoAccount() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client1 = TestClientDescriptor.newClient(); @@ -386,7 +393,7 @@ public void testClearInvalidationAcksTakenIntoAccount() throws Exception { @Test public void testAppendInvalidationDisconnectionOfInvalidatingClientsTakenIntoAccount() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client1 = TestClientDescriptor.newClient(); @@ -423,7 +430,7 @@ public void testAppendInvalidationDisconnectionOfInvalidatingClientsTakenIntoAcc @Test public void testClearInvalidationDisconnectionOfInvalidatingClientsTakenIntoAccount() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client1 = TestClientDescriptor.newClient(); @@ -465,7 +472,7 @@ public void testAppendInvalidationDisconnectionOfBlockingClientTakenIntoAccount( .consistency(Consistency.STRONG) .build(); ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, - new ClusterTierEntityConfiguration(identifier, defaultStoreName, serverStoreConfiguration), DEFAULT_MAPPER); + new ClusterTierEntityConfiguration(identifier, defaultStoreName, serverStoreConfiguration), DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client1 = TestClientDescriptor.newClient(); @@ -497,7 +504,7 @@ public void testClearInvalidationDisconnectionOfBlockingClientTakenIntoAccount() .consistency(Consistency.STRONG) .build(); ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, - new ClusterTierEntityConfiguration(identifier, defaultStoreName, serverStoreConfiguration), DEFAULT_MAPPER); + new ClusterTierEntityConfiguration(identifier, defaultStoreName, serverStoreConfiguration), DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client1 = TestClientDescriptor.newClient(); @@ -524,7 +531,7 @@ public void testClearInvalidationDisconnectionOfBlockingClientTakenIntoAccount() @Test public void testWithAttachmentSucceedsInvokingServerStoreOperation() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client = TestClientDescriptor.newClient(); @@ -543,7 +550,7 @@ public void testWithAttachmentSucceedsInvokingServerStoreOperation() throws Exce @Test public void testCreateDedicatedServerStore() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); assertThat(defaultRegistry.getStoreManagerService().getDedicatedResourcePoolIds(), containsInAnyOrder(defaultStoreName)); @@ -573,10 +580,10 @@ public void testCreateDedicatedServerStore() throws Exception { @Test public void testCreateDedicatedServerStoreExisting() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); - ClusterTierActiveEntity otherEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity otherEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); try { otherEntity.createNew(); fail("Duplicate creation should fail with an exception"); @@ -587,7 +594,7 @@ public void testCreateDedicatedServerStoreExisting() throws Exception { @Test public void testValidateDedicatedServerStore() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client1 = TestClientDescriptor.newClient(); @@ -609,7 +616,7 @@ public void testValidateDedicatedServerStore() throws Exception { @Test public void testValidateDedicatedServerStoreBad() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client = TestClientDescriptor.newClient(); @@ -625,7 +632,7 @@ public void testValidateDedicatedServerStoreBad() throws Exception { @Test public void testValidateUnknown() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client = TestClientDescriptor.newClient(); @@ -642,7 +649,7 @@ public void testCreateSharedServerStore() throws Exception { .shared(defaultSharedPool) .build(); ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, - new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER); + new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); @@ -662,11 +669,11 @@ public void testCreateSharedServerStoreExisting() throws Exception { .shared(defaultSharedPool) .build(); ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, - new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER); + new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); ClusterTierActiveEntity otherEntity = new ClusterTierActiveEntity(defaultRegistry, - new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER); + new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); try { otherEntity.createNew(); fail("Duplicate creation should fail with an exception"); @@ -682,7 +689,7 @@ public void testValidateSharedServerStore() throws Exception { .shared(defaultSharedPool) .build(); ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, - new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER); + new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client = TestClientDescriptor.newClient(); @@ -695,7 +702,7 @@ public void testValidateSharedServerStore() throws Exception { @Test public void testValidateServerStore_DedicatedStoresDifferentSizes() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client = TestClientDescriptor.newClient(); @@ -718,7 +725,7 @@ public void testValidateServerStore_DedicatedStoresDifferentSizes() throws Excep @Test public void testValidateServerStore_DedicatedStoreResourceNamesDifferent() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client = TestClientDescriptor.newClient(); @@ -746,7 +753,7 @@ public void testValidateServerStore_DifferentSharedPools() throws Exception { .shared(defaultSharedPool) .build(); ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, - new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER); + new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client = TestClientDescriptor.newClient(); @@ -769,7 +776,7 @@ public void testValidateServerStore_DifferentSharedPools() throws Exception { @Test public void testDestroyServerStore() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); activeEntity.destroy(); @@ -789,7 +796,7 @@ public void testDestroyServerStore() throws Exception { public void testSharedPoolCacheNameCollision() throws Exception { defaultRegistry.addSharedPool(defaultStoreName, MemoryUnit.MEGABYTES.toBytes(2), defaultResource); - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); assertThat(defaultRegistry.getStoreManagerService().getSharedResourcePoolIds(), contains(defaultStoreName)); @@ -804,7 +811,7 @@ public void testCreateNonExistentSharedPool() throws Exception { .build(); ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, - new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER); + new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); try { activeEntity.createNew(); fail("Creation with non-existent shared pool should have failed"); @@ -819,7 +826,7 @@ public void testCreateUnknownServerResource() throws Exception { .dedicated("unknown", 2, MemoryUnit.MEGABYTES) .build(); ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, - new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER); + new ClusterTierEntityConfiguration(identifier, defaultStoreName, storeConfiguration), DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); try { activeEntity.createNew(); fail("Creation with non-existent shared pool should have failed"); @@ -830,7 +837,7 @@ public void testCreateUnknownServerResource() throws Exception { @Test public void testSyncToPassiveNoData() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client = TestClientDescriptor.newClient(); @@ -848,7 +855,7 @@ public void testSyncToPassiveNoData() throws Exception { @Test public void testSyncToPassiveBatchedByDefault() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client = TestClientDescriptor.newClient(); @@ -922,7 +929,7 @@ public void testDataSyncToPassiveException() throws Exception { @Test public void testLoadExistingRecoversInflightInvalidationsForEventualCache() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); EhcacheStateServiceImpl ehcacheStateService = defaultRegistry.getStoreManagerService(); ehcacheStateService.createStore(defaultStoreName, defaultStoreConfiguration, false); //Passive would have done this before failover @@ -940,7 +947,7 @@ public void testLoadExistingRecoversInflightInvalidationsForEventualCache() thro @SuppressWarnings("unchecked") public void testReplicationMessageAndOriginalServerStoreOpMessageHasSameConcurrency() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); IEntityMessenger entityMessenger = defaultRegistry.getEntityMessenger(); @@ -963,7 +970,7 @@ public void testReplicationMessageAndOriginalServerStoreOpMessageHasSameConcurre @Test public void testInvalidMessageThrowsError() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); TestClientDescriptor client = TestClientDescriptor.newClient(); activeEntity.connected(client); @@ -978,7 +985,7 @@ public void testInvalidMessageThrowsError() throws Exception { @Test public void testActiveMessageTracking() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); EhcacheStateServiceImpl ehcacheStateService = defaultRegistry.getStoreManagerService(); ehcacheStateService.createStore(defaultStoreName, defaultStoreConfiguration, false); //hack to enable message tracking on active @@ -1002,7 +1009,7 @@ public void testActiveMessageTracking() throws Exception { @Test @SuppressWarnings("unchecked") public void testShortIterationIsNotTracked() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); EhcacheStateServiceImpl ehcacheStateService = defaultRegistry.getStoreManagerService(); ehcacheStateService.createStore(defaultStoreName, defaultStoreConfiguration, false); //hack to enable message tracking on active @@ -1029,7 +1036,7 @@ public void testShortIterationIsNotTracked() throws Exception { @Test public void testLongIteration() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); EhcacheStateServiceImpl ehcacheStateService = defaultRegistry.getStoreManagerService(); ehcacheStateService.createStore(defaultStoreName, defaultStoreConfiguration, false); //hack to enable message tracking on active @@ -1064,7 +1071,7 @@ public void testLongIteration() throws Exception { @Test public void testExplicitIteratorClose() throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); EhcacheStateServiceImpl ehcacheStateService = defaultRegistry.getStoreManagerService(); ehcacheStateService.createStore(defaultStoreName, defaultStoreConfiguration, false); //hack to enable message tracking on active @@ -1092,7 +1099,7 @@ public void testExplicitIteratorClose() throws Exception { } private void prepareAndRunActiveEntityForPassiveSync(BiConsumer testConsumer) throws Exception { - ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER); + ClusterTierActiveEntity activeEntity = new ClusterTierActiveEntity(defaultRegistry, defaultConfiguration, DEFAULT_MAPPER, SYNC_GETS_EXECUTOR); activeEntity.createNew(); TestClientDescriptor client = TestClientDescriptor.newClient(); diff --git a/gradle.properties b/gradle.properties index 26153f74bb..51fa827bfc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,11 +10,11 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.3 -terracottaApisVersion = 1.7.0 -terracottaCoreVersion = 5.7.1 -terracottaPassthroughTestingVersion = 1.7.1 -terracottaUtilitiesVersion = 0.0.6 +terracottaPlatformVersion = 5.8.4-pre2 +terracottaApisVersion = 1.8.0-pre3 +terracottaCoreVersion = 5.8.0-pre5 +terracottaPassthroughTestingVersion = 1.8.0-pre5 +terracottaUtilitiesVersion = 0.0.8 # Test lib versions junitVersion = 4.13.1 From eeefd0c8aaf1c4ba4b3b65a0f663577bf861bc30 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Wed, 31 Mar 2021 07:13:12 -1000 Subject: [PATCH 332/372] improper byte buffer array use in decode results in stack overflow --- .../internal/messages/EhcacheServerCodec.java | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java index bd30f8ccff..fa03069f68 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java @@ -23,7 +23,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.terracotta.entity.MessageCodec; -import org.terracotta.entity.MessageCodecException; import org.terracotta.runnel.decoding.Enm; import java.nio.ByteBuffer; @@ -96,7 +95,10 @@ private byte[] encodeCatchup(EhcacheMessageTrackerCatchup catchup) { @Override public EhcacheEntityMessage decodeMessage(byte[] payload) { - ByteBuffer byteBuffer = ByteBuffer.wrap(payload); + return decodeMessage(ByteBuffer.wrap(payload)); + } + + private EhcacheEntityMessage decodeMessage(ByteBuffer byteBuffer) { Enm opCodeEnm = EhcacheCodec.OP_CODE_DECODER.decoder(byteBuffer).enm(MESSAGE_TYPE_FIELD_NAME); if (!opCodeEnm.isFound()) { throw new AssertionError("Got a message without an opCode"); @@ -110,7 +112,7 @@ public EhcacheEntityMessage decodeMessage(byte[] payload) { EhcacheMessageType messageType = opCodeEnm.get(); if (messageType == EhcacheMessageType.MESSAGE_CATCHUP) { - return decodeCatchup(payload); + return decodeCatchup(byteBuffer); } else if (isPassiveReplicationMessage(messageType)) { return replicationCodec.decode(messageType, byteBuffer); } @@ -118,17 +120,17 @@ public EhcacheEntityMessage decodeMessage(byte[] payload) { } @Override - public byte[] encodeResponse(EhcacheEntityResponse response) throws MessageCodecException { + public byte[] encodeResponse(EhcacheEntityResponse response) { return clientCodec.encodeResponse(response); } @Override - public EhcacheEntityResponse decodeResponse(byte[] payload) throws MessageCodecException { + public EhcacheEntityResponse decodeResponse(byte[] payload) { return clientCodec.decodeResponse(payload); } - private EhcacheMessageTrackerCatchup decodeCatchup(byte[] payload) { - StructArrayDecoder> array = MESSAGE_HISTORY.decoder(ByteBuffer.wrap(payload)).structs(MESSAGE_SEQUENCE); + private EhcacheMessageTrackerCatchup decodeCatchup(ByteBuffer payload) { + StructArrayDecoder> array = MESSAGE_HISTORY.decoder(payload).structs(MESSAGE_SEQUENCE); if (array == null) { return new EhcacheMessageTrackerCatchup(Collections.emptyList()); } @@ -138,7 +140,7 @@ private EhcacheMessageTrackerCatchup decodeCatchup(byte[] payload) { long cid = decoder.int64(CLIENT_ID); long transaction = decoder.int64(TRANSACTION_ID); ByteBuffer buff = decoder.byteBuffer(MESSAGE); - EhcacheEntityMessage msg = decodeMessage(buff.array()); + EhcacheEntityMessage msg = decodeMessage(buff); list.add(new RecordedMessage() { @Override @@ -149,11 +151,6 @@ public long toLong() { return cid; } - @Override - public boolean isValidClient() { - return true; - } - @Override public boolean matches(ClientDescriptor cd) { return cd.getSourceId().toLong() == cid; From c12108a5cc49bfc71bbc2d3ef02e23a0d9f31f79 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 25 Mar 2021 15:52:02 -0400 Subject: [PATCH 333/372] Ensure previous connection is fully closed before starting reconnection --- .../client/internal/service/ConnectionState.java | 6 ++++++ .../internal/store/ReconnectingServerStoreProxy.java | 8 ++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java index 16dfcfb517..9c152b3f9d 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java @@ -139,6 +139,12 @@ public void initClusterConnection(Executor asyncWorker) { private void reconnect() { while (true) { try { + try { + //Ensure full closure of existing connection + clusterConnection.close(); + } catch (IOException | ConnectionClosedException | IllegalStateException e) { + LOGGER.debug("Exception closing previous cluster connection", e); + } connect(); LOGGER.info("New connection to server is established, reconnect count is {}", reconnectCounter.incrementAndGet()); break; diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java index 27e19cadac..c28a8d55f5 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java @@ -148,12 +148,11 @@ private interface TimeoutExceptionFunction { V apply(U u) throws TimeoutException; } - private static class ReconnectInProgressProxy extends LockingServerStoreProxyImpl { + private static class ReconnectInProgressProxy implements LockingServerStoreProxy { private final String cacheId; ReconnectInProgressProxy(String cacheId) { - super(null, null); this.cacheId = cacheId; } @@ -206,6 +205,11 @@ public ChainEntry lock(long key) { public void unlock(long key, boolean localonly) { throw new ReconnectInProgressException(); } + + @Override + public void enableEvents(boolean enable) { + throw new ReconnectInProgressException(); + } } private LockingServerStoreProxy unsupportedLocking(ServerStoreProxy serverStoreProxy) { From ac06ed461bc790c2b4a0fb9058921907ab657f98 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 16 Apr 2021 13:24:50 -0400 Subject: [PATCH 334/372] Upgrade to terracotta-platform 5.8.4-pre3 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 51fa827bfc..4fa5ebba5d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.4-pre2 +terracottaPlatformVersion = 5.8.4-pre3 terracottaApisVersion = 1.8.0-pre3 terracottaCoreVersion = 5.8.0-pre5 terracottaPassthroughTestingVersion = 1.8.0-pre5 From 65ca9431a28f539620ec34a7ddb9043c2b843faa Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 20 Apr 2021 20:22:58 -0400 Subject: [PATCH 335/372] Upgrade to release dependencies --- .../management/AbstractClusteringManagementTest.java | 2 +- gradle.properties | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 24c694e7ae..468a0253f9 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -158,7 +158,7 @@ private static void initCM() throws InterruptedException { "ENTITY_REGISTRY_AVAILABLE", "ENTITY_REGISTRY_AVAILABLE", "ENTITY_REGISTRY_AVAILABLE", "ENTITY_REGISTRY_AVAILABLE", "SERVER_ENTITY_CREATED", "SERVER_ENTITY_CREATED", "SERVER_ENTITY_CREATED", "SERVER_ENTITY_CREATED", "SERVER_ENTITY_CREATED", "SERVER_ENTITY_CREATED", "SERVER_ENTITY_DESTROYED", - "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", + "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_FETCHED", "SERVER_ENTITY_UNFETCHED", "EHCACHE_RESOURCE_POOLS_CONFIGURED", diff --git a/gradle.properties b/gradle.properties index 4fa5ebba5d..f5e70e109d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,10 +10,10 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.4-pre3 -terracottaApisVersion = 1.8.0-pre3 -terracottaCoreVersion = 5.8.0-pre5 -terracottaPassthroughTestingVersion = 1.8.0-pre5 +terracottaPlatformVersion = 5.8.4 +terracottaApisVersion = 1.8.0 +terracottaCoreVersion = 5.8.0 +terracottaPassthroughTestingVersion = 1.8.0 terracottaUtilitiesVersion = 0.0.8 # Test lib versions From 0dfd75032e344b7e5852db3aea95c2c452410f5b Mon Sep 17 00:00:00 2001 From: Tom Mesic <59479956+tmesic99@users.noreply.github.com> Date: Thu, 29 Apr 2021 10:40:53 -0400 Subject: [PATCH 336/372] updating sample properties file to new format --- .../src/assemble/server/conf/cluster.cfg | 18 ++++++++++++++++++ .../assemble/server/conf/cluster.properties | 17 ----------------- 2 files changed, 18 insertions(+), 17 deletions(-) create mode 100644 clustered/clustered-dist/src/assemble/server/conf/cluster.cfg delete mode 100644 clustered/clustered-dist/src/assemble/server/conf/cluster.properties diff --git a/clustered/clustered-dist/src/assemble/server/conf/cluster.cfg b/clustered/clustered-dist/src/assemble/server/conf/cluster.cfg new file mode 100644 index 0000000000..7067c3efcc --- /dev/null +++ b/clustered/clustered-dist/src/assemble/server/conf/cluster.cfg @@ -0,0 +1,18 @@ +client-lease-duration=150s +client-reconnect-window=120s +cluster-name=default-cluster +failover-priority=availability +offheap-resources=main:512MB +stripe-names=default-stripe +default-stripe:node-names=default-node +default-node:node-bind-address=0.0.0.0 +default-node:node-group-bind-address=0.0.0.0 +default-node:node-group-port=9430 +default-node:node-hostname=localhost +default-node:node-log-dir=%H/terracotta/logs +default-node:node-logger-overrides= +default-node:node-name=default-server +default-node:node-port=9410 +default-node:node-public-hostname= +default-node:node-public-port= +default-node:tc-properties= diff --git a/clustered/clustered-dist/src/assemble/server/conf/cluster.properties b/clustered/clustered-dist/src/assemble/server/conf/cluster.properties deleted file mode 100644 index 55f37ac5bf..0000000000 --- a/clustered/clustered-dist/src/assemble/server/conf/cluster.properties +++ /dev/null @@ -1,17 +0,0 @@ -client-lease-duration=150s -client-reconnect-window=120s -cluster-name=default-cluster -failover-priority=availability -offheap-resources=main:512MB -stripe.1.node.1.node-bind-address=0.0.0.0 -stripe.1.node.1.node-group-bind-address=0.0.0.0 -stripe.1.node.1.node-group-port=9430 -stripe.1.node.1.node-hostname=localhost -stripe.1.node.1.node-log-dir=%H/terracotta/logs -stripe.1.node.1.node-logger-overrides= -stripe.1.node.1.node-name=default-server -stripe.1.node.1.node-port=9410 -stripe.1.node.1.node-public-hostname= -stripe.1.node.1.node-public-port= -stripe.1.node.1.tc-properties= -stripe.1.stripe-name=default-stripe From 0f6247ece3a46f9766319a4df8ee210aa3a249e0 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 18 May 2021 16:47:59 -0400 Subject: [PATCH 337/372] Fix default config --- .../src/assemble/server/conf/cluster.cfg | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/clustered/clustered-dist/src/assemble/server/conf/cluster.cfg b/clustered/clustered-dist/src/assemble/server/conf/cluster.cfg index 7067c3efcc..230113261a 100644 --- a/clustered/clustered-dist/src/assemble/server/conf/cluster.cfg +++ b/clustered/clustered-dist/src/assemble/server/conf/cluster.cfg @@ -5,14 +5,9 @@ failover-priority=availability offheap-resources=main:512MB stripe-names=default-stripe default-stripe:node-names=default-node -default-node:node-bind-address=0.0.0.0 -default-node:node-group-bind-address=0.0.0.0 -default-node:node-group-port=9430 -default-node:node-hostname=localhost -default-node:node-log-dir=%H/terracotta/logs -default-node:node-logger-overrides= -default-node:node-name=default-server -default-node:node-port=9410 -default-node:node-public-hostname= -default-node:node-public-port= -default-node:tc-properties= +default-node:bind-address=0.0.0.0 +default-node:group-bind-address=0.0.0.0 +default-node:group-port=9430 +default-node:hostname=localhost +default-node:log-dir=%H/terracotta/logs +default-node:port=9410 From da57451983a0dfbb3e13c2b97d07baafb9a831de Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Thu, 20 May 2021 08:41:34 -0700 Subject: [PATCH 338/372] bump dependencies --- .../management/ClusteringManagementServiceTest.java | 6 +++--- gradle.properties | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java index 5a3e7b5999..91955e8130 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java @@ -302,10 +302,10 @@ public void test_E_notifs_on_add_cache() throws Exception { if (cluster.serverStream().count() == 2) { waitForAllNotifications( "SERVER_ENTITY_CREATED", "ENTITY_REGISTRY_AVAILABLE", "EHCACHE_SERVER_STORE_CREATED", "SERVER_ENTITY_FETCHED", "CACHE_ADDED", - "SERVER_ENTITY_CREATED", "ENTITY_REGISTRY_AVAILABLE", "EHCACHE_SERVER_STORE_CREATED"); // passive server + "SERVER_ENTITY_CREATED", "ENTITY_REGISTRY_AVAILABLE", "EHCACHE_SERVER_STORE_CREATED", "CLIENT_REGISTRY_AVAILABLE"); // passive server } else { waitForAllNotifications( - "SERVER_ENTITY_CREATED", "ENTITY_REGISTRY_AVAILABLE", "EHCACHE_SERVER_STORE_CREATED", "SERVER_ENTITY_FETCHED", "CACHE_ADDED"); + "SERVER_ENTITY_CREATED", "ENTITY_REGISTRY_AVAILABLE", "EHCACHE_SERVER_STORE_CREATED", "SERVER_ENTITY_FETCHED", "CACHE_ADDED", "CLIENT_REGISTRY_AVAILABLE"); } } @@ -313,7 +313,7 @@ public void test_E_notifs_on_add_cache() throws Exception { public void test_F_notifs_on_remove_cache() throws Exception { cacheManager.removeCache("cache-2"); - waitForAllNotifications("CACHE_REMOVED", "SERVER_ENTITY_UNFETCHED"); + waitForAllNotifications("CACHE_REMOVED", "SERVER_ENTITY_UNFETCHED", "CLIENT_REGISTRY_AVAILABLE"); } @Test diff --git a/gradle.properties b/gradle.properties index f5e70e109d..19bc731733 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,10 +10,10 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.4 +terracottaPlatformVersion = 5.8.5 terracottaApisVersion = 1.8.0 -terracottaCoreVersion = 5.8.0 -terracottaPassthroughTestingVersion = 1.8.0 +terracottaCoreVersion = 5.8.1 +terracottaPassthroughTestingVersion = 1.8.1 terracottaUtilitiesVersion = 0.0.8 # Test lib versions From 9a0927495ef14a9199782eedd3f59e75e9a597e9 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 26 May 2021 10:56:03 -0400 Subject: [PATCH 339/372] Support not having any offheap-resources defined (activated) or not having any offheap config (diagnostic) --- .../org/ehcache/clustered/NoOffheapTest.java | 53 +++++++++++++++++++ .../state/EhcacheStateServiceProvider.java | 5 +- gradle.properties | 2 +- 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/NoOffheapTest.java diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/NoOffheapTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/NoOffheapTest.java new file mode 100644 index 0000000000..83ac886726 --- /dev/null +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/NoOffheapTest.java @@ -0,0 +1,53 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.clustered; + +import org.ehcache.StateTransitionException; +import org.ehcache.config.units.MemoryUnit; +import org.junit.ClassRule; +import org.junit.Test; +import org.terracotta.testing.rules.Cluster; + +import static java.util.function.UnaryOperator.identity; +import static org.assertj.core.api.Assertions.assertThat; +import static org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder.clusteredDedicated; +import static org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder.cluster; +import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; +import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder; +import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.junit.Assert.fail; + + +public class NoOffheapTest extends ClusteredTests { + + @ClassRule + public static Cluster CLUSTER = newCluster().in(clusterPath()).build(); + + @Test + public void testNoOffheap() throws InterruptedException { + try { + newCacheManagerBuilder().with(cluster(CLUSTER.getConnectionURI().resolve("/no-offheap-cm")) + .autoCreate(identity())) + .withCache("testNoOffheap", newCacheConfigurationBuilder(Long.class, byte[].class, newResourcePoolsBuilder() + .with(clusteredDedicated("primary-server-resource", 1, MemoryUnit.MB)) + )).build(true).close(); + fail(); + } catch (StateTransitionException e) { + assertThat(e).hasMessage("Could not create the cluster tier manager 'no-offheap-cm'."); + } + } +} diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java b/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java index dc5d2693ce..dd2f7fbefb 100644 --- a/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java +++ b/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java @@ -36,6 +36,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -62,6 +63,8 @@ public void addStateTo(StateDumpCollector dump) { @Override public boolean initialize(ServiceProviderConfiguration configuration, PlatformConfiguration platformConfiguration) { Collection extendedConfiguration = platformConfiguration.getExtendedConfiguration(OffHeapResources.class); + // When a server is activated, there will ALWAYS be one OffHeapResources, that will hold the mapping configured by the user with the "offheap-resources" setting. + // In diagnostic mode, no extended configuration is loaded, so there won't be any OffHeapResources. In that case, we ask this service to be discarded (by returning false). if (extendedConfiguration.size() > 1) { throw new UnsupportedOperationException("There are " + extendedConfiguration.size() + " OffHeapResourcesProvider, this is not supported. " + "There must be only one!"); @@ -73,7 +76,7 @@ public boolean initialize(ServiceProviderConfiguration configuration, PlatformCo LOGGER.warn("No offheap-resource defined - this will prevent provider from offering any EhcacheStateService."); } } else { - throw new UnsupportedOperationException("There are no offheap-resource defined, this is not supported"); + return false; } return true; } diff --git a/gradle.properties b/gradle.properties index 19bc731733..ebe04dc04c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.5 +terracottaPlatformVersion = 5.8.6-pre1 terracottaApisVersion = 1.8.0 terracottaCoreVersion = 5.8.1 terracottaPassthroughTestingVersion = 1.8.1 From 502605f8c6a376ae6f8284f5723523bedf4a42b5 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 2 Jun 2021 10:48:28 -0400 Subject: [PATCH 340/372] Fixes #2908 : Upgrade to offheap-store 2.5.2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 929055370e..d5a69969f6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Terracotta third parties -offheapVersion = 2.5.1 +offheapVersion = 2.5.2 statisticVersion = 2.0.5 jcacheVersion = 1.1.0 slf4jVersion = 1.7.25 From 51e48532633757aa2d43fbf753f16b6d54904c7a Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 4 Feb 2021 15:28:25 -0500 Subject: [PATCH 341/372] Ensure everything still functions when using Saxon XML libraries --- .../ClusteredResourceConfigurationParser.java | 2 +- ...acheManagerServiceConfigurationParser.java | 2 +- .../client/TerracottaUriXmlTest.java | 3 +- .../clustered/client/XmlUnknownCacheTest.java | 7 ++- ...ManagerServiceConfigurationParserTest.java | 5 +- .../org/ehcache/osgi/ClusteredOsgiTest.java | 46 ++++++++++++++- .../ehcache/osgi/ehcache-clustered-osgi.xml | 2 +- .../org/ehcache/xml/ConfigurationParser.java | 58 ++++++++++++++----- .../main/java/org/ehcache/xml/DomUtil.java | 12 +--- .../xml/ResourceConfigurationParser.java | 7 +-- .../org/ehcache/xml/XmlConfiguration.java | 3 +- xml/src/main/resources/ehcache-core.xsd | 2 +- .../org/ehcache/xml/XmlConfigurationTest.java | 19 +++--- 13 files changed, 120 insertions(+), 48 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java index 321f8068ed..639b05ef58 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java @@ -94,7 +94,7 @@ protected ResourcePool parseResourceConfig(final Element fragment) { final String sizeValue; try { - sizeValue = fragment.getFirstChild().getNodeValue(); + sizeValue = fragment.getFirstChild().getNodeValue().trim(); } catch (DOMException e) { throw new XmlConfigurationException(String.format("XML configuration element <%s> value is not valid", elementName), e); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java index 16297a8a81..6eb41f4a32 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java @@ -151,7 +151,7 @@ public URI getNamespace() { final NodeList serverNodes = item.getChildNodes(); for (int j = 0; j < serverNodes.getLength(); j++) { final Node serverNode = serverNodes.item(j); - final String host = JaxbParsers.parsePropertyOrString(((Element)serverNode).getAttributeNode(HOST_ATTRIBUTE_NAME).getValue()); + final String host = JaxbParsers.parsePropertyOrString(((Element)serverNode).getAttributeNode(HOST_ATTRIBUTE_NAME).getValue().trim()); final Attr port = ((Element)serverNode).getAttributeNode(PORT_ATTRIBUTE_NAME); InetSocketAddress address; if (port == null) { diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/TerracottaUriXmlTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/TerracottaUriXmlTest.java index 8d132d0790..75ad3a942f 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/TerracottaUriXmlTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/TerracottaUriXmlTest.java @@ -23,6 +23,7 @@ import org.junit.Test; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.containsString; /** @@ -43,7 +44,7 @@ public void testFailsWithInvalidClusterUri() { try { new XmlConfiguration(getClass().getResource("/configs/cluster-invalid-uri.xml")); } catch (XmlConfigurationException e) { - assertThat(e.getCause().getMessage(), containsString("not facet-valid with respect to pattern")); + assertThat(e.getCause().getMessage(), allOf(containsString("facet"), containsString("pattern"))); } } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/XmlUnknownCacheTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/XmlUnknownCacheTest.java index 89bd750366..0b449d0dc9 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/XmlUnknownCacheTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/XmlUnknownCacheTest.java @@ -17,8 +17,9 @@ package org.ehcache.clustered.client; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.fail; import org.ehcache.xml.XmlConfiguration; @@ -43,7 +44,7 @@ public void testGetUnknownCacheInvalidAttribute() { new XmlConfiguration(this.getClass().getResource("/configs/unknown-cluster-cache-invalid-attribute.xml")); fail("Expected XmlConfigurationException"); } catch(XmlConfigurationException xce) { - assertThat(xce.getCause().getMessage(), endsWith("Attribute 'unit' is not allowed to appear in element 'tc:clustered'.")); + assertThat(xce.getCause().getMessage(), allOf(containsString("unit"), containsString("not allowed"), containsString("clustered"))); } } @@ -53,7 +54,7 @@ public void testGetUnknownCacheInvalidElement() { new XmlConfiguration(this.getClass().getResource("/configs/unknown-cluster-cache-invalid-element.xml")); fail("Expected XmlConfigurationException"); } catch(XmlConfigurationException xce) { - assertThat(xce.getCause().getMessage(), endsWith("Element 'tc:clustered' must have no character or element information item [children], because the type's content type is empty.")); + assertThat(xce.getCause().getMessage(), allOf(containsString("haracter"), containsString("clustered"), containsString("empty"))); } } diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java index 1906861600..6598cca839 100644 --- a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java +++ b/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java @@ -67,6 +67,7 @@ import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; import static org.ehcache.xml.XmlModel.convertToJavaTimeUnit; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -244,7 +245,7 @@ public void testGetTimeoutUnitBad() throws Exception { fail("Expecting XmlConfigurationException"); } catch (XmlConfigurationException e) { assertThat(e.getMessage(), containsString("Error parsing XML configuration ")); - assertThat(e.getCause().getMessage(), containsString("Value 'femtos' is not facet-valid with respect to enumeration ")); + assertThat(e.getCause().getMessage(), allOf(containsString("facet"), containsString("enumeration"), containsString("femtos"))); } } @@ -301,7 +302,7 @@ public void testGetTimeoutValueOmitted() throws Exception { fail("Expecting XmlConfigurationException"); } catch (XmlConfigurationException e) { assertThat(e.getMessage(), containsString("Error parsing XML configuration ")); - assertThat(e.getCause().getMessage(), containsString("'' is not a valid value of union type 'propertyOrPositiveInteger")); + assertThat(e.getCause().getMessage(), allOf(containsString("propertyOrPositiveInteger"), containsString("valid"), containsString("not"))); } } diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java index 5350076eee..501757f03d 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java @@ -37,15 +37,20 @@ import org.w3c.dom.Document; import org.w3c.dom.Node; +import javax.xml.namespace.NamespaceContext; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; import java.io.File; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; import java.util.ServiceLoader; import java.util.Set; @@ -61,6 +66,8 @@ import static org.ehcache.osgi.ClusterSupport.startServer; import static org.ehcache.osgi.OsgiTestUtils.baseConfiguration; import static org.ehcache.osgi.OsgiTestUtils.gradleBundle; +import static org.ehcache.xml.ConfigurationParser.discoverSchema; +import static org.ehcache.xml.XmlConfiguration.CORE_SCHEMA_URL; import static org.ehcache.osgi.OsgiTestUtils.jaxbConfiguration; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; @@ -142,9 +149,18 @@ public static void testProgrammaticClusteredCache(ClusterSupport.Cluster cluster public static void testXmlClusteredCache(ClusterSupport.Cluster cluster) throws Exception { File config = cluster.getWorkingArea().resolve("ehcache.xml").toFile(); - Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(TestMethods.class.getResourceAsStream("ehcache-clustered-osgi.xml")); + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + documentBuilderFactory.setSchema(discoverSchema(new StreamSource(CORE_SCHEMA_URL.openStream()))); + + Document doc = documentBuilderFactory.newDocumentBuilder().parse(TestMethods.class.getResourceAsStream("ehcache-clustered-osgi.xml")); + XPath xpath = XPathFactory.newInstance().newXPath(); - Node clusterUriAttribute = (Node) xpath.evaluate("//config/service/cluster/connection/@url", doc, XPathConstants.NODE); + xpath.setNamespaceContext(new SimpleNamespaceContext() + .with("eh", "http://www.ehcache.org/v3") + .with("tc", "http://www.ehcache.org/v3/clustered")); + + Node clusterUriAttribute = (Node) xpath.evaluate("//eh:config/eh:service/tc:cluster/tc:connection/@url", doc, XPathConstants.NODE); clusterUriAttribute.setTextContent(cluster.getConnectionUri().toString() + "/cache-manager"); Transformer xformer = TransformerFactory.newInstance().newTransformer(); xformer.transform(new DOMSource(doc), new StreamResult(config)); @@ -178,4 +194,30 @@ public static void testAllServicesAreAvailable() { assertThat(osgiAvailableClasses, hasItems(jdkAvailableClasses.toArray(new String[0]))); } } + + static class SimpleNamespaceContext implements NamespaceContext { + + public final Map prefixes = new HashMap<>(); + + public SimpleNamespaceContext with(String prefix, String namespaceUri) { + prefixes.put(prefix, namespaceUri); + return this; + } + + @Override + public String getNamespaceURI(String prefix) { + return prefixes.get(prefix); + } + + @Override + public String getPrefix(String namespaceURI) { + return prefixes.entrySet().stream().filter(e -> namespaceURI.equals(e.getValue())) + .map(Map.Entry::getKey).findFirst().orElse(null); + } + + @Override + public Iterator getPrefixes(String namespaceURI) { + return prefixes.keySet().iterator(); + } + }; } diff --git a/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml b/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml index 782cf9ea9a..9444bf37f0 100644 --- a/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml +++ b/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml @@ -23,7 +23,7 @@ - + diff --git a/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java index 5325197c77..d0cd669aa1 100644 --- a/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java @@ -35,6 +35,7 @@ import org.w3c.dom.Element; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXParseException; import javax.xml.XMLConstants; @@ -70,6 +71,7 @@ import java.nio.charset.StandardCharsets; import java.util.AbstractMap; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -88,7 +90,6 @@ import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toMap; -import static java.util.stream.Stream.of; import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; import static org.ehcache.config.builders.ConfigurationBuilder.newConfigurationBuilder; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; @@ -101,11 +102,19 @@ */ public class ConfigurationParser { - private static final SchemaFactory XSD_SCHEMA_FACTORY = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - private static Schema newSchema(Source... schemas) throws SAXException { - synchronized (XSD_SCHEMA_FACTORY) { - return XSD_SCHEMA_FACTORY.newSchema(schemas); + public static Schema newSchema(Source... schemas) throws SAXException { + SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + try { + /* + * Our schema is accidentally not XSD 1.1 compatible. Since Saxon incorrectly (imho) defaults to XSD 1.1 for + * `XMLConstants.W3C_XML_SCHEMA_NS_URI` we force it back to 1.0. + */ + schemaFactory.setProperty("http://saxon.sf.net/feature/xsd-version", "1.0"); + } catch (SAXNotRecognizedException e) { + //not saxon } + schemaFactory.setErrorHandler(new FatalErrorHandler()); + return schemaFactory.newSchema(schemas); } private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance(); @@ -314,9 +323,22 @@ public Document configToDocument(Configuration configuration) throws JAXBExcepti public static class FatalErrorHandler implements ErrorHandler { - private static final Pattern ABSTRACT_TYPE_FAILURES = of("service-creation-configuration", "service-configuration", "resource") - .map(element -> quote(format("\"http://www.ehcache.org/v3\":%s", element))) - .collect(collectingAndThen(joining("|", "^\\Qcvc-complex-type.2.4.a\\E.*'\\{.*(?:", ").*\\}'.*$"), Pattern::compile)); + private static final Collection ABSTRACT_TYPE_FAILURES; + static { + ObjectFactory objectFactory = new ObjectFactory(); + List abstractTypes = asList( + objectFactory.createServiceCreationConfiguration(null).getName(), + objectFactory.createServiceConfiguration(null).getName(), + objectFactory.createResource(null).getName()); + + ABSTRACT_TYPE_FAILURES = asList( + //Xerces + abstractTypes.stream().map(element -> quote(format("\"%s\":%s", element.getNamespaceURI(), element.getLocalPart()))) + .collect(collectingAndThen(joining("|", "^\\Qcvc-complex-type.2.4.a\\E.*'\\{.*(?:", ").*\\}'.*$"), Pattern::compile)), + //Saxon + abstractTypes.stream().map(element -> quote(element.getLocalPart())) + .collect(collectingAndThen(joining("|", "^.*\\QThe content model does not allow element\\E.*(?:", ").*"), Pattern::compile))); + } @Override public void warning(SAXParseException exception) throws SAXException { @@ -330,7 +352,7 @@ public void error(SAXParseException exception) throws SAXException { @Override public void fatalError(SAXParseException exception) throws SAXException { - if (ABSTRACT_TYPE_FAILURES.matcher(exception.getMessage()).matches()) { + if (ABSTRACT_TYPE_FAILURES.stream().anyMatch(pattern -> pattern.matcher(exception.getMessage()).matches())) { throw new XmlConfigurationException( "Cannot confirm XML sub-type correctness. You might be missing client side libraries.", exception); } else { @@ -392,16 +414,26 @@ public static DocumentBuilder documentBuilder(Schema schema) throws ParserConfig } public static Schema discoverSchema(Source ... fixedSources) throws SAXException, IOException { - ArrayList schemaSources = new ArrayList<>(asList(fixedSources)); + Map pluginSchemas = new HashMap<>(); for (CacheManagerServiceConfigurationParser p : servicesOfType(CacheManagerServiceConfigurationParser.class)) { - schemaSources.add(p.getXmlSchema()); + if (!pluginSchemas.containsKey(p.getNamespace())) { + pluginSchemas.put(p.getNamespace(), p.getXmlSchema()); + } } for (CacheServiceConfigurationParser p : servicesOfType(CacheServiceConfigurationParser.class)) { - schemaSources.add(p.getXmlSchema()); + if (!pluginSchemas.containsKey(p.getNamespace())) { + pluginSchemas.put(p.getNamespace(), p.getXmlSchema()); + } } for (CacheResourceConfigurationParser p : servicesOfType(CacheResourceConfigurationParser.class)) { - schemaSources.add(p.getXmlSchema()); + if (!pluginSchemas.containsKey(p.getNamespace())) { + pluginSchemas.put(p.getNamespace(), p.getXmlSchema()); + } } + + List schemaSources = new ArrayList<>(asList(fixedSources)); + schemaSources.addAll(pluginSchemas.values()); + return newSchema(schemaSources.toArray(new Source[0])); } } diff --git a/xml/src/main/java/org/ehcache/xml/DomUtil.java b/xml/src/main/java/org/ehcache/xml/DomUtil.java index 14796f837e..e47f8300d2 100644 --- a/xml/src/main/java/org/ehcache/xml/DomUtil.java +++ b/xml/src/main/java/org/ehcache/xml/DomUtil.java @@ -26,26 +26,18 @@ import java.util.Collection; import java.util.List; -import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; + +import static org.ehcache.xml.ConfigurationParser.newSchema; public class DomUtil { - private static final SchemaFactory XSD_SCHEMA_FACTORY = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); private static final URL CORE_SCHEMA_URL = XmlConfiguration.class.getResource("/ehcache-core.xsd"); - private static Schema newSchema(Source[] schemas) throws SAXException { - synchronized (XSD_SCHEMA_FACTORY) { - return XSD_SCHEMA_FACTORY.newSchema(schemas); - } - } - public static DocumentBuilder createAndGetDocumentBuilder(Collection schemaSources) throws SAXException, ParserConfigurationException { DocumentBuilderFactory factory = createAndGetFactory(schemaSources); DocumentBuilder documentBuilder = factory.newDocumentBuilder(); diff --git a/xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java b/xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java index 97493718fd..7fb910948c 100644 --- a/xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java +++ b/xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java @@ -47,16 +47,16 @@ import java.util.Map; import java.util.Set; -import javax.xml.XMLConstants; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.bind.helpers.DefaultValidationEventHandler; import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; +import static org.ehcache.xml.ConfigurationParser.newSchema; import static org.ehcache.xml.XmlConfiguration.CORE_SCHEMA_URL; public class ResourceConfigurationParser { @@ -64,9 +64,8 @@ public class ResourceConfigurationParser { private static final ObjectFactory OBJECT_FACTORY = new ObjectFactory(); private static final Schema CORE_SCHEMA; static { - SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); try { - CORE_SCHEMA = schemaFactory.newSchema(CORE_SCHEMA_URL); + CORE_SCHEMA = newSchema(new StreamSource(CORE_SCHEMA_URL.toExternalForm())); } catch (Exception e) { throw new AssertionError(e); } diff --git a/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java b/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java index 6e393655a3..f44adb566d 100644 --- a/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java +++ b/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java @@ -368,7 +368,8 @@ public interface Template { } public static Class getClassForName(String name, ClassLoader classLoader) throws ClassNotFoundException { - return PRETTY_FORMATS.stream().filter(p -> p.applies().test(name)).findFirst().map(PrettyClassFormat::lookup).orElseThrow(AssertionError::new).lookup(name, classLoader); + String klazz = name.trim(); + return PRETTY_FORMATS.stream().filter(p -> p.applies().test(klazz)).findFirst().map(PrettyClassFormat::lookup).orElseThrow(AssertionError::new).lookup(klazz, classLoader); } private static final List PRETTY_FORMATS = asList( diff --git a/xml/src/main/resources/ehcache-core.xsd b/xml/src/main/resources/ehcache-core.xsd index 7cd287bc2b..987316b871 100644 --- a/xml/src/main/resources/ehcache-core.xsd +++ b/xml/src/main/resources/ehcache-core.xsd @@ -676,7 +676,7 @@ - + diff --git a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java index 698e5a9be4..4b50e7a2ff 100644 --- a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java +++ b/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java @@ -92,6 +92,7 @@ import static org.ehcache.core.util.ClassLoading.getDefaultClassLoader; import static org.ehcache.xml.XmlConfiguration.getClassForName; import static org.ehcache.xml.XmlConfigurationMatchers.isSameConfigurationAs; +import static org.hamcrest.CoreMatchers.either; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; @@ -255,10 +256,11 @@ public void testInvalidCoreConfiguration() throws Exception { try { new XmlConfiguration(XmlConfigurationTest.class.getResource("/configs/invalid-core.xml")); fail(); - } catch (XmlConfigurationException xce) { - SAXParseException e = (SAXParseException) xce.getCause(); - assertThat(e.getLineNumber(), is(5)); - assertThat(e.getColumnNumber(), is(29)); + } catch (XmlConfigurationException e) { + assertThat(e.getCause().getMessage(), + either(containsString("'ehcache:cach'")) + .or(containsString("'{\"http://www.ehcache.org/v3\":cach}'")) + .or(containsString(""))); } } @@ -267,10 +269,11 @@ public void testInvalidServiceConfiguration() throws Exception { try { new XmlConfiguration(XmlConfigurationTest.class.getResource("/configs/invalid-service.xml")); fail(); - } catch (XmlConfigurationException xce) { - SAXParseException e = (SAXParseException) xce.getCause(); - assertThat(e.getLineNumber(), is(6)); - assertThat(e.getColumnNumber(), is(15)); + } catch (XmlConfigurationException e) { + assertThat(e.getCause().getMessage(), + either(containsString("'foo:bar'")) + .or(containsString("'{\"http://www.example.com/foo\":bar}'")) + .or(containsString(""))); } } From b518715a4be894c21ce7cf08338beda9dc922cd2 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 4 Jun 2021 12:17:00 -0400 Subject: [PATCH 342/372] Upgrade to platform 5.8.6-pre1 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 02ab70c06a..1416c494f5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.6-pre1 +terracottaPlatformVersion = 5.8.6-pre2 terracottaApisVersion = 1.8.0 terracottaCoreVersion = 5.8.1 terracottaPassthroughTestingVersion = 1.8.1 From c5a881abc3510ba7c44c6ad87625ddff5c7c1098 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Thu, 17 Jun 2021 09:27:30 -0700 Subject: [PATCH 343/372] bump dependencies --- gradle.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 1416c494f5..2311928741 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,10 +10,10 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.6-pre2 -terracottaApisVersion = 1.8.0 -terracottaCoreVersion = 5.8.1 -terracottaPassthroughTestingVersion = 1.8.1 +terracottaPlatformVersion = 5.8.6-pre3 +terracottaApisVersion = 1.8.1 +terracottaCoreVersion = 5.8.2-pre3 +terracottaPassthroughTestingVersion = 1.8.2 terracottaUtilitiesVersion = 0.0.8 # Test lib versions From d4ff3af2882654ea0fa3a42a1eb93a9b85d51129 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Tue, 22 Jun 2021 14:10:38 -0700 Subject: [PATCH 344/372] bump dependencies --- gradle.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 2311928741..f4a9072238 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,11 +10,11 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.6-pre3 +terracottaPlatformVersion = 5.8.6-pre5 terracottaApisVersion = 1.8.1 -terracottaCoreVersion = 5.8.2-pre3 +terracottaCoreVersion = 5.8.2-pre5 terracottaPassthroughTestingVersion = 1.8.2 -terracottaUtilitiesVersion = 0.0.8 +terracottaUtilitiesVersion = 0.0.9 # Test lib versions junitVersion = 4.13.1 From 338163798f26f98b4c7ede8ed933d27044f2aa31 Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Wed, 30 Jun 2021 11:09:00 -0700 Subject: [PATCH 345/372] bump dependencies --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index f4a9072238..2c762c53de 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.6-pre5 +terracottaPlatformVersion = 5.8.6-pre7 terracottaApisVersion = 1.8.1 -terracottaCoreVersion = 5.8.2-pre5 +terracottaCoreVersion = 5.8.2-pre6 terracottaPassthroughTestingVersion = 1.8.2 terracottaUtilitiesVersion = 0.0.9 From 0bcb57817c5923646a292a2a720cca9fa71c83b9 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 7 Jul 2021 14:13:56 -0400 Subject: [PATCH 346/372] platform upgrade for TDB-5308 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 2c762c53de..8e4dceb26d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.6-pre7 +terracottaPlatformVersion = 5.8.6-pre8 terracottaApisVersion = 1.8.1 terracottaCoreVersion = 5.8.2-pre6 terracottaPassthroughTestingVersion = 1.8.2 From 160c6b1182a82da20a797b810d4ba6eadf0a0e37 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 7 Jul 2021 18:16:11 -0400 Subject: [PATCH 347/372] platform 5.8.6-pre9 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 8e4dceb26d..28c3befeed 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.6-pre8 +terracottaPlatformVersion = 5.8.6-pre9 terracottaApisVersion = 1.8.1 terracottaCoreVersion = 5.8.2-pre6 terracottaPassthroughTestingVersion = 1.8.2 From 5ed4664d2fab50a94754ce834a267c0022aea157 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 13 Jul 2021 17:52:58 +0200 Subject: [PATCH 348/372] Upgrade to latest versions --- gradle.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 28c3befeed..e5d062bb47 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.6-pre9 +terracottaPlatformVersion = 5.8.6-pre10 terracottaApisVersion = 1.8.1 -terracottaCoreVersion = 5.8.2-pre6 +terracottaCoreVersion = 5.8.2-pre7 terracottaPassthroughTestingVersion = 1.8.2 terracottaUtilitiesVersion = 0.0.9 @@ -21,7 +21,7 @@ junitVersion = 4.13.1 assertjVersion = 3.9.0 hamcrestVersion = 1.3 mockitoVersion = 2.23.4 -jacksonVersion = 2.12.2 +jacksonVersion = 2.12.4 jcacheTckVersion = 1.1.0 # Tools From 012497ef68080d067eff1532c6370112cbc42aae Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 29 Jul 2021 15:57:25 +0200 Subject: [PATCH 349/372] TDB-5409: upgrade platform to fix deadlock in DC --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e5d062bb47..c72865a627 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.6-pre10 +terracottaPlatformVersion = 5.8.6-pre11 terracottaApisVersion = 1.8.1 terracottaCoreVersion = 5.8.2-pre7 terracottaPassthroughTestingVersion = 1.8.2 From 57b2c88834ab3892a20355e87e30100f99507694 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 30 Jul 2021 21:37:43 +0200 Subject: [PATCH 350/372] Upgrade platform to fix another old deadlock in Nomad --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index c72865a627..5bd558df8c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.6-pre11 +terracottaPlatformVersion = 5.8.6-pre12 terracottaApisVersion = 1.8.1 terracottaCoreVersion = 5.8.2-pre7 terracottaPassthroughTestingVersion = 1.8.2 From 5fe6998d1d37e8ffdd6ff9f0fa478cd02b508059 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 30 Jul 2021 22:53:24 +0200 Subject: [PATCH 351/372] Core 5.8.2 and Platform 5.8.6 --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5bd558df8c..e11dc023e5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.6-pre12 +terracottaPlatformVersion = 5.8.6 terracottaApisVersion = 1.8.1 -terracottaCoreVersion = 5.8.2-pre7 +terracottaCoreVersion = 5.8.2 terracottaPassthroughTestingVersion = 1.8.2 terracottaUtilitiesVersion = 0.0.9 From 6a41d83d2b7fd0b0906dde12fad305bffaa9270d Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 2 Aug 2021 16:58:37 -0400 Subject: [PATCH 352/372] Fixes #2912 : Lazily evaluate dependent projects to ensure correct source jar content --- buildSrc/src/main/groovy/EhDistribute.groovy | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/buildSrc/src/main/groovy/EhDistribute.groovy b/buildSrc/src/main/groovy/EhDistribute.groovy index ac75663663..1648c15d6a 100644 --- a/buildSrc/src/main/groovy/EhDistribute.groovy +++ b/buildSrc/src/main/groovy/EhDistribute.groovy @@ -27,7 +27,6 @@ class EhDistribute implements Plugin { @Override void apply(Project project) { def utils = new Utils(project.baseVersion, project.logger) - def hashsetOfProjects = project.configurations.compileOnly.dependencies.withType(ProjectDependency).dependencyProject project.plugins.apply 'java-library' project.plugins.apply 'maven' @@ -73,9 +72,11 @@ class EhDistribute implements Plugin { project.sourceJar { - from hashsetOfProjects.flatten { - it.sourceSets.main.allSource - } + from project.configurations.named('compileOnly').map({ + it.dependencies.withType(ProjectDependency).toSet().collect { + it.dependencyProject.sourceSets.main.allSource + } + }) } project.signing { From 936546fb9dd2a6794acc3df9ae68f1beffc6f164 Mon Sep 17 00:00:00 2001 From: Tom Mesic <59479956+tmesic99@users.noreply.github.com> Date: Mon, 16 Aug 2021 09:01:00 -0400 Subject: [PATCH 353/372] core and platform version bump --- .../management/AbstractClusteringManagementTest.java | 1 + gradle.properties | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 468a0253f9..0d8e83183e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -151,6 +151,7 @@ private static void initCM() throws InterruptedException { "CLIENT_CONNECTED", "CLIENT_PROPERTY_ADDED", "CLIENT_PROPERTY_ADDED", + "CLIENT_PROPERTY_ADDED", "CLIENT_REGISTRY_AVAILABLE", "CLIENT_TAGS_UPDATED", "EHCACHE_RESOURCE_POOLS_CONFIGURED", diff --git a/gradle.properties b/gradle.properties index e11dc023e5..4effe53862 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.6 +terracottaPlatformVersion = 5.8.7-pre1 terracottaApisVersion = 1.8.1 -terracottaCoreVersion = 5.8.2 +terracottaCoreVersion = 5.8.3-pre2 terracottaPassthroughTestingVersion = 1.8.2 terracottaUtilitiesVersion = 0.0.9 From 9d920f428f565d0dab776478041a9f5f70265295 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 16 Aug 2021 18:24:13 +0200 Subject: [PATCH 354/372] platform 5.8.7-pre2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4effe53862..662fd46c75 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.7-pre1 +terracottaPlatformVersion = 5.8.7-pre2 terracottaApisVersion = 1.8.1 terracottaCoreVersion = 5.8.3-pre2 terracottaPassthroughTestingVersion = 1.8.2 From 4ecd8764db9d1b3a6efedc7161c6fe2d6881e2c0 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 16 Aug 2021 13:58:54 -0400 Subject: [PATCH 355/372] Use PortManager for server port allocations --- clustered/osgi-test/build.gradle | 1 + .../java/org/ehcache/osgi/OsgiTestUtils.java | 32 +++++++++++-------- gradle.properties | 1 + 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/clustered/osgi-test/build.gradle b/clustered/osgi-test/build.gradle index f16d5fffa1..0c5e8bb791 100644 --- a/clustered/osgi-test/build.gradle +++ b/clustered/osgi-test/build.gradle @@ -29,6 +29,7 @@ dependencies { osgiModule project(':clustered:clustered-dist') osgiModule "javax.cache:cache-api:$parent.jcacheVersion" osgiModule "org.slf4j:slf4j-simple:$parent.slf4jVersion" + osgiModule "org.terracotta:terracotta-utilities-port-chooser:$terracottaUtilitiesVersion" osgiModule 'org.apache.felix:org.apache.felix.scr:2.1.6' //IDEs cannot handle the :dist or :clustered:clustered-dist dependencies diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java index 3f6e6dfd2e..6e25fa2edc 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/OsgiTestUtils.java @@ -19,22 +19,23 @@ import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.options.UrlProvisionOption; import org.ops4j.pax.exam.options.WrappedUrlProvisionOption; +import org.terracotta.utilities.test.net.PortManager; import java.io.Closeable; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; -import java.net.InetSocketAddress; import java.net.URI; -import java.nio.channels.ServerSocketChannel; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Collection; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; import static java.nio.file.Files.find; import static java.nio.file.Files.isRegularFile; +import static java.util.Arrays.asList; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.joining; import static org.ops4j.pax.exam.CoreOptions.bundle; @@ -50,6 +51,8 @@ public static Option baseConfiguration() { gradleBundle("org.slf4j:slf4j-api"), gradleBundle("org.slf4j:slf4j-simple").noStart(), gradleBundle("org.apache.felix:org.apache.felix.scr"), + wrappedGradleBundle("org.terracotta:terracotta-utilities-port-chooser"), + wrappedGradleBundle("org.terracotta:terracotta-utilities-tools"), systemProperty("pax.exam.osgi.unresolved.fail").value("true"), junitBundles() ); @@ -76,8 +79,10 @@ public static Cluster startServer(Path serverDirectory) throws IOException { Path kitLocation = Paths.get(System.getProperty("kitInstallationPath")); Path configFile = serverDirectory.resolve("tc-config.xml"); - int tsaPort = selectAvailableEphemeralPort(); - int tsaGroupPort = selectAvailableEphemeralPort(); + + PortManager portManager = PortManager.getInstance(); + PortManager.PortRef tsaPort = portManager.reservePort(); + PortManager.PortRef tsaGroupPort = portManager.reservePort(); try (PrintWriter writer = new PrintWriter(new FileWriter(configFile.toFile()))) { writer.println(""); @@ -92,8 +97,8 @@ public static Cluster startServer(Path serverDirectory) throws IOException { writer.println(""); writer.println(""); writer.println("" + serverDirectory.toString() + ""); - writer.println("" + tsaPort + ""); - writer.println("" + tsaGroupPort + ""); + writer.println("" + tsaPort.port() + ""); + writer.println("" + tsaGroupPort.port() + ""); writer.println(""); writer.println("120"); writer.println(""); @@ -125,13 +130,7 @@ public static Cluster startServer(Path serverDirectory) throws IOException { "-f", configFile.toString()) .inheritIO(); - return new Cluster(serverProcess.start(), URI.create("terracotta://localhost:" + tsaPort), serverDirectory); - } - - private static int selectAvailableEphemeralPort() throws IOException { - try (ServerSocketChannel channel = ServerSocketChannel.open().bind(new InetSocketAddress(0))) { - return channel.socket().getLocalPort(); - } + return new Cluster(serverProcess.start(), URI.create("terracotta://localhost:" + tsaPort.port()), serverDirectory, tsaPort, tsaGroupPort); } static class Cluster implements Closeable { @@ -139,11 +138,14 @@ static class Cluster implements Closeable { private final Process serverProcess; private final URI connectionUri; private final Path workingPath; + private final Collection ports; + - Cluster(Process serverProcess, URI connectionUri, Path workingPath) { + Cluster(Process serverProcess, URI connectionUri, Path workingPath, PortManager.PortRef... ports) { this.serverProcess = serverProcess; this.connectionUri = connectionUri; this.workingPath = workingPath; + this.ports = asList(ports); } public URI getConnectionUri() { @@ -159,6 +161,8 @@ public void close() throws IOException { serverProcess.waitFor(60, TimeUnit.SECONDS); } catch (InterruptedException e) { throw new AssertionError(e); + } finally { + ports.forEach(PortManager.PortRef::close); } } } diff --git a/gradle.properties b/gradle.properties index 10a3644ae6..38e39a57c8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,6 +13,7 @@ terracottaPlatformVersion = 5.6.0-pre5 terracottaApisVersion = 1.6.0-pre2 terracottaCoreVersion = 5.6.0-pre6 terracottaPassthroughTestingVersion = 1.6.0-pre2 +terracottaUtilitiesVersion = 0.0.9 # Test lib versions junitVersion = 4.12 From 3ebf789fb7f45bac37774138e5173ccd149dc4e2 Mon Sep 17 00:00:00 2001 From: mobasherul Date: Tue, 24 Aug 2021 21:26:35 +0530 Subject: [PATCH 356/372] Bump up terracotta-platform version. --- .../server/ClusterTierManagerActiveEntityTest.java | 13 +++++++++++++ .../server/ClusterTierManagerPassiveEntityTest.java | 13 +++++++++++++ .../server/store/ClusterTierActiveEntityTest.java | 13 +++++++++++++ .../server/store/ClusterTierPassiveEntityTest.java | 13 +++++++++++++ gradle.properties | 2 +- 5 files changed, 53 insertions(+), 1 deletion(-) diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java index 017c0fd4a6..c58061c0cb 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java @@ -38,6 +38,7 @@ import org.terracotta.offheapresource.OffHeapResource; import org.terracotta.offheapresource.OffHeapResourceIdentifier; import org.terracotta.offheapresource.OffHeapResources; +import org.terracotta.offheapresource.OffHeapUsageEvent; import org.terracotta.offheapstore.util.MemoryUnit; import java.util.Collection; @@ -46,6 +47,8 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.UUID; +import java.util.function.Consumer; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; @@ -676,6 +679,16 @@ public boolean setCapacity(long size) throws IllegalArgumentException { throw new UnsupportedOperationException("Not supported"); } + @Override + public void addUsageListener(UUID listenerUUID, float threshold, Consumer consumer) { + + } + + @Override + public void removeUsageListener(UUID listenerUUID) throws IllegalArgumentException { + + } + private long getUsed() { return used; } diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java index e3eed2ed69..1844b33e55 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java @@ -37,6 +37,7 @@ import org.terracotta.offheapresource.OffHeapResource; import org.terracotta.offheapresource.OffHeapResourceIdentifier; import org.terracotta.offheapresource.OffHeapResources; +import org.terracotta.offheapresource.OffHeapUsageEvent; import org.terracotta.offheapstore.util.MemoryUnit; import java.util.Collection; @@ -45,6 +46,8 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.UUID; +import java.util.function.Consumer; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; @@ -439,6 +442,16 @@ public boolean setCapacity(long size) throws IllegalArgumentException { throw new UnsupportedOperationException("Not supported"); } + @Override + public void addUsageListener(UUID listenerUUID, float threshold, Consumer consumer) { + + } + + @Override + public void removeUsageListener(UUID listenerUUID) throws IllegalArgumentException { + + } + private long getUsed() { return used; } diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index 4c1ad89cc1..e94115722a 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -71,6 +71,7 @@ import org.terracotta.offheapresource.OffHeapResource; import org.terracotta.offheapresource.OffHeapResourceIdentifier; import org.terracotta.offheapresource.OffHeapResources; +import org.terracotta.offheapresource.OffHeapUsageEvent; import org.terracotta.offheapstore.util.MemoryUnit; import java.nio.ByteBuffer; @@ -80,12 +81,14 @@ import java.util.Map; import java.util.Random; import java.util.Set; +import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; +import java.util.function.Consumer; import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.Matchers.entry; @@ -1425,6 +1428,16 @@ public boolean setCapacity(long size) throws IllegalArgumentException { throw new UnsupportedOperationException("Not supported"); } + @Override + public void addUsageListener(UUID listenerUUID, float threshold, Consumer consumer) { + + } + + @Override + public void removeUsageListener(UUID listenerUUID) throws IllegalArgumentException { + + } + private long getUsed() { return used; } diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java index a01df038d3..ad6604a27f 100644 --- a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java +++ b/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java @@ -44,6 +44,7 @@ import org.terracotta.offheapresource.OffHeapResource; import org.terracotta.offheapresource.OffHeapResourceIdentifier; import org.terracotta.offheapresource.OffHeapResources; +import org.terracotta.offheapresource.OffHeapUsageEvent; import org.terracotta.offheapstore.util.MemoryUnit; import java.util.Collection; @@ -52,6 +53,8 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.UUID; +import java.util.function.Consumer; import static org.ehcache.clustered.ChainUtils.createPayload; import static org.ehcache.clustered.ChainUtils.sequencedChainOf; @@ -422,6 +425,16 @@ public boolean setCapacity(long size) throws IllegalArgumentException { throw new UnsupportedOperationException("Not supported"); } + @Override + public void addUsageListener(UUID listenerUUID, float threshold, Consumer consumer) { + + } + + @Override + public void removeUsageListener(UUID listenerUUID) throws IllegalArgumentException { + + } + private long getUsed() { return used; } diff --git a/gradle.properties b/gradle.properties index 662fd46c75..441c0989fa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.7-pre2 +terracottaPlatformVersion = 5.8.7-pre3 terracottaApisVersion = 1.8.1 terracottaCoreVersion = 5.8.3-pre2 terracottaPassthroughTestingVersion = 1.8.2 From ff96e0c4626b923f348d275fc0f417449dd4fe2e Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Tue, 24 Aug 2021 13:14:28 -0700 Subject: [PATCH 357/372] bump to final --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 441c0989fa..ac7d260d75 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.7-pre3 +terracottaPlatformVersion = 5.8.7 terracottaApisVersion = 1.8.1 -terracottaCoreVersion = 5.8.3-pre2 +terracottaCoreVersion = 5.8.3 terracottaPassthroughTestingVersion = 1.8.2 terracottaUtilitiesVersion = 0.0.9 From 08d07700807e8595b8865dd05ae0a6210d0f6da4 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 1 Jul 2021 13:47:23 -0400 Subject: [PATCH 358/372] Add custom manifest entries in jars --- build.gradle | 2 +- buildSrc/src/main/groovy/EhDistribute.groovy | 2 +- buildSrc/src/main/groovy/scripts/Utils.groovy | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 1a6bd85609..96512dd637 100644 --- a/build.gradle +++ b/build.gradle @@ -139,7 +139,7 @@ subprojects { } jar { - utils.fillManifest(manifest,"ehcache-${project.name}") + utils.fillManifest(manifest,"${project.group}","ehcache-${project.name}") from "$rootDir/LICENSE" } diff --git a/buildSrc/src/main/groovy/EhDistribute.groovy b/buildSrc/src/main/groovy/EhDistribute.groovy index 1648c15d6a..22cabd5530 100644 --- a/buildSrc/src/main/groovy/EhDistribute.groovy +++ b/buildSrc/src/main/groovy/EhDistribute.groovy @@ -67,7 +67,7 @@ class EhDistribute implements Plugin { classpath = project.files(project.configurations.shadowCompile, project.configurations.shadowProvided) - utils.fillManifest(manifest, project.archivesBaseName) + utils.fillManifest(manifest, project.group, project.archivesBaseName) } diff --git a/buildSrc/src/main/groovy/scripts/Utils.groovy b/buildSrc/src/main/groovy/scripts/Utils.groovy index 6f46430b9d..1bcec0c570 100644 --- a/buildSrc/src/main/groovy/scripts/Utils.groovy +++ b/buildSrc/src/main/groovy/scripts/Utils.groovy @@ -44,11 +44,13 @@ class Utils { logger.debug(revision) } - def fillManifest(manifest, title) { + def fillManifest(manifest, group, title) { manifest.attributes( 'provider': 'gradle', 'Implementation-Title': title, - 'Implementation-Version': "$version $revision", + 'Implementation-Vendor-Id': group, + 'Implementation-Version': "$version", + 'Implementation-Revision': "$revision", 'Built-By': System.getProperty('user.name'), 'Built-JDK': System.getProperty('java.version')) if (isReleaseVersion) { From 358053496698de6e1dec1e0c04b1f1b054b48b3a Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 1 Sep 2021 11:16:20 -0400 Subject: [PATCH 359/372] Upgrades: * Terracotta Platform 5.8.8-pre1 * Terracotta Core 5.8.4-pre1 --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index ac7d260d75..928dee0782 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.7 +terracottaPlatformVersion = 5.8.8-pre1 terracottaApisVersion = 1.8.1 -terracottaCoreVersion = 5.8.3 +terracottaCoreVersion = 5.8.4-pre1 terracottaPassthroughTestingVersion = 1.8.2 terracottaUtilitiesVersion = 0.0.9 From b1d02062be31823b8b76af9cd04be0e8e3af3738 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Thu, 2 Sep 2021 09:23:47 -0400 Subject: [PATCH 360/372] Respond to interrupt of ExecutorScheduler with immediate shutdown and logging --- .../ehcache/clustered/util/runners/ExecutorScheduler.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ExecutorScheduler.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ExecutorScheduler.java index fc60a33b9a..225eb8a955 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ExecutorScheduler.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/util/runners/ExecutorScheduler.java @@ -16,13 +16,18 @@ package org.ehcache.clustered.util.runners; import org.junit.runners.model.RunnerScheduler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class ExecutorScheduler implements RunnerScheduler { + private static final Logger LOGGER = LoggerFactory.getLogger(ExecutorScheduler.class); + public final ExecutorService executor; public ExecutorScheduler(ExecutorService executor) { @@ -42,7 +47,8 @@ public void finished() { throw new AssertionError(new TimeoutException()); } } catch (InterruptedException e) { - throw new AssertionError(e); + List runnables = executor.shutdownNow(); + LOGGER.warn("Forcibly terminating execution of scheduled test tasks due to interrupt (" + runnables.size() + " tasks remain unscheduled)"); } } } From 13647e3c8241f0f5aaf0e5ff10a777e29bd46c3d Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 3 Sep 2021 12:51:54 -0400 Subject: [PATCH 361/372] Revert "Allow clustered integration tests to run easily in an IDE (close #2118)" This reverts commit c1a87c74bbfc8cedf89e33cd0d145072dddb17a8. --- clustered/integration-test/README.adoc | 16 +++ clustered/integration-test/build.gradle | 1 - .../clustered/BasicClusteredCacheOpsTest.java | 2 +- .../clustered/BasicEntityInteractionTest.java | 2 +- ...anagerLifecycleEhcacheIntegrationTest.java | 2 +- ...gerClientEntityFactoryIntegrationTest.java | 2 +- .../org/ehcache/clustered/ClusteredTests.java | 98 ------------------- .../ehcache/clustered/ClusteredTestsTest.java | 33 ------- .../clustered/JCacheClusteredTest.java | 2 +- .../ResourcePoolAllocationFailureTest.java | 2 +- .../VoltronReadWriteLockIntegrationTest.java | 4 +- ...onReadWriteLockPassiveIntegrationTest.java | 4 +- .../AbstractClusteringManagementTest.java | 3 +- .../EhcacheConfigWithManagementTest.java | 3 +- ...dCacheOpsReplicationMultiThreadedTest.java | 3 +- ...BasicClusteredCacheOpsReplicationTest.java | 3 +- ...OpsReplicationWithMultipleClientsTest.java | 3 +- .../BasicLifeCyclePassiveReplicationTest.java | 3 +- .../clustered/replication/DuplicateTest.java | 3 +- .../clustered/sync/PassiveSyncTest.java | 3 +- 20 files changed, 32 insertions(+), 160 deletions(-) create mode 100644 clustered/integration-test/README.adoc delete mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java delete mode 100644 clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTestsTest.java diff --git a/clustered/integration-test/README.adoc b/clustered/integration-test/README.adoc new file mode 100644 index 0000000000..7326067328 --- /dev/null +++ b/clustered/integration-test/README.adoc @@ -0,0 +1,16 @@ += How to launch tests from an IDE + +== Gradle launch + +Launch the gradle task corresponding to `:clustered:integration-test:test`. + +If that doesn't work (possibly caused by a warning saying `warning: [options] bootstrap class path not set in conjunction with -source 1.6`) +try the Java launch. + +== Java launch + +1. Create the kit with `gradle :clustered:integration-test:copyServerLibs` +2. Launch the test once to make it fail +3. Edit the test configuration to add the following VM options: + +`-Dcom.tc.l2.lockmanager.greedy.locks.enabled=false -DkitInstallationPath=build/ehcache-kit/ehcache-clustered-3.3.0-SNAPSHOT-kit` diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index 8f677ca013..f9e06323fd 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -30,7 +30,6 @@ dependencies { testCompileOnly project(':impl') testCompileOnly project(':xml') testCompileOnly "org.terracotta.internal:client-runtime:$terracottaCoreVersion" - testCompileOnly "org.terracotta:runnel:$terracottaPlatformVersion" testCompile project(':management') testCompile "org.terracotta.management.dist:mnm-nms:$parent.managementVersion" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java index 09361170a5..53edf74319 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicClusteredCacheOpsTest.java @@ -49,7 +49,7 @@ import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class BasicClusteredCacheOpsTest extends ClusteredTests { +public class BasicClusteredCacheOpsTest { private static final String RESOURCE_CONFIG = "" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java index 994dac275d..b3dd2d6cb0 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/BasicEntityInteractionTest.java @@ -41,7 +41,7 @@ import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class BasicEntityInteractionTest extends ClusteredTests { +public class BasicEntityInteractionTest { private static final String RESOURCE_CONFIG = "" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java index 2534e71466..e919d45fdd 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/CacheManagerLifecycleEhcacheIntegrationTest.java @@ -58,7 +58,7 @@ import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class CacheManagerLifecycleEhcacheIntegrationTest extends ClusteredTests { +public class CacheManagerLifecycleEhcacheIntegrationTest { private static final String RESOURCE_CONFIG = "" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java index 9e861b9a3b..b9abda8d9b 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusterTierManagerClientEntityFactoryIntegrationTest.java @@ -40,7 +40,7 @@ import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class ClusterTierManagerClientEntityFactoryIntegrationTest extends ClusteredTests { +public class ClusterTierManagerClientEntityFactoryIntegrationTest { private static final Map EMPTY_RESOURCE_MAP = Collections.emptyMap(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java deleted file mode 100644 index 63e573d6c8..0000000000 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTests.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.ehcache.clustered; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Comparator; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; - -/** - * Base class for all clustered tests. It makes sure the environment is correctly configured to launch the servers. Especially - * in the IDE. - */ -public abstract class ClusteredTests { - - private static final boolean FORCE_KIT_REFRESH = false; - - static { - initInstallationPath(); - } - - private static void initInstallationPath() { - if(System.getProperty("kitInstallationPath") != null) { - return; // nothing to do, all set - } - - String currentDir = System.getProperty("user.dir"); - - // We might have the root of ehcache or in the integration-test directory - // as current working directory - String diskPrefix; - if(Paths.get(currentDir).getFileName().toString().equals("integration-test")) { - diskPrefix = ""; - } - else { - diskPrefix = "clustered/integration-test/"; - } - - String kitInstallationPath = getKitInstallationPath(diskPrefix); - - if (kitInstallationPath == null || FORCE_KIT_REFRESH) { - installKit(diskPrefix); - kitInstallationPath = getKitInstallationPath(diskPrefix); - } - - System.setProperty("kitInstallationPath", kitInstallationPath); - } - - private static void installKit(String diskPrefix) { - try { - Process process = new ProcessBuilder(diskPrefix + "../../gradlew", "copyServerLibs") - .redirectError(ProcessBuilder.Redirect.INHERIT) - .redirectOutput(ProcessBuilder.Redirect.INHERIT) - .start(); - int status = process.waitFor(); - assertThat(status).isZero(); - } catch (IOException e) { - fail("Failed to start gradle to install kit", e); - } catch (InterruptedException e) { - fail("Interrupted while installing kit", e); - } - } - - private static String getKitInstallationPath(String diskPrefix) { - String basedir = diskPrefix + "build/ehcache-kit"; - if(!new File(basedir).exists()) { - return null; - } - try { - return Files.list(Paths.get(basedir)) - .sorted(Comparator.naturalOrder().reversed()) // the last one should be the one with the highest version - .findFirst() - .map(path -> path.toAbsolutePath().normalize().toString()) - .orElse(null); - } catch (IOException e) { - fail("Failed to set kitInstallationPath from " + basedir, e); - return null; - } - } -} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTestsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTestsTest.java deleted file mode 100644 index 7acfa1dddd..0000000000 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ClusteredTestsTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.ehcache.clustered; - -import org.junit.Test; - -import java.io.File; - -import static org.assertj.core.api.Assertions.assertThat; - -public class ClusteredTestsTest extends ClusteredTests { - - @Test - public void test() { - String value = System.getProperty("kitInstallationPath"); - assertThat(new File(value)).exists(); - assertThat(new File(value)).isAbsolute(); - assertThat(new File(value).toString()).doesNotContain(".."); - } -} diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java index 0d8474405f..75c32e3661 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java @@ -33,7 +33,7 @@ /** * JCacheClusteredTest */ -public class JCacheClusteredTest extends ClusteredTests { +public class JCacheClusteredTest { private static final String RESOURCE_CONFIG = "" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java index d067541f17..979b3628df 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/ResourcePoolAllocationFailureTest.java @@ -41,7 +41,7 @@ import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class ResourcePoolAllocationFailureTest extends ClusteredTests { +public class ResourcePoolAllocationFailureTest { private static final String RESOURCE_CONFIG = "" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java index 1ce060a630..351ea4276e 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockIntegrationTest.java @@ -25,8 +25,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; - -import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock.Hold; import org.junit.BeforeClass; @@ -40,7 +38,7 @@ import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class VoltronReadWriteLockIntegrationTest extends ClusteredTests { +public class VoltronReadWriteLockIntegrationTest { @ClassRule public static Cluster CLUSTER = newCluster().in(new File("build/cluster")).build(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java index e75feeeda4..80cc659251 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/lock/VoltronReadWriteLockPassiveIntegrationTest.java @@ -20,8 +20,6 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; - -import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock.Hold; import org.junit.Before; @@ -34,7 +32,7 @@ import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class VoltronReadWriteLockPassiveIntegrationTest extends ClusteredTests { +public class VoltronReadWriteLockPassiveIntegrationTest { @ClassRule public static Cluster CLUSTER = newCluster(2).in(new File("build/cluster")).build(); diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 7db4e28c89..c9ce95c474 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -17,7 +17,6 @@ import org.ehcache.CacheManager; import org.ehcache.Status; -import org.ehcache.clustered.ClusteredTests; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; @@ -64,7 +63,7 @@ import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public abstract class AbstractClusteringManagementTest extends ClusteredTests { +public abstract class AbstractClusteringManagementTest { private static final String RESOURCE_CONFIG = "" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java index fd941deb85..cf053c9b65 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/EhcacheConfigWithManagementTest.java @@ -16,7 +16,6 @@ package org.ehcache.clustered.management; import org.ehcache.CacheManager; -import org.ehcache.clustered.ClusteredTests; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.ehcache.management.registry.DefaultManagementRegistryConfiguration; @@ -35,7 +34,7 @@ import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class EhcacheConfigWithManagementTest extends ClusteredTests { +public class EhcacheConfigWithManagementTest { private static final String RESOURCE_CONFIG = "" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index 3cc647adac..c23a8c0de9 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -18,7 +18,6 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; -import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteredStoreConfigurationBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; @@ -72,7 +71,7 @@ * Finally the same key set correctness is asserted. */ @RunWith(Parameterized.class) -public class BasicClusteredCacheOpsReplicationMultiThreadedTest extends ClusteredTests { +public class BasicClusteredCacheOpsReplicationMultiThreadedTest { private static final int NUM_OF_THREADS = 10; private static final int JOB_SIZE = 100; diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java index 0580d27d4d..e81fb590b1 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationTest.java @@ -18,7 +18,6 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; -import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteredStoreConfigurationBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; @@ -53,7 +52,7 @@ import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; @RunWith(Parameterized.class) -public class BasicClusteredCacheOpsReplicationTest extends ClusteredTests { +public class BasicClusteredCacheOpsReplicationTest { private static final String RESOURCE_CONFIG = "" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java index b755d1d046..1472aa5c16 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationWithMultipleClientsTest.java @@ -18,7 +18,6 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; -import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteredStoreConfigurationBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; @@ -61,7 +60,7 @@ * The point of this test is to assert proper data read after fail-over handling. */ @RunWith(Parameterized.class) -public class BasicClusteredCacheOpsReplicationWithMultipleClientsTest extends ClusteredTests { +public class BasicClusteredCacheOpsReplicationWithMultipleClientsTest { private static final String RESOURCE_CONFIG = "" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java index a2ed0c85ea..4d0588993a 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicLifeCyclePassiveReplicationTest.java @@ -17,7 +17,6 @@ package org.ehcache.clustered.replication; import org.ehcache.PersistentCacheManager; -import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.internal.lock.VoltronReadWriteLock; import org.ehcache.config.builders.CacheManagerBuilder; import org.junit.After; @@ -39,7 +38,7 @@ import static org.junit.Assert.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class BasicLifeCyclePassiveReplicationTest extends ClusteredTests { +public class BasicLifeCyclePassiveReplicationTest { private static final String RESOURCE_CONFIG = "" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java index aef4facb06..78c9cd8cbe 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/DuplicateTest.java @@ -17,7 +17,6 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; -import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteredStoreConfigurationBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; @@ -49,7 +48,7 @@ import static org.assertj.core.api.Assertions.fail; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class DuplicateTest extends ClusteredTests { +public class DuplicateTest { private static final String RESOURCE_CONFIG = "" diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java index f2b5cc88f3..bfd364125f 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/sync/PassiveSyncTest.java @@ -18,7 +18,6 @@ import org.ehcache.Cache; import org.ehcache.PersistentCacheManager; -import org.ehcache.clustered.ClusteredTests; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.config.CacheConfiguration; @@ -43,7 +42,7 @@ import static org.junit.Assert.assertThat; import static org.terracotta.testing.rules.BasicExternalClusterBuilder.newCluster; -public class PassiveSyncTest extends ClusteredTests { +public class PassiveSyncTest { private static final String RESOURCE_CONFIG = "" + "" From 99f797776a27257cd977a1577c9190d108d88046 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 3 Sep 2021 15:56:27 -0400 Subject: [PATCH 362/372] Remove unncessary readme. --- clustered/integration-test/README.adoc | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 clustered/integration-test/README.adoc diff --git a/clustered/integration-test/README.adoc b/clustered/integration-test/README.adoc deleted file mode 100644 index 7326067328..0000000000 --- a/clustered/integration-test/README.adoc +++ /dev/null @@ -1,16 +0,0 @@ -= How to launch tests from an IDE - -== Gradle launch - -Launch the gradle task corresponding to `:clustered:integration-test:test`. - -If that doesn't work (possibly caused by a warning saying `warning: [options] bootstrap class path not set in conjunction with -source 1.6`) -try the Java launch. - -== Java launch - -1. Create the kit with `gradle :clustered:integration-test:copyServerLibs` -2. Launch the test once to make it fail -3. Edit the test configuration to add the following VM options: - -`-Dcom.tc.l2.lockmanager.greedy.locks.enabled=false -DkitInstallationPath=build/ehcache-kit/ehcache-clustered-3.3.0-SNAPSHOT-kit` From a40503d2374d6c555a8959df2a127bba725742a8 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Tue, 7 Sep 2021 17:45:54 -0400 Subject: [PATCH 363/372] Don't wait for a client operation to push pending invalidations after reconnect --- .../server/state/InvalidationTrackerImpl.java | 5 +- .../server/store/ClusterTierActiveEntity.java | 97 ++++++++----------- .../store/ClusterTierActiveEntityTest.java | 16 ++- 3 files changed, 55 insertions(+), 63 deletions(-) diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/state/InvalidationTrackerImpl.java b/clustered/server/src/main/java/org/ehcache/clustered/server/state/InvalidationTrackerImpl.java index 02f118b354..b060aaaba6 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/state/InvalidationTrackerImpl.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/state/InvalidationTrackerImpl.java @@ -16,11 +16,14 @@ package org.ehcache.clustered.server.state; +import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicBoolean; +import static java.util.Collections.unmodifiableSet; + public class InvalidationTrackerImpl implements InvalidationTracker { private final ConcurrentMap invalidationMap = new ConcurrentHashMap<>(); @@ -67,7 +70,7 @@ public void untrackHashInvalidation(long chainKey) { @Override public Set getTrackedKeys() { - return getInvalidationMap().keySet(); + return unmodifiableSet(new HashSet<>(getInvalidationMap().keySet())); } @Override diff --git a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java b/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java index baa353aa73..7cbda2db25 100644 --- a/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java +++ b/clustered/server/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java @@ -83,7 +83,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; @@ -117,14 +116,11 @@ public class ClusterTierActiveEntity implements ActiveServerEntity messageHandler; private final IEntityMessenger entityMessenger; private final ServerStoreCompatibility storeCompatibility = new ServerStoreCompatibility(); - private final AtomicBoolean reconnectComplete = new AtomicBoolean(true); private final AtomicInteger invalidationIdGenerator = new AtomicInteger(); private final ConcurrentMap clientsWaitingForInvalidation = new ConcurrentHashMap<>(); private final ReconnectMessageCodec reconnectMessageCodec = new ReconnectMessageCodec(); private final ClusterTierManagement management; private final String managerIdentifier; - private final Object inflightInvalidationsMutex = new Object(); - private volatile List inflightInvalidations; private final Set connectedClients = ConcurrentHashMap.newKeySet(); @SuppressWarnings("unchecked") @@ -181,19 +177,9 @@ public void createNew() throws ConfigurationException { management.init(); } - List getInflightInvalidations() { - return this.inflightInvalidations; - } - @Override public void loadExisting() { - inflightInvalidations = new ArrayList<>(); - if (!isStrong()) { - LOGGER.debug("Preparing for handling inflight invalidations"); - addInflightInvalidationsForEventualCaches(); - } stateService.loadStore(storeIdentifier, configuration).setEvictionListener(this::invalidateHashAfterEviction); - reconnectComplete.set(false); management.reload(); } @@ -299,25 +285,6 @@ private EhcacheEntityResponse invokeServerStoreOperation(InvokeContext context, throw new LifecycleException("cluster tier does not exist : '" + storeIdentifier + "'"); } - if (inflightInvalidations != null) { - synchronized (inflightInvalidationsMutex) { - // This logic totally counts on the fact that invokes will only happen - // after all handleReconnects are done, else this is flawed. - if (inflightInvalidations != null) { - List tmpInflightInvalidations = this.inflightInvalidations; - this.inflightInvalidations = null; - LOGGER.debug("Stalling all operations for cluster tier {} for firing inflight invalidations again.", storeIdentifier); - tmpInflightInvalidations.forEach(invalidationState -> { - if (invalidationState.isClearInProgress()) { - invalidateAll(invalidationState.getClientDescriptor()); - } - invalidationState.getInvalidationsInProgress() - .forEach(hashInvalidationToBeResent -> invalidateHashForClient(invalidationState.getClientDescriptor(), hashInvalidationToBeResent)); - }); - } - } - } - switch (message.getMessageType()) { case GET_STORE: { ServerStoreOpMessage.GetMessage getMessage = (ServerStoreOpMessage.GetMessage) message; @@ -522,14 +489,6 @@ private void sendMessageToSelfAndDeferRetirement(ActiveInvokeContext context, Ke } } - private void addInflightInvalidationsForEventualCaches() { - InvalidationTracker invalidationTracker = stateService.getInvalidationTracker(storeIdentifier); - if (invalidationTracker != null) { - inflightInvalidations.add(new InvalidationTuple(null, invalidationTracker.getTrackedKeys(), invalidationTracker.isClearInProgress())); - invalidationTracker.clear(); - } - } - @Override public void notifyDestroyed(ClientSourceId sourceId) { messageHandler.untrackClient(sourceId); @@ -537,28 +496,48 @@ public void notifyDestroyed(ClientSourceId sourceId) { @Override public ReconnectHandler startReconnect() { - return (clientDescriptor, bytes) -> { - if (inflightInvalidations == null) { - throw new AssertionError("Load existing was not invoked before handleReconnect"); - } + List inflightInvalidations = new ArrayList<>(); + + InvalidationTracker invalidationTracker = stateService.getInvalidationTracker(storeIdentifier); + if (invalidationTracker != null) { + inflightInvalidations.add(new InvalidationTuple(null, invalidationTracker.getTrackedKeys(), invalidationTracker.isClearInProgress())); + invalidationTracker.clear(); + } - ClusterTierReconnectMessage reconnectMessage = reconnectMessageCodec.decode(bytes); - ServerSideServerStore serverStore = stateService.getStore(storeIdentifier); - addInflightInvalidationsForStrongCache(clientDescriptor, reconnectMessage, serverStore); + return new ReconnectHandler() { - LOGGER.info("Client '{}' successfully reconnected to newly promoted ACTIVE after failover.", clientDescriptor); + @Override + public void handleReconnect(ClientDescriptor clientDescriptor, byte[] bytes) { + ClusterTierReconnectMessage reconnectMessage = reconnectMessageCodec.decode(bytes); + ServerSideServerStore serverStore = stateService.getStore(storeIdentifier); + addInflightInvalidationsForStrongCache(clientDescriptor, reconnectMessage, serverStore); - connectedClients.add(clientDescriptor); - }; - } + LOGGER.info("Client '{}' successfully reconnected to newly promoted ACTIVE after failover.", clientDescriptor); - private void addInflightInvalidationsForStrongCache(ClientDescriptor clientDescriptor, ClusterTierReconnectMessage reconnectMessage, ServerSideServerStore serverStore) { - if (serverStore.getStoreConfiguration().getConsistency().equals(Consistency.STRONG)) { - Set invalidationsInProgress = reconnectMessage.getInvalidationsInProgress(); - LOGGER.debug("Number of Inflight Invalidations from client ID {} for cache {} is {}.", clientDescriptor.getSourceId().toLong(), storeIdentifier, invalidationsInProgress - .size()); - inflightInvalidations.add(new InvalidationTuple(clientDescriptor, invalidationsInProgress, reconnectMessage.isClearInProgress())); - } + connectedClients.add(clientDescriptor); + } + + private void addInflightInvalidationsForStrongCache(ClientDescriptor clientDescriptor, ClusterTierReconnectMessage reconnectMessage, ServerSideServerStore serverStore) { + if (serverStore.getStoreConfiguration().getConsistency().equals(Consistency.STRONG)) { + Set invalidationsInProgress = reconnectMessage.getInvalidationsInProgress(); + LOGGER.debug("Number of Inflight Invalidations from client ID {} for cache {} is {}.", clientDescriptor.getSourceId().toLong(), storeIdentifier, invalidationsInProgress + .size()); + inflightInvalidations.add(new InvalidationTuple(clientDescriptor, invalidationsInProgress, reconnectMessage.isClearInProgress())); + } + } + + @Override + public void close() { + LOGGER.debug("Stalling all operations for cluster tier {} for firing inflight invalidations again.", storeIdentifier); + inflightInvalidations.forEach(invalidationState -> { + if (invalidationState.isClearInProgress()) { + invalidateAll(invalidationState.getClientDescriptor()); + } + invalidationState.getInvalidationsInProgress() + .forEach(hashInvalidationToBeResent -> invalidateHashForClient(invalidationState.getClientDescriptor(), hashInvalidationToBeResent)); + }); + } + }; } @Override diff --git a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java index 5d77fb0a3e..dc4c572145 100644 --- a/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java +++ b/clustered/server/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java @@ -24,14 +24,17 @@ import org.ehcache.clustered.common.internal.ServerStoreConfiguration; import org.ehcache.clustered.common.internal.exceptions.InvalidServerStoreConfigurationException; import org.ehcache.clustered.common.internal.exceptions.LifecycleException; +import org.ehcache.clustered.common.internal.messages.ClusterTierReconnectMessage; import org.ehcache.clustered.common.internal.messages.ConcurrentEntityMessage; import org.ehcache.clustered.common.internal.messages.EhcacheEntityMessage; import org.ehcache.clustered.common.internal.messages.EhcacheEntityResponse; import org.ehcache.clustered.common.internal.messages.EhcacheResponseType; import org.ehcache.clustered.common.internal.messages.LifeCycleMessageFactory; import org.ehcache.clustered.common.internal.messages.ServerStoreMessageFactory; +import org.ehcache.clustered.common.internal.messages.ReconnectMessageCodec; import org.ehcache.clustered.common.internal.messages.ServerStoreOpMessage; import org.ehcache.clustered.common.internal.store.ClusterTierEntityConfiguration; +import org.ehcache.clustered.server.CommunicatorServiceConfiguration; import org.ehcache.clustered.server.ConcurrencyStrategies; import org.ehcache.clustered.server.EhcacheStateServiceImpl; import org.ehcache.clustered.server.KeySegmentMapper; @@ -50,6 +53,8 @@ import org.terracotta.client.message.tracker.OOOMessageHandler; import org.terracotta.client.message.tracker.OOOMessageHandlerConfiguration; import org.terracotta.client.message.tracker.OOOMessageHandlerImpl; +import org.mockito.ArgumentMatchers; +import org.terracotta.entity.ActiveServerEntity; import org.terracotta.entity.ClientCommunicator; import org.terracotta.entity.ClientDescriptor; import org.terracotta.entity.ConfigurationException; @@ -925,11 +930,16 @@ public void testLoadExistingRecoversInflightInvalidationsForEventualCache() thro InvalidationTracker invalidationTracker = ehcacheStateService.getInvalidationTracker(defaultStoreName); Random random = new Random(); - random.ints(0, 100).limit(10).forEach(invalidationTracker::trackHashInvalidation); + random.ints(0, 100).distinct().limit(10).forEach(invalidationTracker::trackHashInvalidation); - activeEntity.loadExisting(); + ClientDescriptor client = mock(ClientDescriptor.class); + try (ActiveServerEntity.ReconnectHandler reconnect = activeEntity.startReconnect()) { + reconnect.handleReconnect(client, new ReconnectMessageCodec().encode(new ClusterTierReconnectMessage())); + } + + ClientCommunicator clientCommunicator = defaultRegistry.getService(new CommunicatorServiceConfiguration()); - assertThat(activeEntity.getInflightInvalidations().isEmpty(), is(false)); + verify(clientCommunicator, times(10)).sendNoResponse(ArgumentMatchers.eq(client), ArgumentMatchers.isA(EhcacheEntityResponse.ClientInvalidateHash.class)); } @Test From ec1d907c23e7f78d948390b7814830251155eda8 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 24 Sep 2021 17:49:20 -0400 Subject: [PATCH 364/372] Fixes #2938 Fix source and javadoc uber jars --- buildSrc/src/main/groovy/EhDistribute.groovy | 10 ++++++++-- buildSrc/src/main/groovy/EhDocs.groovy | 16 ++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/buildSrc/src/main/groovy/EhDistribute.groovy b/buildSrc/src/main/groovy/EhDistribute.groovy index 1648c15d6a..12b6d952fa 100644 --- a/buildSrc/src/main/groovy/EhDistribute.groovy +++ b/buildSrc/src/main/groovy/EhDistribute.groovy @@ -72,11 +72,17 @@ class EhDistribute implements Plugin { project.sourceJar { - from project.configurations.named('compileOnly').map({ + from(project.configurations.named('compileOnly').map({ it.dependencies.withType(ProjectDependency).toSet().collect { it.dependencyProject.sourceSets.main.allSource } - }) + })) { + exclude 'META-INF/**', 'LICENSE', 'NOTICE' + } + from(project.jar) { + include 'META-INF/**', 'LICENSE', 'NOTICE' + } + duplicatesStrategy = 'fail' } project.signing { diff --git a/buildSrc/src/main/groovy/EhDocs.groovy b/buildSrc/src/main/groovy/EhDocs.groovy index c1897f3863..6db5c59bcd 100644 --- a/buildSrc/src/main/groovy/EhDocs.groovy +++ b/buildSrc/src/main/groovy/EhDocs.groovy @@ -4,7 +4,6 @@ import org.gradle.api.artifacts.ProjectDependency import org.gradle.api.tasks.bundling.Jar import org.gradle.api.tasks.bundling.Zip import org.gradle.api.tasks.javadoc.Javadoc -import scripts.Utils /* * Copyright Terracotta, Inc. @@ -30,14 +29,15 @@ class EhDocs implements Plugin { @Override void apply(Project project) { - def utils = new Utils(project.baseVersion, project.logger) - def hashsetOfProjects = project.configurations.compile.dependencies.withType(ProjectDependency).dependencyProject + - project.configurations.compileOnly.dependencies.withType(ProjectDependency).dependencyProject + def incomingProjects = project.provider { + project.configurations.compile.dependencies.withType(ProjectDependency).dependencyProject + + project.configurations.compileOnly.dependencies.withType(ProjectDependency).dependencyProject + } project.javadoc { title "$project.archivesBaseName $project.version API" - source hashsetOfProjects.javadoc.source - classpath = project.files(hashsetOfProjects.javadoc.classpath) + source incomingProjects.map { it*.javadoc.source } + classpath = project.files(incomingProjects.map { it*.javadoc.classpath }) project.ext.properties.javadocExclude?.tokenize(',').each { exclude it.trim() } @@ -47,8 +47,8 @@ class EhDocs implements Plugin { project.task('spiJavadoc', type: Javadoc) { title "$project.archivesBaseName $project.version API & SPI" - source hashsetOfProjects.javadoc.source - classpath = project.files(hashsetOfProjects.javadoc.classpath) + source incomingProjects.map { it*.javadoc.source } + classpath = project.files(incomingProjects.map { it*.javadoc.classpath }) exclude '**/internal/**' destinationDir = project.file("$project.docsDir/spi-javadoc") } From 80f6c3501bc21ab245a30f4cb5fbaeda4bb74103 Mon Sep 17 00:00:00 2001 From: Tom Mesic <59479956+tmesic99@users.noreply.github.com> Date: Fri, 1 Oct 2021 09:08:27 -0400 Subject: [PATCH 365/372] core and platform version bump --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 928dee0782..5e7a123682 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.8-pre1 +terracottaPlatformVersion = 5.8.8-pre2 terracottaApisVersion = 1.8.1 -terracottaCoreVersion = 5.8.4-pre1 +terracottaCoreVersion = 5.8.4-pre3 terracottaPassthroughTestingVersion = 1.8.2 terracottaUtilitiesVersion = 0.0.9 From d0caa49ba0c435a05f4025d749fd1954288a841b Mon Sep 17 00:00:00 2001 From: Myron Scott Date: Wed, 13 Oct 2021 14:07:30 -0700 Subject: [PATCH 366/372] bump versions --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5e7a123682..3277ff18db 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.8-pre2 +terracottaPlatformVersion = 5.8.8 terracottaApisVersion = 1.8.1 -terracottaCoreVersion = 5.8.4-pre3 +terracottaCoreVersion = 5.8.4 terracottaPassthroughTestingVersion = 1.8.2 terracottaUtilitiesVersion = 0.0.9 From f5efc425247e8e1c611610bb60ae9618d25b8c64 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 22 Oct 2021 17:49:52 +0200 Subject: [PATCH 367/372] New platform and angela --- .../ehcache/clustered/client/internal/ConnectionSource.java | 4 ++-- gradle.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java index cfeb60e9e0..03be1079c9 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java @@ -126,8 +126,8 @@ public LeasedConnection connect(Properties connectionProperties) throws Connecti dynamicTopologyEntity.setListener(new DynamicTopologyEntity.Listener() { @Override public void onNodeRemoval(Cluster cluster, UID stripeUID, Node removedNode) { - servers.remove(removedNode.getInternalAddress()); - removedNode.getPublicAddress().ifPresent(servers::remove); + servers.remove(removedNode.getInternalSocketAddress()); + removedNode.getPublicSocketAddress().ifPresent(servers::remove); } @Override diff --git a/gradle.properties b/gradle.properties index 3277ff18db..ee2ef912e9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.8 +terracottaPlatformVersion = 5.8.9-pre1 terracottaApisVersion = 1.8.1 terracottaCoreVersion = 5.8.4 terracottaPassthroughTestingVersion = 1.8.2 From cd0f97b387bc88ee26b9a5c4b4e57f366d5236dc Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 23 Oct 2021 00:08:02 +0200 Subject: [PATCH 368/372] New platform and angela --- .../clustered/client/internal/ConnectionSource.java | 9 ++------- gradle.properties | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java index 03be1079c9..1b5bafe547 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java +++ b/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java @@ -126,17 +126,12 @@ public LeasedConnection connect(Properties connectionProperties) throws Connecti dynamicTopologyEntity.setListener(new DynamicTopologyEntity.Listener() { @Override public void onNodeRemoval(Cluster cluster, UID stripeUID, Node removedNode) { - servers.remove(removedNode.getInternalSocketAddress()); - removedNode.getPublicSocketAddress().ifPresent(servers::remove); + removedNode.getEndpoints().forEach(e -> servers.remove(e.getAddress())); } @Override public void onNodeAddition(Cluster cluster, UID addedNodeUID) { - InetSocketAddress anAddress = servers.iterator().next(); // a random address from the user provided URI - cluster.getEndpoints(anAddress).stream() // get the cluster node endpoints for this user address - .filter(endpoint -> endpoint.getNodeUID().equals(addedNodeUID)) - .map(Node.Endpoint::getAddress) - .forEach(servers::add); + servers.add(cluster.determineEndpoint(addedNodeUID, servers).get().getAddress()); } }); return new LeasedConnection() { diff --git a/gradle.properties b/gradle.properties index ee2ef912e9..24b8926f7f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.9-pre1 +terracottaPlatformVersion = 5.8.9-pre3 terracottaApisVersion = 1.8.1 terracottaCoreVersion = 5.8.4 terracottaPassthroughTestingVersion = 1.8.2 From 0afce8f589e7a91cb7a651cd0611934c9581e513 Mon Sep 17 00:00:00 2001 From: Gary Keim Date: Wed, 1 Dec 2021 18:32:31 -0500 Subject: [PATCH 369/372] TDB-5470: ensure ehcache server stores are properly associated with a default offheap resource --- .../server/management/ClusterTierManagement.java | 2 +- .../ServerStoreSettingsManagementProvider.java | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagement.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagement.java index 4d75e11b77..854376401f 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagement.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagement.java @@ -53,7 +53,7 @@ public ClusterTierManagement(ServiceRegistry services, EhcacheStateService ehcac if (managementRegistry != null) { // expose settings about server stores - managementRegistry.addManagementProvider(new ServerStoreSettingsManagementProvider(clusterTierManagerIdentifier)); + managementRegistry.addManagementProvider(new ServerStoreSettingsManagementProvider(clusterTierManagerIdentifier, ehcacheStateService.getDefaultServerResource())); // expose settings about pools managementRegistry.addManagementProvider(new PoolSettingsManagementProvider()); diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java index c09c714499..fbad7fd5e7 100644 --- a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java +++ b/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java @@ -34,10 +34,12 @@ class ServerStoreSettingsManagementProvider extends AliasBindingManagementProvider { private final String clusterTierManagerIdentifier; + private final String defaultServerResource; - ServerStoreSettingsManagementProvider(String clusterTierManagerIdentifier) { + ServerStoreSettingsManagementProvider(String clusterTierManagerIdentifier, String defaultServerResource) { super(ServerStoreBinding.class); this.clusterTierManagerIdentifier = clusterTierManagerIdentifier; + this.defaultServerResource = defaultServerResource; } @Override @@ -46,12 +48,16 @@ public Collection getDescriptors() { descriptors.add(new Settings() .set("type", getCapabilityName()) .set("clusterTierManager", clusterTierManagerIdentifier) - .set("time", System.currentTimeMillis())); + .set("time", System.currentTimeMillis()) + .set("defaultServerResource", defaultServerResource)); return descriptors; } @Override protected ExposedServerStoreBinding internalWrap(Context context, ServerStoreBinding managedObject) { + if (defaultServerResource != null) { + context = context.with("defaultServerResource", defaultServerResource); + } return new ExposedServerStoreBinding(context, managedObject); } @@ -84,7 +90,8 @@ Settings getSettings() { .set("dataVitalMemoryAtTime", internals.getDataVitalMemory()); } if (poolAllocation instanceof PoolAllocation.DedicatedPoolAllocation) { - settings.set("resourcePoolDedicatedResourceName", ((PoolAllocation.DedicatedPoolAllocation) poolAllocation).getResourceName()); + String resourceName = ((PoolAllocation.DedicatedPoolAllocation) poolAllocation).getResourceName(); + settings.set("resourcePoolDedicatedResourceName", resourceName != null ? resourceName : settings.getString("defaultServerResource")); settings.set("resourcePoolDedicatedSize", ((PoolAllocation.DedicatedPoolAllocation) poolAllocation).getSize()); } else if (poolAllocation instanceof PoolAllocation.SharedPoolAllocation) { settings.set("resourcePoolSharedPoolName", ((PoolAllocation.SharedPoolAllocation) poolAllocation).getResourcePoolName()); From b401166bddea68fe4232912a04a9ddf4315ee644 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 30 Nov 2021 23:29:31 +0100 Subject: [PATCH 370/372] Fix missing "instanceId" routing information for monitoring events and management calls --- .../AbstractClusteringManagementTest.java | 3 +- .../ManagementClusterConnectionTest.java | 10 +------ gradle.properties | 2 +- .../DefaultClusteringManagementService.java | 5 +++- .../management/providers/CacheBinding.java | 2 +- .../EhcacheStatisticCollectorProvider.java | 2 +- .../actions/EhcacheActionProvider.java | 2 +- .../settings/EhcacheSettingsProvider.java | 2 +- ...efaultManagementRegistryConfiguration.java | 5 +++- .../DefaultManagementRegistryService.java | 7 ++++- .../java/org/ehcache/docs/ManagementTest.java | 9 ++++-- .../actions/EhcacheActionProviderTest.java | 14 +++++---- .../settings/EhcacheSettingsProviderTest.java | 4 ++- .../EhcacheStatisticsProviderTest.java | 5 +++- .../providers/statistics/StatsUtil.java | 30 +------------------ .../registry/DefaultCollectorServiceTest.java | 2 +- .../DefaultManagementRegistryServiceTest.java | 18 +++++------ .../DefaultSharedManagementServiceTest.java | 24 ++++----------- .../management/registry/XmlConfigTest.java | 2 +- .../test/resources/settings-capability.json | 2 +- 20 files changed, 60 insertions(+), 90 deletions(-) diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java index 7156acfed7..fef40076f7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java @@ -221,8 +221,7 @@ public static org.terracotta.management.model.cluster.Cluster readTopology() thr public static void sendManagementCallOnClientToCollectStats() throws Exception { org.terracotta.management.model.cluster.Cluster topology = readTopology(); Client manageableClient = topology.getClient(ehcacheClientIdentifier).filter(AbstractManageableNode::isManageable).get(); - Context cmContext = manageableClient.getContext() - .with("cacheManagerName", "my-super-cache-manager"); + Context cmContext = manageableClient.getContext(); CLUSTER.getNmsService().startStatisticCollector(cmContext, 1, TimeUnit.SECONDS).waitForReturn(); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java index 1e77ef0346..86c4cb55ee 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java @@ -30,7 +30,6 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; -import org.terracotta.management.model.capabilities.descriptors.Settings; import org.terracotta.utilities.test.rules.TestRetryer; import java.net.URI; @@ -54,7 +53,6 @@ import static org.ehcache.testing.StandardTimeouts.eventually; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; - import static org.terracotta.utilities.test.rules.TestRetryer.OutputIs.CLASS_RULE; import static org.terracotta.utilities.test.rules.TestRetryer.tryValues; @@ -179,12 +177,6 @@ public void test_reconnection() throws Exception { private String getInstanceId() throws Exception { return CLUSTER.get().getNmsService().readTopology().clientStream() .filter(client -> client.getName().startsWith("Ehcache:") && client.isManageable()) - .findFirst().get() - .getManagementRegistry().get() - .getCapability("SettingsCapability").get() - .getDescriptors(Settings.class).stream() - .filter(settings -> settings.containsKey("instanceId")) - .map(settings -> settings.getString("instanceId")) - .findFirst().get(); + .findFirst().get().getContext().get("instanceId"); } } diff --git a/gradle.properties b/gradle.properties index 24b8926f7f..aa7e26adb2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.9-pre3 +terracottaPlatformVersion = 5.8.9-pre4 terracottaApisVersion = 1.8.1 terracottaCoreVersion = 5.8.4 terracottaPassthroughTestingVersion = 1.8.2 diff --git a/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java b/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java index 9b4661962c..22d2d14bd8 100644 --- a/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java +++ b/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java @@ -36,6 +36,7 @@ import org.terracotta.management.entity.nms.agent.client.DefaultNmsAgentService; import org.terracotta.management.entity.nms.agent.client.NmsAgentEntity; import org.terracotta.management.entity.nms.agent.client.NmsAgentService; +import org.terracotta.management.model.context.Context; import org.terracotta.management.model.notification.ContextualNotification; import org.terracotta.management.model.stats.ContextualStatistics; @@ -144,7 +145,9 @@ public void stateTransition(Status from, Status to) { } private NmsAgentService createNmsAgentService() { - DefaultNmsAgentService nmsAgentService = new DefaultNmsAgentService(() -> { + // root context will contain: instanceId=... and cacheManagerName=... + final Context rootContext = managementRegistryService.getConfiguration().getContext(); + DefaultNmsAgentService nmsAgentService = new DefaultNmsAgentService(rootContext, () -> { try { return nmsAgentFactory.retrieve(); } catch (EntityNotFoundException e) { diff --git a/management/src/main/java/org/ehcache/management/providers/CacheBinding.java b/management/src/main/java/org/ehcache/management/providers/CacheBinding.java index b3dcdbf781..d03f86b367 100644 --- a/management/src/main/java/org/ehcache/management/providers/CacheBinding.java +++ b/management/src/main/java/org/ehcache/management/providers/CacheBinding.java @@ -24,7 +24,7 @@ /** * Class representing an association between an object and an alias, name, identifier */ -@RequiredContext({@Named("cacheManagerName"), @Named("cacheName")}) +@RequiredContext({@Named("instanceId"), @Named("cacheManagerName"), @Named("cacheName")}) public final class CacheBinding { private final String alias; diff --git a/management/src/main/java/org/ehcache/management/providers/EhcacheStatisticCollectorProvider.java b/management/src/main/java/org/ehcache/management/providers/EhcacheStatisticCollectorProvider.java index 9f2dee44e1..dc159e82ef 100644 --- a/management/src/main/java/org/ehcache/management/providers/EhcacheStatisticCollectorProvider.java +++ b/management/src/main/java/org/ehcache/management/providers/EhcacheStatisticCollectorProvider.java @@ -20,7 +20,7 @@ import org.terracotta.management.registry.RequiredContext; import org.terracotta.management.registry.collect.StatisticCollectorProvider; -@RequiredContext(@Named("cacheManagerName")) +@RequiredContext({@Named("instanceId"), @Named("cacheManagerName")}) public class EhcacheStatisticCollectorProvider extends StatisticCollectorProvider { public EhcacheStatisticCollectorProvider(ManagementRegistryServiceConfiguration configuration) { super(configuration.getContext()); diff --git a/management/src/main/java/org/ehcache/management/providers/actions/EhcacheActionProvider.java b/management/src/main/java/org/ehcache/management/providers/actions/EhcacheActionProvider.java index 32bb963b2a..97234095a6 100644 --- a/management/src/main/java/org/ehcache/management/providers/actions/EhcacheActionProvider.java +++ b/management/src/main/java/org/ehcache/management/providers/actions/EhcacheActionProvider.java @@ -23,7 +23,7 @@ import org.terracotta.management.registry.ExposedObject; @Named("ActionsCapability") -@RequiredContext({@Named("cacheManagerName"), @Named("cacheName")}) +@RequiredContext({@Named("instanceId"), @Named("cacheManagerName"), @Named("cacheName")}) public class EhcacheActionProvider extends AbstractActionManagementProvider { private final ManagementRegistryServiceConfiguration registryServiceConfiguration; diff --git a/management/src/main/java/org/ehcache/management/providers/settings/EhcacheSettingsProvider.java b/management/src/main/java/org/ehcache/management/providers/settings/EhcacheSettingsProvider.java index d219a30d3c..c34705d2a3 100644 --- a/management/src/main/java/org/ehcache/management/providers/settings/EhcacheSettingsProvider.java +++ b/management/src/main/java/org/ehcache/management/providers/settings/EhcacheSettingsProvider.java @@ -29,7 +29,7 @@ import java.util.Collection; @Named("SettingsCapability") -@RequiredContext({@Named("cacheManagerName")}) +@RequiredContext({@Named("instanceId"), @Named("cacheManagerName")}) public class EhcacheSettingsProvider extends CacheBindingManagementProvider { private final ManagementRegistryServiceConfiguration configuration; diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java index e7dc7a3629..0bdb03c729 100644 --- a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java +++ b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java @@ -32,7 +32,7 @@ public class DefaultManagementRegistryConfiguration implements ManagementRegistr private final Collection tags = new TreeSet<>(); private final String instanceId = UUID.randomUUID().toString(); - private Context context = Context.empty(); + private Context context = Context.empty().with("instanceId", instanceId); private String collectorExecutorAlias = "collectorExecutor"; private LatencyHistogramConfiguration latencyHistogramConfiguration = LatencyHistogramConfiguration.DEFAULT; @@ -48,6 +48,9 @@ public DefaultManagementRegistryConfiguration setContext(Context context) { if (!this.context.contains("cacheManagerName") && !context.contains("cacheManagerName")) { throw new IllegalArgumentException("'cacheManagerName' is missing from context"); } + if (context.contains("instanceId") && !Objects.equals(context.get("instanceId"), instanceId)) { + throw new IllegalArgumentException("Cannot override instanceId in context " + this.context + " by " + context); + } this.context = this.context.with(context); return this; } diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java index 53d7fc5513..d72208de54 100644 --- a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java +++ b/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java @@ -38,6 +38,7 @@ import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceDependencies; import org.ehcache.spi.service.ServiceProvider; +import org.terracotta.management.model.context.Context; import org.terracotta.management.model.context.ContextContainer; import org.terracotta.management.registry.DefaultManagementRegistry; @@ -62,7 +63,6 @@ public DefaultManagementRegistryService() { } public DefaultManagementRegistryService(ManagementRegistryServiceConfiguration configuration) { - super(null); // context container creation is overriden here this.configuration = configuration == null ? new DefaultManagementRegistryConfiguration() : configuration; } @@ -161,4 +161,9 @@ public ContextContainer getContextContainer() { return new ContextContainer("cacheManagerName", getConfiguration().getContext().get("cacheManagerName"), cacheCtx); } + @Override + public Context getContext() { + // contains instanceId + cacheManagerName keys + return configuration.getContext(); + } } diff --git a/management/src/test/java/org/ehcache/docs/ManagementTest.java b/management/src/test/java/org/ehcache/docs/ManagementTest.java index 0c20a94e91..53bebb923f 100644 --- a/management/src/test/java/org/ehcache/docs/ManagementTest.java +++ b/management/src/test/java/org/ehcache/docs/ManagementTest.java @@ -126,14 +126,17 @@ public void capabilitiesAndContexts() throws Exception { assertThat(capabilityDescriptions.isEmpty(), Matchers.is(false)); CapabilityContext capabilityContext = capability.getCapabilityContext(); Collection attributes = capabilityContext.getAttributes(); // <4> - assertThat(attributes.size(), Matchers.is(2)); + assertThat(attributes.size(), Matchers.is(3)); Iterator iterator = attributes.iterator(); CapabilityContext.Attribute attribute1 = iterator.next(); - assertThat(attribute1.getName(), Matchers.equalTo("cacheManagerName")); // <5> + assertThat(attribute1.getName(), Matchers.equalTo("instanceId")); // <5> assertThat(attribute1.isRequired(), Matchers.is(true)); CapabilityContext.Attribute attribute2 = iterator.next(); - assertThat(attribute2.getName(), Matchers.equalTo("cacheName")); // <6> + assertThat(attribute2.getName(), Matchers.equalTo("cacheManagerName")); // <5> assertThat(attribute2.isRequired(), Matchers.is(true)); + CapabilityContext.Attribute attribute3 = iterator.next(); + assertThat(attribute3.getName(), Matchers.equalTo("cacheName")); // <6> + assertThat(attribute3.isRequired(), Matchers.is(true)); ContextContainer contextContainer = managementRegistry.getContextContainer(); // <7> assertThat(contextContainer.getName(), Matchers.equalTo("cacheManagerName")); // <8> diff --git a/management/src/test/java/org/ehcache/management/providers/actions/EhcacheActionProviderTest.java b/management/src/test/java/org/ehcache/management/providers/actions/EhcacheActionProviderTest.java index 060fe2edc4..cdf495f79a 100644 --- a/management/src/test/java/org/ehcache/management/providers/actions/EhcacheActionProviderTest.java +++ b/management/src/test/java/org/ehcache/management/providers/actions/EhcacheActionProviderTest.java @@ -45,10 +45,11 @@ public class EhcacheActionProviderTest { - Context cmContext = Context.create("cacheManagerName", "myCacheManagerName"); - Context cmContext_0 = Context.create("cacheManagerName", "cache-manager-0"); - ManagementRegistryServiceConfiguration cmConfig = new DefaultManagementRegistryConfiguration().setContext(cmContext); - ManagementRegistryServiceConfiguration cmConfig_0 = new DefaultManagementRegistryConfiguration().setContext(cmContext_0); + ManagementRegistryServiceConfiguration cmConfig = new DefaultManagementRegistryConfiguration().setCacheManagerAlias("myCacheManagerName"); + ManagementRegistryServiceConfiguration cmConfig_0 = new DefaultManagementRegistryConfiguration().setCacheManagerAlias("cache-manager-0"); + + Context cmContext = cmConfig.getContext(); + Context cmContext_0 = cmConfig_0.getContext(); @Test @SuppressWarnings("unchecked") @@ -77,10 +78,13 @@ public void testCapabilityContext() throws Exception { CapabilityContext capabilityContext = ehcacheActionProvider.getCapabilityContext(); - assertThat(capabilityContext.getAttributes().size(), is(2)); + assertThat(capabilityContext.getAttributes().size(), is(3)); Iterator iterator = capabilityContext.getAttributes().iterator(); CapabilityContext.Attribute next = iterator.next(); + assertThat(next.getName(), equalTo("instanceId")); + assertThat(next.isRequired(), is(true)); + next = iterator.next(); assertThat(next.getName(), equalTo("cacheManagerName")); assertThat(next.isRequired(), is(true)); next = iterator.next(); diff --git a/management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java b/management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java index 2e97b92a45..0761bf46ea 100644 --- a/management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java +++ b/management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java @@ -106,7 +106,9 @@ public void test_standalone_ehcache() throws IOException { String expected = read("/settings-capability.json") .replaceAll("instance-id", serviceConfiguration.getInstanceId()); String actual = mapper.writeValueAsString(getSettingsCapability()) - .replaceAll("\\\"cacheManagerDescription\\\":\\\".*\\\",\\\"instanceId\\\"", "\\\"cacheManagerDescription\\\":\\\"\\\",\\\"instanceId\\\""); + .replaceAll("\\\"cacheManagerDescription\\\":\\\".*\\\",\\\"instanceId\\\"", "\\\"cacheManagerDescription\\\":\\\"\\\",\\\"instanceId\\\"") + .replaceAll("\\\"instanceId\\\":\\\".*\\\",\\\"managementContext\\\"", "\\\"instanceId\\\":\\\"UUID\\\",\\\"managementContext\\\"") + .replaceAll("\\\"instanceId\\\":\\\".*\\\",\\\"cacheManagerName\\\"", "\\\"instanceId\\\":\\\"UUID\\\",\\\"cacheManagerName\\\""); // assertThat for formatted string comparison: ide support is bad assertEquals(expected, actual); diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java b/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java index 659ff56f4a..67fbc958b0 100644 --- a/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java @@ -101,10 +101,13 @@ protected ExposedCacheBinding wrap(CacheBinding cacheBinding) { CapabilityContext capabilityContext = ehcacheStatisticsProvider.getCapabilityContext(); - assertThat(capabilityContext.getAttributes().size(), is(2)); + assertThat(capabilityContext.getAttributes().size(), is(3)); Iterator iterator = capabilityContext.getAttributes().iterator(); CapabilityContext.Attribute next = iterator.next(); + assertThat(next.getName(), equalTo("instanceId")); + assertThat(next.isRequired(), is(true)); + next = iterator.next(); assertThat(next.getName(), equalTo("cacheManagerName")); assertThat(next.isRequired(), is(true)); next = iterator.next(); diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StatsUtil.java b/management/src/test/java/org/ehcache/management/providers/statistics/StatsUtil.java index 76625b0c52..bc9629e138 100755 --- a/management/src/test/java/org/ehcache/management/providers/statistics/StatsUtil.java +++ b/management/src/test/java/org/ehcache/management/providers/statistics/StatsUtil.java @@ -31,35 +31,7 @@ public class StatsUtil { public static Context createContext(ManagementRegistryService managementRegistry) { ContextContainer cacheManagerCtx = managementRegistry.getContextContainer(); ContextContainer firstCacheCtx = cacheManagerCtx.getSubContexts().iterator().next(); - return Context.empty() - .with(cacheManagerCtx.getName(), cacheManagerCtx.getValue()) + return managementRegistry.getConfiguration().getContext() .with(firstCacheCtx.getName(), firstCacheCtx.getValue()); } - - /* - NOTE: When using this method in other unit tests, make sure to declare a timeout as it is possible to get an infinite loop. - This should only occur if the stats value is different from your expectedResult, which may happen if the stats calculations - change, the stats value isn't accessible or if you enter the wrong expectedResult. - */ - public static long getAndAssertExpectedValueFromCounter(String statName, Context context, ManagementRegistryService managementRegistry, long expectedResult) { - - StatisticQuery query = managementRegistry.withCapability("StatisticsCapability") - .queryStatistics(singletonList(statName)) - .on(context) - .build(); - - ResultSet counters = query.execute(); - - ContextualStatistics statisticsContext = counters.getResult(context); - - assertThat(counters.size(), Matchers.is(1)); - - Number counter = statisticsContext.getLatestSampleValue(statName).get(); - long value = counter.longValue(); - - assertThat(value, Matchers.is(expectedResult)); - - return value; - } - } diff --git a/management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java b/management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java index a4cf0f9108..551a47e2a8 100644 --- a/management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java +++ b/management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java @@ -95,7 +95,7 @@ void onEvent(Object event) { .call("startStatisticCollector", new Parameter(1L, long.class.getName()), new Parameter(TimeUnit.SECONDS, TimeUnit.class.getName())) - .on(Context.create("cacheManagerName", "my-cm-1")) + .on(managementRegistry.getConfiguration().getContext()) .build() .execute() .getSingleResult(); diff --git a/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java b/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java index 982bed6dad..9245abef53 100644 --- a/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java +++ b/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java @@ -246,8 +246,8 @@ public void testCanGetCapabilities() { assertThat(capabilities.get(0).getDescriptors()).hasSize(4); assertThat(capabilities.get(3).getDescriptors()).hasSize(ONHEAP_DESCRIPTORS.size() + CACHE_DESCRIPTORS.size()); - assertThat(capabilities.get(0).getCapabilityContext().getAttributes()).hasSize(2); - assertThat(capabilities.get(3).getCapabilityContext().getAttributes()).hasSize(2); + assertThat(capabilities.get(0).getCapabilityContext().getAttributes()).hasSize(3); + assertThat(capabilities.get(3).getCapabilityContext().getAttributes()).hasSize(3); } } @@ -266,12 +266,10 @@ public void testCanGetStats() { .using(managementRegistry) .build(true)) { - Context context1 = Context.empty() - .with("cacheManagerName", "myCM") + Context context1 = managementRegistry.getConfiguration().getContext() .with("cacheName", "aCache1"); - Context context2 = Context.empty() - .with("cacheManagerName", "myCM") + Context context2 = managementRegistry.getConfiguration().getContext() .with("cacheName", "aCache2"); Cache cache1 = cacheManager.getCache("aCache1", Long.class, String.class); @@ -355,8 +353,7 @@ public void testCall() throws ExecutionException { .using(managementRegistry) .build(true)) { - Context context = Context.empty() - .with("cacheManagerName", "myCM") + Context context = managementRegistry.getConfiguration().getContext() .with("cacheName", "aCache1"); cacheManager.getCache("aCache1", Long.class, String.class).put(1L, "1"); @@ -390,9 +387,8 @@ public void testCallOnInexistignContext() throws ExecutionException { .using(managementRegistry) .build(true)) { - Context inexisting = Context.empty() - .with("cacheManagerName", "myCM2") - .with("cacheName", "aCache2"); + Context inexisting = managementRegistry.getConfiguration().getContext() + .with("cacheName", "aCache3"); ResultSet> results = managementRegistry.withCapability("ActionsCapability") .call("clear") diff --git a/management/src/test/java/org/ehcache/management/registry/DefaultSharedManagementServiceTest.java b/management/src/test/java/org/ehcache/management/registry/DefaultSharedManagementServiceTest.java index 351e9711c9..516564259a 100644 --- a/management/src/test/java/org/ehcache/management/registry/DefaultSharedManagementServiceTest.java +++ b/management/src/test/java/org/ehcache/management/registry/DefaultSharedManagementServiceTest.java @@ -158,15 +158,9 @@ public void testStats() { String statisticName = "Cache:MissCount"; List contextList = Arrays.asList( - Context.empty() - .with("cacheManagerName", "myCM1") - .with("cacheName", "aCache1"), - Context.empty() - .with("cacheManagerName", "myCM2") - .with("cacheName", "aCache2"), - Context.empty() - .with("cacheManagerName", "myCM2") - .with("cacheName", "aCache3")); + config1.getContext().with("cacheName", "aCache1"), + config2.getContext().with("cacheName", "aCache2"), + config2.getContext().with("cacheName", "aCache3")); cacheManager1.getCache("aCache1", Long.class, String.class).get(1L); cacheManager2.getCache("aCache2", Long.class, String.class).get(2L); @@ -210,15 +204,9 @@ private static ResultSet getResultSet(StatisticQuery.Build @Test public void testCall() throws ExecutionException { List contextList = Arrays.asList( - Context.empty() - .with("cacheManagerName", "myCM1") - .with("cacheName", "aCache1"), - Context.empty() - .with("cacheManagerName", "myCM1") - .with("cacheName", "aCache4"), - Context.empty() - .with("cacheManagerName", "myCM2") - .with("cacheName", "aCache2"), + config1.getContext().with("cacheName", "aCache1"), + config1.getContext().with("cacheName", "aCache4"), + config2.getContext().with("cacheName", "aCache2"), Context.empty() .with("cacheManagerName", "myCM55") .with("cacheName", "aCache55")); diff --git a/management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java b/management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java index 6b9edebb87..48e2a097ab 100644 --- a/management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java +++ b/management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java @@ -101,7 +101,7 @@ public void test_config_loaded() throws Exception { assertThat(registryConfiguration.getCacheManagerAlias(), equalTo(expectedConfiguration.getCacheManagerAlias())); assertThat(registryConfiguration.getCollectorExecutorAlias(), equalTo(expectedConfiguration.getCollectorExecutorAlias())); - assertThat(registryConfiguration.getContext(), equalTo(expectedConfiguration.getContext())); + assertThat(registryConfiguration.getContext().without("instanceId"), equalTo(expectedConfiguration.getContext().without("instanceId"))); assertThat(registryConfiguration.getTags(), equalTo(expectedConfiguration.getTags())); } finally { diff --git a/management/src/test/resources/settings-capability.json b/management/src/test/resources/settings-capability.json index 4a87917bfc..f8702c8da7 100644 --- a/management/src/test/resources/settings-capability.json +++ b/management/src/test/resources/settings-capability.json @@ -1 +1 @@ -{"name":"SettingsCapability","descriptors":[{"cacheName":"cache-1","keyType":"java.lang.String","valueType":"java.lang.String","resourcePools":{"heap":{"level":10000,"persistent":false,"type":"ENTRY","size":10,"unit":"entries"},"offheap":{"level":1000,"persistent":false,"type":"MEMORY","size":1,"unit":"MB"},"disk":{"level":100,"persistent":true,"type":"MEMORY","size":2,"unit":"MB"}}},{"cacheName":"cache-2","keyType":"java.lang.String","valueType":"java.lang.String","resourcePools":{"heap":{"level":10000,"persistent":false,"type":"ENTRY","size":10,"unit":"entries"},"offheap":{"level":1000,"persistent":false,"type":"MEMORY","size":1,"unit":"MB"},"disk":{"level":100,"persistent":true,"type":"MEMORY","size":2,"unit":"MB"}}},{"cacheManagerDescription":"","instanceId":"instance-id","managementContext":{"cacheManagerName":"my-cm-1"},"tags":["baz","boo","foo"]}],"capabilityContext":{"attributes":[{"name":"cacheManagerName","required":true},{"name":"cacheName","required":true}]}} +{"name":"SettingsCapability","descriptors":[{"cacheName":"cache-1","keyType":"java.lang.String","valueType":"java.lang.String","resourcePools":{"heap":{"level":10000,"persistent":false,"type":"ENTRY","size":10,"unit":"entries"},"offheap":{"level":1000,"persistent":false,"type":"MEMORY","size":1,"unit":"MB"},"disk":{"level":100,"persistent":true,"type":"MEMORY","size":2,"unit":"MB"}}},{"cacheName":"cache-2","keyType":"java.lang.String","valueType":"java.lang.String","resourcePools":{"heap":{"level":10000,"persistent":false,"type":"ENTRY","size":10,"unit":"entries"},"offheap":{"level":1000,"persistent":false,"type":"MEMORY","size":1,"unit":"MB"},"disk":{"level":100,"persistent":true,"type":"MEMORY","size":2,"unit":"MB"}}},{"cacheManagerDescription":"","instanceId":"UUID","cacheManagerName":"my-cm-1"},"tags":["baz","boo","foo"]}],"capabilityContext":{"attributes":[{"name":"instanceId","required":true},{"name":"cacheManagerName","required":true},{"name":"cacheName","required":true}]}} From b06e30c1f2db9379a5eff5219340c20b36e86d14 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 3 Dec 2021 15:34:21 +0100 Subject: [PATCH 371/372] Upgrade tc-platform --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index aa7e26adb2..d00d675194 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ sizeofVersion = 0.4.0 jaxbVersion = [2.2,3) # Terracotta clustered -terracottaPlatformVersion = 5.8.9-pre4 +terracottaPlatformVersion = 5.8.9-pre5 terracottaApisVersion = 1.8.1 terracottaCoreVersion = 5.8.4 terracottaPassthroughTestingVersion = 1.8.2 From e0f494e942b1be285c0cb822da619a7df0eaaf9c Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Fri, 3 Dec 2021 09:46:07 -0500 Subject: [PATCH 372/372] Upgrade to Gradle 7.2 --- .gitignore | 24 +- 107/.gitignore | 1 - 107/gradle.properties | 2 - api/.gitignore | 1 - api/gradle.properties | 18 -- build-logic/build.gradle | 67 ++++ .../ehcache/build/ClusteredEhcacheModule.java | 12 + .../ehcache/build/ClusteredServerModule.java | 17 ++ .../java/org/ehcache/build/EhcacheModule.java | 17 ++ .../org/ehcache/build/EhcachePackage.java | 16 + .../ehcache/build/InternalEhcacheModule.java | 13 + .../ehcache/build/PublicEhcacheModule.java | 11 + .../build/conventions/BaseConvention.java | 23 ++ .../build/conventions/BndConvention.java | 89 ++++++ .../conventions/CheckstyleConvention.java | 22 ++ .../build/conventions/DeployConvention.java | 167 ++++++++++ .../build/conventions/JacocoConvention.java | 28 ++ .../build/conventions/JavaBaseConvention.java | 131 ++++++++ .../build/conventions/JavaConvention.java | 27 ++ .../conventions/JavaLibraryConvention.java | 14 + .../build/conventions/SpotbugsConvention.java | 53 ++++ .../build/conventions/WarConvention.java | 13 + .../ehcache/build/plugins/PackagePlugin.java | 285 ++++++++++++++++++ .../ehcache/build/plugins/VariantPlugin.java | 228 ++++++++++++++ .../ehcache/build/plugins/VoltronPlugin.java | 66 ++++ ...enerateDeclarativeServicesDescriptors.java | 113 +++++++ .../build/plugins/osgids/OsgiDsPlugin.java | 22 ++ .../plugins/osgids/ScrLoggerAdapter.java | 149 +++++++++ .../build/util/OsgiManifestJarExtension.java | 103 +++++++ .../org/ehcache/build/util/PluginUtils.java | 48 +++ build.gradle | 233 +------------- buildSrc/build.gradle | 49 --- buildSrc/src/main/groovy/EhDeploy.groovy | 93 ------ buildSrc/src/main/groovy/EhDistribute.groovy | 94 ------ buildSrc/src/main/groovy/EhDocs.groovy | 76 ----- buildSrc/src/main/groovy/EhPomGenerate.groovy | 125 -------- buildSrc/src/main/groovy/EhPomMangle.groovy | 97 ------ buildSrc/src/main/groovy/EhVoltron.groovy | 45 --- buildSrc/src/main/groovy/scripts/Utils.groovy | 105 ------- clustered/build.gradle | 3 - clustered/client/gradle.properties | 18 -- clustered/clustered-dist/gradle.properties | 22 -- clustered/common-api/gradle.properties | 18 -- clustered/common/gradle.properties | 18 -- .../{client => ehcache-client}/build.gradle | 43 +-- .../config/checkstyle-suppressions.xml | 0 .../client/config/ClusteredResourcePool.java | 0 .../client/config/ClusteredResourceType.java | 0 .../config/ClusteredStoreConfiguration.java | 0 .../ClusteringServiceConfiguration.java | 0 .../DedicatedClusteredResourcePool.java | 0 .../config/SharedClusteredResourcePool.java | 0 .../clustered/client/config/Timeouts.java | 0 .../ClusteredResourcePoolBuilder.java | 0 .../ClusteredStoreConfigurationBuilder.java | 0 ...ClusteringServiceConfigurationBuilder.java | 0 .../ServerSideConfigurationBuilder.java | 0 .../config/builders/TimeoutsBuilder.java | 0 .../ClusterTierManagerClientEntity.java | 0 ...ClusterTierManagerClientEntityFactory.java | 0 ...ClusterTierManagerClientEntityService.java | 0 .../ClusterTierManagerCreationException.java | 0 .../ClusterTierManagerNotFoundException.java | 0 ...ClusterTierManagerValidationException.java | 0 .../client/internal/ConnectionSource.java | 0 .../PerpetualCachePersistenceException.java | 0 .../SimpleClusterTierManagerClientEntity.java | 0 .../config/ClusteredResourcePoolImpl.java | 0 .../DedicatedClusteredResourcePoolImpl.java | 0 .../SharedClusteredResourcePoolImpl.java | 0 .../config/xml/ClusteredCacheConstants.java | 0 .../ClusteredResourceConfigurationParser.java | 0 ...acheManagerServiceConfigurationParser.java | 0 ...teringCacheServiceConfigurationParser.java | 0 .../ClusteredLoaderWriterStore.java | 0 ...teredLoaderWriterStoreProviderFactory.java | 0 .../DelegatingLoaderWriterStore.java | 0 .../DelegatingLoaderWriterStoreProvider.java | 0 ...atingLoaderWriterStoreProviderFactory.java | 0 .../writebehind/ClusteredWriteBehind.java | 0 .../ClusteredWriteBehindStore.java | 0 ...steredWriteBehindStoreProviderFactory.java | 0 .../internal/lock/VoltronReadWriteLock.java | 0 .../lock/VoltronReadWriteLockClient.java | 0 ...ltronReadWriteLockEntityClientService.java | 0 .../service/AbstractClientEntityFactory.java | 0 .../service/ClusterStateRepository.java | 0 .../service/ClusterTierCreationException.java | 0 .../ClusterTierDestructionException.java | 0 .../service/ClusterTierException.java | 0 ...sterTierManagerConfigurationException.java | 0 .../service/ClusterTierReleaseException.java | 0 .../ClusterTierValidationException.java | 0 .../service/ClusteredMapException.java | 0 .../service/ClusteredStateHolder.java | 0 .../service/ClusteringServiceFactory.java | 0 .../internal/service/ConnectionState.java | 3 +- .../service/DefaultClusteringService.java | 0 .../client/internal/service/ValueCodec.java | 0 .../internal/service/ValueCodecFactory.java | 0 .../store/ClusterTierClientEntity.java | 0 .../store/ClusterTierClientEntityService.java | 0 .../internal/store/ClusterTierUserData.java | 0 .../client/internal/store/ClusteredStore.java | 0 .../store/ClusteredStoreProviderFactory.java | 0 .../internal/store/ClusteredValueHolder.java | 0 .../store/CommonServerStoreProxy.java | 0 .../store/EventualServerStoreProxy.java | 0 .../store/FailedReconnectStoreProxy.java | 0 .../InternalClusterTierClientEntity.java | 0 .../store/ReconnectInProgressException.java | 0 .../store/ReconnectingServerStoreProxy.java | 0 .../internal/store/ServerStoreProxy.java | 0 .../store/ServerStoreProxyException.java | 0 .../store/SimpleClusterTierClientEntity.java | 0 .../store/StrongServerStoreProxy.java | 0 .../internal/store/lock/LockManager.java | 0 .../store/lock/LockingServerStoreProxy.java | 0 .../lock/LockingServerStoreProxyImpl.java | 0 .../store/operations/ChainResolver.java | 0 .../operations/EternalChainResolver.java | 0 .../store/operations/ExpiryChainResolver.java | 0 .../client/service/ClientEntityFactory.java | 0 .../client/service/ClusteringService.java | 0 .../client/service/EntityBusyException.java | 0 .../client/service/EntityService.java | 0 ...rg.ehcache.core.spi.service.ServiceFactory | 0 ...xml.CacheManagerServiceConfigurationParser | 0 ...cache.xml.CacheResourceConfigurationParser | 0 ...hcache.xml.CacheServiceConfigurationParser | 0 .../org.terracotta.entity.EntityClientService | 0 .../main/resources/ehcache-clustered-ext.xsd | 0 .../ClusteredResourcePoolUpdationTest.java | 0 .../client/BasicClusteredCacheExpiryTest.java | 0 .../client/BasicClusteredCacheTest.java | 0 .../client/CacheManagerDestroyTest.java | 0 .../client/ClusteredCacheDestroyTest.java | 0 .../client/ClusteredCacheExpirationTest.java | 0 .../client/ClusteredConcurrencyTest.java | 0 .../clustered/client/ClusteredEventsTest.java | 0 .../clustered/client/EntityServiceTest.java | 0 .../client/NonClusteredCacheTest.java | 0 .../client/SimpleClusteredCacheByXmlTest.java | 0 .../client/TerracottaUriXmlTest.java | 0 .../clustered/client/TestTimeSource.java | 0 ...tedCombinationsWithClusteredCacheTest.java | 0 .../clustered/client/XmlConsistencyTest.java | 0 .../clustered/client/XmlUnknownCacheTest.java | 0 .../ClusteredConfigurationDerivationTest.java | 0 .../ClusteredStoreConfigurationTest.java | 0 .../ClusteringServiceConfigurationTest.java | 0 .../ClusteredResourcePoolBuilderTest.java | 0 .../config/builders/TimeoutsBuilderTest.java | 0 .../client/docs/ConfigurationDerivation.java | 0 .../clustered/client/docs/GettingStarted.java | 0 .../clustered/client/docs/Resilience.java | 0 .../clustered/client/docs/Tiering.java | 0 ...terTierManagerClientEntityFactoryTest.java | 0 .../internal/MockConnectionService.java | 0 .../internal/UnitTestConnectionService.java | 0 .../config/ClusteredResourcePoolImplTest.java | 0 ...edicatedClusteredResourcePoolImplTest.java | 0 .../SharedClusteredResourcePoolImplTest.java | 0 .../ClusteredCacheConfigurationParserIT.java | 0 ...steredResourceConfigurationParserTest.java | 0 ...ManagerServiceConfigurationParserTest.java | 0 ...ngCacheServiceConfigurationParserTest.java | 0 ...lusteredLoaderWriterStoreProviderTest.java | 0 .../ClusteredLoaderWriterStoreTest.java | 0 ...ClusteredWriteBehindStoreProviderTest.java | 0 .../writebehind/ClusteredWriteBehindTest.java | 0 .../lock/VoltronReadWriteLockClientTest.java | 0 .../lock/VoltronReadWriteLockTest.java | 0 ...ClusterStateRepositoryReplicationTest.java | 0 ...rTierManagerClientEntityExceptionTest.java | 0 .../service/ClusteringServiceFactoryTest.java | 0 .../service/ConnectionClosedTest.java | 0 .../internal/service/ConnectionStateTest.java | 0 .../DefaultClusteringServiceDestroyTest.java | 0 .../service/DefaultClusteringServiceTest.java | 0 .../internal/service/ReconnectTest.java | 0 .../StateRepositoryWhitelistingTest.java | 0 .../internal/service/TestServiceProvider.java | 0 .../store/AbstractServerStoreProxyTest.java | 0 .../internal/store/ChainBuilderTest.java | 0 .../store/ClusteredStoreEventsTest.java | 0 .../store/ClusteredStoreProviderTest.java | 0 .../internal/store/ClusteredStoreTest.java | 0 .../store/CommonServerStoreProxyTest.java | 0 .../store/EventualServerStoreProxyTest.java | 0 ...ltiThreadedStrongServerStoreProxyTest.java | 0 .../ReconnectingServerStoreProxyTest.java | 0 .../store/StrongServerStoreProxyTest.java | 0 .../internal/store/lock/LockManagerTest.java | 0 .../lock/LockRetentionDuringFailoverTest.java | 0 .../ActivePassiveClientIdTest.java | 0 .../client/replication/ReplicationUtil.java | 0 .../operations/AbstractChainResolverTest.java | 0 .../operations/BaseKeyValueOperationTest.java | 0 .../ConditionalRemoveOperationTest.java | 0 .../ConditionalReplaceOperationTest.java | 0 .../operations/EternalChainResolverTest.java | 0 .../operations/ExpiryChainResolverTest.java | 0 .../store/operations/LazyValueHolderTest.java | 0 .../operations/PutIfAbsentOperationTest.java | 0 .../store/operations/PutOperationTest.java | 0 .../PutWithWriterOperationTest.java | 0 .../store/operations/RemoveOperationTest.java | 0 .../operations/ReplaceOperationTest.java | 0 .../operations/TimestampOperationTest.java | 0 .../BasicClusteredLoaderWriterTest.java | 0 .../loaderWriter/TestCacheLoaderWriter.java | 0 ...icClusteredWriteBehindPassthroughTest.java | 0 .../writebehind/RecordingLoaderWriter.java | 0 .../ObservableEhcacheServerEntityService.java | 0 .../clustered/server/package-info.java | 0 ...ervableClusterTierServerEntityService.java | 0 .../clustered/util/StatisticsTestUtils.java | 0 ...rg.terracotta.connection.ConnectionService | 0 .../src/test/resources/configs/cluster-ha.xml | 0 .../resources/configs/cluster-invalid-uri.xml | 0 .../resources/configs/clustered-cache.xml | 0 .../test/resources/configs/consistency.xml | 6 +- .../configs/docs/ehcache-clustered.xml | 6 +- .../resources/configs/offheap-resource.xml | 1 - .../test/resources/configs/simple-cluster.xml | 0 ...nknown-cluster-cache-invalid-attribute.xml | 1 - .../unknown-cluster-cache-invalid-element.xml | 1 - .../configs/unknown-cluster-cache.xml | 1 - .../build.gradle | 92 +++--- .../src/assemble/README.txt | 0 .../assemble/legal/APACHE_PUBLIC_LICENSE.txt | 0 .../src/assemble/legal/LICENSE | 0 .../src/assemble/server/conf/cluster.cfg | 0 .../build.gradle | 9 +- .../config/checkstyle-suppressions.xml | 0 .../ehcache/clustered/common/Consistency.java | 0 .../clustered/common/PoolAllocation.java | 0 .../common/ServerSideConfiguration.java | 0 .../ClusterTierManagerConfiguration.java | 0 .../internal/ServerStoreConfiguration.java | 0 .../internal/exceptions/ClusterException.java | 0 .../DestroyInProgressException.java | 0 ...validServerSideConfigurationException.java | 0 .../exceptions/InvalidStoreException.java | 0 .../exceptions/LifecycleException.java | 0 .../messages/EhcacheEntityMessage.java | 0 .../messages/EhcacheEntityResponse.java | 0 .../internal/messages/EhcacheMessageType.java | 0 .../messages/EhcacheOperationMessage.java | 0 .../messages/EhcacheResponseType.java | 0 .../messages/StateRepositoryOpMessage.java | 0 .../common/internal/store/Chain.java | 0 .../common/internal/store/Element.java | 0 .../common/internal/store/ServerStore.java | 0 .../common/internal/store/ValueWrapper.java | 0 .../common/ServerSideConfigurationTest.java | 0 .../{common => ehcache-common}/build.gradle | 17 +- .../config/checkstyle-suppressions.xml | 0 .../common/EhcacheEntityVersion.java | 0 .../exceptions/IllegalMessageException.java | 0 .../exceptions/InvalidOperationException.java | 0 ...alidServerStoreConfigurationException.java | 0 .../exceptions/UnknownClusterException.java | 0 .../common/internal/lock/LockMessaging.java | 0 .../common/internal/messages/BaseCodec.java | 0 .../common/internal/messages/ChainCodec.java | 0 .../messages/ClusterTierReconnectMessage.java | 0 .../common/internal/messages/CodecUtil.java | 0 .../internal/messages/CommonConfigCodec.java | 0 .../messages/ConcurrentEntityMessage.java | 0 .../common/internal/messages/ConfigCodec.java | 0 .../internal/messages/EhcacheCodec.java | 0 .../messages/EntityConfigurationCodec.java | 0 .../internal/messages/ExceptionCodec.java | 0 .../messages/LifeCycleMessageCodec.java | 0 .../messages/LifeCycleMessageFactory.java | 0 .../internal/messages/LifecycleMessage.java | 0 .../internal/messages/MessageCodecUtils.java | 0 .../messages/ReconnectMessageCodec.java | 0 .../internal/messages/ResponseCodec.java | 0 .../internal/messages/ServerStoreOpCodec.java | 0 .../messages/ServerStoreOpMessage.java | 0 .../StateRepositoryMessageFactory.java | 0 .../messages/StateRepositoryOpCodec.java | 0 .../store/ClusterTierEntityConfiguration.java | 0 .../CustomLoaderBasedObjectInputStream.java | 0 .../store/FilteredObjectInputStream.java | 0 .../internal/store/SequencedElement.java | 0 .../clustered/common/internal/store/Util.java | 0 .../operations/BaseKeyValueOperation.java | 0 .../ConditionalRemoveOperation.java | 0 .../ConditionalReplaceOperation.java | 0 .../store/operations/LazyValueHolder.java | 0 .../internal/store/operations/Operation.java | 0 .../store/operations/OperationCode.java | 0 .../operations/PutIfAbsentOperation.java | 0 .../store/operations/PutOperation.java | 0 .../operations/PutWithWriterOperation.java | 0 .../store/operations/RemoveOperation.java | 0 .../store/operations/ReplaceOperation.java | 0 .../internal/store/operations/Result.java | 0 .../store/operations/TimestampOperation.java | 0 .../operations/codecs/CodecException.java | 0 .../operations/codecs/OperationsCodec.java | 0 .../internal/util/ByteBufferInputStream.java | 0 .../common/internal/util/ChainBuilder.java | 0 .../Store/WhitelistedUnmarshallingTest.java | 0 .../Store/operations/OperationCodeTest.java | 0 .../BaseClusteredEhcacheExceptionTest.java | 0 .../IllegalMessageExceptionTest.java | 0 .../InvalidOperationExceptionTest.java | 0 ...dServerSideConfigurationExceptionTest.java | 0 ...ServerStoreConfigurationExceptionTest.java | 0 .../exceptions/InvalidStoreExceptionTest.java | 0 .../exceptions/LifecycleExceptionTest.java | 0 .../internal/messages/ChainCodecTest.java | 0 .../messages/CommonConfigCodecTest.java | 0 .../internal/messages/EhcacheCodecTest.java | 0 .../messages/LifeCycleMessageCodecTest.java | 0 .../messages/ReconnectMessageCodecTest.java | 0 .../internal/messages/ResponseCodecTest.java | 0 .../messages/ServerStoreOpCodecTest.java | 0 .../messages/ServerStoreOpMessageTest.java | 0 clustered/integration-test/build.gradle | 36 +-- clustered/integration-test/gradle.properties | 18 -- .../resources/configs/offheap-resource.xml | 1 - clustered/ops-tool/build.gradle | 4 + clustered/ops-tool/gradle.properties | 18 -- clustered/osgi-test/build.gradle | 40 +-- .../org/ehcache/osgi/ClusteredOsgiTest.java | 14 +- .../ehcache/osgi/ehcache-clustered-osgi.xml | 5 +- .../{entity => ehcache-entity}/build.gradle | 16 +- .../config/checkstyle-suppressions.xml | 0 .../VoltronReadWriteLockActiveEntity.java | 0 .../VoltronReadWriteLockPassiveEntity.java | 0 ...ltronReadWriteLockServerEntityService.java | 0 .../server/messages/LockSyncMessaging.java | 0 .../ClusterTierManagerActiveEntity.java | 0 .../server/ClusterTierManagerDump.java | 0 .../ClusterTierManagerPassiveEntity.java | 0 ...ClusterTierManagerServerEntityService.java | 0 .../CommunicatorServiceConfiguration.java | 0 .../server/ConcurrencyStrategies.java | 0 .../server/EhcacheExecutionStrategy.java | 0 .../server/ServerStoreCompatibility.java | 0 .../messages/EhcacheDataSyncMessage.java | 0 .../EhcacheMessageTrackerCatchup.java | 0 .../EhcacheMessageTrackerMessage.java | 0 .../internal/messages/EhcacheServerCodec.java | 0 .../messages/EhcacheSyncMessageCodec.java | 0 .../messages/PassiveReplicationMessage.java | 0 .../PassiveReplicationMessageCodec.java | 0 .../management/ClusterTierManagement.java | 0 .../management/ClusterTierManagerBinding.java | 0 ...TierManagerSettingsManagementProvider.java | 0 .../server/management/Management.java | 0 .../server/management/Notification.java | 0 .../server/management/PoolBinding.java | 0 .../PoolSettingsManagementProvider.java | 0 .../PoolStatisticsManagementProvider.java | 0 .../server/management/ServerStoreBinding.java | 0 ...ServerStoreSettingsManagementProvider.java | 0 ...rverStoreStatisticsManagementProvider.java | 0 .../server/store/ClusterTierActiveEntity.java | 0 .../server/store/ClusterTierDump.java | 0 .../store/ClusterTierPassiveEntity.java | 0 .../store/ClusterTierServerEntityService.java | 0 .../server/store/LockManagerImpl.java | 0 .../MessageToTrackerSegmentFunction.java | 0 .../server/store/NoopLockManager.java | 0 .../server/store/ServerLockManager.java | 0 .../org.terracotta.entity.EntityServerService | 0 .../VoltronReadWriteLockActiveEntityTest.java | 0 .../ClusterTierManagerActiveEntityTest.java | 0 .../ClusterTierManagerPassiveEntityTest.java | 0 .../DefaultConcurrencyStrategyTest.java | 0 .../server/ServerStoreCompatibilityTest.java | 0 .../server/TestClientDescriptor.java | 0 .../clustered/server/TestClientSourceId.java | 0 .../clustered/server/TestInvokeContext.java | 0 .../EhcacheMessageTrackerMessageTest.java | 0 .../messages/EhcacheServerCodecTest.java | 0 .../messages/EhcacheSyncMessageCodecTest.java | 0 .../PassiveReplicationMessageCodecTest.java | 0 .../store/ClusterTierActiveEntityTest.java | 0 .../store/ClusterTierPassiveEntityTest.java | 0 .../server/store/InvalidMessage.java | 0 .../server/store/LockManagerImplTest.java | 0 .../build.gradle | 12 +- .../config/checkstyle-suppressions.xml | 0 .../clustered/server/KeySegmentMapper.java | 0 .../server/ServerSideServerStore.java | 0 .../server/ServerStoreEventListener.java | 0 .../messages/EhcacheStateRepoSyncMessage.java | 0 .../internal/messages/EhcacheSyncMessage.java | 0 .../internal/messages/SyncMessageType.java | 0 .../server/offheap/InternalChain.java | 0 .../server/repo/ServerStateRepository.java | 0 .../server/repo/StateRepositoryManager.java | 0 .../server/state/EhcacheStateContext.java | 0 .../server/state/EhcacheStateService.java | 0 .../server/state/InvalidationTracker.java | 0 .../config/EhcacheStateServiceConfig.java | 0 .../EhcacheStoreStateServiceConfig.java | 0 .../repo/ServerStateRepositoryTest.java | 0 .../repo/StateRepositoryManagerTest.java | 0 .../{service => ehcache-service}/build.gradle | 14 +- .../config/checkstyle-suppressions.xml | 0 .../server/EhcacheStateServiceImpl.java | 0 .../clustered/server/ServerStoreImpl.java | 0 .../server/offheap/ChainStorageEngine.java | 0 .../server/offheap/LongPortability.java | 0 .../server/offheap/OffHeapChainMap.java | 0 .../offheap/OffHeapChainStorageEngine.java | 0 .../server/offheap/OffHeapServerStore.java | 0 .../offheap/PinningOffHeapChainMap.java | 0 .../server/state/EhcacheStateServiceDump.java | 0 .../state/EhcacheStateServiceProvider.java | 0 .../server/state/InvalidationTrackerImpl.java | 0 .../server/state/ResourcePageSource.java | 0 .../org.terracotta.entity.ServiceProvider | 0 .../main/resources/offheap-message.properties | 0 .../server/EhcacheStateServiceImplTest.java | 0 .../server/offheap/ChainMapExtensionTest.java | 0 .../server/offheap/ChainMapTest.java | 0 .../offheap/OffHeapServerStoreTest.java | 0 .../offheap/PinningOffHeapChainMapTest.java | 0 .../EhcacheStateServiceProviderTest.java | 0 .../state/InvalidationTrackerImplTest.java | 0 .../clustered/server/store/ChainBuilder.java | 0 .../server/store/ElementBuilder.java | 0 .../server/store/ServerStoreTest.java | 0 .../server/store/impl/HeapChainBuilder.java | 0 .../server/store/impl/HeapChainImpl.java | 0 .../server/store/impl/HeapElementBuilder.java | 0 .../server/store/impl/HeapElementImpl.java | 0 .../server/store/impl/ReferenceStoreImpl.java | 0 .../server/store/impl/ReferenceStoreTest.java | 0 clustered/server/entity/gradle.properties | 18 -- .../server/service-api/gradle.properties | 18 -- clustered/server/service/gradle.properties | 18 -- clustered/test-utils/build.gradle | 6 +- config/owasp-supressions.xml | 26 +- core-spi-test/.gitignore | 1 - core-spi-test/build.gradle | 7 +- core-spi-test/gradle.properties | 18 -- core/.gitignore | 1 - core/gradle.properties | 2 - demos/00-NoCache/gradle.properties | 18 -- demos/01-CacheAside/gradle.properties | 18 -- demos/build.gradle | 5 +- deploy.sh | 16 +- dist/.gitignore | 1 - dist/build.gradle | 48 --- dist/gradle.properties | 19 -- docs/build.gradle | 3 +- docs/gradle.properties | 2 - docs/src/docs/asciidoc/user/107.adoc | 20 +- .../asciidoc/user/cache-event-listeners.adoc | 6 +- .../docs/asciidoc/user/clustered-cache.adoc | 16 +- .../src/docs/asciidoc/user/config-derive.adoc | 20 +- .../docs/asciidoc/user/eviction-advisor.adoc | 2 +- docs/src/docs/asciidoc/user/examples.adoc | 2 +- docs/src/docs/asciidoc/user/expiry.adoc | 10 +- .../docs/asciidoc/user/getting-started.adoc | 10 +- docs/src/docs/asciidoc/user/management.adoc | 8 +- .../docs/asciidoc/user/migration-guide.adoc | 2 +- docs/src/docs/asciidoc/user/resilience.adoc | 2 +- .../asciidoc/user/serializers-copiers.adoc | 4 +- docs/src/docs/asciidoc/user/thread-pools.adoc | 8 +- docs/src/docs/asciidoc/user/tiering.adoc | 20 +- docs/src/docs/asciidoc/user/usermanaged.adoc | 10 +- docs/src/docs/asciidoc/user/writers.adoc | 4 +- docs/src/docs/asciidoc/user/xa.adoc | 14 +- docs/src/docs/asciidoc/user/xml.adoc | 26 +- docs/src/docs/asciidoc/user/xsds.adoc | 8 +- {107 => ehcache-107}/README.adoc | 1 - {107 => ehcache-107}/build.gradle | 21 +- .../config/checkstyle-suppressions.xml | 0 .../org/ehcache/jsr107/CacheResources.java | 0 .../java/org/ehcache/jsr107/CloseUtil.java | 0 .../ehcache/jsr107/ConfigurationMerger.java | 0 .../jsr107/DefaultConfigurationResolver.java | 0 .../java/org/ehcache/jsr107/Eh107Cache.java | 0 .../ehcache/jsr107/Eh107CacheEntryEvent.java | 0 .../jsr107/Eh107CacheLoaderWriter.java | 0 .../Eh107CacheLoaderWriterProvider.java | 0 .../org/ehcache/jsr107/Eh107CacheMXBean.java | 0 .../org/ehcache/jsr107/Eh107CacheManager.java | 0 .../jsr107/Eh107CacheStatisticsMXBean.java | 0 .../jsr107/Eh107CompleteConfiguration.java | 0 .../ehcache/jsr107/Eh107Configuration.java | 0 .../java/org/ehcache/jsr107/Eh107Expiry.java | 0 .../ehcache/jsr107/Eh107IdentityCopier.java | 0 .../java/org/ehcache/jsr107/Eh107MXBean.java | 0 .../jsr107/Eh107ReverseConfiguration.java | 0 .../jsr107/EhcacheCachingProvider.java | 0 .../ehcache/jsr107/EhcacheExpiryWrapper.java | 0 .../ehcache/jsr107/EventListenerAdaptors.java | 0 .../jsr107/ExpiryPolicyToEhcacheExpiry.java | 0 .../org/ehcache/jsr107/Jsr107Service.java | 0 .../org/ehcache/jsr107/ListenerResources.java | 0 .../jsr107/NullCompletionListener.java | 0 .../main/java/org/ehcache/jsr107/Unwrap.java | 0 .../config/ConfigurationElementState.java | 0 .../config/Jsr107CacheConfiguration.java | 0 .../jsr107/config/Jsr107Configuration.java | 0 .../ehcache/jsr107/config/package-info.java | 0 .../jsr107/internal/DefaultJsr107Service.java | 0 .../Jsr107CacheConfigurationParser.java | 0 .../internal/Jsr107CacheLoaderWriter.java | 0 .../jsr107/internal/Jsr107LatencyMonitor.java | 0 .../Jsr107ServiceConfigurationParser.java | 0 .../internal/WrappedCacheLoaderWriter.java | 0 .../internal/tck/Eh107MBeanServerBuilder.java | 0 .../java/org/ehcache/jsr107/package-info.java | 0 .../services/javax.cache.spi.CachingProvider | 0 ...xml.CacheManagerServiceConfigurationParser | 0 ...hcache.xml.CacheServiceConfigurationParser | 0 .../src/main/resources/ehcache-107-ext.xsd | 0 .../src/tck/resources/ExcludeList | 0 .../src/test/java/com/pany/domain/Client.java | 0 .../test/java/com/pany/domain/Customer.java | 0 .../test/java/com/pany/domain/Product.java | 0 .../java/com/pany/ehcache/ClientCopier.java | 0 .../com/pany/ehcache/MyEvictionAdvisor.java | 0 .../ehcache/Test107CacheEntryListener.java | 0 .../pany/ehcache/TestCacheEventListener.java | 0 .../integration/ProductCacheLoaderWriter.java | 0 .../ParsesConfigurationExtensionTest.java | 0 ...che107ConfigurationIntegrationDocTest.java | 0 .../ehcache/jsr107/CacheResourcesTest.java | 0 .../ConfigStatsManagementActivationTest.java | 0 .../jsr107/ConfigurationMergerTest.java | 0 .../DefaultConfigurationResolverTest.java | 0 .../ehcache/jsr107/Eh107CacheTypeTest.java | 0 .../jsr107/Eh107XmlIntegrationTest.java | 0 .../ehcache/jsr107/EhCachingProviderTest.java | 0 .../java/org/ehcache/jsr107/IteratorTest.java | 0 .../ehcache/jsr107/Jsr107CacheParserIT.java | 0 .../jsr107/LoadAtomicsWith107Test.java | 0 .../jsr107/LoaderWriterConfigTest.java | 0 .../org/ehcache/jsr107/LoaderWriterTest.java | 0 .../org/ehcache/jsr107/LongSerializer.java | 0 .../jsr107/ResourceCombinationsTest.java | 0 .../org/ehcache/jsr107/SerializerTest.java | 0 .../ehcache/jsr107/SimpleEh107ConfigTest.java | 0 .../org/ehcache/jsr107/StatisticsTest.java | 0 .../org/ehcache/jsr107/StringSerializer.java | 0 .../java/org/ehcache/jsr107/UnwrapTest.java | 0 .../Jsr107CacheConfigurationParserTest.java | 0 .../Jsr107ServiceConfigurationParserTest.java | 0 .../ehcache-107-copiers-immutable-types.xml | 1 - .../resources/ehcache-107-default-copiers.xml | 1 - ...e-107-immutable-types-cm-level-copiers.xml | 1 - .../resources/ehcache-107-integration.xml | 0 .../test/resources/ehcache-107-listeners.xml | 5 +- .../ehcache-107-mbeans-cache-config.xml | 5 +- .../ehcache-107-mbeans-template-config.xml | 5 +- .../test/resources/ehcache-107-serializer.xml | 6 +- .../src/test/resources/ehcache-107-stats.xml | 5 +- .../src/test/resources/ehcache-107-types.xml | 0 .../src/test/resources/ehcache-107.xml | 5 +- .../src/test/resources/ehcache-example.xml | 0 ...ehcache-loader-writer-107-load-atomics.xml | 1 - .../resources/ehcache-loader-writer-107.xml | 1 - ...hcache-107-mbeans-cache-manager-config.xml | 6 +- .../docs/ehcache-jsr107-cache-through.xml | 1 - .../ehcache/docs/ehcache-jsr107-config.xml | 6 +- .../docs/ehcache-jsr107-template-override.xml | 6 +- .../org/ehcache/docs/public-xsds-location.xml | 0 {api => ehcache-api}/build.gradle | 13 +- .../config/checkstyle-suppressions.xml | 0 {api => ehcache-api}/config/checkstyle.xml | 1 - .../src/main/java/org/ehcache/Cache.java | 0 .../org/ehcache/CacheIterationException.java | 0 .../main/java/org/ehcache/CacheManager.java | 0 .../ehcache/CachePersistenceException.java | 0 .../org/ehcache/PersistentCacheManager.java | 0 .../ehcache/PersistentUserManagedCache.java | 0 .../org/ehcache/StateTransitionException.java | 0 .../src/main/java/org/ehcache/Status.java | 0 .../java/org/ehcache/UserManagedCache.java | 0 .../main/java/org/ehcache/ValueSupplier.java | 0 .../main/java/org/ehcache/config/Builder.java | 0 .../ehcache/config/CacheConfiguration.java | 0 .../config/CacheRuntimeConfiguration.java | 0 .../org/ehcache/config/Configuration.java | 0 .../java/org/ehcache/config/Eviction.java | 0 .../org/ehcache/config/EvictionAdvisor.java | 0 .../FluentCacheConfigurationBuilder.java | 0 .../config/FluentConfigurationBuilder.java | 0 .../java/org/ehcache/config/ResourcePool.java | 0 .../org/ehcache/config/ResourcePools.java | 0 .../java/org/ehcache/config/ResourceType.java | 0 .../java/org/ehcache/config/ResourceUnit.java | 0 .../org/ehcache/config/SizedResourcePool.java | 0 .../java/org/ehcache/config/package-info.java | 0 .../org/ehcache/config/units/EntryUnit.java | 0 .../org/ehcache/config/units/MemoryUnit.java | 0 .../ehcache/config/units/package-info.java | 0 .../java/org/ehcache/event/CacheEvent.java | 0 .../org/ehcache/event/CacheEventListener.java | 0 .../java/org/ehcache/event/EventFiring.java | 0 .../java/org/ehcache/event/EventOrdering.java | 0 .../java/org/ehcache/event/EventType.java | 0 .../java/org/ehcache/event/package-info.java | 0 .../java/org/ehcache/expiry/Duration.java | 0 .../java/org/ehcache/expiry/Expirations.java | 0 .../main/java/org/ehcache/expiry/Expiry.java | 0 .../java/org/ehcache/expiry/ExpiryPolicy.java | 0 .../java/org/ehcache/expiry/package-info.java | 0 .../main/java/org/ehcache/package-info.java | 0 .../java/org/ehcache/spi/copy/Copier.java | 0 .../org/ehcache/spi/copy/CopyProvider.java | 0 .../org/ehcache/spi/copy/package-info.java | 0 .../BulkCacheLoadingException.java | 0 .../BulkCacheWritingException.java | 0 .../spi/loaderwriter/CacheLoaderWriter.java | 0 .../CacheLoaderWriterConfiguration.java | 0 .../CacheLoaderWriterProvider.java | 0 .../loaderwriter/CacheLoadingException.java | 0 .../loaderwriter/CacheWritingException.java | 0 .../WriteBehindConfiguration.java | 0 .../spi/loaderwriter/WriteBehindProvider.java | 0 .../spi/loaderwriter/package-info.java | 0 .../PersistableResourceService.java | 0 .../ehcache/spi/persistence/StateHolder.java | 0 .../spi/persistence/StateRepository.java | 0 .../ehcache/spi/persistence/package-info.java | 0 .../ehcache/spi/resilience/RecoveryStore.java | 0 .../spi/resilience/ResilienceStrategy.java | 0 .../ResilienceStrategyProvider.java | 0 .../spi/resilience/StoreAccessException.java | 0 .../ehcache/spi/resilience/package-info.java | 0 .../serialization/SerializationProvider.java | 0 .../ehcache/spi/serialization/Serializer.java | 0 .../serialization/SerializerException.java | 0 .../spi/serialization/StatefulSerializer.java | 0 .../UnsupportedTypeException.java | 0 .../spi/serialization/package-info.java | 0 .../spi/service/MaintainableService.java | 0 .../service/OptionalServiceDependencies.java | 0 .../ehcache/spi/service/PluralService.java | 0 .../java/org/ehcache/spi/service/Service.java | 0 .../spi/service/ServiceConfiguration.java | 0 .../service/ServiceCreationConfiguration.java | 0 .../spi/service/ServiceDependencies.java | 0 .../ehcache/spi/service/ServiceProvider.java | 0 .../org/ehcache/spi/service/package-info.java | 0 .../java/org/ehcache/CacheManagerTest.java | 0 .../org/ehcache/UserManagedCacheTest.java | 0 .../ehcache/config/units/MemoryUnitTest.java | 0 .../java/org/ehcache/expiry/DurationTest.java | 0 .../org/ehcache/expiry/ExpirationsTest.java | 0 {core => ehcache-core}/build.gradle | 12 +- .../config/checkstyle-suppressions.xml | 0 .../core/CacheConfigurationChangeEvent.java | 0 .../CacheConfigurationChangeListener.java | 0 .../core/CacheConfigurationProperty.java | 0 .../DefaultCacheManagerProviderService.java | 0 .../main/java/org/ehcache/core/Ehcache.java | 0 .../java/org/ehcache/core/EhcacheBase.java | 0 .../java/org/ehcache/core/EhcacheManager.java | 0 .../core/EhcacheRuntimeConfiguration.java | 0 .../java/org/ehcache/core/HumanReadable.java | 0 .../java/org/ehcache/core/InternalCache.java | 0 .../core/InternalRuntimeConfiguration.java | 0 .../java/org/ehcache/core/InternalStatus.java | 0 .../java/org/ehcache/core/Jsr107Cache.java | 0 .../core/PersistentUserManagedEhcache.java | 0 .../java/org/ehcache/core/SpecIterator.java | 0 .../org/ehcache/core/StatusTransitioner.java | 0 .../ConcurrentWeakIdentityHashMap.java | 0 .../core/config/CoreConfigurationBuilder.java | 0 .../core/config/DefaultConfiguration.java | 0 .../org/ehcache/core/config/ExpiryUtils.java | 0 .../org/ehcache/core/config/package-info.java | 0 .../store/StoreEventSourceConfiguration.java | 0 .../store/StoreStatisticsConfiguration.java | 0 .../core/config/store/package-info.java | 0 .../core/events/CacheEventDispatcher.java | 0 .../events/CacheEventDispatcherFactory.java | 0 .../CacheEventListenerConfiguration.java | 0 .../events/CacheEventListenerProvider.java | 0 .../org/ehcache/core/events/CacheEvents.java | 0 .../core/events/CacheManagerListener.java | 0 .../core/events/EventListenerWrapper.java | 0 .../core/events/NullStoreEventDispatcher.java | 0 .../core/events/StateChangeListener.java | 0 .../core/events/StoreEventDispatcher.java | 0 .../ehcache/core/events/StoreEventSink.java | 0 .../org/ehcache/core/events/package-info.java | 0 .../core/exceptions/ExceptionFactory.java | 0 .../exceptions/StorePassThroughException.java | 0 .../ehcache/core/exceptions/package-info.java | 0 .../ThrowingResilienceStrategy.java | 0 .../statistics/DefaultCacheStatistics.java | 0 .../statistics/DefaultStatisticsService.java | 0 .../DefaultStatisticsServiceFactory.java | 0 .../statistics/DefaultTierStatistics.java | 0 .../DelegatedMappedOperationStatistics.java | 0 .../DelegatingOperationObserver.java | 0 .../DelegatingOperationStatistic.java | 0 .../core/internal/statistics/StatsUtils.java | 0 .../core/internal/util/ValueSuppliers.java | 0 .../ehcache/core/osgi/EhcacheActivator.java | 0 .../ehcache/core/osgi/OsgiServiceLoader.java | 0 .../java/org/ehcache/core/osgi/SafeOsgi.java | 0 .../java/org/ehcache/core/package-info.java | 0 .../core/resilience/DefaultRecoveryStore.java | 0 .../java/org/ehcache/core/spi/LifeCycled.java | 0 .../ehcache/core/spi/LifeCycledAdapter.java | 0 .../org/ehcache/core/spi/ServiceLocator.java | 0 .../org/ehcache/core/spi/package-info.java | 0 .../service/CacheManagerProviderService.java | 0 .../core/spi/service/DiskResourceService.java | 0 .../core/spi/service/ExecutionService.java | 0 .../service/FileBasedPersistenceContext.java | 0 .../spi/service/LocalPersistenceService.java | 0 .../core/spi/service/ServiceFactory.java | 0 .../core/spi/service/ServiceUtils.java | 0 .../core/spi/service/StatisticsService.java | 0 .../core/spi/service/package-info.java | 0 .../core/spi/store/AbstractValueHolder.java | 0 .../store/AbstractWrapperStoreProvider.java | 0 .../spi/store/ConfigurationChangeSupport.java | 0 .../core/spi/store/InternalCacheManager.java | 0 .../org/ehcache/core/spi/store/Store.java | 0 .../ehcache/core/spi/store/WrapperStore.java | 0 .../core/spi/store/events/StoreEvent.java | 0 .../spi/store/events/StoreEventFilter.java | 0 .../spi/store/events/StoreEventListener.java | 0 .../spi/store/events/StoreEventSource.java | 0 .../core/spi/store/events/package-info.java | 0 .../store/heap/LimitExceededException.java | 0 .../core/spi/store/heap/SizeOfEngine.java | 0 .../spi/store/heap/SizeOfEngineProvider.java | 0 .../core/spi/store/heap/package-info.java | 0 .../ehcache/core/spi/store/package-info.java | 0 .../spi/store/tiering/AuthoritativeTier.java | 0 .../core/spi/store/tiering/CachingTier.java | 0 .../spi/store/tiering/HigherCachingTier.java | 0 .../spi/store/tiering/LowerCachingTier.java | 0 .../core/spi/store/tiering/package-info.java | 0 .../core/spi/time/SystemTimeSource.java | 0 .../core/spi/time/TickingTimeSource.java | 0 .../org/ehcache/core/spi/time/TimeSource.java | 0 .../core/spi/time/TimeSourceService.java | 0 .../ehcache/core/spi/time/package-info.java | 0 .../AuthoritativeTierOperationOutcomes.java | 0 .../org/ehcache/core/statistics/BulkOps.java | 0 .../statistics/CacheOperationOutcomes.java | 0 .../core/statistics/CacheStatistics.java | 0 .../CachingTierOperationOutcomes.java | 0 .../core/statistics/ChainedObserver.java | 0 .../statistics/ChainedOperationObserver.java | 0 .../HigherCachingTierOperationOutcomes.java | 0 .../LowerCachingTierOperationsOutcome.java | 0 .../core/statistics/OperationObserver.java | 0 .../core/statistics/OperationStatistic.java | 0 .../core/statistics/SourceStatistic.java | 0 .../core/statistics/StatisticType.java | 0 .../statistics/StoreOperationOutcomes.java | 0 .../statistics/SuppliedValueStatistic.java | 0 .../statistics/TierOperationOutcomes.java | 0 .../core/statistics/TierStatistics.java | 0 .../core/statistics/ValueStatistic.java | 0 .../statistics/ZeroOperationStatistic.java | 0 .../ehcache/core/statistics/package-info.java | 0 .../core/store/StoreConfigurationImpl.java | 0 .../org/ehcache/core/store/StoreSupport.java | 0 .../core/util/ByteBufferInputStream.java | 0 .../org/ehcache/core/util/ClassLoading.java | 0 .../org/ehcache/core/util/CollectionUtil.java | 0 ...rg.ehcache.core.spi.service.ServiceFactory | 0 .../CacheConfigurationChangeListenerTest.java | 0 .../test/java/org/ehcache/core/CacheTest.java | 0 .../ehcache/core/EhcacheBasicBulkUtil.java | 0 .../ehcache/core/EhcacheBasicClearTest.java | 0 .../core/EhcacheBasicContainsKeyTest.java | 0 .../ehcache/core/EhcacheBasicCrudBase.java | 0 .../ehcache/core/EhcacheBasicGetAllTest.java | 0 .../org/ehcache/core/EhcacheBasicGetTest.java | 0 .../core/EhcacheBasicIteratorTest.java | 0 .../ehcache/core/EhcacheBasicPutAllTest.java | 0 .../core/EhcacheBasicPutIfAbsentTest.java | 0 .../org/ehcache/core/EhcacheBasicPutTest.java | 0 .../core/EhcacheBasicRemoveAllTest.java | 0 .../ehcache/core/EhcacheBasicRemoveTest.java | 0 .../core/EhcacheBasicRemoveValueTest.java | 0 .../ehcache/core/EhcacheBasicReplaceTest.java | 0 .../core/EhcacheBasicReplaceValueTest.java | 0 .../ehcache/core/EhcacheBulkMethodsTest.java | 0 .../org/ehcache/core/EhcacheManagerTest.java | 0 .../java/org/ehcache/core/EhcacheTest.java | 0 .../ehcache/core/StatusTransitionerTest.java | 0 .../ehcache/core/UserManagedCacheTest.java | 0 .../ConcurrentWeakIdentityHashMapTest.java | 0 .../config/CoreConfigurationBuilderTest.java | 0 .../ehcache/core/config/ExpiryUtilsTest.java | 0 .../core/config/ResourcePoolsHelper.java | 0 .../StoreStatisticsConfigurationTest.java | 0 .../ehcache/core/events/CacheEventsTest.java | 0 .../core/exceptions/ExceptionFactoryTest.java | 0 .../StorePassThroughExceptionTest.java | 0 .../internal/util/CollectionUtilTest.java | 0 .../core/spi/ServiceLocatorPluralTest.java | 0 .../ehcache/core/spi/ServiceLocatorTest.java | 0 .../core/spi/service/ServiceUtilsTest.java | 0 .../services/DefaultTestProvidedService.java | 0 .../core/spi/services/DefaultTestService.java | 0 .../core/spi/services/FancyCacheProvider.java | 0 .../services/FancyCacheProviderFactory.java | 0 .../services/TestMandatoryServiceFactory.java | 0 .../spi/services/TestProvidedService.java | 0 .../services/TestProvidedServiceFactory.java | 0 .../core/spi/services/TestService.java | 0 .../core/spi/services/TestServiceFactory.java | 0 .../ranking/HighRankServiceAFactory.java | 0 .../ranking/LowRankServiceBFactory.java | 0 .../MandatoryHighRankServiceBFactory.java | 0 .../MandatoryLowRankServiceAFactory.java | 0 .../spi/services/ranking/RankServiceA.java | 0 .../spi/services/ranking/RankServiceB.java | 0 .../spi/store/AbstractValueHolderTest.java | 0 .../ehcache/core/spi/store/CacheProvider.java | 0 .../core/spi/time/TickingTimeSourceTest.java | 0 .../ehcache/core/store/StoreSupportTest.java | 0 .../ehcache/core/util/ClassLoadingTest.java | 0 .../java/org/ehcache/core/util/IsCreated.java | 0 .../java/org/ehcache/core/util/IsRemoved.java | 0 .../java/org/ehcache/core/util/IsUpdated.java | 0 .../java/org/ehcache/core/util/Matchers.java | 0 .../ehcache/core/util/TestCacheConfig.java | 0 ...rg.ehcache.core.spi.service.ServiceFactory | 0 {impl => ehcache-impl}/build.gradle | 41 ++- .../config/checkstyle-suppressions.xml | 0 .../builders/CacheConfigurationBuilder.java | 0 ...acheEventListenerConfigurationBuilder.java | 0 .../config/builders/CacheManagerBuilder.java | 0 .../builders/CacheManagerConfiguration.java | 0 .../config/builders/ConfigurationBuilder.java | 0 .../config/builders/ExpiryPolicyBuilder.java | 0 ...dExecutionServiceConfigurationBuilder.java | 0 .../config/builders/ResourcePoolsBuilder.java | 0 .../builders/UserManagedCacheBuilder.java | 0 .../UserManagedCacheConfiguration.java | 0 .../WriteBehindConfigurationBuilder.java | 0 .../ehcache/config/builders/package-info.java | 0 .../impl/config/AbstractResourcePool.java | 0 .../impl/config/BaseCacheConfiguration.java | 0 .../impl/config/ResourcePoolsImpl.java | 0 .../impl/config/SizedResourcePoolImpl.java | 0 .../copy/DefaultCopierConfiguration.java | 0 .../DefaultCopyProviderConfiguration.java | 0 .../impl/config/copy/package-info.java | 0 ...heEventDispatcherFactoryConfiguration.java | 0 ...aultCacheEventDispatcherConfiguration.java | 0 ...efaultCacheEventListenerConfiguration.java | 0 .../DefaultEventSourceConfiguration.java | 0 .../impl/config/event/package-info.java | 0 .../PooledExecutionServiceConfiguration.java | 0 .../impl/config/executor/package-info.java | 0 ...DefaultCacheLoaderWriterConfiguration.java | 0 ...acheLoaderWriterProviderConfiguration.java | 0 .../config/loaderwriter/package-info.java | 0 .../DefaultBatchingConfiguration.java | 0 .../DefaultWriteBehindConfiguration.java | 0 .../WriteBehindProviderConfiguration.java | 0 .../writebehind/package-info.java | 0 .../CacheManagerPersistenceConfiguration.java | 0 .../DefaultPersistenceConfiguration.java | 0 .../UserManagedPersistenceContext.java | 0 .../impl/config/persistence/package-info.java | 0 ...efaultResilienceStrategyConfiguration.java | 0 ...silienceStrategyProviderConfiguration.java | 0 ...ultSerializationProviderConfiguration.java | 0 .../DefaultSerializerConfiguration.java | 0 .../impl/config/serializer/package-info.java | 0 .../disk/OffHeapDiskStoreConfiguration.java | 0 ...OffHeapDiskStoreProviderConfiguration.java | 0 .../impl/config/store/disk/package-info.java | 0 .../DefaultSizeOfEngineConfiguration.java | 0 ...aultSizeOfEngineProviderConfiguration.java | 0 .../impl/config/store/heap/package-info.java | 0 .../org/ehcache/impl/copy/IdentityCopier.java | 0 .../ehcache/impl/copy/ReadWriteCopier.java | 0 .../ehcache/impl/copy/SerializingCopier.java | 0 .../org/ehcache/impl/copy/package-info.java | 0 .../impl/events/CacheEventAdapter.java | 0 .../impl/events/CacheEventDispatcherImpl.java | 0 .../impl/events/EventDispatchTask.java | 0 .../org/ehcache/impl/events/package-info.java | 0 .../internal/DefaultTimeSourceService.java | 0 .../internal/TimeSourceConfiguration.java | 0 .../internal/TimeSourceServiceFactory.java | 0 .../classes/ClassInstanceConfiguration.java | 0 .../classes/ClassInstanceProvider.java | 0 .../ClassInstanceProviderConfiguration.java | 0 .../classes/commonslang/ArrayUtils.java | 0 .../classes/commonslang/ClassUtils.java | 0 .../commonslang/reflect/ConstructorUtils.java | 0 .../commonslang/reflect/MemberUtils.java | 0 .../commonslang/reflect/MethodUtils.java | 0 .../events/AbstractStoreEventDispatcher.java | 0 .../CacheEventDispatcherFactoryImpl.java | 0 ...icationListenerServiceProviderFactory.java | 0 .../events/CloseableStoreEventSink.java | 0 ...DisabledCacheEventNotificationService.java | 0 .../events/FireableStoreEventHolder.java | 0 .../FudgingInvocationScopedEventSink.java | 0 .../events/InvocationScopedEventSink.java | 0 .../impl/internal/events/StoreEventImpl.java | 0 .../impl/internal/events/StoreEvents.java | 0 .../ThreadLocalStoreEventDispatcher.java | 0 .../DefaultExecutionServiceFactory.java | 0 .../impl/internal/executor/ExecutorUtil.java | 0 .../executor/OnDemandExecutionService.java | 0 .../executor/OutOfBandScheduledExecutor.java | 0 .../executor/PartitionedOrderedExecutor.java | 0 .../PartitionedScheduledExecutor.java | 0 .../PartitionedUnorderedExecutor.java | 0 .../executor/PooledExecutionService.java | 0 .../writebehind/AbstractWriteBehind.java | 0 .../BatchingLocalHeapWriteBehindQueue.java | 0 .../NonBatchingLocalHeapWriteBehindQueue.java | 0 .../writebehind/StripedWriteBehind.java | 0 .../loaderwriter/writebehind/WriteBehind.java | 0 .../WriteBehindProviderFactory.java | 0 .../operations/BatchOperation.java | 0 .../operations/DeleteAllOperation.java | 0 .../operations/DeleteOperation.java | 0 .../operations/KeyBasedOperation.java | 0 .../operations/SingleOperation.java | 0 .../operations/WriteAllOperation.java | 0 .../operations/WriteOperation.java | 0 .../DefaultDiskResourceServiceFactory.java | 0 ...DefaultLocalPersistenceServiceFactory.java | 0 .../AbstractResilienceStrategy.java | 0 .../RobustLoaderWriterResilienceStrategy.java | 0 .../resilience/RobustResilienceStrategy.java | 0 .../internal/sizeof/DefaultSizeOfEngine.java | 0 .../sizeof/DefaultSizeOfEngineProvider.java | 0 .../DefaultSizeOfEngineProviderFactory.java | 0 .../internal/sizeof/NoopSizeOfEngine.java | 0 .../listeners/EhcacheVisitorListener.java | 0 .../exceptions/VisitorListenerException.java | 0 .../spi/copy/DefaultCopyProvider.java | 0 .../spi/copy/DefaultCopyProviderFactory.java | 0 .../DefaultCacheEventListenerProvider.java | 0 ...aultCacheEventListenerProviderFactory.java | 0 .../DefaultCacheLoaderWriterProvider.java | 0 ...faultCacheLoaderWriterProviderFactory.java | 0 .../DefaultResilienceStrategyProvider.java | 0 ...aultResilienceStrategyProviderFactory.java | 0 .../DefaultSerializationProvider.java | 0 .../DefaultSerializationProviderFactory.java | 0 .../internal/store/BinaryValueHolder.java | 0 .../impl/internal/store/basic/NopStore.java | 0 .../store/disk/DiskWriteThreadPool.java | 0 ...PersistentConcurrentOffHeapClockCache.java | 0 .../internal/store/disk/OffHeapDiskStore.java | 0 .../disk/OffHeapDiskStoreProviderFactory.java | 0 .../EhcachePersistentSegmentFactory.java | 0 .../impl/internal/store/heap/Backend.java | 0 .../internal/store/heap/KeyCopyBackend.java | 0 .../impl/internal/store/heap/OnHeapStore.java | 0 .../heap/OnHeapStoreProviderFactory.java | 0 .../internal/store/heap/OnHeapStrategy.java | 0 .../internal/store/heap/SimpleBackend.java | 0 .../store/heap/holders/BaseOnHeapKey.java | 0 .../store/heap/holders/CopiedOnHeapKey.java | 0 .../heap/holders/CopiedOnHeapValueHolder.java | 0 .../heap/holders/LookupOnlyOnHeapKey.java | 0 .../store/heap/holders/OnHeapKey.java | 0 .../store/heap/holders/OnHeapValueHolder.java | 0 .../holders/SerializedOnHeapValueHolder.java | 0 .../LoaderWriterStoreProvider.java | 0 .../LoaderWriterStoreProviderFactory.java | 0 .../loaderwriter/LoaderWriterValueHolder.java | 0 .../loaderwriter/LocalLoaderWriterStore.java | 0 .../LocalWriteBehindLoaderWriterStore.java | 0 .../store/offheap/AbstractOffHeapStore.java | 0 .../offheap/BasicOffHeapValueHolder.java | 0 .../offheap/BinaryOffHeapValueHolder.java | 0 .../EhcacheConcurrentOffHeapClockCache.java | 0 .../offheap/EhcacheOffHeapBackingMap.java | 0 .../store/offheap/HeuristicConfiguration.java | 0 .../store/offheap/LazyOffHeapValueHolder.java | 0 .../store/offheap/MemorySizeParser.java | 0 .../store/offheap/OffHeapMapStatistics.java | 0 .../internal/store/offheap/OffHeapStore.java | 0 .../offheap/OffHeapStoreProviderFactory.java | 0 .../store/offheap/OffHeapStoreUtils.java | 0 .../store/offheap/OffHeapValueHolder.java | 0 .../offheap/SwitchableEvictionAdvisor.java | 0 .../factories/EhcacheSegmentFactory.java | 0 .../OffHeapValueHolderPortability.java | 0 .../portability/SerializerPortability.java | 0 .../store/tiering/CompoundCachingTier.java | 0 .../CompoundCachingTierProviderFactory.java | 0 .../internal/store/tiering/TieredStore.java | 0 .../tiering/TieredStoreProviderFactory.java | 0 .../org/ehcache/impl/internal/util/Pacer.java | 0 .../impl/internal/util/ServiceUtil.java | 0 .../impl/internal/util/ThreadFactoryUtil.java | 0 .../DefaultDiskResourceService.java | 0 .../DefaultLocalPersistenceService.java | 0 .../persistence/FileBasedStateRepository.java | 0 .../ehcache/impl/persistence/FileUtils.java | 0 .../impl/persistence/package-info.java | 0 .../serialization/ByteArraySerializer.java | 0 .../impl/serialization/CharSerializer.java | 0 .../serialization/CompactJavaSerializer.java | 0 .../impl/serialization/DoubleSerializer.java | 0 .../impl/serialization/FloatSerializer.java | 0 .../impl/serialization/IntegerSerializer.java | 0 .../impl/serialization/LongSerializer.java | 0 .../serialization/PlainJavaSerializer.java | 0 .../impl/serialization/StringSerializer.java | 0 .../serialization/TransientStateHolder.java | 0 .../TransientStateRepository.java | 0 .../impl/serialization/package-info.java | 0 .../org/ehcache/impl/store/BaseStore.java | 0 .../store/DefaultStoreEventDispatcher.java | 0 .../org/ehcache/impl/store/HashUtils.java | 0 ...rg.ehcache.core.spi.service.ServiceFactory | 0 .../concurrent/ConcurrentHashMapITest.java | 0 .../EhcacheRuntimeConfigurationTest.java | 0 .../CacheConfigurationBuilderTest.java | 0 .../builders/CacheManagerBuilderTest.java | 0 .../builders/ExpiryPolicyBuilderTest.java | 0 .../builders/PersistentCacheManagerTest.java | 0 .../builders/ResourcePoolsBuilderTest.java | 0 .../ehcache/config/builders/TieringTest.java | 0 .../builders/UserManagedCacheBuilderTest.java | 0 .../WriteBehindConfigurationBuilderTest.java | 0 .../CacheManagerListenerInteractionsTest.java | 0 .../core/events/CacheManagerListenerTest.java | 0 .../ehcache/core/spi/ServiceProviderTest.java | 0 .../ehcache/docs/ConfigurationDerivation.java | 0 .../test/java/org/ehcache/docs/Ehcache3.java | 0 .../java/org/ehcache/docs/GettingStarted.java | 0 .../java/org/ehcache/docs/ThreadPools.java | 0 .../test/java/org/ehcache/docs/Tiering.java | 0 .../org/ehcache/docs/UserManagedCaches.java | 0 .../ehcache/docs/plugs/ListenerObject.java | 0 .../org/ehcache/docs/plugs/LongCopier.java | 0 .../docs/plugs/OddKeysEvictionAdvisor.java | 0 .../docs/plugs/SampleLoaderWriter.java | 0 .../org/ehcache/docs/plugs/StringCopier.java | 0 .../config/BaseCacheConfigurationTest.java | 0 .../impl/config/ResourcePoolsImplTest.java | 0 .../config/SizedResourcePoolImplTest.java | 0 .../DefaultCopyProviderConfigurationTest.java | 0 ...entDispatcherFactoryConfigurationTest.java | 0 ...CacheEventDispatcherConfigurationTest.java | 0 ...ltCacheEventListenerConfigurationTest.java | 0 .../DefaultEventSourceConfigurationTest.java | 0 ...oledExecutionServiceConfigurationTest.java | 0 ...ultCacheLoaderWriterConfigurationTest.java | 0 ...LoaderWriterProviderConfigurationTest.java | 0 .../WriteBehindProviderConfigurationTest.java | 0 .../DefaultPersistenceConfigurationTest.java | 0 ...ltResilienceStrategyConfigurationTest.java | 0 ...enceStrategyProviderConfigurationTest.java | 0 ...erializationProviderConfigurationTest.java | 0 .../serializer/SerializerCountingTest.java | 0 .../OffHeapDiskStoreConfigurationTest.java | 0 ...eapDiskStoreProviderConfigurationTest.java | 0 .../events/CacheEventDispatcherImplTest.java | 0 .../DefaultTimeSourceServiceTest.java | 0 .../internal/TimeSourceConfigurationTest.java | 0 ...lassInstanceProviderConfigurationTest.java | 0 .../classes/ClassInstanceProviderTest.java | 0 .../concurrent/ConcurrentHashMapTest.java | 0 .../otherPackage/V8FeaturesTest.java | 0 .../internal/copy/IdentityCopierTest.java | 0 .../internal/copy/SerializingCopierTest.java | 0 .../CacheEventDispatcherFactoryImplTest.java | 0 .../FudgingInvocationScopedEventSinkTest.java | 0 .../events/InvocationScopedEventSinkTest.java | 0 .../events/TestStoreEventDispatcher.java | 0 .../PartitionedOrderedExecutorTest.java | 0 .../PartitionedScheduledExecutorTest.java | 0 .../PartitionedUnorderedExecutorTest.java | 0 .../executor/PooledExecutionServiceTest.java | 0 .../AbstractWriteBehindTestBase.java | 0 .../PooledExecutorWriteBehindTest.java | 0 .../writebehind/WriteBehindEvictionTest.java | 0 .../WriteBehindProviderFactoryTest.java | 0 .../writebehind/WriteBehindTest.java | 0 .../WriteBehindTestLoaderWriter.java | 0 ...eManagerDestroyRemovesPersistenceTest.java | 0 .../persistence/TestDiskResourceService.java | 0 ...ustLoaderWriterResilienceStrategyTest.java | 0 .../RobustResilienceStrategyTest.java | 0 .../DefaultSizeOfEngineConfigurationTest.java | 0 ...SizeOfEngineProviderConfigurationTest.java | 0 ...efaultSizeOfEngineProviderFactoryTest.java | 0 .../sizeof/DefaultSizeOfEngineTest.java | 0 .../internal/spi/TestServiceProvider.java | 0 .../spi/copy/DefaultCopyProviderTest.java | 0 ...DefaultCacheEventListenerProviderTest.java | 0 .../DefaultCacheLoaderWriterProviderTest.java | 0 ...ResilienceStrategyProviderFactoryTest.java | 0 ...DefaultResilienceStrategyProviderTest.java | 0 .../DefaultSerializationProviderTest.java | 0 .../DefaultCacheStatisticsTest.java | 0 .../DefaultStatisticsServiceTest.java | 0 .../DefaultTierStatisticsDisabledTest.java | 0 .../statistics/DefaultTierStatisticsTest.java | 0 .../internal/statistics/StatsUtilsTest.java | 0 .../store/basic/DelegatingValueHolder.java | 0 .../store/basic/SimpleValueHolder.java | 0 ...istentConcurrentOffHeapClockCacheTest.java | 0 .../disk/OffHeapDiskStoreProviderTest.java | 0 .../store/disk/OffHeapDiskStoreSPITest.java | 0 .../store/disk/OffHeapDiskStoreTest.java | 0 .../EhcachePersistentSegmentTest.java | 0 .../store/heap/BaseOnHeapStoreTest.java | 0 .../ByteSizedOnHeapStoreByRefSPITest.java | 0 .../ByteSizedOnHeapStoreByValueSPITest.java | 0 .../heap/CountSizedOnHeapStoreByRefTest.java | 0 .../CountSizedOnHeapStoreByValueTest.java | 0 .../heap/OnHeapStoreBulkMethodsTest.java | 0 .../store/heap/OnHeapStoreByRefSPITest.java | 0 .../store/heap/OnHeapStoreByRefTest.java | 0 .../store/heap/OnHeapStoreByValueSPITest.java | 0 .../store/heap/OnHeapStoreByValueTest.java | 0 .../OnHeapStoreCachingTierByRefSPITest.java | 0 .../OnHeapStoreCachingTierByValueSPITest.java | 0 .../store/heap/OnHeapStoreEvictionTest.java | 0 .../store/heap/OnHeapStoreKeyCopierTest.java | 0 .../store/heap/OnHeapStoreProviderTest.java | 0 .../heap/OnHeapStoreValueCopierTest.java | 0 .../store/heap/OnHeapStrategyTest.java | 0 .../heap/bytesized/ByteAccountingTest.java | 0 .../ByteSizedOnHeapStoreByRefTest.java | 0 .../ByteSizedOnHeapStoreByValueTest.java | 0 .../bytesized/OnHeapStoreBulkMethodsTest.java | 0 .../OnHeapStoreCachingTierByRefSPITest.java | 0 .../OnHeapStoreCachingTierByValueSPITest.java | 0 .../bytesized/OnHeapStoreEvictionTest.java | 0 .../heap/bytesized/OversizeMappingTest.java | 0 .../heap/holders/CopiedOnHeapKeyTest.java | 0 .../holders/CopiedOnHeapValueHolderTest.java | 0 .../SerializedOnHeapValueHolderTest.java | 0 .../AbstractEhcacheOffHeapBackingMapTest.java | 0 .../offheap/AbstractOffHeapStoreTest.java | 0 .../offheap/AssertingOffHeapValueHolder.java | 0 .../AssertingOffHeapValueHolderTest.java | 0 .../offheap/BasicOffHeapValueHolderTest.java | 0 .../offheap/BinaryOffHeapValueHolderTest.java | 0 ...hcacheConcurrentOffHeapClockCacheTest.java | 0 .../offheap/LazyOffHeapValueHolderTest.java | 0 .../store/offheap/MemorySizeParserTest.java | 0 .../offheap/OffHeapStoreLifecycleHelper.java | 0 .../store/offheap/OffHeapStoreSPITest.java | 0 .../store/offheap/OffHeapStoreTest.java | 0 .../store/offheap/OffHeapStoreUtilsTest.java | 0 .../OffHeapValueHolderPortabilityTest.java | 0 .../offheap/factories/EhcacheSegmentTest.java | 0 ...ssertingOffHeapValueHolderPortability.java | 0 .../tiering/CompoundCachingTierSPITest.java | 0 .../tiering/CompoundCachingTierTest.java | 0 .../TieredStoreFlushWhileShutdownTest.java | 0 .../store/tiering/TieredStoreMutatorTest.java | 0 .../store/tiering/TieredStoreSPITest.java | 0 .../store/tiering/TieredStoreTest.java | 0 .../tiering/TieredStoreWith3TiersSPITest.java | 0 .../util/ByteBufferInputStreamTest.java | 0 .../internal/util/FileExistenceMatchers.java | 0 .../util/FileExistenceMatchersTest.java | 0 .../ehcache/impl/internal/util/Matchers.java | 0 .../ehcache/impl/internal/util/PacerTest.java | 0 .../internal/util/StatisticsTestUtils.java | 0 .../internal/util/ThreadFactoryUtilTest.java | 0 .../internal/util/UnmatchedResourceType.java | 0 .../DefaultDiskResourceServiceTest.java | 0 .../DefaultLocalPersistenceServiceTest.java | 0 .../FileBasedStateRepositoryTest.java | 0 .../impl/serialization/AddedFieldTest.java | 0 .../serialization/AddedSuperClassTest.java | 0 .../serialization/ArrayPackageScopeTest.java | 0 .../serialization/BasicSerializationTest.java | 0 .../ByteArraySerializerTest.java | 0 .../serialization/CharSerializerTest.java | 0 .../CompactJavaSerializerClassLoaderTest.java | 0 ...mpactJavaSerializerClassUnloadingTest.java | 0 .../CompactJavaSerializerTest.java | 0 .../serialization/DoubleSerializerTest.java | 0 .../serialization/DuplicateClassLoader.java | 0 .../ehcache/impl/serialization/EnumTest.java | 0 .../serialization/FieldTypeChangeTest.java | 0 .../serialization/FloatSerializerTest.java | 0 .../impl/serialization/GetFieldTest.java | 0 .../serialization/IntegerSerializerTest.java | 0 .../impl/serialization/JavaSerializer.java | 0 .../serialization/LongSerializerTest.java | 0 .../impl/serialization/PutFieldTest.java | 0 .../serialization/ReadObjectNoDataTest.java | 0 .../SerializeAfterEvolutionTest.java | 0 .../SerializerTestUtilities.java | 0 .../serialization/StringSerializerTest.java | 0 .../TransientStateRepositoryTest.java | 0 .../DefaultStoreEventDispatcherTest.java | 0 .../org/ehcache/impl/store/HashUtilsTest.java | 0 .../java/org/ehcache/test/MockitoUtil.java | 0 .../concurrent/ConcurrentHashMap.java | 0 .../concurrent/EvictingConcurrentMap.java | 0 .../concurrent/ThreadLocalRandomUtil.java | 0 .../internal/concurrent/package-info.java | 0 .../build.gradle | 25 +- .../config/checkstyle-suppressions.xml | 0 .../ehcache/management/CollectorService.java | 0 .../management/ExtendedStatisticsService.java | 0 .../management/ManagementRegistryService.java | 0 ...anagementRegistryServiceConfiguration.java | 0 .../management/SharedManagementService.java | 0 .../management/cluster/Clustering.java | 0 .../cluster/ClusteringManagementService.java | 0 ...steringManagementServiceConfiguration.java | 0 .../DefaultClusteringManagementService.java | 0 ...steringManagementServiceConfiguration.java | 0 .../management/cluster/LoggingExecutor.java | 0 .../management/providers/CacheBinding.java | 0 .../CacheBindingManagementProvider.java | 0 .../EhcacheStatisticCollectorProvider.java | 0 .../providers/ExposedCacheBinding.java | 0 .../actions/EhcacheActionProvider.java | 0 .../actions/EhcacheActionWrapper.java | 0 .../settings/EhcacheSettingsProvider.java | 0 .../settings/ExposedCacheSettings.java | 0 .../providers/settings/Reflect.java | 0 .../statistics/EhcacheStatisticsProvider.java | 0 .../statistics/StandardEhcacheStatistics.java | 0 .../registry/DefaultCollectorService.java | 0 ...efaultManagementRegistryConfiguration.java | 0 .../DefaultManagementRegistryFactory.java | 0 .../DefaultManagementRegistryService.java | 0 .../DefaultSharedManagementService.java | 0 .../LatencyHistogramConfiguration.java | 0 ...entRegistryServiceConfigurationParser.java | 0 .../management/registry/NodeListIterable.java | 0 .../statistics/DefaultCacheStatistics.java | 0 .../DefaultExtendedStatisticsService.java | 0 ...faultExtendedStatisticsServiceFactory.java | 0 .../statistics/DefaultTierStatistics.java | 0 .../DelegatedMappedOperationStatistics.java | 0 .../DelegatingOperationObserver.java | 0 .../management/statistics/StatsUtils.java | 0 ...rg.ehcache.core.spi.service.ServiceFactory | 0 ...xml.CacheManagerServiceConfigurationParser | 0 .../main/resources/ehcache-management-ext.xsd | 0 .../java/org/ehcache/docs/ManagementTest.java | 0 ...tRegistryServiceConfigurationParserIT.java | 0 .../actions/EhcacheActionProviderTest.java | 0 .../settings/EhcacheSettingsProviderTest.java | 0 .../EhcacheStatisticsProviderTest.java | 0 .../LatencyHistogramConfigurationTest.java | 0 .../StandardEhCacheStatisticsQueryTest.java | 0 .../StandardEhcacheStatisticsTest.java | 0 .../providers/statistics/StatsUtil.java | 0 .../registry/DefaultCollectorServiceTest.java | 0 .../DefaultManagementRegistryServiceTest.java | 0 .../DefaultSharedManagementServiceTest.java | 0 ...egistryServiceConfigurationParserTest.java | 0 .../management/registry/XmlConfigTest.java | 0 .../test/resources/ehcache-management-1.xml | 16 + .../test/resources/ehcache-management-2.xml | 5 +- .../test/resources/ehcache-management-3.xml | 5 +- .../test/resources/ehcache-management-4.xml | 5 +- .../test/resources/ehcache-management-5.xml | 5 +- .../src/test/resources/ehcache-management.xml | 5 +- .../test/resources/settings-capability.json | 0 ehcache-transactions/build.gradle | 75 +++++ .../config/checkstyle-suppressions.xml | 0 .../transactions/xa/EhcacheXAException.java | 0 .../transactions/xa/XACacheException.java | 0 .../configuration/XAStoreConfiguration.java | 0 .../xa/internal/EhcacheXAResource.java | 0 .../xa/internal/SerializableXid.java | 0 .../transactions/xa/internal/SoftLock.java | 0 .../xa/internal/SoftLockSerializer.java | 0 .../internal/SoftLockValueCombinedCopier.java | 0 .../SoftLockValueCombinedSerializer.java | 0 ...atefulSoftLockValueCombinedSerializer.java | 0 .../xa/internal/StoreEventSourceWrapper.java | 0 .../xa/internal/TransactionId.java | 0 .../transactions/xa/internal/TypeUtil.java | 0 .../transactions/xa/internal/XAStore.java | 0 .../xa/internal/XATransactionContext.java | 0 .../internal/XATransactionContextFactory.java | 0 .../xa/internal/XAValueHolder.java | 0 .../xa/internal/commands/Command.java | 0 .../internal/commands/StoreEvictCommand.java | 0 .../xa/internal/commands/StorePutCommand.java | 0 .../internal/commands/StoreRemoveCommand.java | 0 .../configuration/XAStoreProviderFactory.java | 0 .../journal/DefaultJournalProvider.java | 0 .../DefaultJournalProviderFactory.java | 0 .../xa/internal/journal/Journal.java | 0 .../xa/internal/journal/JournalProvider.java | 0 .../internal/journal/PersistentJournal.java | 0 .../xa/internal/journal/TransientJournal.java | 0 .../txmgr/NullXAResourceRegistry.java | 0 ...aultTransactionManagerProviderFactory.java | 0 ...acheManagerServiceConfigurationParser.java | 0 .../TxCacheServiceConfigurationParser.java | 0 .../xa/txmgr/TransactionManagerWrapper.java | 0 .../xa/txmgr/XAResourceRegistry.java | 0 .../btm/BitronixTransactionManagerLookup.java | 0 .../txmgr/btm/BitronixXAResourceRegistry.java | 0 .../txmgr/btm/Ehcache3XAResourceHolder.java | 0 .../txmgr/btm/Ehcache3XAResourceProducer.java | 0 .../LookupTransactionManagerProvider.java | 0 ...ansactionManagerProviderConfiguration.java | 0 .../provider/TransactionManagerLookup.java | 0 .../provider/TransactionManagerProvider.java | 0 ...rg.ehcache.core.spi.service.ServiceFactory | 0 ...xml.CacheManagerServiceConfigurationParser | 0 ...hcache.xml.CacheServiceConfigurationParser | 0 .../src/main/resources/ehcache-tx-ext.xsd | 0 .../transactions/xa/XAGettingStarted.java | 0 .../offheap/OffHeapStoreLifecycleHelper.java | 6 +- .../ehcache/transactions/NonXACacheTest.java | 0 .../TransactionalCacheParserIT.java | 0 .../ehcache/transactions/XmlConfigTest.java | 0 .../XAStoreConfigurationTest.java | 0 .../integration/StatefulSerializerTest.java | 0 .../xa/internal/EhcacheXAResourceTest.java | 0 .../internal/UnSupportedResourceTypeTest.java | 0 .../xa/internal/XAStoreProviderTest.java | 0 .../transactions/xa/internal/XAStoreTest.java | 0 .../xa/internal/XATransactionContextTest.java | 0 .../xa/internal/XAValueHolderTest.java | 0 .../internal/journal/AbstractJournalTest.java | 0 .../journal/PersistentJournalTest.java | 0 .../journal/TransientJournalTest.java | 0 ...ManagerServiceConfigurationParserTest.java | 0 ...TxCacheServiceConfigurationParserTest.java | 0 ...ctionManagerProviderConfigurationTest.java | 0 .../transactions/xa/utils/JavaSerializer.java | 0 .../transactions/xa/utils/TestXid.java | 0 .../src/test/resources/configs/simple-xa.xml | 5 +- .../test/resources/configs/template-xa.xml | 5 +- .../resources/configs/transactional-cache.xml | 5 +- .../docs/configs/xa-getting-started.xml | 5 +- {xml => ehcache-xml}/README.adoc | 0 ehcache-xml/build.gradle | 97 ++++++ .../config/checkstyle-suppressions.xml | 2 +- .../org/ehcache/xml/BaseConfigParser.java | 0 ...acheManagerServiceConfigurationParser.java | 0 .../xml/CacheResourceConfigurationParser.java | 0 .../xml/CacheServiceConfigurationParser.java | 0 .../org/ehcache/xml/ConfigurationParser.java | 0 .../xml/CoreCacheConfigurationParser.java | 0 .../xml/CoreServiceConfigurationParser.java | 0 ...oreServiceCreationConfigurationParser.java | 0 .../main/java/org/ehcache/xml/DomUtil.java | 0 .../main/java/org/ehcache/xml/JaxbHelper.java | 0 .../java/org/ehcache/xml/JaxbParsers.java | 0 .../xml/ResourceConfigurationParser.java | 0 .../xml/ServiceConfigurationParser.java | 0 .../ServiceCreationConfigurationParser.java | 0 .../org/ehcache/xml/XmlConfiguration.java | 0 .../main/java/org/ehcache/xml/XmlModel.java | 0 .../exceptions/XmlConfigurationException.java | 0 .../ehcache/xml/model/CacheDefinition.java | 0 .../java/org/ehcache/xml/model/CacheSpec.java | 0 .../org/ehcache/xml/model/CacheTemplate.java | 0 .../java/org/ehcache/xml/model/Expiry.java | 0 .../ehcache/xml/model/ListenersConfig.java | 0 .../ehcache/xml/model/SizeOfEngineLimits.java | 0 .../xml/multi/XmlMultiConfiguration.java | 0 ...tDispatcherFactoryConfigurationParser.java | 0 ...ManagerPersistenceConfigurationParser.java | 0 ...efaultCopyProviderConfigurationParser.java | 0 ...ializationProviderConfigurationParser.java | 0 ...zeOfEngineProviderConfigurationParser.java | 0 ...pDiskStoreProviderConfigurationParser.java | 0 ...edExecutionServiceConfigurationParser.java | 0 ...oreServiceCreationConfigurationParser.java | 0 ...oolServiceCreationConfigurationParser.java | 0 ...riteBehindProviderConfigurationParser.java | 0 ...cheEventDispatcherConfigurationParser.java | 0 ...CacheEventListenerConfigurationParser.java | 0 ...tCacheLoaderWriterConfigurationParser.java | 0 .../DefaultCopierConfigurationParser.java | 0 ...ResilienceStrategyConfigurationParser.java | 0 .../DefaultSerializerConfigurationParser.java | 0 ...efaultSizeOfEngineConfigurationParser.java | 0 ...DefaultWriteBehindConfigurationParser.java | 0 .../OffHeapDiskStoreConfigurationParser.java | 0 .../SimpleCoreServiceConfigurationParser.java | 0 .../src/main/schema}/ehcache-core.xsd | 0 .../src/main/schema}/ehcache-multi.xsd | 0 .../com/pany/ehcache/DeprecatedExpiry.java | 0 .../test/java/com/pany/ehcache/MyExpiry.java | 0 .../copier/AnotherDescriptionCopier.java | 0 .../ehcache/copier/AnotherPersonCopier.java | 0 .../com/pany/ehcache/copier/Description.java | 0 .../ehcache/copier/DescriptionCopier.java | 0 .../com/pany/ehcache/copier/Employee.java | 0 .../java/com/pany/ehcache/copier/Person.java | 0 .../com/pany/ehcache/copier/PersonCopier.java | 0 .../integration/TestCacheEventListener.java | 0 .../integration/TestCacheLoaderWriter.java | 0 .../integration/TestEvictionAdvisor.java | 0 .../integration/TestResilienceStrategy.java | 0 .../TestSecondCacheEventListener.java | 0 .../ThreadRememberingLoaderWriter.java | 0 .../ehcache/serializer/TestSerializer.java | 0 .../ehcache/serializer/TestSerializer2.java | 0 .../ehcache/serializer/TestSerializer3.java | 0 .../ehcache/serializer/TestSerializer4.java | 0 .../java/org/ehcache/docs/GettingStarted.java | 0 .../org/ehcache/docs/MultiGettingStarted.java | 0 .../org/ehcache/xml/BarConfiguration.java | 0 .../test/java/org/ehcache/xml/BarParser.java | 0 .../test/java/org/ehcache/xml/BazParser.java | 0 .../java/org/ehcache/xml/BazResource.java | 0 .../xml/CoreCacheConfigurationParserTest.java | 0 .../java/org/ehcache/xml/FancyParser.java | 0 .../org/ehcache/xml/FooConfiguration.java | 0 .../test/java/org/ehcache/xml/FooParser.java | 0 ...eCacheConfigurationBuilderDefaultTest.java | 0 .../xml/IntegrationConfigurationTest.java | 0 .../java/org/ehcache/xml/JaxbParsersTest.java | 0 .../java/org/ehcache/xml/NiResilience.java | 0 .../ehcache/xml/PropertySubstitutionTest.java | 0 .../org/ehcache/xml/ShrubberyResilience.java | 0 .../org/ehcache/xml/XmlConfigurationTest.java | 0 .../xml/multi/XmlMultiConfigurationTest.java | 0 ...patcherFactoryConfigurationParserTest.java | 0 ...gerPersistenceConfigurationParserTest.java | 0 ...ltCopyProviderConfigurationParserTest.java | 0 ...zationProviderConfigurationParserTest.java | 0 ...EngineProviderConfigurationParserTest.java | 0 ...kStoreProviderConfigurationParserTest.java | 0 ...ecutionServiceConfigurationParserTest.java | 0 ...BehindProviderConfigurationParserTest.java | 0 ...ventDispatcherConfigurationParserTest.java | 0 ...eEventListenerConfigurationParserTest.java | 0 ...heLoaderWriterConfigurationParserTest.java | 0 .../DefaultCopierConfigurationParserTest.java | 0 ...lienceStrategyConfigurationParserTest.java | 0 ...aultSerializerConfigurationParserTest.java | 0 ...ltSizeOfEngineConfigurationParserTest.java | 0 ...ultWriteBehindConfigurationParserTest.java | 0 ...fHeapDiskStoreConfigurationParserTest.java | 0 ...xml.CacheManagerServiceConfigurationParser | 0 ...cache.xml.CacheResourceConfigurationParser | 0 ...hcache.xml.CacheServiceConfigurationParser | 0 .../test/resources/configs/all-extensions.xml | 5 +- .../src/test/resources/configs/bar.xsd | 0 .../src/test/resources/configs/baz.xsd | 0 .../test/resources/configs/cache-copiers.xml | 4 +- .../resources/configs/cache-integration.xml | 5 +- .../resources/configs/custom-resource.xml | 5 +- .../resources/configs/default-serializer.xml | 4 +- .../resources/configs/defaultTypes-cache.xml | 5 +- .../configs/disk-persistent-cache.xml | 5 +- .../test/resources/configs/docs/expiry.xml | 5 +- .../configs/docs/getting-started.xml | 5 +- .../configs/docs/multi/multiple-managers.xml | 5 +- .../configs/docs/multi/multiple-variants.xml | 5 +- .../configs/docs/template-sample.xml | 5 +- .../resources/configs/docs/thread-pools.xml | 5 +- .../configs/ehcache-cacheEventListener.xml | 5 +- .../resources/configs/ehcache-complete.xml | 5 +- .../ehcache-multipleCacheEventListener.xml | 5 +- .../configs/ehcache-system-props.xml | 5 +- .../test/resources/configs/expiry-caches.xml | 5 +- .../src/test/resources/configs/fancy.xsd | 0 .../src/test/resources/configs/foo.xsd | 0 .../test/resources/configs/invalid-core.xml | 1 - .../resources/configs/invalid-service.xml | 1 - .../resources/configs/invalid-two-caches.xml | 11 + .../test/resources/configs/multi/empty.xml | 2 + .../test/resources/configs/multi/extended.xml | 1 - .../configs/multi/multiple-configs.xml | 1 - .../configs/multi/multiple-variants.xml | 1 - .../configs/nonExistentAdvisor-cache.xml | 5 +- .../configs/nonExistentAdvisor-template.xml | 5 +- .../src/test/resources/configs/one-cache.xml | 5 +- .../test/resources/configs/one-service.xml | 5 +- .../resources/configs/persistence-config.xml | 5 + .../resources/configs/pretty-typed-caches.xml | 5 +- .../resources/configs/resilience-config.xml | 5 +- .../resources/configs/resources-caches.xml | 5 +- .../resources/configs/resources-templates.xml | 5 +- .../configs/sizeof-engine-cm-defaults-one.xml | 5 +- .../configs/sizeof-engine-cm-defaults-two.xml | 5 +- .../test/resources/configs/sizeof-engine.xml | 5 +- .../test/resources/configs/template-cache.xml | 5 +- .../resources/configs/template-defaults.xml | 7 +- .../test/resources/configs/thread-pools.xml | 4 +- .../resources/configs/unknown-resource.xml | 1 - .../configs/unknown-service-creation.xml | 1 - .../resources/configs/unknown-service.xml | 1 - .../resources/configs/writebehind-cache.xml | 5 +- .../ehcache/xml/XmlConfigurationMatchers.java | 0 ehcache/build.gradle | 96 ++++++ .../templates/github-release-issue.md | 0 {dist => ehcache}/templates/github-release.md | 0 gradle.properties | 6 +- gradle/wrapper/gradle-wrapper.properties | 2 +- impl/.gitignore | 1 - impl/gradle.properties | 2 - integration-test/.gitignore | 1 - integration-test/build.gradle | 14 +- integration-test/gradle.properties | 2 - .../src/test/resources/configs/simple-xa.xml | 5 +- management/.gitignore | 1 - management/gradle.properties | 3 - .../test/resources/ehcache-management-1.xml | 19 -- osgi-test/build.gradle | 29 +- .../ehcache/osgi/ByteSizedOnHeapOsgiTest.java | 8 +- .../java/org/ehcache/osgi/Jsr107OsgiTest.java | 12 +- .../org/ehcache/osgi/OffHeapOsgiTest.java | 10 +- .../java/org/ehcache/osgi/SimpleOsgiTest.java | 12 +- .../ehcache/osgi/TransactionalOsgiTest.java | 14 +- .../org/ehcache/osgi/ehcache-107-osgi.xml | 5 +- .../org/ehcache/osgi/ehcache-osgi.xml | 4 +- .../org/ehcache/osgi/ehcache-xa-osgi.xml | 1 - settings.gradle | 29 +- spi-tester/.gitignore | 1 - spi-tester/build.gradle | 3 + spi-tester/gradle.properties | 2 - transactions/build.gradle | 56 ---- transactions/gradle.properties | 2 - xml/.gitignore | 1 - xml/build.gradle | 76 ----- xml/gradle.properties | 18 -- .../xml/ConfigurationParserTestHelper.java | 31 -- .../resources/configs/invalid-two-caches.xml | 14 - .../test/resources/configs/multi/empty.xml | 5 - .../resources/configs/persistence-config.xml | 8 - 1542 files changed, 2591 insertions(+), 2073 deletions(-) delete mode 100755 107/.gitignore delete mode 100644 107/gradle.properties delete mode 100755 api/.gitignore delete mode 100644 api/gradle.properties create mode 100644 build-logic/build.gradle create mode 100644 build-logic/src/main/java/org/ehcache/build/ClusteredEhcacheModule.java create mode 100644 build-logic/src/main/java/org/ehcache/build/ClusteredServerModule.java create mode 100644 build-logic/src/main/java/org/ehcache/build/EhcacheModule.java create mode 100644 build-logic/src/main/java/org/ehcache/build/EhcachePackage.java create mode 100644 build-logic/src/main/java/org/ehcache/build/InternalEhcacheModule.java create mode 100644 build-logic/src/main/java/org/ehcache/build/PublicEhcacheModule.java create mode 100644 build-logic/src/main/java/org/ehcache/build/conventions/BaseConvention.java create mode 100644 build-logic/src/main/java/org/ehcache/build/conventions/BndConvention.java create mode 100644 build-logic/src/main/java/org/ehcache/build/conventions/CheckstyleConvention.java create mode 100644 build-logic/src/main/java/org/ehcache/build/conventions/DeployConvention.java create mode 100644 build-logic/src/main/java/org/ehcache/build/conventions/JacocoConvention.java create mode 100644 build-logic/src/main/java/org/ehcache/build/conventions/JavaBaseConvention.java create mode 100644 build-logic/src/main/java/org/ehcache/build/conventions/JavaConvention.java create mode 100644 build-logic/src/main/java/org/ehcache/build/conventions/JavaLibraryConvention.java create mode 100644 build-logic/src/main/java/org/ehcache/build/conventions/SpotbugsConvention.java create mode 100644 build-logic/src/main/java/org/ehcache/build/conventions/WarConvention.java create mode 100644 build-logic/src/main/java/org/ehcache/build/plugins/PackagePlugin.java create mode 100644 build-logic/src/main/java/org/ehcache/build/plugins/VariantPlugin.java create mode 100644 build-logic/src/main/java/org/ehcache/build/plugins/VoltronPlugin.java create mode 100644 build-logic/src/main/java/org/ehcache/build/plugins/osgids/GenerateDeclarativeServicesDescriptors.java create mode 100644 build-logic/src/main/java/org/ehcache/build/plugins/osgids/OsgiDsPlugin.java create mode 100644 build-logic/src/main/java/org/ehcache/build/plugins/osgids/ScrLoggerAdapter.java create mode 100644 build-logic/src/main/java/org/ehcache/build/util/OsgiManifestJarExtension.java create mode 100644 build-logic/src/main/java/org/ehcache/build/util/PluginUtils.java delete mode 100644 buildSrc/build.gradle delete mode 100644 buildSrc/src/main/groovy/EhDeploy.groovy delete mode 100644 buildSrc/src/main/groovy/EhDistribute.groovy delete mode 100644 buildSrc/src/main/groovy/EhDocs.groovy delete mode 100644 buildSrc/src/main/groovy/EhPomGenerate.groovy delete mode 100644 buildSrc/src/main/groovy/EhPomMangle.groovy delete mode 100644 buildSrc/src/main/groovy/EhVoltron.groovy delete mode 100644 buildSrc/src/main/groovy/scripts/Utils.groovy delete mode 100644 clustered/build.gradle delete mode 100644 clustered/client/gradle.properties delete mode 100644 clustered/clustered-dist/gradle.properties delete mode 100644 clustered/common-api/gradle.properties delete mode 100644 clustered/common/gradle.properties rename clustered/{client => ehcache-client}/build.gradle (57%) rename clustered/{client => ehcache-client}/config/checkstyle-suppressions.xml (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/config/ClusteredResourcePool.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/config/ClusteredResourceType.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/config/ClusteredStoreConfiguration.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/config/DedicatedClusteredResourcePool.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/config/SharedClusteredResourcePool.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/config/Timeouts.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/config/builders/ClusteredResourcePoolBuilder.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/config/builders/ClusteredStoreConfigurationBuilder.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/config/builders/ClusteringServiceConfigurationBuilder.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/config/builders/ServerSideConfigurationBuilder.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/config/builders/TimeoutsBuilder.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntity.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityService.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerCreationException.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerNotFoundException.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerValidationException.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/PerpetualCachePersistenceException.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/SimpleClusterTierManagerClientEntity.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/config/ClusteredResourcePoolImpl.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/config/DedicatedClusteredResourcePoolImpl.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/config/SharedClusteredResourcePoolImpl.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConstants.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderFactory.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProviderFactory.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderFactory.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLock.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockClient.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockEntityClientService.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/AbstractClientEntityFactory.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/ClusterStateRepository.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierCreationException.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierDestructionException.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierException.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerConfigurationException.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierReleaseException.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierValidationException.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/ClusteredMapException.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/ClusteredStateHolder.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java (99%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/ValueCodec.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/service/ValueCodecFactory.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntity.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierUserData.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredValueHolder.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/FailedReconnectStoreProxy.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectInProgressException.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxy.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxyException.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManager.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/operations/EternalChainResolver.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/service/ClientEntityFactory.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/service/ClusteringService.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/service/EntityBusyException.java (100%) rename clustered/{client => ehcache-client}/src/main/java/org/ehcache/clustered/client/service/EntityService.java (100%) rename clustered/{client => ehcache-client}/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory (100%) rename clustered/{client => ehcache-client}/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser (100%) rename clustered/{client => ehcache-client}/src/main/resources/META-INF/services/org.ehcache.xml.CacheResourceConfigurationParser (100%) rename clustered/{client => ehcache-client}/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser (100%) rename clustered/{client => ehcache-client}/src/main/resources/META-INF/services/org.terracotta.entity.EntityClientService (100%) rename clustered/{client => ehcache-client}/src/main/resources/ehcache-clustered-ext.xsd (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/SimpleClusteredCacheByXmlTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/TerracottaUriXmlTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/TestTimeSource.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/XmlConsistencyTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/XmlUnknownCacheTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/config/ClusteredConfigurationDerivationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/config/ClusteredStoreConfigurationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/config/builders/ClusteredResourcePoolBuilderTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/config/builders/TimeoutsBuilderTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/docs/Resilience.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/docs/Tiering.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/MockConnectionService.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/config/ClusteredResourcePoolImplTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/config/DedicatedClusteredResourcePoolImplTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/config/SharedClusteredResourcePoolImplTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockClientTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/service/TestServiceProvider.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/store/ChainBuilderTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxyTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/client/replication/ReplicationUtil.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/common/internal/store/operations/BaseKeyValueOperationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/common/internal/store/operations/ConditionalRemoveOperationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/common/internal/store/operations/EternalChainResolverTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/common/internal/store/operations/LazyValueHolderTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutIfAbsentOperationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutOperationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutWithWriterOperationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/common/internal/store/operations/RemoveOperationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/common/internal/store/operations/ReplaceOperationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperationTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/loaderWriter/TestCacheLoaderWriter.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/RecordingLoaderWriter.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/server/ObservableEhcacheServerEntityService.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/server/package-info.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/server/store/ObservableClusterTierServerEntityService.java (100%) rename clustered/{client => ehcache-client}/src/test/java/org/ehcache/clustered/util/StatisticsTestUtils.java (100%) rename clustered/{client => ehcache-client}/src/test/resources/META-INF/services/org.terracotta.connection.ConnectionService (100%) rename clustered/{client => ehcache-client}/src/test/resources/configs/cluster-ha.xml (100%) rename clustered/{client => ehcache-client}/src/test/resources/configs/cluster-invalid-uri.xml (100%) rename clustered/{client => ehcache-client}/src/test/resources/configs/clustered-cache.xml (100%) rename clustered/{client => ehcache-client}/src/test/resources/configs/consistency.xml (86%) rename clustered/{client => ehcache-client}/src/test/resources/configs/docs/ehcache-clustered.xml (82%) rename clustered/{client => ehcache-client}/src/test/resources/configs/offheap-resource.xml (94%) rename clustered/{client => ehcache-client}/src/test/resources/configs/simple-cluster.xml (100%) rename clustered/{client => ehcache-client}/src/test/resources/configs/unknown-cluster-cache-invalid-attribute.xml (94%) rename clustered/{client => ehcache-client}/src/test/resources/configs/unknown-cluster-cache-invalid-element.xml (94%) rename clustered/{client => ehcache-client}/src/test/resources/configs/unknown-cluster-cache.xml (94%) rename clustered/{clustered-dist => ehcache-clustered}/build.gradle (62%) rename clustered/{clustered-dist => ehcache-clustered}/src/assemble/README.txt (100%) rename clustered/{clustered-dist => ehcache-clustered}/src/assemble/legal/APACHE_PUBLIC_LICENSE.txt (100%) rename clustered/{clustered-dist => ehcache-clustered}/src/assemble/legal/LICENSE (100%) rename clustered/{clustered-dist => ehcache-clustered}/src/assemble/server/conf/cluster.cfg (100%) rename clustered/{common-api => ehcache-common-api}/build.gradle (75%) rename clustered/{common-api => ehcache-common-api}/config/checkstyle-suppressions.xml (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/Consistency.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/PoolAllocation.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/ServerSideConfiguration.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/ClusterTierManagerConfiguration.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/ServerStoreConfiguration.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/exceptions/ClusterException.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/exceptions/DestroyInProgressException.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationException.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreException.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/exceptions/LifecycleException.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityMessage.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheOperationMessage.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpMessage.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/store/Chain.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/store/Element.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java (100%) rename clustered/{common-api => ehcache-common-api}/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java (100%) rename clustered/{common-api => ehcache-common-api}/src/test/java/org/ehcache/clustered/common/ServerSideConfigurationTest.java (100%) rename clustered/{common => ehcache-common}/build.gradle (60%) rename clustered/{common => ehcache-common}/config/checkstyle-suppressions.xml (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/EhcacheEntityVersion.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/exceptions/IllegalMessageException.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidOperationException.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerStoreConfigurationException.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/exceptions/UnknownClusterException.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/lock/LockMessaging.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/BaseCodec.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/ClusterTierReconnectMessage.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/CodecUtil.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodec.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/ConcurrentEntityMessage.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/ConfigCodec.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheCodec.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/EntityConfigurationCodec.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/ExceptionCodec.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodec.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageFactory.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/LifecycleMessage.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/MessageCodecUtils.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodec.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessage.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryMessageFactory.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpCodec.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/ClusterTierEntityConfiguration.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/CustomLoaderBasedObjectInputStream.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/FilteredObjectInputStream.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/SequencedElement.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/Util.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/BaseKeyValueOperation.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/ConditionalRemoveOperation.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperation.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/LazyValueHolder.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/Operation.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/OperationCode.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutIfAbsentOperation.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutOperation.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutWithWriterOperation.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/RemoveOperation.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/ReplaceOperation.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/Result.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperation.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/codecs/CodecException.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/store/operations/codecs/OperationsCodec.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/util/ByteBufferInputStream.java (100%) rename clustered/{common => ehcache-common}/src/main/java/org/ehcache/clustered/common/internal/util/ChainBuilder.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/Store/operations/OperationCodeTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/exceptions/BaseClusteredEhcacheExceptionTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/exceptions/IllegalMessageExceptionTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidOperationExceptionTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationExceptionTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerStoreConfigurationExceptionTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreExceptionTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/exceptions/LifecycleExceptionTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodecTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/messages/EhcacheCodecTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodecTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodecTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java (100%) rename clustered/{common => ehcache-common}/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessageTest.java (100%) delete mode 100644 clustered/integration-test/gradle.properties delete mode 100644 clustered/ops-tool/gradle.properties rename clustered/server/{entity => ehcache-entity}/build.gradle (72%) rename clustered/server/{entity => ehcache-entity}/config/checkstyle-suppressions.xml (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntity.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockPassiveEntity.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockServerEntityService.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/lock/server/messages/LockSyncMessaging.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntity.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/ClusterTierManagerDump.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntity.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/ClusterTierManagerServerEntityService.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/CommunicatorServiceConfiguration.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/ConcurrencyStrategies.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/EhcacheExecutionStrategy.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/ServerStoreCompatibility.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheDataSyncMessage.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerCatchup.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessage.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagement.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerBinding.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerSettingsManagementProvider.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/management/Management.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/management/Notification.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/management/PoolBinding.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/management/PoolSettingsManagementProvider.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/management/PoolStatisticsManagementProvider.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/management/ServerStoreBinding.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/management/ServerStoreStatisticsManagementProvider.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/store/ClusterTierDump.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/store/LockManagerImpl.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/store/MessageToTrackerSegmentFunction.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/store/NoopLockManager.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/java/org/ehcache/clustered/server/store/ServerLockManager.java (100%) rename clustered/server/{entity => ehcache-entity}/src/main/resources/META-INF/services/org.terracotta.entity.EntityServerService (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/DefaultConcurrencyStrategyTest.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/TestClientSourceId.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/TestInvokeContext.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessageTest.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodecTest.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/store/InvalidMessage.java (100%) rename clustered/server/{entity => ehcache-entity}/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java (100%) rename clustered/server/{service-api => ehcache-service-api}/build.gradle (68%) rename clustered/server/{service-api => ehcache-service-api}/config/checkstyle-suppressions.xml (100%) rename clustered/server/{service-api => ehcache-service-api}/src/main/java/org/ehcache/clustered/server/KeySegmentMapper.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessage.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/main/java/org/ehcache/clustered/server/repo/ServerStateRepository.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/main/java/org/ehcache/clustered/server/repo/StateRepositoryManager.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/main/java/org/ehcache/clustered/server/state/EhcacheStateContext.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/main/java/org/ehcache/clustered/server/state/InvalidationTracker.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStateServiceConfig.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStoreStateServiceConfig.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/test/java/org/ehcache/clustered/server/repo/ServerStateRepositoryTest.java (100%) rename clustered/server/{service-api => ehcache-service-api}/src/test/java/org/ehcache/clustered/server/repo/StateRepositoryManagerTest.java (100%) rename clustered/server/{service => ehcache-service}/build.gradle (73%) rename clustered/server/{service => ehcache-service}/config/checkstyle-suppressions.xml (100%) rename clustered/server/{service => ehcache-service}/src/main/java/org/ehcache/clustered/server/EhcacheStateServiceImpl.java (100%) rename clustered/server/{service => ehcache-service}/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java (100%) rename clustered/server/{service => ehcache-service}/src/main/java/org/ehcache/clustered/server/offheap/ChainStorageEngine.java (100%) rename clustered/server/{service => ehcache-service}/src/main/java/org/ehcache/clustered/server/offheap/LongPortability.java (100%) rename clustered/server/{service => ehcache-service}/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java (100%) rename clustered/server/{service => ehcache-service}/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java (100%) rename clustered/server/{service => ehcache-service}/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java (100%) rename clustered/server/{service => ehcache-service}/src/main/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMap.java (100%) rename clustered/server/{service => ehcache-service}/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceDump.java (100%) rename clustered/server/{service => ehcache-service}/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java (100%) rename clustered/server/{service => ehcache-service}/src/main/java/org/ehcache/clustered/server/state/InvalidationTrackerImpl.java (100%) rename clustered/server/{service => ehcache-service}/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java (100%) rename clustered/server/{service => ehcache-service}/src/main/resources/META-INF/services/org.terracotta.entity.ServiceProvider (100%) rename clustered/server/{service => ehcache-service}/src/main/resources/offheap-message.properties (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/EhcacheStateServiceImplTest.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/state/EhcacheStateServiceProviderTest.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/state/InvalidationTrackerImplTest.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/store/ChainBuilder.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/store/ElementBuilder.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainBuilder.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainImpl.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementBuilder.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementImpl.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java (100%) rename clustered/server/{service => ehcache-service}/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreTest.java (100%) delete mode 100644 clustered/server/entity/gradle.properties delete mode 100644 clustered/server/service-api/gradle.properties delete mode 100644 clustered/server/service/gradle.properties delete mode 100755 core-spi-test/.gitignore delete mode 100644 core-spi-test/gradle.properties delete mode 100755 core/.gitignore delete mode 100644 core/gradle.properties delete mode 100755 demos/00-NoCache/gradle.properties delete mode 100755 demos/01-CacheAside/gradle.properties delete mode 100755 dist/.gitignore delete mode 100644 dist/build.gradle delete mode 100644 dist/gradle.properties delete mode 100644 docs/gradle.properties rename {107 => ehcache-107}/README.adoc (98%) rename {107 => ehcache-107}/build.gradle (86%) rename {107 => ehcache-107}/config/checkstyle-suppressions.xml (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/CacheResources.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/CloseUtil.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/ConfigurationMerger.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/DefaultConfigurationResolver.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Eh107Cache.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Eh107CacheEntryEvent.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Eh107CacheLoaderWriter.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Eh107CacheLoaderWriterProvider.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Eh107CacheMXBean.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Eh107CacheManager.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Eh107CompleteConfiguration.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Eh107Configuration.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Eh107Expiry.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Eh107IdentityCopier.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Eh107MXBean.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Eh107ReverseConfiguration.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/EhcacheExpiryWrapper.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/EventListenerAdaptors.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/ExpiryPolicyToEhcacheExpiry.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Jsr107Service.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/ListenerResources.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/NullCompletionListener.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/Unwrap.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/config/ConfigurationElementState.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/config/Jsr107CacheConfiguration.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/config/Jsr107Configuration.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/config/package-info.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/internal/DefaultJsr107Service.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheLoaderWriter.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/internal/Jsr107LatencyMonitor.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/internal/WrappedCacheLoaderWriter.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/internal/tck/Eh107MBeanServerBuilder.java (100%) rename {107 => ehcache-107}/src/main/java/org/ehcache/jsr107/package-info.java (100%) rename {107 => ehcache-107}/src/main/resources/META-INF/services/javax.cache.spi.CachingProvider (100%) rename {107 => ehcache-107}/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser (100%) rename {107 => ehcache-107}/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser (100%) rename {107 => ehcache-107}/src/main/resources/ehcache-107-ext.xsd (100%) rename {107 => ehcache-107}/src/tck/resources/ExcludeList (100%) rename {107 => ehcache-107}/src/test/java/com/pany/domain/Client.java (100%) rename {107 => ehcache-107}/src/test/java/com/pany/domain/Customer.java (100%) rename {107 => ehcache-107}/src/test/java/com/pany/domain/Product.java (100%) rename {107 => ehcache-107}/src/test/java/com/pany/ehcache/ClientCopier.java (100%) rename {107 => ehcache-107}/src/test/java/com/pany/ehcache/MyEvictionAdvisor.java (100%) rename {107 => ehcache-107}/src/test/java/com/pany/ehcache/Test107CacheEntryListener.java (100%) rename {107 => ehcache-107}/src/test/java/com/pany/ehcache/TestCacheEventListener.java (100%) rename {107 => ehcache-107}/src/test/java/com/pany/ehcache/integration/ProductCacheLoaderWriter.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/ParsesConfigurationExtensionTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/CacheResourcesTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/ConfigStatsManagementActivationTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/DefaultConfigurationResolverTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/Eh107CacheTypeTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/Eh107XmlIntegrationTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/EhCachingProviderTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/IteratorTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/Jsr107CacheParserIT.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/LoadAtomicsWith107Test.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/LoaderWriterConfigTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/LoaderWriterTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/LongSerializer.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/SerializerTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/SimpleEh107ConfigTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/StatisticsTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/StringSerializer.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/UnwrapTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParserTest.java (100%) rename {107 => ehcache-107}/src/test/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParserTest.java (100%) rename {107 => ehcache-107}/src/test/resources/ehcache-107-copiers-immutable-types.xml (97%) rename {107 => ehcache-107}/src/test/resources/ehcache-107-default-copiers.xml (95%) rename {107 => ehcache-107}/src/test/resources/ehcache-107-immutable-types-cm-level-copiers.xml (97%) rename {107 => ehcache-107}/src/test/resources/ehcache-107-integration.xml (100%) rename {107 => ehcache-107}/src/test/resources/ehcache-107-listeners.xml (80%) rename {107 => ehcache-107}/src/test/resources/ehcache-107-mbeans-cache-config.xml (74%) rename {107 => ehcache-107}/src/test/resources/ehcache-107-mbeans-template-config.xml (78%) rename {107 => ehcache-107}/src/test/resources/ehcache-107-serializer.xml (69%) rename {107 => ehcache-107}/src/test/resources/ehcache-107-stats.xml (73%) rename {107 => ehcache-107}/src/test/resources/ehcache-107-types.xml (100%) rename {107 => ehcache-107}/src/test/resources/ehcache-107.xml (61%) rename {107 => ehcache-107}/src/test/resources/ehcache-example.xml (100%) rename {107 => ehcache-107}/src/test/resources/ehcache-loader-writer-107-load-atomics.xml (89%) rename {107 => ehcache-107}/src/test/resources/ehcache-loader-writer-107.xml (88%) rename {107 => ehcache-107}/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml (81%) rename {107 => ehcache-107}/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml (93%) rename {107 => ehcache-107}/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml (57%) rename {107 => ehcache-107}/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml (85%) rename {107 => ehcache-107}/src/test/resources/org/ehcache/docs/public-xsds-location.xml (100%) rename {api => ehcache-api}/build.gradle (72%) rename {api => ehcache-api}/config/checkstyle-suppressions.xml (100%) rename {api => ehcache-api}/config/checkstyle.xml (97%) rename {api => ehcache-api}/src/main/java/org/ehcache/Cache.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/CacheIterationException.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/CacheManager.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/CachePersistenceException.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/PersistentCacheManager.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/PersistentUserManagedCache.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/StateTransitionException.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/Status.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/UserManagedCache.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/ValueSupplier.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/Builder.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/CacheConfiguration.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/CacheRuntimeConfiguration.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/Configuration.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/Eviction.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/EvictionAdvisor.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/FluentCacheConfigurationBuilder.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/FluentConfigurationBuilder.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/ResourcePool.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/ResourcePools.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/ResourceType.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/ResourceUnit.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/SizedResourcePool.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/package-info.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/units/EntryUnit.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/units/MemoryUnit.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/config/units/package-info.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/event/CacheEvent.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/event/CacheEventListener.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/event/EventFiring.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/event/EventOrdering.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/event/EventType.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/event/package-info.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/expiry/Duration.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/expiry/Expirations.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/expiry/Expiry.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/expiry/ExpiryPolicy.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/expiry/package-info.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/package-info.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/copy/Copier.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/copy/CopyProvider.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/copy/package-info.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/loaderwriter/BulkCacheLoadingException.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/loaderwriter/BulkCacheWritingException.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriter.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterConfiguration.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterProvider.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/loaderwriter/CacheLoadingException.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/loaderwriter/CacheWritingException.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindConfiguration.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindProvider.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/loaderwriter/package-info.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/persistence/PersistableResourceService.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/persistence/StateHolder.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/persistence/StateRepository.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/persistence/package-info.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/resilience/RecoveryStore.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/resilience/ResilienceStrategy.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/resilience/ResilienceStrategyProvider.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/resilience/StoreAccessException.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/resilience/package-info.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/serialization/SerializationProvider.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/serialization/Serializer.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/serialization/SerializerException.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/serialization/StatefulSerializer.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/serialization/UnsupportedTypeException.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/serialization/package-info.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/service/MaintainableService.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/service/OptionalServiceDependencies.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/service/PluralService.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/service/Service.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/service/ServiceConfiguration.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/service/ServiceCreationConfiguration.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/service/ServiceDependencies.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/service/ServiceProvider.java (100%) rename {api => ehcache-api}/src/main/java/org/ehcache/spi/service/package-info.java (100%) rename {api => ehcache-api}/src/test/java/org/ehcache/CacheManagerTest.java (100%) rename {api => ehcache-api}/src/test/java/org/ehcache/UserManagedCacheTest.java (100%) rename {api => ehcache-api}/src/test/java/org/ehcache/config/units/MemoryUnitTest.java (100%) rename {api => ehcache-api}/src/test/java/org/ehcache/expiry/DurationTest.java (100%) rename {api => ehcache-api}/src/test/java/org/ehcache/expiry/ExpirationsTest.java (100%) rename {core => ehcache-core}/build.gradle (82%) rename {core => ehcache-core}/config/checkstyle-suppressions.xml (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/CacheConfigurationChangeEvent.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/CacheConfigurationChangeListener.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/CacheConfigurationProperty.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/DefaultCacheManagerProviderService.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/Ehcache.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/EhcacheBase.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/EhcacheManager.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/EhcacheRuntimeConfiguration.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/HumanReadable.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/InternalCache.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/InternalRuntimeConfiguration.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/InternalStatus.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/Jsr107Cache.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/PersistentUserManagedEhcache.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/SpecIterator.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/StatusTransitioner.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/collections/ConcurrentWeakIdentityHashMap.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/config/CoreConfigurationBuilder.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/config/DefaultConfiguration.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/config/ExpiryUtils.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/config/package-info.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/config/store/StoreEventSourceConfiguration.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/config/store/StoreStatisticsConfiguration.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/config/store/package-info.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/events/CacheEventDispatcher.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/events/CacheEventDispatcherFactory.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/events/CacheEventListenerConfiguration.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/events/CacheEventListenerProvider.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/events/CacheEvents.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/events/CacheManagerListener.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/events/EventListenerWrapper.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/events/NullStoreEventDispatcher.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/events/StateChangeListener.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/events/StoreEventDispatcher.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/events/StoreEventSink.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/events/package-info.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/exceptions/ExceptionFactory.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/exceptions/StorePassThroughException.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/exceptions/package-info.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/internal/resilience/ThrowingResilienceStrategy.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/internal/statistics/DefaultCacheStatistics.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsService.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsServiceFactory.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/internal/statistics/DefaultTierStatistics.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/internal/statistics/DelegatedMappedOperationStatistics.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationObserver.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationStatistic.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/internal/statistics/StatsUtils.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/internal/util/ValueSuppliers.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/osgi/EhcacheActivator.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/osgi/OsgiServiceLoader.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/osgi/SafeOsgi.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/package-info.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/resilience/DefaultRecoveryStore.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/LifeCycled.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/LifeCycledAdapter.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/ServiceLocator.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/package-info.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/service/CacheManagerProviderService.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/service/DiskResourceService.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/service/ExecutionService.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/service/FileBasedPersistenceContext.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/service/LocalPersistenceService.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/service/ServiceFactory.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/service/ServiceUtils.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/service/StatisticsService.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/service/package-info.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/ConfigurationChangeSupport.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/InternalCacheManager.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/Store.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/WrapperStore.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/events/StoreEvent.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/events/StoreEventFilter.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/events/StoreEventListener.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/events/StoreEventSource.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/events/package-info.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/heap/LimitExceededException.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/heap/SizeOfEngine.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/heap/SizeOfEngineProvider.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/heap/package-info.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/package-info.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/tiering/AuthoritativeTier.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/tiering/CachingTier.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/tiering/HigherCachingTier.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/tiering/LowerCachingTier.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/store/tiering/package-info.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/time/SystemTimeSource.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/time/TickingTimeSource.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/time/TimeSource.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/time/TimeSourceService.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/spi/time/package-info.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/AuthoritativeTierOperationOutcomes.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/BulkOps.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/CacheOperationOutcomes.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/CacheStatistics.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/CachingTierOperationOutcomes.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/ChainedObserver.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/ChainedOperationObserver.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/HigherCachingTierOperationOutcomes.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/LowerCachingTierOperationsOutcome.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/OperationObserver.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/OperationStatistic.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/SourceStatistic.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/StatisticType.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/StoreOperationOutcomes.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/TierOperationOutcomes.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/TierStatistics.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/ValueStatistic.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/ZeroOperationStatistic.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/statistics/package-info.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/store/StoreConfigurationImpl.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/store/StoreSupport.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/util/ByteBufferInputStream.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/util/ClassLoading.java (100%) rename {core => ehcache-core}/src/main/java/org/ehcache/core/util/CollectionUtil.java (100%) rename {core => ehcache-core}/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/CacheConfigurationChangeListenerTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/CacheTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicBulkUtil.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicClearTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicContainsKeyTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicGetTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicIteratorTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicPutAllTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicPutTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicRemoveAllTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicRemoveTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicRemoveValueTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicReplaceTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBasicReplaceValueTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheBulkMethodsTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheManagerTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/EhcacheTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/StatusTransitionerTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/UserManagedCacheTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/collections/ConcurrentWeakIdentityHashMapTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/config/CoreConfigurationBuilderTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/config/ExpiryUtilsTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/config/ResourcePoolsHelper.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/config/store/StoreStatisticsConfigurationTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/events/CacheEventsTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/exceptions/ExceptionFactoryTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/exceptions/StorePassThroughExceptionTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/internal/util/CollectionUtilTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/ServiceLocatorPluralTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/service/ServiceUtilsTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/DefaultTestProvidedService.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/DefaultTestService.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/FancyCacheProvider.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/FancyCacheProviderFactory.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/TestMandatoryServiceFactory.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/TestProvidedService.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/TestProvidedServiceFactory.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/TestService.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/TestServiceFactory.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/ranking/HighRankServiceAFactory.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/ranking/LowRankServiceBFactory.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryHighRankServiceBFactory.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryLowRankServiceAFactory.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/ranking/RankServiceA.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/services/ranking/RankServiceB.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/store/CacheProvider.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/spi/time/TickingTimeSourceTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/store/StoreSupportTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/util/ClassLoadingTest.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/util/IsCreated.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/util/IsRemoved.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/util/IsUpdated.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/util/Matchers.java (100%) rename {core => ehcache-core}/src/test/java/org/ehcache/core/util/TestCacheConfig.java (100%) rename {core => ehcache-core}/src/test/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory (100%) rename {impl => ehcache-impl}/build.gradle (66%) rename {impl => ehcache-impl}/config/checkstyle-suppressions.xml (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/config/builders/CacheConfigurationBuilder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/config/builders/CacheEventListenerConfigurationBuilder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/config/builders/CacheManagerBuilder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/config/builders/CacheManagerConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/config/builders/ConfigurationBuilder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/config/builders/ExpiryPolicyBuilder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/config/builders/PooledExecutionServiceConfigurationBuilder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/config/builders/ResourcePoolsBuilder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/config/builders/UserManagedCacheConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/config/builders/WriteBehindConfigurationBuilder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/config/builders/package-info.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/AbstractResourcePool.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/BaseCacheConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/ResourcePoolsImpl.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/SizedResourcePoolImpl.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/copy/DefaultCopierConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/copy/package-info.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventListenerConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/event/DefaultEventSourceConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/event/package-info.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/executor/package-info.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/loaderwriter/package-info.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/DefaultBatchingConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/DefaultWriteBehindConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/package-info.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/persistence/CacheManagerPersistenceConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/persistence/UserManagedPersistenceContext.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/persistence/package-info.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializerConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/serializer/package-info.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/store/disk/package-info.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineProviderConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/config/store/heap/package-info.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/copy/IdentityCopier.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/copy/ReadWriteCopier.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/copy/SerializingCopier.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/copy/package-info.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/events/CacheEventAdapter.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/events/CacheEventDispatcherImpl.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/events/EventDispatchTask.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/events/package-info.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/DefaultTimeSourceService.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/TimeSourceConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/classes/commonslang/ArrayUtils.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/classes/commonslang/ClassUtils.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/ConstructorUtils.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MemberUtils.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MethodUtils.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/events/AbstractStoreEventDispatcher.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImpl.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/events/CacheEventNotificationListenerServiceProviderFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/events/CloseableStoreEventSink.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/events/DisabledCacheEventNotificationService.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/events/FireableStoreEventHolder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/events/FudgingInvocationScopedEventSink.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/events/InvocationScopedEventSink.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/events/StoreEventImpl.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/events/StoreEvents.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/events/ThreadLocalStoreEventDispatcher.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/executor/ExecutorUtil.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/executor/OnDemandExecutionService.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/executor/OutOfBandScheduledExecutor.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/executor/PartitionedOrderedExecutor.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/executor/PartitionedScheduledExecutor.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/executor/PartitionedUnorderedExecutor.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/executor/PooledExecutionService.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehind.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/BatchingLocalHeapWriteBehindQueue.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/NonBatchingLocalHeapWriteBehindQueue.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/StripedWriteBehind.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehind.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/BatchOperation.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/DeleteAllOperation.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/DeleteOperation.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/KeyBasedOperation.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/SingleOperation.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/WriteAllOperation.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/WriteOperation.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/resilience/AbstractResilienceStrategy.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategy.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategy.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngine.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProvider.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/sizeof/NoopSizeOfEngine.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/sizeof/listeners/EhcacheVisitorListener.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/sizeof/listeners/exceptions/VisitorListenerException.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProvider.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProvider.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProvider.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProvider.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProvider.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/BinaryValueHolder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/disk/DiskWriteThreadPool.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCache.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/heap/Backend.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/heap/KeyCopyBackend.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/heap/SimpleBackend.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/heap/holders/BaseOnHeapKey.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapKey.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/heap/holders/LookupOnlyOnHeapKey.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/heap/holders/OnHeapKey.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/heap/holders/OnHeapValueHolder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProviderFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterValueHolder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalWriteBehindLoaderWriterStore.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/EhcacheConcurrentOffHeapClockCache.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/EhcacheOffHeapBackingMap.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/HeuristicConfiguration.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/MemorySizeParser.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapMapStatistics.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreUtils.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/SwitchableEvictionAdvisor.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/offheap/portability/SerializerPortability.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/util/Pacer.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/util/ServiceUtil.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/internal/util/ThreadFactoryUtil.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/persistence/DefaultDiskResourceService.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/persistence/DefaultLocalPersistenceService.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/persistence/FileBasedStateRepository.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/persistence/FileUtils.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/persistence/package-info.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/serialization/ByteArraySerializer.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/serialization/CharSerializer.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/serialization/CompactJavaSerializer.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/serialization/DoubleSerializer.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/serialization/FloatSerializer.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/serialization/IntegerSerializer.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/serialization/LongSerializer.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/serialization/StringSerializer.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/serialization/TransientStateHolder.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/serialization/TransientStateRepository.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/serialization/package-info.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/store/BaseStore.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/store/DefaultStoreEventDispatcher.java (100%) rename {impl => ehcache-impl}/src/main/java/org/ehcache/impl/store/HashUtils.java (100%) rename {impl => ehcache-impl}/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory (100%) rename {impl => ehcache-impl}/src/slow-test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapITest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/config/builders/CacheManagerBuilderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/config/builders/ExpiryPolicyBuilderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/config/builders/ResourcePoolsBuilderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/config/builders/TieringTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/config/builders/UserManagedCacheBuilderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/config/builders/WriteBehindConfigurationBuilderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/core/events/CacheManagerListenerInteractionsTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/docs/ConfigurationDerivation.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/docs/Ehcache3.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/docs/GettingStarted.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/docs/ThreadPools.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/docs/Tiering.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/docs/UserManagedCaches.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/docs/plugs/ListenerObject.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/docs/plugs/LongCopier.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/docs/plugs/OddKeysEvictionAdvisor.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/docs/plugs/SampleLoaderWriter.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/docs/plugs/StringCopier.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/BaseCacheConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/ResourcePoolsImplTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/SizedResourcePoolImplTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventListenerConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/event/DefaultEventSourceConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/events/CacheEventDispatcherImplTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/DefaultTimeSourceServiceTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/TimeSourceConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/concurrent/otherPackage/V8FeaturesTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/copy/IdentityCopierTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/copy/SerializingCopierTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImplTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/events/FudgingInvocationScopedEventSinkTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/events/InvocationScopedEventSinkTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/events/TestStoreEventDispatcher.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/executor/PartitionedOrderedExecutorTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/executor/PartitionedScheduledExecutorTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/executor/PartitionedUnorderedExecutorTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/executor/PooledExecutionServiceTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehindTestBase.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/PooledExecutorWriteBehindTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindEvictionTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactoryTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindTestLoaderWriter.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/persistence/CacheManagerDestroyRemovesPersistenceTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/persistence/TestDiskResourceService.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategyTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategyTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderConfigurationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactoryTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/spi/TestServiceProvider.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactoryTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsDisabledTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/basic/DelegatingValueHolder.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/basic/SimpleValueHolder.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByRefTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByValueTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByRefTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByValueTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreEvictionTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OversizeMappingTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapKeyTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractEhcacheOffHeapBackingMapTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolder.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/EhcacheConcurrentOffHeapClockCacheTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/MemorySizeParserTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreUtilsTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolderPortabilityTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/offheap/portability/AssertingOffHeapValueHolderPortability.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/util/ByteBufferInputStreamTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchers.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/util/Matchers.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/util/PacerTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/util/StatisticsTestUtils.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/util/ThreadFactoryUtilTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/internal/util/UnmatchedResourceType.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/persistence/DefaultDiskResourceServiceTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/AddedSuperClassTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/ArrayPackageScopeTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/BasicSerializationTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/ByteArraySerializerTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/CharSerializerTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassLoaderTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassUnloadingTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/DoubleSerializerTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/DuplicateClassLoader.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/EnumTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/FieldTypeChangeTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/FloatSerializerTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/GetFieldTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/IntegerSerializerTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/LongSerializerTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/PutFieldTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/ReadObjectNoDataTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/SerializerTestUtilities.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/StringSerializerTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/serialization/TransientStateRepositoryTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/store/DefaultStoreEventDispatcherTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/impl/store/HashUtilsTest.java (100%) rename {impl => ehcache-impl}/src/test/java/org/ehcache/test/MockitoUtil.java (100%) rename {impl => ehcache-impl}/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java (100%) rename {impl => ehcache-impl}/src/unsafe/java/org/ehcache/impl/internal/concurrent/EvictingConcurrentMap.java (100%) rename {impl => ehcache-impl}/src/unsafe/java/org/ehcache/impl/internal/concurrent/ThreadLocalRandomUtil.java (100%) rename {impl => ehcache-impl}/src/unsafe/java/org/ehcache/impl/internal/concurrent/package-info.java (100%) rename {management => ehcache-management}/build.gradle (68%) rename {management => ehcache-management}/config/checkstyle-suppressions.xml (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/CollectorService.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/ExtendedStatisticsService.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/ManagementRegistryService.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/SharedManagementService.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/cluster/Clustering.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/cluster/ClusteringManagementService.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/cluster/ClusteringManagementServiceConfiguration.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementServiceConfiguration.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/cluster/LoggingExecutor.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/providers/CacheBinding.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/providers/CacheBindingManagementProvider.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/providers/EhcacheStatisticCollectorProvider.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/providers/ExposedCacheBinding.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/providers/actions/EhcacheActionProvider.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/providers/actions/EhcacheActionWrapper.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/providers/settings/EhcacheSettingsProvider.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/providers/settings/ExposedCacheSettings.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/providers/settings/Reflect.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProvider.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/registry/DefaultCollectorService.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryFactory.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/registry/DefaultSharedManagementService.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/registry/LatencyHistogramConfiguration.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/registry/NodeListIterable.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/statistics/DefaultCacheStatistics.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsService.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsServiceFactory.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/statistics/DefaultTierStatistics.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/statistics/DelegatedMappedOperationStatistics.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/statistics/DelegatingOperationObserver.java (100%) rename {management => ehcache-management}/src/main/java/org/ehcache/management/statistics/StatsUtils.java (100%) rename {management => ehcache-management}/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory (100%) rename {management => ehcache-management}/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser (100%) rename {management => ehcache-management}/src/main/resources/ehcache-management-ext.xsd (100%) rename {management => ehcache-management}/src/test/java/org/ehcache/docs/ManagementTest.java (100%) rename {management => ehcache-management}/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java (100%) rename {management => ehcache-management}/src/test/java/org/ehcache/management/providers/actions/EhcacheActionProviderTest.java (100%) rename {management => ehcache-management}/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java (100%) rename {management => ehcache-management}/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java (100%) rename {management => ehcache-management}/src/test/java/org/ehcache/management/providers/statistics/LatencyHistogramConfigurationTest.java (100%) rename {management => ehcache-management}/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java (100%) rename {management => ehcache-management}/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java (100%) rename {management => ehcache-management}/src/test/java/org/ehcache/management/providers/statistics/StatsUtil.java (100%) rename {management => ehcache-management}/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java (100%) rename {management => ehcache-management}/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java (100%) rename {management => ehcache-management}/src/test/java/org/ehcache/management/registry/DefaultSharedManagementServiceTest.java (100%) rename {management => ehcache-management}/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java (100%) rename {management => ehcache-management}/src/test/java/org/ehcache/management/registry/XmlConfigTest.java (100%) create mode 100644 ehcache-management/src/test/resources/ehcache-management-1.xml rename {management => ehcache-management}/src/test/resources/ehcache-management-2.xml (59%) rename {management => ehcache-management}/src/test/resources/ehcache-management-3.xml (62%) rename {management => ehcache-management}/src/test/resources/ehcache-management-4.xml (59%) rename {management => ehcache-management}/src/test/resources/ehcache-management-5.xml (59%) rename {management => ehcache-management}/src/test/resources/ehcache-management.xml (80%) rename {management => ehcache-management}/src/test/resources/settings-capability.json (100%) create mode 100644 ehcache-transactions/build.gradle rename {transactions => ehcache-transactions}/config/checkstyle-suppressions.xml (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/EhcacheXAException.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/XACacheException.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/configuration/XAStoreConfiguration.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/EhcacheXAResource.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/SerializableXid.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/SoftLock.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/SoftLockValueCombinedCopier.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/SoftLockValueCombinedSerializer.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/StatefulSoftLockValueCombinedSerializer.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/StoreEventSourceWrapper.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/TransactionId.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/TypeUtil.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/XATransactionContext.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/XATransactionContextFactory.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/commands/Command.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/commands/StoreEvictCommand.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/commands/StorePutCommand.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/commands/StoreRemoveCommand.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProvider.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/journal/Journal.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/journal/JournalProvider.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/journal/PersistentJournal.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/journal/TransientJournal.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/txmgr/NullXAResourceRegistry.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/txmgr/TransactionManagerWrapper.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/txmgr/XAResourceRegistry.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixTransactionManagerLookup.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixXAResourceRegistry.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/txmgr/btm/Ehcache3XAResourceHolder.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/txmgr/btm/Ehcache3XAResourceProducer.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfiguration.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/txmgr/provider/TransactionManagerLookup.java (100%) rename {transactions => ehcache-transactions}/src/main/java/org/ehcache/transactions/xa/txmgr/provider/TransactionManagerProvider.java (100%) rename {transactions => ehcache-transactions}/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory (100%) rename {transactions => ehcache-transactions}/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser (100%) rename {transactions => ehcache-transactions}/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser (100%) rename {transactions => ehcache-transactions}/src/main/resources/ehcache-tx-ext.xsd (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java (79%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/NonXACacheTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/XmlConfigTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/configuration/XAStoreConfigurationTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/integration/StatefulSerializerTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/internal/EhcacheXAResourceTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/internal/UnSupportedResourceTypeTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/internal/XAStoreProviderTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/internal/XAValueHolderTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/internal/journal/AbstractJournalTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/internal/journal/TransientJournalTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfigurationTest.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java (100%) rename {transactions => ehcache-transactions}/src/test/java/org/ehcache/transactions/xa/utils/TestXid.java (100%) rename {transactions => ehcache-transactions}/src/test/resources/configs/simple-xa.xml (77%) rename {transactions => ehcache-transactions}/src/test/resources/configs/template-xa.xml (79%) rename {transactions => ehcache-transactions}/src/test/resources/configs/transactional-cache.xml (78%) rename {transactions => ehcache-transactions}/src/test/resources/docs/configs/xa-getting-started.xml (78%) rename {xml => ehcache-xml}/README.adoc (100%) create mode 100644 ehcache-xml/build.gradle rename {xml => ehcache-xml}/config/checkstyle-suppressions.xml (80%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/BaseConfigParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/CacheManagerServiceConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/CacheResourceConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/CacheServiceConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/ConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/CoreServiceConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/CoreServiceCreationConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/DomUtil.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/JaxbHelper.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/JaxbParsers.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/ServiceConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/ServiceCreationConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/XmlConfiguration.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/XmlModel.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/exceptions/XmlConfigurationException.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/model/CacheDefinition.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/model/CacheSpec.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/model/CacheTemplate.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/model/Expiry.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/model/ListenersConfig.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/model/SizeOfEngineLimits.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/provider/CacheEventDispatcherFactoryConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/provider/CacheManagerPersistenceConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/provider/DefaultSerializationProviderConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/provider/DefaultSizeOfEngineProviderConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/provider/OffHeapDiskStoreProviderConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/provider/PooledExecutionServiceConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/provider/SimpleCoreServiceCreationConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/provider/ThreadPoolServiceCreationConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/provider/WriteBehindProviderConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/service/DefaultCacheEventDispatcherConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/service/DefaultCopierConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/service/DefaultSerializerConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/service/DefaultSizeOfEngineConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/service/OffHeapDiskStoreConfigurationParser.java (100%) rename {xml => ehcache-xml}/src/main/java/org/ehcache/xml/service/SimpleCoreServiceConfigurationParser.java (100%) rename {xml/src/main/resources => ehcache-xml/src/main/schema}/ehcache-core.xsd (100%) rename {xml/src/main/resources => ehcache-xml/src/main/schema}/ehcache-multi.xsd (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/DeprecatedExpiry.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/MyExpiry.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/copier/AnotherDescriptionCopier.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/copier/AnotherPersonCopier.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/copier/Description.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/copier/DescriptionCopier.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/copier/Employee.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/copier/Person.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/copier/PersonCopier.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/integration/TestCacheEventListener.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/integration/TestCacheLoaderWriter.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/integration/TestEvictionAdvisor.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/integration/TestResilienceStrategy.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/integration/TestSecondCacheEventListener.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/integration/ThreadRememberingLoaderWriter.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/serializer/TestSerializer.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/serializer/TestSerializer2.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/serializer/TestSerializer3.java (100%) rename {xml => ehcache-xml}/src/test/java/com/pany/ehcache/serializer/TestSerializer4.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/docs/GettingStarted.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/docs/MultiGettingStarted.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/BarConfiguration.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/BarParser.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/BazParser.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/BazResource.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/CoreCacheConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/FancyParser.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/FooConfiguration.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/FooParser.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/FromTemplateCacheConfigurationBuilderDefaultTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/JaxbParsersTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/NiResilience.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/PropertySubstitutionTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/ShrubberyResilience.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/XmlConfigurationTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/provider/CacheEventDispatcherFactoryConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/provider/CacheManagerPersistenceConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/provider/DefaultSerializationProviderConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/provider/DefaultSizeOfEngineProviderConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/provider/OffHeapDiskStoreProviderConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/provider/PooledExecutionServiceConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/provider/WriteBehindProviderConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/service/DefaultCacheEventDispatcherConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/service/DefaultCopierConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/service/DefaultSerializerConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/service/DefaultSizeOfEngineConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/java/org/ehcache/xml/service/OffHeapDiskStoreConfigurationParserTest.java (100%) rename {xml => ehcache-xml}/src/test/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser (100%) rename {xml => ehcache-xml}/src/test/resources/META-INF/services/org.ehcache.xml.CacheResourceConfigurationParser (100%) rename {xml => ehcache-xml}/src/test/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser (100%) rename {xml => ehcache-xml}/src/test/resources/configs/all-extensions.xml (80%) rename {xml => ehcache-xml}/src/test/resources/configs/bar.xsd (100%) rename {xml => ehcache-xml}/src/test/resources/configs/baz.xsd (100%) rename {xml => ehcache-xml}/src/test/resources/configs/cache-copiers.xml (93%) rename {xml => ehcache-xml}/src/test/resources/configs/cache-integration.xml (87%) rename {xml => ehcache-xml}/src/test/resources/configs/custom-resource.xml (78%) rename {xml => ehcache-xml}/src/test/resources/configs/default-serializer.xml (95%) rename {xml => ehcache-xml}/src/test/resources/configs/defaultTypes-cache.xml (81%) rename {xml => ehcache-xml}/src/test/resources/configs/disk-persistent-cache.xml (84%) rename {xml => ehcache-xml}/src/test/resources/configs/docs/expiry.xml (83%) rename {xml => ehcache-xml}/src/test/resources/configs/docs/getting-started.xml (86%) rename {xml => ehcache-xml}/src/test/resources/configs/docs/multi/multiple-managers.xml (73%) rename {xml => ehcache-xml}/src/test/resources/configs/docs/multi/multiple-variants.xml (81%) rename {xml => ehcache-xml}/src/test/resources/configs/docs/template-sample.xml (81%) rename {xml => ehcache-xml}/src/test/resources/configs/docs/thread-pools.xml (90%) rename {xml => ehcache-xml}/src/test/resources/configs/ehcache-cacheEventListener.xml (92%) rename {xml => ehcache-xml}/src/test/resources/configs/ehcache-complete.xml (95%) rename {xml => ehcache-xml}/src/test/resources/configs/ehcache-multipleCacheEventListener.xml (90%) rename {xml => ehcache-xml}/src/test/resources/configs/ehcache-system-props.xml (92%) rename {xml => ehcache-xml}/src/test/resources/configs/expiry-caches.xml (91%) rename {xml => ehcache-xml}/src/test/resources/configs/fancy.xsd (100%) rename {xml => ehcache-xml}/src/test/resources/configs/foo.xsd (100%) rename {xml => ehcache-xml}/src/test/resources/configs/invalid-core.xml (84%) rename {xml => ehcache-xml}/src/test/resources/configs/invalid-service.xml (75%) create mode 100644 ehcache-xml/src/test/resources/configs/invalid-two-caches.xml create mode 100644 ehcache-xml/src/test/resources/configs/multi/empty.xml rename {xml => ehcache-xml}/src/test/resources/configs/multi/extended.xml (92%) rename {xml => ehcache-xml}/src/test/resources/configs/multi/multiple-configs.xml (90%) rename {xml => ehcache-xml}/src/test/resources/configs/multi/multiple-variants.xml (95%) rename {xml => ehcache-xml}/src/test/resources/configs/nonExistentAdvisor-cache.xml (79%) rename {xml => ehcache-xml}/src/test/resources/configs/nonExistentAdvisor-template.xml (80%) rename {xml => ehcache-xml}/src/test/resources/configs/one-cache.xml (78%) rename {xml => ehcache-xml}/src/test/resources/configs/one-service.xml (75%) create mode 100644 ehcache-xml/src/test/resources/configs/persistence-config.xml rename {xml => ehcache-xml}/src/test/resources/configs/pretty-typed-caches.xml (87%) rename {xml => ehcache-xml}/src/test/resources/configs/resilience-config.xml (86%) rename {xml => ehcache-xml}/src/test/resources/configs/resources-caches.xml (91%) rename {xml => ehcache-xml}/src/test/resources/configs/resources-templates.xml (92%) rename {xml => ehcache-xml}/src/test/resources/configs/sizeof-engine-cm-defaults-one.xml (84%) rename {xml => ehcache-xml}/src/test/resources/configs/sizeof-engine-cm-defaults-two.xml (84%) rename {xml => ehcache-xml}/src/test/resources/configs/sizeof-engine.xml (92%) rename {xml => ehcache-xml}/src/test/resources/configs/template-cache.xml (81%) rename {xml => ehcache-xml}/src/test/resources/configs/template-defaults.xml (69%) rename {xml => ehcache-xml}/src/test/resources/configs/thread-pools.xml (87%) rename {xml => ehcache-xml}/src/test/resources/configs/unknown-resource.xml (84%) rename {xml => ehcache-xml}/src/test/resources/configs/unknown-service-creation.xml (81%) rename {xml => ehcache-xml}/src/test/resources/configs/unknown-service.xml (81%) rename {xml => ehcache-xml}/src/test/resources/configs/writebehind-cache.xml (90%) rename {xml => ehcache-xml}/src/testFixtures/java/org/ehcache/xml/XmlConfigurationMatchers.java (100%) create mode 100644 ehcache/build.gradle rename {dist => ehcache}/templates/github-release-issue.md (100%) rename {dist => ehcache}/templates/github-release.md (100%) delete mode 100755 impl/.gitignore delete mode 100644 impl/gradle.properties delete mode 100644 integration-test/.gitignore delete mode 100644 integration-test/gradle.properties delete mode 100755 management/.gitignore delete mode 100644 management/gradle.properties delete mode 100644 management/src/test/resources/ehcache-management-1.xml delete mode 100755 spi-tester/.gitignore create mode 100644 spi-tester/build.gradle delete mode 100644 spi-tester/gradle.properties delete mode 100644 transactions/build.gradle delete mode 100644 transactions/gradle.properties delete mode 100755 xml/.gitignore delete mode 100644 xml/build.gradle delete mode 100644 xml/gradle.properties delete mode 100644 xml/src/test/java/org/ehcache/xml/ConfigurationParserTestHelper.java delete mode 100644 xml/src/test/resources/configs/invalid-two-caches.xml delete mode 100644 xml/src/test/resources/configs/multi/empty.xml delete mode 100644 xml/src/test/resources/configs/persistence-config.xml diff --git a/.gitignore b/.gitignore index 1830fcc7ef..fac95318bd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,22 +1,4 @@ -*/target/ - -build/ -*/src/generated/ +# Gradle .gradle/ - -.project -.classpath -.settings/org.eclipse.m2e.core.prefs -*/.classpath -*.prefs - -*.iml -.idea -out/ - -.nb-gradle -.nb-gradle-properties - -/classes - -**/*.*~ +**/build/ +!**/src/**/build/ diff --git a/107/.gitignore b/107/.gitignore deleted file mode 100755 index ae3c172604..0000000000 --- a/107/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/107/gradle.properties b/107/gradle.properties deleted file mode 100644 index afb38dd5de..0000000000 --- a/107/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -subPomName = Ehcache 3 JSR-107 module -subPomDesc = The JSR-107 compatibility module of Ehcache 3 diff --git a/api/.gitignore b/api/.gitignore deleted file mode 100755 index ae3c172604..0000000000 --- a/api/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/api/gradle.properties b/api/gradle.properties deleted file mode 100644 index 3736cff405..0000000000 --- a/api/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache 3 API module -subPomDesc = The API module of Ehcache 3 diff --git a/build-logic/build.gradle b/build-logic/build.gradle new file mode 100644 index 0000000000..78eed08c1a --- /dev/null +++ b/build-logic/build.gradle @@ -0,0 +1,67 @@ +plugins { + id 'java-gradle-plugin' +} + +repositories { + gradlePluginPortal() + mavenCentral() +} + +gradlePlugin { + plugins { + internalModule { + id = 'org.ehcache.build.internal-module' + implementationClass = 'org.ehcache.build.InternalEhcacheModule' + } + publicModule { + id = 'org.ehcache.build.public-module' + implementationClass = 'org.ehcache.build.PublicEhcacheModule' + } + clusteredModule { + id = 'org.ehcache.build.clustered-module' + implementationClass = 'org.ehcache.build.ClusteredEhcacheModule' + } + serverModule { + id = 'org.ehcache.build.clustered-server-module' + implementationClass = 'org.ehcache.build.ClusteredServerModule' + } + distribution { + id = 'org.ehcache.build.package' + implementationClass = 'org.ehcache.build.EhcachePackage' + } + + variant { + id = 'org.ehcache.build.plugins.variant' + implementationClass = 'org.ehcache.build.plugins.VariantPlugin' + } + + base { + id = 'org.ehcache.build.conventions.base' + implementationClass = 'org.ehcache.build.conventions.BaseConvention' + } + java { + id = 'org.ehcache.build.conventions.java' + implementationClass = 'org.ehcache.build.conventions.JavaConvention' + } + javaLibrary { + id = 'org.ehcache.build.conventions.java-library' + implementationClass = 'org.ehcache.build.conventions.JavaLibraryConvention' + } + war { + id = 'org.ehcache.build.conventions.war' + implementationClass = 'org.ehcache.build.conventions.WarConvention' + } + } +} + +dependencies { + api gradleApi() + api 'biz.aQute.bnd:biz.aQute.bnd.gradle:6.0.0' + api 'gradle.plugin.com.github.jengelman.gradle.plugins:shadow:7.0.0' + api 'org.unbroken-dome.gradle-plugins:gradle-xjc-plugin:2.0.0' + api 'com.github.spotbugs.snom:spotbugs-gradle-plugin:4.7.9' + implementation 'biz.aQute.bnd:biz.aQute.bndlib:6.0.0' + implementation 'org.osgi:org.osgi.service.component.annotations:1.5.0' + implementation 'org.apache.felix:org.apache.felix.scr.generator:1.18.4' + implementation 'org.apache.felix:org.apache.felix.scr.ds-annotations:1.2.10' +} diff --git a/build-logic/src/main/java/org/ehcache/build/ClusteredEhcacheModule.java b/build-logic/src/main/java/org/ehcache/build/ClusteredEhcacheModule.java new file mode 100644 index 0000000000..5ca1afbab9 --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/ClusteredEhcacheModule.java @@ -0,0 +1,12 @@ +package org.ehcache.build; + +import org.gradle.api.Project; + +public class ClusteredEhcacheModule extends EhcacheModule { + + @Override + public void apply(Project project) { + project.setGroup("org.ehcache.modules.clustered"); + super.apply(project); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/ClusteredServerModule.java b/build-logic/src/main/java/org/ehcache/build/ClusteredServerModule.java new file mode 100644 index 0000000000..64be60977d --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/ClusteredServerModule.java @@ -0,0 +1,17 @@ +package org.ehcache.build; + +import org.ehcache.build.conventions.DeployConvention; +import org.ehcache.build.plugins.VoltronPlugin; +import org.gradle.api.Plugin; +import org.gradle.api.Project; + +public class ClusteredServerModule implements Plugin { + + @Override + public void apply(Project project) { + project.setGroup("org.ehcache.modules.clustered"); + + project.getPlugins().apply(DeployConvention.class); + project.getPlugins().apply(VoltronPlugin.class); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/EhcacheModule.java b/build-logic/src/main/java/org/ehcache/build/EhcacheModule.java new file mode 100644 index 0000000000..dd3aa59140 --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/EhcacheModule.java @@ -0,0 +1,17 @@ +package org.ehcache.build; + +import org.ehcache.build.conventions.BndConvention; +import org.ehcache.build.conventions.JavaLibraryConvention; +import org.ehcache.build.conventions.DeployConvention; +import org.gradle.api.Plugin; +import org.gradle.api.Project; + +public abstract class EhcacheModule implements Plugin { + + @Override + public void apply(Project project) { + project.getPlugins().apply(JavaLibraryConvention.class); + project.getPlugins().apply(DeployConvention.class); + project.getPlugins().apply(BndConvention.class); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/EhcachePackage.java b/build-logic/src/main/java/org/ehcache/build/EhcachePackage.java new file mode 100644 index 0000000000..112fd3d0d2 --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/EhcachePackage.java @@ -0,0 +1,16 @@ +package org.ehcache.build; + +import org.ehcache.build.conventions.DeployConvention; +import org.ehcache.build.plugins.PackagePlugin; +import org.gradle.api.Plugin; +import org.gradle.api.Project; + +public class EhcachePackage implements Plugin { + + @Override + public void apply(Project project) { + project.setGroup("org.ehcache"); + project.getPlugins().apply(PackagePlugin.class); + project.getPlugins().apply(DeployConvention.class); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/InternalEhcacheModule.java b/build-logic/src/main/java/org/ehcache/build/InternalEhcacheModule.java new file mode 100644 index 0000000000..1ba6b69b8a --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/InternalEhcacheModule.java @@ -0,0 +1,13 @@ +package org.ehcache.build; + +import org.gradle.api.Project; + +public class InternalEhcacheModule extends EhcacheModule { + + @Override + public void apply(Project project) { + project.setGroup("org.ehcache.modules"); + super.apply(project); + } +} + diff --git a/build-logic/src/main/java/org/ehcache/build/PublicEhcacheModule.java b/build-logic/src/main/java/org/ehcache/build/PublicEhcacheModule.java new file mode 100644 index 0000000000..477c54b3e7 --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/PublicEhcacheModule.java @@ -0,0 +1,11 @@ +package org.ehcache.build; + +import org.gradle.api.Project; + +public class PublicEhcacheModule extends EhcacheModule { + @Override + public void apply(Project project) { + project.setGroup("org.ehcache"); + super.apply(project); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/BaseConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/BaseConvention.java new file mode 100644 index 0000000000..edf95548a1 --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/conventions/BaseConvention.java @@ -0,0 +1,23 @@ +package org.ehcache.build.conventions; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.artifacts.ResolutionStrategy; +import org.gradle.api.plugins.BasePlugin; + +import java.net.URI; + +public class BaseConvention implements Plugin { + + @Override + public void apply(Project project) { + project.getPlugins().apply(BasePlugin.class); + + project.getRepositories().mavenCentral(); + project.getRepositories().maven(repo -> repo.setUrl(URI.create("https://repo.terracotta.org/maven2"))); + + project.getConfigurations().configureEach( + config -> config.resolutionStrategy(ResolutionStrategy::failOnVersionConflict) + ); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/BndConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/BndConvention.java new file mode 100644 index 0000000000..bbb915168e --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/conventions/BndConvention.java @@ -0,0 +1,89 @@ +package org.ehcache.build.conventions; + +import aQute.bnd.gradle.BndBuilderPlugin; +import aQute.bnd.gradle.BundleTaskExtension; +import aQute.bnd.osgi.Constants; +import org.ehcache.build.plugins.osgids.OsgiDsPlugin; +import org.gradle.api.Action; +import org.gradle.api.GradleException; +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Dependency; +import org.gradle.api.artifacts.ExternalDependency; +import org.gradle.api.artifacts.ProjectDependency; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.provider.MapProperty; +import org.gradle.api.publish.PublishingExtension; +import org.gradle.api.publish.maven.MavenPublication; +import org.gradle.api.publish.plugins.PublishingPlugin; +import org.gradle.api.tasks.bundling.Jar; + +import static java.lang.System.lineSeparator; +import static java.util.stream.Collectors.joining; + +public class BndConvention implements Plugin { + + @Override + public void apply(Project project) { + project.getPlugins().apply(BndBuilderPlugin.class); + project.getPlugins().apply(OsgiDsPlugin.class); + project.getPlugins().apply(DeployConvention.class); + + project.getTasks().named(JavaPlugin.JAR_TASK_NAME, Jar.class, jar -> { + jar.getExtensions().configure(BundleTaskExtension.class, bundle -> configureBundleDefaults(project, bundle)); + }); + + project.getConfigurations().named("baseline", config -> { + config.getResolutionStrategy().getComponentSelection().all(selection -> { + if (!selection.getCandidate().getVersion().matches("^\\d+(?:\\.\\d+)*$")) { + selection.reject("Only full releases can be used as OSGi baselines"); + } + }); + }); + + String dependencyNotation = project.getGroup() + ":" + project.getName() + ":(," + project.getVersion() + "["; + Dependency baseline = project.getDependencies().add("baseline", dependencyNotation); + if (baseline instanceof ProjectDependency) { + throw new GradleException("Baseline should not be a project dependency"); + } else if (baseline instanceof ExternalDependency) { + ((ExternalDependency) baseline).setForce(true); + ((ExternalDependency) baseline).setTransitive(false); + } else { + throw new IllegalArgumentException("Unexpected dependency type: " + baseline); + } + } + + public static void configureBundleDefaults(Project project, BundleTaskExtension bundle) { + MapProperty defaultInstructions = project.getObjects().mapProperty(String.class, String.class); + bundleDefaults(project).execute(defaultInstructions); + bundle.bnd(defaultInstructions.map(kv -> kv.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(joining(lineSeparator())))); + } + + public static Action> bundleDefaults(Project project) { + return properties -> { + project.getPlugins().withType(PublishingPlugin.class).configureEach(publishingPlugin -> { + project.getExtensions().getByType(PublishingExtension.class).getPublications().withType(MavenPublication.class).stream().findAny().ifPresent(publication -> { + properties.put(Constants.BUNDLE_NAME, publication.getPom().getName()); + properties.put(Constants.BUNDLE_DESCRIPTION, publication.getPom().getDescription()); + }); + }); + properties.put(Constants.BUNDLE_SYMBOLICNAME, project.getGroup() + "." + project.getName()); + properties.put(Constants.BUNDLE_DOCURL, "http://ehcache.org"); + properties.put(Constants.BUNDLE_LICENSE, "LICENSE"); + properties.put(Constants.BUNDLE_VENDOR, "Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc."); + properties.put(Constants.BUNDLE_VERSION, osgiFixedVersion(project.getVersion().toString())); + properties.put(Constants.SERVICE_COMPONENT, "OSGI-INF/*.xml"); + }; + } + + public static String osgiFixedVersion(String version) { + /* + * The bnd gradle plugin does not handle our 2-digit snapshot versioning scheme very well. It maps `x.y-SNAPSHOT` + * to `x.y.0.SNAPSHOT`. This is bad since `x.y.0.SNAPSHOT` is considered to be less than *all* `x.y.z`. This means + * the baseline version range expression `(,x.y.0.SNAPSHOT[` will always pick the last release from the previous + * minor line. To fix this we manually map to a 3-digit snapshot version where the 3rd digit is a number chosen + * to be higher than we would ever release ('All the worlds a VAX'). + */ + return version.replaceAll("^(\\d+.\\d+)-SNAPSHOT$", "$1.999-SNAPSHOT"); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/CheckstyleConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/CheckstyleConvention.java new file mode 100644 index 0000000000..0973fc1237 --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/conventions/CheckstyleConvention.java @@ -0,0 +1,22 @@ +package org.ehcache.build.conventions; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.quality.CheckstyleExtension; +import org.gradle.api.plugins.quality.CheckstylePlugin; + +import java.util.Map; + +public class CheckstyleConvention implements Plugin { + @Override + public void apply(Project project) { + project.getPlugins().apply(CheckstylePlugin.class); + + project.getExtensions().configure(CheckstyleExtension.class, checkstyle -> { + checkstyle.setConfigFile(project.getRootProject().file("config/checkstyle.xml")); + Map properties = checkstyle.getConfigProperties(); + properties.put("projectDir", project.getProjectDir()); + properties.put("rootDir", project.getRootDir()); + }); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/DeployConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/DeployConvention.java new file mode 100644 index 0000000000..bd7376ef8b --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/conventions/DeployConvention.java @@ -0,0 +1,167 @@ +package org.ehcache.build.conventions; + +import org.gradle.api.Action; +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.artifacts.ProjectDependency; +import org.gradle.api.internal.artifacts.ivyservice.projectmodule.ProjectComponentPublication; +import org.gradle.api.internal.component.SoftwareComponentInternal; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.plugins.JavaPluginExtension; +import org.gradle.api.publish.PublishingExtension; +import org.gradle.api.publish.maven.MavenPublication; +import org.gradle.api.publish.maven.internal.publication.MavenPomInternal; +import org.gradle.api.publish.maven.internal.publisher.MavenProjectIdentity; +import org.gradle.api.publish.maven.plugins.MavenPublishPlugin; +import org.gradle.api.publish.maven.tasks.AbstractPublishToMaven; +import org.gradle.api.publish.maven.tasks.GenerateMavenPom; +import org.gradle.api.publish.maven.tasks.PublishToMavenRepository; +import org.gradle.api.tasks.TaskProvider; +import org.gradle.api.tasks.WriteProperties; +import org.gradle.jvm.tasks.Jar; +import org.gradle.plugins.signing.SigningExtension; +import org.gradle.plugins.signing.SigningPlugin; + +import java.io.File; +import java.util.Collection; +import java.util.concurrent.Callable; +import java.util.function.Predicate; + +import static java.util.stream.Collectors.toList; +import static org.gradle.api.publish.plugins.PublishingPlugin.PUBLISH_TASK_GROUP; + +/** + * Deploy plugin for published artifacts. This is an abstraction over the {@code maven-publish} plugin. + * + * Defaults: + *
    + *
  • POM: population of general content: organization, issue-management, scm, etc.
  • + *
  • POM copied to {@code META-INF/maven/groupId/artifactId/pom.xml}
  • + *
  • POM properties file copied to {@code META-INF/maven/groupId/artifactId/pom.properties}
  • + *
  • Javadoc and Source JAR Publishing
  • + *
  • {@code install} as alias of {@code publishToMavenLocal}
  • + *
+ */ +public class DeployConvention implements Plugin { + + private static final Predicate IS_RELEASE = p -> !p.getVersion().toString().endsWith("-SNAPSHOT"); + + @Override + public void apply(Project project) { + project.getPlugins().apply(SigningPlugin.class); + project.getPlugins().apply(MavenPublishPlugin.class); + + project.getExtensions().configure(PublishingExtension.class, publishing -> { + publishing.getPublications().withType(MavenPublication.class).configureEach(mavenPublication -> mavenPublication.pom(pom -> { + pom.getUrl().set("http://ehcache.org"); + pom.organization(org -> { + org.getName().set("Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc."); + org.getUrl().set("http://terracotta.org"); + }); + pom.issueManagement(issue -> { + issue.getSystem().set("Github"); + issue.getUrl().set("https://github.com/ehcache/ehcache3/issues"); + }); + pom.scm(scm -> { + scm.getUrl().set("https://github.com/ehcache/ehcache3"); + scm.getConnection().set("scm:git:https://github.com/ehcache/ehcache3.git"); + scm.getDeveloperConnection().set("scm:git:git@github.com:ehcache/ehcache3.git"); + }); + pom.licenses(licenses -> licenses.license(license -> { + license.getName().set("The Apache Software License, Version 2.0"); + license.getUrl().set("http://www.apache.org/licenses/LICENSE-2.0.txt"); + license.getDistribution().set("repo"); + })); + pom.developers(devs -> devs.developer(dev -> { + dev.getName().set("Terracotta Engineers"); + dev.getEmail().set("tc-oss@softwareag.com"); + dev.getOrganization().set("Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc."); + dev.getOrganizationUrl().set("http://ehcache.org"); + })); + })); + publishing.repositories(repositories -> repositories.maven(maven -> { + if (IS_RELEASE.test(project)) { + maven.setUrl(project.property("deployUrl")); + maven.credentials(creds -> { + creds.setUsername(project.property("deployUser").toString()); + creds.setPassword(project.property("deployPwd").toString()); + }); + } else { + maven.setName("sonatype-nexus-snapshot"); + maven.setUrl("https://oss.sonatype.org/content/repositories/snapshots"); + maven.credentials(creds -> { + creds.setUsername(project.property("sonatypeUser").toString()); + creds.setPassword(project.property("sonatypePwd").toString()); + }); + } + })); + }); + + project.getExtensions().configure(SigningExtension.class, signing -> { + signing.setRequired((Callable) () -> IS_RELEASE.test(project) && project.getGradle().getTaskGraph().getAllTasks().stream().anyMatch(t -> t instanceof PublishToMavenRepository)); + signing.sign(project.getExtensions().getByType(PublishingExtension.class).getPublications()); + }); + + /* + * Do **not** convert the anonymous Action here to a lambda expression - it will break Gradle's up-to-date tracking + * and cause tasks to be needlessly rerun. + */ + //noinspection Convert2Lambda + project.getTasks().withType(AbstractPublishToMaven.class).configureEach(publishTask -> publishTask.doFirst(new Action() { + @Override + public void execute(Task task) { + MavenPublication publication = publishTask.getPublication(); + if (publication instanceof ProjectComponentPublication) { + SoftwareComponentInternal component = ((ProjectComponentPublication) publication).getComponent(); + if (component != null) { //The shadow plugin doesn"t associate a component with the publication + Collection unpublishedDeps = component.getUsages().stream().flatMap(usage -> + usage.getDependencies().stream().filter(ProjectDependency.class::isInstance).map(ProjectDependency.class::cast).filter(moduleDependency -> + !moduleDependency.getDependencyProject().getPlugins().hasPlugin(DeployConvention.class))).collect(toList()); + if (!unpublishedDeps.isEmpty()) { + project.getLogger().warn("{} has applied the deploy plugin but has unpublished project dependencies: {}", project, unpublishedDeps); + } + } + } + } + })); + + project.getTasks().register("install", task -> + task.dependsOn(project.getTasks().named(MavenPublishPlugin.PUBLISH_LOCAL_LIFECYCLE_TASK_NAME)) + ); + + project.getPlugins().withType(JavaPlugin.class).configureEach(plugin -> { + project.getExtensions().configure(JavaPluginExtension.class, java -> { + java.withJavadocJar(); + java.withSourcesJar(); + }); + + project.afterEvaluate(p -> { + p.getExtensions().configure(PublishingExtension.class, publishing -> { + if (publishing.getPublications().isEmpty()) { + publishing.publications(publications -> publications.register("mavenJava", MavenPublication.class, mavenJava -> mavenJava.from(p.getComponents().getByName("java")))); + } + }); + + p.getTasks().withType(GenerateMavenPom.class).all(pomTask -> { + MavenProjectIdentity identity = ((MavenPomInternal) pomTask.getPom()).getProjectIdentity(); + TaskProvider pomPropertiesTask = project.getTasks().register(pomTask.getName().replace("PomFile", "PomProperties"), WriteProperties.class, task -> { + task.dependsOn(pomTask); + task.setGroup(PUBLISH_TASK_GROUP); + task.setOutputFile(new File(pomTask.getDestination().getParentFile(), "pom.properties")); + task.property("groupId", identity.getGroupId()); + task.property("artifactId", identity.getArtifactId()); + task.property("version", identity.getVersion()); + }); + + project.getTasks().withType(Jar.class).configureEach(jar -> { + jar.into("META-INF/maven/" + identity.getGroupId().get() + "/" + identity.getArtifactId().get(), spec -> { + spec.from(pomTask, pom -> pom.rename(".*", "pom.xml")); + spec.from(pomPropertiesTask); + }); + }); + }); + }); + }); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/JacocoConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/JacocoConvention.java new file mode 100644 index 0000000000..66f96ef814 --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/conventions/JacocoConvention.java @@ -0,0 +1,28 @@ +package org.ehcache.build.conventions; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.tasks.testing.Test; +import org.gradle.testing.jacoco.plugins.JacocoPlugin; +import org.gradle.testing.jacoco.plugins.JacocoTaskExtension; +import org.gradle.testing.jacoco.tasks.JacocoReport; + +public class JacocoConvention implements Plugin { + + @Override + public void apply(Project project) { + project.getPlugins().apply(JacocoPlugin.class); + + project.getTasks().withType(JacocoReport.class).configureEach(jacocoReport -> { + jacocoReport.getReports().configureEach(report -> { + report.getRequired().set(false); + }); + }); + + project.getTasks().withType(Test.class).configureEach(test -> { + test.getExtensions().configure(JacocoTaskExtension.class, jacoco -> { + jacoco.getExcludes().add("org.terracotta.tripwire.*"); + }); + }); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/JavaBaseConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/JavaBaseConvention.java new file mode 100644 index 0000000000..83ce040a2c --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/conventions/JavaBaseConvention.java @@ -0,0 +1,131 @@ +package org.ehcache.build.conventions; + +import org.gradle.api.JavaVersion; +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.java.archives.Attributes; +import org.gradle.api.plugins.JavaBasePlugin; +import org.gradle.api.plugins.JavaPluginExtension; +import org.gradle.api.tasks.bundling.Jar; +import org.gradle.api.tasks.compile.JavaCompile; +import org.gradle.api.tasks.javadoc.Javadoc; +import org.gradle.api.tasks.testing.Test; +import org.gradle.external.javadoc.CoreJavadocOptions; +import org.gradle.internal.jvm.JavaInfo; +import org.gradle.internal.jvm.Jvm; +import org.gradle.process.internal.ExecException; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.OutputStream; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.util.Arrays.asList; + +public class JavaBaseConvention implements Plugin { + @Override + public void apply(Project project) { + project.getPlugins().apply(JavaBasePlugin.class); + project.getPlugins().apply(BaseConvention.class); + + JavaInfo testJava = fetchTestJava(project); + project.getExtensions().getExtraProperties().set("testJava", testJava); + + project.getExtensions().configure(JavaPluginExtension.class, java -> { + java.setSourceCompatibility(JavaVersion.VERSION_1_8); + java.setTargetCompatibility(JavaVersion.VERSION_1_8); + }); + + project.getTasks().withType(Jar.class).configureEach(jar -> { + jar.manifest(manifest -> { + Attributes attributes = manifest.getAttributes(); + attributes.put("Implementation-Title", project.getName()); + attributes.put("Implementation-Vendor-Id", project.getGroup()); + attributes.put("Implementation-Version", project.getVersion()); + attributes.put("Implementation-Revision", getRevision(project)); + attributes.put("Built-By", System.getProperty("user.name")); + attributes.put("Built-JDK", System.getProperty("java.version")); + }); + jar.from(project.getRootProject().file("LICENSE")); + }); + + project.getTasks().withType(Test.class).configureEach(test -> { + test.setExecutable(testJava.getJavaExecutable()); + test.setMaxHeapSize("256m"); + test.setMaxParallelForks(16); + test.systemProperty("java.awt.headless", "true"); + }); + + project.getTasks().withType(JavaCompile.class).configureEach(compile -> { + compile.getOptions().setEncoding("UTF-8"); + compile.getOptions().setCompilerArgs(asList("-Werror", "-Xlint:all")); + }); + + project.getTasks().withType(Javadoc.class).configureEach(javadoc -> { + javadoc.setTitle(project.getName() + " " + project.getVersion() + " API"); + javadoc.exclude("**/internal/**"); + javadoc.getOptions().setEncoding("UTF-8"); + ((CoreJavadocOptions) javadoc.getOptions()).addStringOption("Xdoclint:none", "-quiet"); + }); + } + + private static JavaInfo fetchTestJava(Project project) { + Object testVM = project.findProperty("testVM"); + if (testVM == null) { + return Jvm.current(); + } else { + File jvmHome = project.file(testVM); + if (!jvmHome.exists() && project.hasProperty(testVM.toString())) { + testVM = project.property(testVM.toString()); + jvmHome = project.file(testVM); + } + + return jvmForHome(project, jvmHome); + } + } + + private static final Pattern VERSION_OUTPUT = Pattern.compile("\\w+ version \"(?.+)\""); + private static Jvm jvmForHome(Project project, File home) { + File java = Jvm.forHome(home).getJavaExecutable(); + + OutputStream stdout = new ByteArrayOutputStream(); + OutputStream stderr = new ByteArrayOutputStream(); + project.exec(spec -> { + spec.executable(java); + spec.args("-version"); + spec.setStandardOutput(stdout); + spec.setErrorOutput(stderr); + }); + String versionOutput = stderr.toString(); + Matcher matcher = VERSION_OUTPUT.matcher(versionOutput); + if (matcher.find()) { + return Jvm.discovered(home, null, JavaVersion.toVersion(matcher.group("version"))); + } else { + throw new IllegalArgumentException("Could not parse version of " + java + " from output:\n" + versionOutput); + } + } + + + private static Object getRevision(Project project) { + String envCommit = System.getenv("GIT_COMMIT"); + if(envCommit != null) { + return envCommit; + } else { + try { + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + ByteArrayOutputStream stderr = new ByteArrayOutputStream(); + project.exec(spec -> { + spec.executable("git"); + spec.args("rev-parse", "HEAD"); + spec.setStandardOutput(stdout); + spec.setErrorOutput(stderr); + }).assertNormalExitValue(); + + return stdout.toString().trim(); + } catch (ExecException e) { + return "Unknown"; + } + } + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/JavaConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/JavaConvention.java new file mode 100644 index 0000000000..5e50b677ae --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/conventions/JavaConvention.java @@ -0,0 +1,27 @@ +package org.ehcache.build.conventions; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.artifacts.dsl.DependencyHandler; +import org.gradle.api.plugins.JavaPlugin; + +public class JavaConvention implements Plugin { + @Override + public void apply(Project project) { + project.getPlugins().apply(JavaBaseConvention.class); + project.getPlugins().apply(JavaPlugin.class); + project.getPlugins().apply(CheckstyleConvention.class); + project.getPlugins().apply(JacocoConvention.class); + project.getPlugins().apply(SpotbugsConvention.class); + + DependencyHandler dependencies = project.getDependencies(); + dependencies.add(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME, "org.slf4j:slf4j-api:" + project.property("slf4jVersion")); + dependencies.add(JavaPlugin.TEST_RUNTIME_ONLY_CONFIGURATION_NAME, "org.slf4j:slf4j-simple:" + project.property("slf4jVersion")); + + dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "junit:junit:" + project.property("junitVersion")); + dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.assertj:assertj-core:" + project.property("assertjVersion")); + dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.hamcrest:hamcrest-library:" + project.property("hamcrestVersion")); + dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.mockito:mockito-core:" + project.property("mockitoVersion")); + dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.terracotta:terracotta-utilities-test-tools:" + project.property("terracottaUtilitiesVersion")); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/JavaLibraryConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/JavaLibraryConvention.java new file mode 100644 index 0000000000..77b15e4b37 --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/conventions/JavaLibraryConvention.java @@ -0,0 +1,14 @@ +package org.ehcache.build.conventions; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.JavaLibraryPlugin; + +public class JavaLibraryConvention implements Plugin { + + @Override + public void apply(Project project) { + project.getPlugins().apply(JavaConvention.class); + project.getPlugins().apply(JavaLibraryPlugin.class); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/SpotbugsConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/SpotbugsConvention.java new file mode 100644 index 0000000000..9815385453 --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/conventions/SpotbugsConvention.java @@ -0,0 +1,53 @@ +package org.ehcache.build.conventions; + +import com.github.spotbugs.snom.SpotBugsExtension; +import com.github.spotbugs.snom.SpotBugsPlugin; +import com.github.spotbugs.snom.SpotBugsTask; +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.JavaBasePlugin; +import org.gradle.api.plugins.JavaPluginExtension; + +public class SpotbugsConvention implements Plugin { + + @Override + public void apply(Project project) { + project.getPlugins().apply(SpotBugsPlugin.class); + + SpotBugsExtension spotbugs = project.getExtensions().getByType(SpotBugsExtension.class); + + spotbugs.getIgnoreFailures().set(false); + // Later versions of Spotbugs have stupid heuristics for EI_EXPOSE_REP* + spotbugs.getToolVersion().set("4.2.3"); + + project.getPlugins().withType(JavaBasePlugin.class).configureEach(plugin -> { + + project.getExtensions().configure(JavaPluginExtension.class, java -> { + java.getSourceSets().configureEach(sourceSet -> { + project.getDependencies().add(sourceSet.getCompileOnlyConfigurationName(), + "com.github.spotbugs:spotbugs-annotations:" + spotbugs.getToolVersion().get()); + }); + + project.getTasks().withType(SpotBugsTask.class).configureEach(task -> { + if (task.getName().contains("Test")) { + task.setEnabled(false); + } else { + task.getReports().register("xml", report -> report.setEnabled(true)); + task.getReports().register("html", report -> report.setEnabled(false)); + } + }); + }); + + }); + + + project.getConfigurations().named("spotbugs", config -> { + config.getResolutionStrategy().dependencySubstitution(subs -> { + subs.substitute(subs.module("org.apache.commons:commons-lang3:3.11")) + .using(subs.module("org.apache.commons:commons-lang3:3.12.0")) + .because("Spotbugs has dependency divergences"); + }); + }); + + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/WarConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/WarConvention.java new file mode 100644 index 0000000000..ec469eda6a --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/conventions/WarConvention.java @@ -0,0 +1,13 @@ +package org.ehcache.build.conventions; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.WarPlugin; + +public class WarConvention implements Plugin { + @Override + public void apply(Project project) { + project.getPlugins().apply(WarPlugin.class); + project.getPlugins().apply(JavaConvention.class); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/plugins/PackagePlugin.java b/build-logic/src/main/java/org/ehcache/build/plugins/PackagePlugin.java new file mode 100644 index 0000000000..40070ea348 --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/plugins/PackagePlugin.java @@ -0,0 +1,285 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ehcache.build.plugins; + +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar; +import org.ehcache.build.conventions.BaseConvention; +import org.ehcache.build.conventions.BndConvention; +import org.ehcache.build.conventions.JavaBaseConvention; +import org.ehcache.build.util.OsgiManifestJarExtension; +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.capabilities.Capability; +import org.gradle.api.component.AdhocComponentWithVariants; +import org.gradle.api.component.SoftwareComponentFactory; +import org.gradle.api.file.DuplicatesStrategy; +import org.gradle.api.file.FileCollection; +import org.gradle.api.file.FileTree; +import org.gradle.api.internal.project.ProjectInternal; +import org.gradle.api.plugins.BasePlugin; +import org.gradle.api.plugins.JavaBasePlugin; +import org.gradle.api.plugins.jvm.internal.JvmPluginServices; +import org.gradle.api.provider.Provider; +import org.gradle.api.publish.PublishingExtension; +import org.gradle.api.publish.maven.MavenPublication; +import org.gradle.api.publish.maven.plugins.MavenPublishPlugin; +import org.gradle.api.tasks.Sync; +import org.gradle.api.tasks.TaskProvider; +import org.gradle.api.tasks.bundling.Jar; +import org.gradle.api.tasks.bundling.Zip; +import org.gradle.api.tasks.javadoc.Javadoc; +import org.gradle.internal.jvm.Jvm; +import org.gradle.internal.resolve.ArtifactResolveException; +import org.gradle.internal.service.ServiceRegistry; +import org.gradle.language.base.plugins.LifecycleBasePlugin; + +import java.io.File; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import static java.lang.Integer.parseInt; +import static java.util.Collections.emptyList; +import static org.ehcache.build.plugins.VariantPlugin.COMMON_SOURCE_SET_NAME; +import static org.ehcache.build.util.PluginUtils.bucket; +import static org.ehcache.build.util.PluginUtils.createBucket; +import static org.ehcache.build.util.PluginUtils.capitalize; +import static org.gradle.api.attributes.DocsType.JAVADOC; +import static org.gradle.api.attributes.DocsType.SOURCES; +import static org.gradle.api.attributes.DocsType.USER_MANUAL; +import static org.gradle.api.internal.artifacts.JavaEcosystemSupport.configureDefaultTargetPlatform; +import static org.gradle.api.plugins.JavaPlugin.API_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.COMPILE_ONLY_API_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.JAVADOC_ELEMENTS_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.SOURCES_ELEMENTS_CONFIGURATION_NAME; + +/** + * EhDistribute + */ +public class PackagePlugin implements Plugin { + + private static final String CONTENTS_CONFIGURATION_NAME = "contents"; + + @Override + public void apply(Project project) { + project.getPlugins().apply(BaseConvention.class); + project.getPlugins().apply(JavaBaseConvention.class); + + ServiceRegistry projectServices = ((ProjectInternal) project).getServices(); + JvmPluginServices jvmPluginServices = projectServices.get(JvmPluginServices.class); + SoftwareComponentFactory softwareComponentFactory = projectServices.get(SoftwareComponentFactory.class); + AdhocComponentWithVariants javaComponent = softwareComponentFactory.adhoc("java"); + project.getComponents().add(javaComponent); + + TaskProvider asciidocZip = project.getTasks().register("asciidocZip", Zip.class, zip -> { + zip.getArchiveClassifier().set("docs"); + zip.from(project.getTasks().getByPath(":docs:userDoc")); + }); + Configuration userdocElements = jvmPluginServices.createOutgoingElements("userdocElements", builder -> + builder.published().artifact(asciidocZip).providesAttributes(attributes -> attributes.documentation(USER_MANUAL))); + javaComponent.addVariantsFromConfiguration(userdocElements, variantDetails -> {}); + + createDefaultPackage(project); + + project.getPlugins().withType(VariantPlugin.class).configureEach(plugin -> { + Configuration commonContents = createBucket(project, CONTENTS_CONFIGURATION_NAME, COMMON_SOURCE_SET_NAME); + Configuration commonApi = createBucket(project, API_CONFIGURATION_NAME, COMMON_SOURCE_SET_NAME); + Configuration commonImplementation = createBucket(project, IMPLEMENTATION_CONFIGURATION_NAME, COMMON_SOURCE_SET_NAME).extendsFrom(commonApi); + Configuration commonCompileOnlyApi = createBucket(project, COMPILE_ONLY_API_CONFIGURATION_NAME, COMMON_SOURCE_SET_NAME); + Configuration commonRuntimeOnly = createBucket(project, RUNTIME_ONLY_CONFIGURATION_NAME, COMMON_SOURCE_SET_NAME); + + project.getConfigurations().named(CONTENTS_CONFIGURATION_NAME).configure(conf -> conf.extendsFrom(commonContents)); + project.getConfigurations().named(API_CONFIGURATION_NAME).configure(conf -> conf.extendsFrom(commonApi)); + project.getConfigurations().named(IMPLEMENTATION_CONFIGURATION_NAME).configure(conf -> conf.extendsFrom(commonImplementation)); + project.getConfigurations().named(COMPILE_ONLY_API_CONFIGURATION_NAME).configure(conf -> conf.extendsFrom(commonCompileOnlyApi)); + project.getConfigurations().named(RUNTIME_ONLY_CONFIGURATION_NAME).configure(conf -> conf.extendsFrom(commonRuntimeOnly)); + + project.getExtensions().configure(VariantPlugin.VariantExtension.class, variants -> { + variants.getVariants().configureEach(variant -> { + createPackage(project, variant.getName(), variant.getCapabilities().get()); + + bucket(project, CONTENTS_CONFIGURATION_NAME, variant.getName()).extendsFrom(commonContents); + bucket(project, API_CONFIGURATION_NAME, variant.getName()).extendsFrom(commonApi); + bucket(project, IMPLEMENTATION_CONFIGURATION_NAME, variant.getName()).extendsFrom(commonImplementation); + bucket(project, COMPILE_ONLY_API_CONFIGURATION_NAME, variant.getName()).extendsFrom(commonCompileOnlyApi); + bucket(project, RUNTIME_ONLY_CONFIGURATION_NAME, variant.getName()).extendsFrom(commonRuntimeOnly); + }); + }); + }); + + project.getPlugins().withType(MavenPublishPlugin.class).configureEach(plugin -> { + project.getExtensions().configure(PublishingExtension.class, publishing -> { + publishing.getPublications().register("mavenJava", MavenPublication.class, mavenPublication -> { + mavenPublication.from(javaComponent); + }); + }); + }); + } + + private void createDefaultPackage(Project project) { + createPackage(project, null, emptyList()); + } + + private void createPackage(Project project, String variant, List capabilities) { + ServiceRegistry projectServices = ((ProjectInternal) project).getServices(); + JvmPluginServices jvmPluginServices = projectServices.get(JvmPluginServices.class); + + Configuration contents = createBucket(project, CONTENTS_CONFIGURATION_NAME, variant); + + Configuration contentsRuntimeElements = jvmPluginServices.createResolvableConfiguration(camelPrefix(variant, "contentsRuntimeElements"), builder -> + builder.extendsFrom(contents).requiresJavaLibrariesRuntime()); + + Configuration contentSourcesElements = jvmPluginServices.createResolvableConfiguration(camelPrefix(variant, "contentsSourcesElements"), builder -> + builder.extendsFrom(contents).requiresAttributes(refiner -> refiner.documentation(SOURCES))); + + TaskProvider shadowJar = project.getTasks().register(camelPrefix(variant, "jar"), ShadowJar.class, shadow -> { + shadow.setGroup(BasePlugin.BUILD_GROUP); + shadow.getArchiveClassifier().set(variant); + + shadow.setConfigurations(Collections.singletonList(contentsRuntimeElements)); + shadow.relocate("org.terracotta.statistics.", "org.ehcache.shadow.org.terracotta.statistics."); + shadow.relocate("org.terracotta.offheapstore.", "org.ehcache.shadow.org.terracotta.offheapstore."); + shadow.relocate("org.terracotta.context.", "org.ehcache.shadow.org.terracotta.context."); + shadow.relocate("org.terracotta.utilities.", "org.ehcache.shadow.org.terracotta.utilities."); + + shadow.mergeServiceFiles(); + + shadow.exclude("META-INF/MANIFEST.MF", "LICENSE", "NOTICE"); + + // LICENSE is included in root gradle build + shadow.from(new File(project.getRootDir(), "NOTICE")); + shadow.setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE); + }); + + Provider sourcesTree = project.provider(() -> contentSourcesElements.getResolvedConfiguration().getLenientConfiguration().getAllModuleDependencies().stream().flatMap(d -> d.getModuleArtifacts().stream()) + .map(artifact -> { + try { + return Optional.of(artifact.getFile()); + } catch (ArtifactResolveException e) { + return Optional.empty(); + } + }).filter(Optional::isPresent).map(Optional::get).distinct().map(file -> { + if (file.isFile()) { + return project.zipTree(file); + } else { + return project.fileTree(file); + } + }).reduce(FileTree::plus).orElse(project.files().getAsFileTree())); + + TaskProvider sources = project.getTasks().register(camelPrefix(variant, "sources"), Sync.class, sync -> { + sync.dependsOn(contentSourcesElements); + sync.from(sourcesTree, spec -> spec.exclude("META-INF/**", "LICENSE", "NOTICE")); + sync.into(project.getLayout().getBuildDirectory().dir(camelPrefix(variant,"sources"))); + }); + + TaskProvider sourcesJar = project.getTasks().register(camelPrefix(variant, "sourcesJar"), Jar.class, jar -> { + jar.setGroup(BasePlugin.BUILD_GROUP); + jar.from(sources); + jar.from(shadowJar, spec -> spec.include("META-INF/**", "LICENSE", "NOTICE")); + jar.getArchiveClassifier().set(kebabPrefix(variant, "sources")); + }); + + TaskProvider javadoc = project.getTasks().register(camelPrefix(variant, "javadoc"), Javadoc.class, task -> { + task.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP); + task.setTitle(project.getName() + " " + project.getVersion() + " API"); + task.source(sources); + task.include("*.java"); + task.setClasspath(contentsRuntimeElements); + task.setDestinationDir(new File(project.getBuildDir(), "docs/" + camelPrefix(variant, "javadoc"))); + }); + TaskProvider javadocJar = project.getTasks().register(camelPrefix(variant, "javadocJar"), Jar.class, jar -> { + jar.setGroup(BasePlugin.BUILD_GROUP); + jar.from(javadoc); + jar.getArchiveClassifier().set(kebabPrefix(variant, "javadoc")); + }); + + Configuration api = createBucket(project, API_CONFIGURATION_NAME, variant); + Configuration implementation = createBucket(project, IMPLEMENTATION_CONFIGURATION_NAME, variant).extendsFrom(api); + Configuration compileOnlyApi = createBucket(project, COMPILE_ONLY_API_CONFIGURATION_NAME, variant); + Configuration runtimeOnly = createBucket(project, RUNTIME_ONLY_CONFIGURATION_NAME, variant); + + Configuration apiElements = jvmPluginServices.createOutgoingElements(camelPrefix(variant, API_ELEMENTS_CONFIGURATION_NAME), builder -> + builder.extendsFrom(api, compileOnlyApi).published().providesApi().withCapabilities(capabilities).artifact(shadowJar)); + configureDefaultTargetPlatform(apiElements, parseInt(Jvm.current().getJavaVersion().getMajorVersion())); + Configuration compileClasspath = jvmPluginServices.createResolvableConfiguration(camelPrefix(variant, COMPILE_CLASSPATH_CONFIGURATION_NAME), builder -> + builder.extendsFrom(apiElements).requiresJavaLibrariesRuntime()); + Configuration runtimeElements = jvmPluginServices.createOutgoingElements(camelPrefix(variant, RUNTIME_ELEMENTS_CONFIGURATION_NAME), builder -> + builder.extendsFrom(implementation, runtimeOnly).published().providesRuntime().withCapabilities(capabilities).artifact(shadowJar)); + configureDefaultTargetPlatform(runtimeElements, parseInt(Jvm.current().getJavaVersion().getMajorVersion())); + Configuration runtimeClasspath = jvmPluginServices.createResolvableConfiguration(camelPrefix(variant, RUNTIME_CLASSPATH_CONFIGURATION_NAME), builder -> + builder.extendsFrom(runtimeElements).requiresJavaLibrariesRuntime()); + + Configuration sourcesElements = jvmPluginServices.createOutgoingElements(camelPrefix(variant, SOURCES_ELEMENTS_CONFIGURATION_NAME), builder -> + builder.published().artifact(sourcesJar).withCapabilities(capabilities).providesAttributes(attributes -> attributes.documentation(SOURCES).asJar())); + Configuration javadocElements = jvmPluginServices.createOutgoingElements(camelPrefix(variant, JAVADOC_ELEMENTS_CONFIGURATION_NAME), builder -> + builder.published().artifact(javadocJar).withCapabilities(capabilities).providesAttributes(attributes -> attributes.documentation(JAVADOC).asJar())); + + shadowJar.configure(shadow -> { + OsgiManifestJarExtension osgiExtension = new OsgiManifestJarExtension(shadow); + osgiExtension.getClasspath().from(runtimeClasspath); + osgiExtension.getSources().from(sources); + BndConvention.bundleDefaults(project).execute(osgiExtension.getInstructions()); + }); + + project.getComponents().named("java", AdhocComponentWithVariants.class, java -> { + java.addVariantsFromConfiguration(apiElements, variantDetails -> { + variantDetails.mapToMavenScope("compile"); + if (variant != null) { + variantDetails.mapToOptional(); + } + }); + java.addVariantsFromConfiguration(runtimeElements, variantDetails -> { + variantDetails.mapToMavenScope("runtime"); + if (variant != null) { + variantDetails.mapToOptional(); + } + }); + java.addVariantsFromConfiguration(sourcesElements, variantDetails -> {}); + java.addVariantsFromConfiguration(javadocElements, variantDetails -> {}); + }); + + + project.getTasks().named(LifecycleBasePlugin.ASSEMBLE_TASK_NAME).configure(task -> { + task.dependsOn(shadowJar); + task.dependsOn(javadocJar); + task.dependsOn(sourcesJar); + }); + } + + private static String camelPrefix(String variant, String thing) { + if (variant == null) { + return thing; + } else { + return variant + capitalize(thing); + } + } + + private static String kebabPrefix(String variant, String thing) { + if (variant == null) { + return thing; + } else { + return variant + "-" + thing; + } + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/plugins/VariantPlugin.java b/build-logic/src/main/java/org/ehcache/build/plugins/VariantPlugin.java new file mode 100644 index 0000000000..8cc14e802b --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/plugins/VariantPlugin.java @@ -0,0 +1,228 @@ +package org.ehcache.build.plugins; + +import aQute.bnd.gradle.BndBuilderPlugin; +import aQute.bnd.gradle.BundleTaskExtension; +import org.ehcache.build.conventions.BndConvention; +import org.ehcache.build.util.PluginUtils; +import org.gradle.api.Action; +import org.gradle.api.NamedDomainObjectContainer; +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.capabilities.Capability; +import org.gradle.api.file.Directory; +import org.gradle.api.file.SourceDirectorySet; +import org.gradle.api.internal.HasConvention; +import org.gradle.api.internal.artifacts.dsl.CapabilityNotationParserFactory; +import org.gradle.api.internal.project.ProjectInternal; +import org.gradle.api.model.ObjectFactory; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.plugins.JavaPluginExtension; +import org.gradle.api.plugins.jvm.internal.JvmPluginServices; +import org.gradle.api.provider.ListProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.provider.Provider; +import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.Sync; +import org.gradle.api.tasks.TaskProvider; +import org.gradle.api.tasks.bundling.Jar; +import org.gradle.internal.typeconversion.NotationParser; +import org.gradle.language.base.plugins.LifecycleBasePlugin; +import org.unbrokendome.gradle.plugins.xjc.XjcPlugin; +import org.unbrokendome.gradle.plugins.xjc.XjcSourceSetConvention; + +import java.util.function.Function; + +import static java.util.Objects.requireNonNull; +import static org.ehcache.build.util.PluginUtils.capitalize; +import static org.gradle.api.attributes.DocsType.SOURCES; +import static org.gradle.api.plugins.JavaPlugin.API_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.COMPILE_ONLY_API_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME; +import static org.gradle.api.plugins.JavaPlugin.SOURCES_ELEMENTS_CONFIGURATION_NAME; +import static org.gradle.api.tasks.SourceSet.MAIN_SOURCE_SET_NAME; + +public class VariantPlugin implements Plugin { + + protected static final String COMMON_SOURCE_SET_NAME = "common"; + + @Override + public void apply(Project project) { + VariantExtension variants = project.getExtensions().create("variants", VariantExtension.class, project); + configureJavaPluginBehavior(project, variants); + } + + private void configureJavaPluginBehavior(Project project, VariantExtension variants) { + project.getPlugins().withType(JavaPlugin.class).configureEach(javaPlugin -> { + JavaPluginExtension java = project.getExtensions().getByType(JavaPluginExtension.class); + + variants.getVariants().configureEach(variant -> { + if (variant.hasSources().get()) { + SourceSet commonSources = java.getSourceSets().findByName(COMMON_SOURCE_SET_NAME); + if (commonSources == null) { + commonSources = java.getSourceSets().create(COMMON_SOURCE_SET_NAME, common -> { + project.getTasks().named(common.getCompileJavaTaskName(), task -> task.setEnabled(false)); + project.getTasks().named(common.getClassesTaskName(), task -> task.setEnabled(false)); + linkToCommonSource(project, common, java.getSourceSets().getByName(MAIN_SOURCE_SET_NAME)); + }); + } + SourceSet variantSources = java.getSourceSets().create(variant.getName()); + + linkToCommonSource(project, commonSources, variantSources); + + java.registerFeature(variant.getName(), feature -> { + feature.usingSourceSet(variantSources); + feature.withSourcesJar(); + variant.getCapabilities().get().forEach(capability -> { + feature.capability(capability.getGroup(), capability.getName(), requireNonNull(capability.getVersion())); + }); + }); + + project.getPlugins().withType(BndBuilderPlugin.class).configureEach(bnd -> { + project.getTasks().named(variantSources.getJarTaskName(), Jar.class, jar -> { + jar.setDescription("Assembles a bundle containing the " + variant + " variant classes."); + BundleTaskExtension extension = jar.getExtensions().create(BundleTaskExtension.NAME, BundleTaskExtension.class, jar); + BndConvention.configureBundleDefaults(project, extension); + jar.doLast("buildBundle", extension.buildAction()); + }); + }); + + project.getTasks().named(LifecycleBasePlugin.ASSEMBLE_TASK_NAME).configure(task -> { + task.dependsOn(variantSources.getJarTaskName()); + task.dependsOn(variantSources.getSourcesJarTaskName()); + }); + } else { + SourceSet mainSource = java.getSourceSets().getByName(MAIN_SOURCE_SET_NAME); + + JvmPluginServices jvmPluginServices = ((ProjectInternal) project).getServices().get(JvmPluginServices.class); + + Configuration commonApi = PluginUtils.createBucket(project, API_CONFIGURATION_NAME, COMMON_SOURCE_SET_NAME); + project.getConfigurations().named(mainSource.getApiConfigurationName()).configure(config -> config.extendsFrom(commonApi)); + Configuration commonCompileOnlyApi = PluginUtils.createBucket(project, COMPILE_ONLY_API_CONFIGURATION_NAME, COMMON_SOURCE_SET_NAME); + project.getConfigurations().named(mainSource.getCompileOnlyApiConfigurationName()).configure(config -> config.extendsFrom(commonCompileOnlyApi)); + Configuration commonImplementation = PluginUtils.createBucket(project, IMPLEMENTATION_CONFIGURATION_NAME, COMMON_SOURCE_SET_NAME); + project.getConfigurations().named(mainSource.getImplementationConfigurationName()).configure(config -> config.extendsFrom(commonImplementation)); + Configuration commonRuntimeOnly = PluginUtils.createBucket(project, RUNTIME_ONLY_CONFIGURATION_NAME, COMMON_SOURCE_SET_NAME); + project.getConfigurations().named(mainSource.getRuntimeOnlyConfigurationName()).configure(config -> config.extendsFrom(commonRuntimeOnly)); + + Configuration api = PluginUtils.createBucket(project, API_CONFIGURATION_NAME, variant.getName()).extendsFrom(commonApi); + Configuration implementation = PluginUtils.createBucket(project, IMPLEMENTATION_CONFIGURATION_NAME, variant.getName()).extendsFrom(api, commonImplementation); + Configuration compileOnlyApi = PluginUtils.createBucket(project, COMPILE_ONLY_API_CONFIGURATION_NAME, variant.getName()).extendsFrom(commonCompileOnlyApi); + Configuration runtimeOnly = PluginUtils.createBucket(project, RUNTIME_ONLY_CONFIGURATION_NAME, variant.getName()).extendsFrom(commonRuntimeOnly); + + Configuration apiElements = jvmPluginServices.createOutgoingElements(variant.getName() + capitalize(API_ELEMENTS_CONFIGURATION_NAME), builder -> + builder.fromSourceSet(mainSource).withCapabilities(variant.getCapabilities().get()) + .extendsFrom(api, compileOnlyApi).withClassDirectoryVariant().providesApi()); + project.getConfigurations().named(mainSource.getApiElementsConfigurationName(), + config -> config.getOutgoing().getArtifacts().configureEach(artifact -> apiElements.getOutgoing().getArtifacts().add(artifact))); + + Configuration runtimeElements = jvmPluginServices.createOutgoingElements(variant.getName() + capitalize(RUNTIME_ELEMENTS_CONFIGURATION_NAME), builder -> + builder.fromSourceSet(mainSource).withCapabilities(variant.getCapabilities().get()).published() + .extendsFrom(implementation, runtimeOnly).providesRuntime()); + project.getConfigurations().named(mainSource.getRuntimeElementsConfigurationName(), + config -> config.getOutgoing().getArtifacts().configureEach(artifact -> runtimeElements.getOutgoing().getArtifacts().add(artifact))); + + Configuration sourcesElements = jvmPluginServices.createOutgoingElements(variant.getName() + capitalize(SOURCES_ELEMENTS_CONFIGURATION_NAME), builder -> + builder.fromSourceSet(mainSource).withCapabilities(variant.getCapabilities().get()).published() + .providesAttributes(attributes -> attributes.documentation(SOURCES).asJar())); + project.getConfigurations().named(mainSource.getSourcesElementsConfigurationName(), + config -> config.getOutgoing().getArtifacts().configureEach(artifact -> sourcesElements.getOutgoing().getArtifacts().add(artifact))); + } + }); + }); + } + + private static void linkToCommonSource(Project project, SourceSet commonSources, SourceSet derivedSources) { + registerCommonCopyTask(project, commonSources, derivedSources, SourceSet::getJava); + registerCommonCopyTask(project, commonSources, derivedSources, SourceSet::getResources); + + Configuration commonApi = project.getConfigurations().maybeCreate(commonSources.getApiConfigurationName()); + project.getConfigurations().maybeCreate(derivedSources.getApiConfigurationName()).extendsFrom(commonApi); + Configuration commonImplementation = project.getConfigurations().maybeCreate(commonSources.getImplementationConfigurationName()); + project.getConfigurations().maybeCreate(derivedSources.getImplementationConfigurationName()).extendsFrom(commonImplementation); + + project.getPlugins().withType(XjcPlugin.class).configureEach(plugin -> { + Function xjc = sourceSet -> ((HasConvention) sourceSet).getConvention().getPlugin(XjcSourceSetConvention.class); + + XjcSourceSetConvention commonXjc = xjc.apply(commonSources); + project.getTasks().named(commonXjc.getXjcGenerateTaskName(), task -> task.setEnabled(false)); + + registerCommonCopyTask(project, commonSources, derivedSources, xjc.andThen(XjcSourceSetConvention::getXjcSchema)); + registerCommonCopyTask(project, commonSources, derivedSources, xjc.andThen(XjcSourceSetConvention::getXjcCatalog)); + registerCommonCopyTask(project, commonSources, derivedSources, xjc.andThen(XjcSourceSetConvention::getXjcBinding)); + registerCommonCopyTask(project, commonSources, derivedSources, xjc.andThen(XjcSourceSetConvention::getXjcUrl)); + }); + } + + private static void registerCommonCopyTask(Project project, SourceSet common, SourceSet variant, Function type) { + SourceDirectorySet commonSource = type.apply(common); + Provider variantLocation = project.getLayout().getBuildDirectory().dir("generated/sources/common/" + variant.getName() + "/" + commonSource.getName()); + TaskProvider variantTask = project.getTasks().register(variant.getTaskName("copyCommon", commonSource.getName()), Sync.class, sync -> { + sync.from(commonSource); + sync.into(variantLocation); + }); + type.apply(variant).srcDir(variantTask); + } + + public static class Variant { + + private static final NotationParser CAPABILITY_NOTATION_PARSER = new CapabilityNotationParserFactory(true).create(); + + private final String name; + private final Property hasSources; + private final ListProperty capabilities; + + public Variant(String name, ObjectFactory objectFactory) { + this.name = name; + this.hasSources = objectFactory.property(Boolean.class).convention(false); + this.capabilities = objectFactory.listProperty(Capability.class); + + this.hasSources.finalizeValueOnRead(); + this.capabilities.finalizeValueOnRead(); + } + + public String getName() { + return name; + } + + public Property hasSources() { + return hasSources; + } + + public ListProperty getCapabilities() { + return capabilities; + } + + public void withSeparateSource() { + this.hasSources.set(true); + } + + public void capability(Object notation) { + this.capabilities.add(CAPABILITY_NOTATION_PARSER.parseNotation(notation)); + } + } + + public static class VariantExtension { + + private final ObjectFactory objectFactory; + private final NamedDomainObjectContainer variants; + + public VariantExtension(Project project) { + this.objectFactory = project.getObjects(); + this.variants = project.container(Variant.class); + } + + public void variant(String variant, Action action) { + Variant v = new Variant(variant, objectFactory); + action.execute(v); + variants.add(v); + } + + public NamedDomainObjectContainer getVariants() { + return variants; + } + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/plugins/VoltronPlugin.java b/build-logic/src/main/java/org/ehcache/build/plugins/VoltronPlugin.java new file mode 100644 index 0000000000..db5299198f --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/plugins/VoltronPlugin.java @@ -0,0 +1,66 @@ +package org.ehcache.build.plugins; + +import org.ehcache.build.conventions.JavaLibraryConvention; +import org.gradle.api.Action; +import org.gradle.api.NamedDomainObjectProvider; +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.artifacts.dsl.DependencyHandler; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.tasks.bundling.Jar; + +import java.io.File; +import java.util.jar.Attributes; +import java.util.stream.Collectors; + +import static java.util.Collections.singletonMap; + +public class VoltronPlugin implements Plugin { + + private static final String VOLTRON_CONFIGURATION_NAME = "voltron"; + private static final String SERVICE_CONFIGURATION_NAME = "service"; + + @Override + public void apply(Project project) { + project.getPlugins().apply(JavaLibraryConvention.class); + + NamedDomainObjectProvider voltron = project.getConfigurations().register(VOLTRON_CONFIGURATION_NAME, config -> { + config.setDescription("Dependencies provided by Voltron from server/lib"); + config.setCanBeConsumed(true); + config.setCanBeResolved(true); + + DependencyHandler dependencyHandler = project.getDependencies(); + String terracottaApisVersion = project.property("terracottaApisVersion").toString(); + String slf4jVersion = project.property("slf4jVersion").toString(); + config.getDependencies().add(dependencyHandler.create("org.terracotta:entity-server-api:" + terracottaApisVersion)); + config.getDependencies().add(dependencyHandler.create("org.terracotta:standard-cluster-services:" + terracottaApisVersion)); + config.getDependencies().add(dependencyHandler.create("org.terracotta:packaging-support:" + terracottaApisVersion)); + config.getDependencies().add(dependencyHandler.create("org.slf4j:slf4j-api:" + slf4jVersion)); + }); + + NamedDomainObjectProvider service = project.getConfigurations().register(SERVICE_CONFIGURATION_NAME, config -> { + config.setDescription("Services consumed by this plugin"); + config.setCanBeResolved(true); + config.setCanBeConsumed(true); + }); + + project.getConfigurations().named(JavaPlugin.API_CONFIGURATION_NAME, config -> { + config.extendsFrom(voltron.get()); + config.extendsFrom(service.get()); + }); + + project.getTasks().named(JavaPlugin.JAR_TASK_NAME, Jar.class, jar -> { + //noinspection Convert2Lambda + jar.doFirst(new Action() { + @Override + public void execute(Task task) { + jar.manifest(manifest -> manifest.attributes(singletonMap(Attributes.Name.CLASS_PATH.toString(), + (project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME).minus(voltron.get()).minus(service.get())) + .getFiles().stream().map(File::getName).collect(Collectors.joining(" "))))); + } + }); + }); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/plugins/osgids/GenerateDeclarativeServicesDescriptors.java b/build-logic/src/main/java/org/ehcache/build/plugins/osgids/GenerateDeclarativeServicesDescriptors.java new file mode 100644 index 0000000000..c285f97550 --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/plugins/osgids/GenerateDeclarativeServicesDescriptors.java @@ -0,0 +1,113 @@ +package org.ehcache.build.plugins.osgids; + +import org.apache.felix.scrplugin.Options; +import org.apache.felix.scrplugin.Project; +import org.apache.felix.scrplugin.SCRDescriptorException; +import org.apache.felix.scrplugin.SCRDescriptorFailureException; +import org.apache.felix.scrplugin.SCRDescriptorGenerator; +import org.apache.felix.scrplugin.Source; +import org.gradle.api.DefaultTask; +import org.gradle.api.GradleException; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.DirectoryProperty; +import org.gradle.api.file.EmptyFileVisitor; +import org.gradle.api.file.FileCollection; +import org.gradle.api.file.FileVisitDetails; +import org.gradle.api.tasks.Classpath; +import org.gradle.api.tasks.InputFiles; +import org.gradle.api.tasks.OutputDirectory; +import org.gradle.api.tasks.TaskAction; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Set; + +public abstract class GenerateDeclarativeServicesDescriptors extends DefaultTask { + + @InputFiles + public abstract ConfigurableFileCollection getInputFiles(); + + @Classpath + public abstract ConfigurableFileCollection getClasspath(); + + @OutputDirectory + public abstract DirectoryProperty getOutputDirectory(); + + @TaskAction + public void generateDeclarativeServicesDescriptors() throws SCRDescriptorException, SCRDescriptorFailureException, IOException { + final Options scrOptions = createOptions(); + + try (GradleScrProject scrProject = new GradleScrProject(getInputFiles(), getClasspath())) { + final SCRDescriptorGenerator scrGenerator = new SCRDescriptorGenerator(new ScrLoggerAdapter(getLogger())); + scrGenerator.setOptions(scrOptions); + scrGenerator.setProject(scrProject); + + scrGenerator.execute(); + } + } + + private Options createOptions() { + final Options scrOptions = new Options(); + scrOptions.setOutputDirectory(getOutputDirectory().get().getAsFile()); + scrOptions.setStrictMode(false); + scrOptions.setSpecVersion(null); + + return scrOptions; + } + + static class GradleScrProject extends Project implements Closeable { + + private final URLClassLoader urlClassLoader; + + GradleScrProject(FileCollection input, FileCollection classpath) { + Set classpathFiles = classpath.getFiles(); + URL[] classpathUrls = classpathFiles.stream().map(f -> { + try { + return f.toURI().toURL(); + } catch (MalformedURLException e) { + throw new GradleException("Malformed URL in classpath", e); + } + }).toArray(URL[]::new); + this.urlClassLoader = URLClassLoader.newInstance(classpathUrls, getClass().getClassLoader()); + setClassLoader(urlClassLoader); + setDependencies(classpathFiles); + setSources(createScrSources(input)); + } + + @Override + public void close() throws IOException { + urlClassLoader.close(); + } + + private static Collection createScrSources(FileCollection input) { + Collection sources = new ArrayList<>(); + + input.getAsFileTree().matching(f -> f.include("**/*.class")).visit(new EmptyFileVisitor() { + @Override + public void visitFile(FileVisitDetails fileVisitDetails) { + String dotSeparated = String.join(".", fileVisitDetails.getRelativePath().getSegments()); + String className = dotSeparated.substring(0, dotSeparated.length() - ".class".length()); + File file = fileVisitDetails.getFile(); + sources.add(new Source() { + @Override + public String getClassName() { + return className; + } + + @Override + public File getFile() { + return file; + } + }); + } + }); + return sources; + } + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/plugins/osgids/OsgiDsPlugin.java b/build-logic/src/main/java/org/ehcache/build/plugins/osgids/OsgiDsPlugin.java new file mode 100644 index 0000000000..a844ab0af9 --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/plugins/osgids/OsgiDsPlugin.java @@ -0,0 +1,22 @@ +package org.ehcache.build.plugins.osgids; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.tasks.SourceSetContainer; +import org.gradle.api.tasks.TaskProvider; + +public class OsgiDsPlugin implements Plugin { + @Override + public void apply(Project project) { + project.getExtensions().configure(SourceSetContainer.class, sourceSets -> sourceSets.configureEach(sourceSet -> { + String taskName = sourceSet.getTaskName("generate", "DeclarativeServicesDescriptors"); + TaskProvider generateTask = project.getTasks().register(taskName, GenerateDeclarativeServicesDescriptors.class, task -> { + task.setDescription("Generate OSGi Declarative Services XML descriptors for " + sourceSet.getName() + " classes"); + task.getInputFiles().from(sourceSet.getOutput().getClassesDirs()); + task.getClasspath().from(sourceSet.getRuntimeClasspath()); + task.getOutputDirectory().set(project.getLayout().getBuildDirectory().dir("generated/resources/osgi-ds/" + sourceSet.getName())); + }); + sourceSet.getOutput().getGeneratedSourcesDirs().plus(project.fileTree(generateTask)); + })); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/plugins/osgids/ScrLoggerAdapter.java b/build-logic/src/main/java/org/ehcache/build/plugins/osgids/ScrLoggerAdapter.java new file mode 100644 index 0000000000..279b26714f --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/plugins/osgids/ScrLoggerAdapter.java @@ -0,0 +1,149 @@ +/** + * Copyright (C) 2016 Elmar Schug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.build.plugins.osgids; + +import org.apache.felix.scrplugin.Log; +import org.gradle.api.logging.Logger; + + +final class ScrLoggerAdapter implements Log +{ + private final Logger logger; + + ScrLoggerAdapter(Logger logger) { + this.logger = logger; + } + + @Override + public boolean isDebugEnabled() + { + return logger.isDebugEnabled(); + } + + @Override + public void debug(String content) + { + logger.debug(content); + } + + @Override + public void debug(String content, Throwable error) + { + logger.debug(content, error); + } + + @Override + public void debug(Throwable error) + { + logger.debug(error.toString()); + } + + @Override + public boolean isInfoEnabled() + { + return logger.isInfoEnabled(); + } + + @Override + public void info(String content) + { + logger.info(content); + } + + @Override + public void info(String content, Throwable error) + { + logger.info(content, error); + } + + @Override + public void info(Throwable error) + { + logger.info(error.toString()); + } + + @Override + public boolean isWarnEnabled() + { + return logger.isWarnEnabled(); + } + + @Override + public void warn(String content) + { + logger.warn(content); + } + + @Override + public void warn(String content, String location, int lineNumber) + { + logger.warn("{} [{},{}]", content, location, lineNumber); + } + + @Override + public void warn(String content, String location, int lineNumber, int columNumber) + { + logger.warn("{} [{},{}:{}]", content, location, lineNumber, columNumber); + } + + @Override + public void warn(String content, Throwable error) + { + logger.warn(content, error); + } + + @Override + public void warn(Throwable error) + { + logger.warn(error.toString()); + } + + @Override + public boolean isErrorEnabled() + { + return logger.isErrorEnabled(); + } + + @Override + public void error(String content) + { + logger.error(content); + } + + @Override + public void error(String content, String location, int lineNumber) + { + logger.error("{} [{},}{}]", content, location, lineNumber); + } + + @Override + public void error(String content, String location, int lineNumber, int columnNumber) + { + logger.error("{} [{},{}:{}]", content, location, lineNumber, columnNumber); + } + + @Override + public void error(String content, Throwable error) + { + logger.error(content, error); + } + + @Override + public void error(Throwable error) + { + logger.error(error.toString()); + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/util/OsgiManifestJarExtension.java b/build-logic/src/main/java/org/ehcache/build/util/OsgiManifestJarExtension.java new file mode 100644 index 0000000000..d2e8556173 --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/util/OsgiManifestJarExtension.java @@ -0,0 +1,103 @@ +package org.ehcache.build.util; + +import aQute.bnd.osgi.Builder; +import aQute.bnd.osgi.Jar; +import aQute.service.reporter.Report; +import org.gradle.api.Action; +import org.gradle.api.GradleException; +import org.gradle.api.Task; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.provider.MapProperty; +import org.gradle.api.provider.Provider; +import org.gradle.api.tasks.Classpath; +import org.gradle.api.tasks.ClasspathNormalizer; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.InputFiles; + +import java.io.File; +import java.util.Map; +import java.util.concurrent.Callable; + +public class OsgiManifestJarExtension { + + private final org.gradle.api.tasks.bundling.Jar jarTask; + private final MapProperty instructions; + private final ConfigurableFileCollection classpath; + private final ConfigurableFileCollection sources; + + public OsgiManifestJarExtension(org.gradle.api.tasks.bundling.Jar jarTask) { + this.jarTask = jarTask; + this.instructions = jarTask.getProject().getObjects().mapProperty(String.class, String.class); + this.classpath = jarTask.getProject().getObjects().fileCollection(); + this.sources = jarTask.getProject().getObjects().fileCollection(); + + jarTask.getInputs().files(classpath).withNormalizer(ClasspathNormalizer.class).withPropertyName("osgi.classpath"); + jarTask.getInputs().files(sources).withPropertyName("osgi.sources"); + jarTask.getInputs().property("osgi.instructions", (Callable>) instructions::get); + + jarTask.getExtensions().add("osgi", this); + jarTask.doLast("buildManifest", new BuildAction()); + } + + public void instruction(String key, String value) { + instructions.put(key, value); + } + + public void instruction(String key, Provider value) { + instructions.put(key, value); + } + + @Input @Classpath + public ConfigurableFileCollection getClasspath() { + return classpath; + } + + @InputFiles + public ConfigurableFileCollection getSources() { + return sources; + } + + @Input + public MapProperty getInstructions() { + return instructions; + } + + + private class BuildAction implements Action { + @Override + public void execute(Task t) { + try (Builder builder = new Builder()) { + File archiveFile = jarTask.getArchiveFile().get().getAsFile(); + + jarTask.getProject().sync(sync -> sync.from(archiveFile).into(jarTask.getTemporaryDir())); + File archiveCopyFile = new File(jarTask.getTemporaryDir(), archiveFile.getName()); + + Jar bundleJar = new Jar(archiveCopyFile); + + builder.setJar(bundleJar); + builder.setClasspath(getClasspath().getFiles()); + builder.setSourcepath(getSources().getFiles().toArray(new File[0])); + builder.addProperties(getInstructions().get()); + + try (Jar builtJar = builder.build()) { + builtJar.write(archiveFile); + } + + if (!builder.isOk()) { + jarTask.getProject().delete(archiveFile); + builder.getErrors().forEach((String msg) -> { + Report.Location location = builder.getLocation(msg); + if ((location != null) && (location.file != null)) { + jarTask.getLogger().error("{}:{}: error: {}", location.file, location.line, msg); + } else { + jarTask.getLogger().error("error : {}", msg); + } + }); + throw new GradleException("Bundle " + archiveFile.getName() + " has errors"); + } + } catch (Exception e) { + throw new GradleException("Error building bundle", e); + } + } + } +} diff --git a/build-logic/src/main/java/org/ehcache/build/util/PluginUtils.java b/build-logic/src/main/java/org/ehcache/build/util/PluginUtils.java new file mode 100644 index 0000000000..619b6413f3 --- /dev/null +++ b/build-logic/src/main/java/org/ehcache/build/util/PluginUtils.java @@ -0,0 +1,48 @@ +package org.ehcache.build.util; + +import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; + +import java.util.Locale; + +public class PluginUtils { + + public static Configuration createBucket(Project project, String kind, String variant) { + if (variant == null) { + return createBucket(project, kind); + } else { + Configuration configuration = project.getConfigurations().maybeCreate(variant + capitalize(kind)); + configuration.setDescription(capitalize(kind) + " dependencies for " + variant); + configuration.setVisible(false); + configuration.setCanBeResolved(false); + configuration.setCanBeConsumed(false); + return configuration; + } + } + + public static Configuration createBucket(Project project, String kind) { + Configuration configuration = project.getConfigurations().maybeCreate(kind); + configuration.setDescription(capitalize(kind) + " dependencies"); + configuration.setVisible(false); + configuration.setCanBeResolved(false); + configuration.setCanBeConsumed(false); + return configuration; + } + + public static Configuration bucket(Project project, String kind, String variant) { + if (variant == null) { + return bucket(project, kind); + } else { + return project.getConfigurations().getByName(variant + capitalize(kind)); + } + } + + public static Configuration bucket(Project project, String kind) { + return project.getConfigurations().getByName(kind); + } + + public static String capitalize(String word) { + return word.substring(0, 1).toUpperCase(Locale.ROOT) + word.substring(1); + } + +} diff --git a/build.gradle b/build.gradle index 96512dd637..b107ffb59d 100644 --- a/build.gradle +++ b/build.gradle @@ -13,8 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import scripts.* -import org.gradle.internal.jvm.Jvm plugins { // This adds tasks to auto close or release nexus staging repos @@ -22,16 +20,16 @@ plugins { id 'io.codearte.nexus-staging' //OWASP Security Vulnerability Detection id 'org.owasp.dependencycheck' - // Declare spotbugs at the top - id 'com.github.spotbugs' apply false - // Declare bnd at the top - id 'biz.aQute.bnd.builder' apply false } wrapper { distributionType = Wrapper.DistributionType.ALL } +allprojects { + version = findProperty('overrideVersion') ?: ehcacheVersion +} + if (deployUrl.contains('nexus')) { //internal terracotta config, shorten url for this plugin to end at local/ project.nexusStaging { @@ -52,238 +50,25 @@ if (deployUrl.contains('nexus')) { } } -project.nexusStaging { +nexusStaging { username = project.ext.deployUser password = project.ext.deployPwd logger.debug("Nexus Staging: Using login ${username} and url ${serverUrl}") } -// Disable automatic promotion for added safety -closeAndReleaseRepository.enabled = false - - -ext { - - baseVersion = findProperty('overrideVersion') ?: ehcacheVersion - - utils = new Utils(baseVersion, logger) - isReleaseVersion = !baseVersion.endsWith('SNAPSHOT') +tasks.named('closeAndReleaseRepository') { + // Disable automatic promotion for added safety + enabled = false; } - assert (JavaVersion.current().isJava8Compatible()) : 'The Ehcache 3 build requires Java 8+ to run' -ext { - testJava = Jvm.current() -} - -if (hasProperty('testVM')) { - File jvmHome = new File(testVM) - if (!jvmHome.exists() && hasProperty(testVM)) { - jvmHome = new File(project.property(testVM).toString()) - } - testJava = Utils.jvmForHome(jvmHome) - println "Using Test JVM $testJava [Version: $testJava.javaVersion.majorVersion]" -} dependencyCheck { failBuildOnCVSS = 0 suppressionFile = 'config/owasp-supressions.xml' - skipConfigurations += ['checkstyle', 'spotbugs'] + skipConfigurations += ['checkstyle', 'spotbugs', 'xjcClasspath'] skipProjects += [':docs', ':demos:00-NoCache', ':demos:01-CacheAside'] } tasks.register('check') { dependsOn dependencyCheckAggregate } - -subprojects { - apply plugin: 'java-library' - apply plugin: 'checkstyle' - apply plugin: 'com.github.spotbugs' - apply plugin: 'jacoco' - - group = 'org.ehcache.modules' - version = baseVersion - - archivesBaseName = "ehcache-${project.name}" - - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - - repositories { - if (project.hasProperty('mvnlocal')) { - mavenLocal() - } - mavenCentral() - maven { url "https://repo.terracotta.org/maven2" } - } - - sourceSets { - slowTest { - java.srcDir 'src/slow-test/java' - resources.srcDir 'src/slow-test/resources' - compileClasspath += sourceSets.test.compileClasspath - runtimeClasspath += sourceSets.test.runtimeClasspath - } - } - - dependencies { - implementation "org.slf4j:slf4j-api:$parent.slf4jVersion" - compileOnly "com.github.spotbugs:spotbugs-annotations:${project.spotbugs.toolVersion}" - testCompileOnly "com.github.spotbugs:spotbugs-annotations:${project.spotbugs.toolVersion}" - testImplementation "junit:junit:$junitVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.hamcrest:hamcrest-library:$hamcrestVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.terracotta:terracotta-utilities-test-tools:$terracottaUtilitiesVersion" - testRuntimeOnly "org.slf4j:slf4j-simple:$parent.slf4jVersion" - } - - jar { - utils.fillManifest(manifest,"${project.group}","ehcache-${project.name}") - from "$rootDir/LICENSE" - } - - test { - jacoco { - excludes += "org.terracotta.tripwire.*" - } - } - - task slowTest(type: Test) { - testClassesDirs = sourceSets.slowTest.output.classesDirs - classpath += sourceSets.slowTest.runtimeClasspath - - binResultsDir file("$buildDir/slow-tests-results/binary/$name") - reports.junitXml.destination = file("$buildDir/slow-tests-results") - reports.html.destination = file("$buildDir/reports/slow-tests") - } - - task sourceJar(type: Jar, dependsOn: classes) { - from sourceSets.main.allJava - archiveClassifier = 'sources' - } - - javadoc { - title "$project.archivesBaseName $project.version API" - exclude '**/internal/**' - } - - task javadocJar(type: Jar, dependsOn: javadoc) { - from javadoc.destinationDir - archiveClassifier = 'javadoc' - } - - artifacts { - archives javadocJar - archives sourceJar - } - - checkstyle { - configFile = file("$rootDir/config/checkstyle.xml") - configProperties = ['projectDir':projectDir, 'rootDir':rootDir] - } - - spotbugs { - ignoreFailures = false - sourceSets = [sourceSets.main] - - } - - // Spotbugs itself has a divergence in it's slf4j dependencies. - // This version is independent of the version we use. - configurations.spotbugs.resolutionStrategy { - force 'org.slf4j:slf4j-api:1.8.0-beta4' - } - spotbugsMain { - reports { - // Switch from xml to html by changing these flags - xml.enabled = true - html.enabled = false - } - } - - jacoco { - toolVersion = jacocoVersion - } - - jacocoTestReport { - reports { - xml.enabled false - csv.enabled false - } - } - - tasks.withType(AbstractCompile) { - options.with { - fork = true - } - } - tasks.withType(Test) { - executable = testJava.javaExecutable - maxHeapSize = "256m" - maxParallelForks 16 - systemProperty 'java.awt.headless', 'true' - } - tasks.withType(Javadoc) { - options.addStringOption('Xdoclint:none', '-quiet') - } - - configurations.all { - resolutionStrategy { - failOnVersionConflict() - // If you want to override a dependency, instead of changing gradle.properties, use something like below - // force 'org.terracotta:statistics:2.0-SNAPSHOT' - } - } - - plugins.withId('biz.aQute.bnd.builder') { - /* - * The bnd gradle plugin does not handle our 2-digit snapshot versioning scheme very well. It maps `x.y-SNAPSHOT` - * to `x.y.0.SNAPSHOT`. This is bad since `x.y.0.SNAPSHOT` is considered to be less than *all* `x.y.z`. This means - * the baseline version range expression `(,x.y.0.SNAPSHOT[` will always pick the last release from the previous - * minor line. To fix this we manually map to a 3-digit snapshot version where the 3rd digit is a number chosen - * to be higher than we would ever release ('All the worlds a VAX'). - */ - def fixedVersion = project.version.asType(String).replaceAll(/^(\d+.\d+)-SNAPSHOT$/, "\$1.999-SNAPSHOT") - - jar { - bnd( - 'Bundle-Name': project.properties.subPomName, - 'Bundle-Description': project.properties.subPomDesc, - 'Bundle-SymbolicName': "org.ehcache.modules.$project.archivesBaseName", - 'Bundle-DocURL': 'http://ehcache.org', - 'Bundle-License': 'LICENSE', - 'Bundle-Vendor': 'Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.', - 'Bundle-Version': fixedVersion, - 'Service-Component': 'OSGI-INF/*.xml' - ) - } - dependencies { - baseline(group: group, name: jar.archiveBaseName.get(), version: "(,${fixedVersion}[") { - force = true - transitive = false - } - } - configurations.baseline { - resolutionStrategy { - componentSelection { - all { selection -> - if (!selection.candidate.version.matches(/\d+(?:\.\d+)*/)) { - selection.reject("Only full releases can be used as OSGi baselines") - } - } - } - } - } - } -} - -allprojects { - tasks.withType(JavaCompile) { - options.encoding = 'UTF-8' - options.compilerArgs += ['-Werror', '-Xlint:all'] - } - tasks.withType(Javadoc) { - options.encoding = 'UTF-8' - } -} diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle deleted file mode 100644 index 0af1840fab..0000000000 --- a/buildSrc/build.gradle +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -plugins { - id 'groovy' - id 'java-gradle-plugin' -} - -repositories { jcenter() } - -gradlePlugin { - plugins { - ehDeploy { - id = 'org.ehcache.build.deploy' - implementationClass = 'EhDeploy' - } - ehDistribute { - id = 'org.ehcache.build.distribute' - implementationClass = 'EhDistribute' - } - ehPomMangle { - id = 'org.ehcache.build.pom-mangle' - implementationClass = 'EhPomMangle' - } - ehVoltron { - id = 'org.ehcache.build.voltron' - implementationClass = 'EhVoltron' - } - } -} - -dependencies { - api gradleApi() - implementation localGroovy() - api 'com.github.jengelman.gradle.plugins:shadow:5.2.0' -} diff --git a/buildSrc/src/main/groovy/EhDeploy.groovy b/buildSrc/src/main/groovy/EhDeploy.groovy deleted file mode 100644 index 2ae5ff59d9..0000000000 --- a/buildSrc/src/main/groovy/EhDeploy.groovy +++ /dev/null @@ -1,93 +0,0 @@ -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer -import org.gradle.api.artifacts.maven.MavenDeployment -import org.gradle.api.plugins.MavenPlugin -import scripts.Utils - -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * EhDeploy - */ -class EhDeploy implements Plugin { - @Override - void apply(Project project) { - - def utils = new Utils(project.baseVersion, project.logger) - - project.plugins.apply 'signing' - project.plugins.apply 'maven' - project.plugins.apply EhPomGenerate // for generating pom.* - - project.configurations { - providedApi - providedImplementation - - api.extendsFrom providedApi - implementation.extendsFrom providedImplementation - } - - project.signing { - required { project.isReleaseVersion && project.gradle.taskGraph.hasTask("uploadArchives") } - sign project.configurations.getByName('archives') - } - - def artifactFiltering = { - project.configurations.matching {it.name.startsWith('test')}.forEach { - pom.scopeMappings.mappings.remove(it) - } - pom.scopeMappings.addMapping(MavenPlugin.COMPILE_PRIORITY, project.configurations.providedApi, Conf2ScopeMappingContainer.PROVIDED) - pom.scopeMappings.addMapping(MavenPlugin.COMPILE_PRIORITY, project.configurations.providedImplementation, Conf2ScopeMappingContainer.PROVIDED) - project.configurations.configureEach { Configuration conf -> - if (conf.name in [EhVoltron.VOLTRON_CONFIGURATION_NAME, EhVoltron.SERVICE_CONFIGURATION_NAME]) { - pom.scopeMappings.addMapping(MavenPlugin.PROVIDED_COMPILE_PRIORITY, conf, Conf2ScopeMappingContainer.PROVIDED) - } - } - - utils.pomFiller(pom, project.subPomName, project.subPomDesc) - - } - - project.install { - repositories.mavenInstaller artifactFiltering - } - - project.uploadArchives { - repositories { - mavenDeployer ({ - beforeDeployment { MavenDeployment deployment -> project.signing.signPom(deployment)} - - if (project.isReleaseVersion) { - repository(url: project.deployUrl) { - authentication(userName: project.deployUser, password: project.deployPwd) - } - } else { - repository(id: 'sonatype-nexus-snapshot', url: 'https://oss.sonatype.org/content/repositories/snapshots') { - authentication(userName: project.sonatypeUser, password: project.sonatypePwd) - } - } - } << artifactFiltering) - } - } - - def installer = project.install.repositories.mavenInstaller - def deployer = project.uploadArchives.repositories.mavenDeployer - - } -} diff --git a/buildSrc/src/main/groovy/EhDistribute.groovy b/buildSrc/src/main/groovy/EhDistribute.groovy deleted file mode 100644 index 28a973833e..0000000000 --- a/buildSrc/src/main/groovy/EhDistribute.groovy +++ /dev/null @@ -1,94 +0,0 @@ -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.artifacts.ProjectDependency -import scripts.Utils - -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * EhDistribute - */ -class EhDistribute implements Plugin { - - @Override - void apply(Project project) { - def utils = new Utils(project.baseVersion, project.logger) - - project.plugins.apply 'java-library' - project.plugins.apply 'maven' - project.plugins.apply 'signing' - project.plugins.apply 'biz.aQute.bnd.builder' - project.plugins.apply 'com.github.johnrengelman.shadow' - project.plugins.apply EhPomMangle - project.plugins.apply EhDocs - project.plugins.apply EhPomGenerate - - project.configurations { - shadowCompile - shadowProvided - } - - project.shadowJar { - configurations = [[project.configurations.compileOnly]] - baseName = "$project.archivesBaseName-shadow" - classifier = '' - dependencies { - exclude({ rdep -> !['org.ehcache', 'org.terracotta'].any({ prefix -> rdep.moduleGroup.startsWith(prefix) })}) - } - relocate ('org.terracotta.statistics.', 'org.ehcache.shadow.org.terracotta.statistics.') - relocate ('org.terracotta.offheapstore.', 'org.ehcache.shadow.org.terracotta.offheapstore.') - relocate ('org.terracotta.context.', 'org.ehcache.shadow.org.terracotta.context.') - - mergeServiceFiles() - } - - project.jar { - dependsOn project.shadowJar - from(project.zipTree(project.shadowJar.archivePath.getPath())) { - exclude 'META-INF/MANIFEST.MF', 'LICENSE', 'NOTICE' - } - // LICENSE is included in root gradle build - from "$project.rootDir/NOTICE" - duplicatesStrategy = 'exclude' - - classpath = project.files(project.configurations.shadowCompile, project.configurations.shadowProvided) - - utils.fillManifest(manifest, project.group, project.archivesBaseName) - } - - - project.sourceJar { - from(project.configurations.named('compileOnly').map({ - it.dependencies.withType(ProjectDependency).toSet().collect { - it.dependencyProject.sourceSets.main.allSource - } - })) { - exclude 'META-INF/**', 'LICENSE', 'NOTICE' - } - from(project.jar) { - include 'META-INF/**', 'LICENSE', 'NOTICE' - } - duplicatesStrategy = 'fail' - } - - project.signing { - required { project.isReleaseVersion && project.gradle.taskGraph.hasTask("uploadArchives") } - sign project.configurations.getByName('archives') - } - - } -} diff --git a/buildSrc/src/main/groovy/EhDocs.groovy b/buildSrc/src/main/groovy/EhDocs.groovy deleted file mode 100644 index 6db5c59bcd..0000000000 --- a/buildSrc/src/main/groovy/EhDocs.groovy +++ /dev/null @@ -1,76 +0,0 @@ -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.artifacts.ProjectDependency -import org.gradle.api.tasks.bundling.Jar -import org.gradle.api.tasks.bundling.Zip -import org.gradle.api.tasks.javadoc.Javadoc - -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * EhDocs - * Handle javadocs and API/SPI/asciidoc - */ -class EhDocs implements Plugin { - - @Override - void apply(Project project) { - def incomingProjects = project.provider { - project.configurations.compile.dependencies.withType(ProjectDependency).dependencyProject + - project.configurations.compileOnly.dependencies.withType(ProjectDependency).dependencyProject - } - - project.javadoc { - title "$project.archivesBaseName $project.version API" - source incomingProjects.map { it*.javadoc.source } - classpath = project.files(incomingProjects.map { it*.javadoc.classpath }) - project.ext.properties.javadocExclude?.tokenize(',').each { - exclude it.trim() - } - } - - if (!project.hasProperty('spiJavadocDisable')) { - - project.task('spiJavadoc', type: Javadoc) { - title "$project.archivesBaseName $project.version API & SPI" - source incomingProjects.map { it*.javadoc.source } - classpath = project.files(incomingProjects.map { it*.javadoc.classpath }) - exclude '**/internal/**' - destinationDir = project.file("$project.docsDir/spi-javadoc") - } - - project.task('spiJavadocJar', type: Jar, dependsOn: 'spiJavadoc') { - archiveClassifier = 'spi-javadoc' - from project.tasks.getByPath('spiJavadoc').destinationDir - } - - } - - project.task('asciidocZip', type: Zip, dependsOn: ':docs:userDoc') { - archiveClassifier = 'docs' - from project.tasks.getByPath(':docs:userDoc').outputDir - } - - project.artifacts { - archives project.asciidocZip - if (!project.hasProperty('spiJavadocDisable')) { - archives project.spiJavadocJar - } - } - - } -} diff --git a/buildSrc/src/main/groovy/EhPomGenerate.groovy b/buildSrc/src/main/groovy/EhPomGenerate.groovy deleted file mode 100644 index 81761ffe63..0000000000 --- a/buildSrc/src/main/groovy/EhPomGenerate.groovy +++ /dev/null @@ -1,125 +0,0 @@ - - -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.publish.maven.MavenPublication -import scripts.Utils - -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * EhPomGenerate: - * Creates pom.xml and pom.properties to be included in produced jars - * Mimics standard maven jar layout. - */ -class EhPomGenerate implements Plugin { - - @Override - void apply(Project project) { - - def utils = new Utils(project.baseVersion, project.logger) - - project.plugins.apply 'maven-publish' // for generating pom.* - - def mavenTempResourcePath = "${project.buildDir}/mvn/META-INF/maven/${project.group}/${project.archivesBaseName}" - - project.model { - // Write pom to temp location to be picked up later, - // generatePomFileForMavenJavaPublication task comes from maven-publish. - tasks.generatePomFileForMavenJavaPublication { - destination = project.file("$mavenTempResourcePath/pom.xml") - } - } - - // Configure pom generation - project.publishing { - publications { - mavenJava(MavenPublication) { - artifactId project.archivesBaseName - from project.components.java - utils.pomFiller(pom, project.subPomName, project.subPomDesc) - if (project.hasProperty('shadowJar')) { - pom.withXml { - if (asNode().dependencies.isEmpty()) { - asNode().appendNode('dependencies') - } - project.configurations.shadowCompile.dependencies.each { - def dep = asNode().dependencies[0].appendNode('dependency') - dep.appendNode('groupId', it.group) - dep.appendNode('artifactId', it.name) - dep.appendNode('version', it.version) - dep.appendNode('scope', 'compile') - } - project.configurations.pomOnlyCompile.dependencies.each { - def dep = asNode().dependencies[0].appendNode('dependency') - dep.appendNode('groupId', it.group) - dep.appendNode('artifactId', it.name) - dep.appendNode('version', it.version) - dep.appendNode('scope', 'compile') - } - project.configurations.shadowProvided.dependencies.each { - def dep = asNode().dependencies[0].appendNode('dependency') - dep.appendNode('groupId', it.group) - dep.appendNode('artifactId', it.name) - dep.appendNode('version', it.version) - dep.appendNode('scope', 'provided') - } - project.configurations.pomOnlyProvided.dependencies.each { - def dep = asNode().dependencies[0].appendNode('dependency') - dep.appendNode('groupId', it.group) - dep.appendNode('artifactId', it.name) - dep.appendNode('version', it.version) - dep.appendNode('scope', 'provided') - } - } - } - } - } - } - - // Write pom.properties to temp location - project.task('writeMavenProperties') { - doLast { - project.file(mavenTempResourcePath).mkdirs() - def propertyFile = project.file "$mavenTempResourcePath/pom.properties" - def props = new Properties() - props.setProperty('version', project.version) - props.setProperty('groupId', project.group) - props.setProperty('artifactId', project.archivesBaseName) - props.store propertyFile.newWriter(), null - } - } - - if (utils.isReleaseVersion) { - //ensure that we generate maven stuff and delay resolution as the first task is created dynamically - project.processResources.dependsOn { - project.tasks.findAll { task -> - task.name == 'generatePomFileForMavenJavaPublication' || task.name == 'writeMavenProperties' - } - } - - // Pick up pom.xml and pom.properties from temp location - project.sourceSets { - main { - resources { - srcDir "${project.buildDir}/mvn" - } - } - } - } - } -} diff --git a/buildSrc/src/main/groovy/EhPomMangle.groovy b/buildSrc/src/main/groovy/EhPomMangle.groovy deleted file mode 100644 index 2bc761fdb9..0000000000 --- a/buildSrc/src/main/groovy/EhPomMangle.groovy +++ /dev/null @@ -1,97 +0,0 @@ -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.artifacts.ProjectDependency -import org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer -import org.gradle.api.artifacts.maven.MavenDeployment -import org.gradle.api.plugins.MavenPlugin -import scripts.Utils - -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * EhPomMangle - * Removes all implicit dependencies from the pom - * and adds only what is specified in (from shadowJar) - * - * project.configurations.shadowCompile (as compile) - * project.configurations.shadowProvided (as provided) - * - * as well as (these do not affect shadow) - * - * project.configurations.pomOnlyCompile - * project.configurations.pomOnlyProvided - * - * Also defines the pom defaults (name, desc, etc) unless overridden in gradle.properties - * Also sets up upload repositories - */ -class EhPomMangle implements Plugin { - - @Override - void apply(Project project) { - def utils = new Utils(project.baseVersion, project.logger) - - project.plugins.apply 'java-library' - project.plugins.apply 'maven' - project.plugins.apply 'signing' - - project.configurations { - shadowCompile - shadowProvided - pomOnlyCompile - pomOnlyProvided - } - - def artifactFiltering = { - project.configurations.forEach { - pom.scopeMappings.mappings.remove(it) - } - - pom.scopeMappings.addMapping(MavenPlugin.COMPILE_PRIORITY, project.configurations.shadowCompile, Conf2ScopeMappingContainer.COMPILE) - pom.scopeMappings.addMapping(MavenPlugin.COMPILE_PRIORITY, project.configurations.shadowProvided, Conf2ScopeMappingContainer.PROVIDED) - - //Anything extra to add to pom that isn't in the shadowed jar or compilation - pom.scopeMappings.addMapping(MavenPlugin.COMPILE_PRIORITY, project.configurations.pomOnlyCompile, Conf2ScopeMappingContainer.COMPILE) - pom.scopeMappings.addMapping(MavenPlugin.COMPILE_PRIORITY, project.configurations.pomOnlyProvided, Conf2ScopeMappingContainer.PROVIDED) - - utils.pomFiller(pom, project.subPomName, project.subPomDesc) - - } - - project.install { - repositories.mavenInstaller artifactFiltering - } - - project.uploadArchives { - repositories { - mavenDeployer ({ - beforeDeployment { MavenDeployment deployment -> project.signing.signPom(deployment)} - - if (project.isReleaseVersion) { - repository(url: project.deployUrl) { - authentication(userName: project.deployUser, password: project.deployPwd) - } - } else { - repository(id: 'sonatype-nexus-snapshot', url: 'https://oss.sonatype.org/content/repositories/snapshots') { - authentication(userName: project.sonatypeUser, password: project.sonatypePwd) - } - } - } << artifactFiltering) - } - } - - } -} diff --git a/buildSrc/src/main/groovy/EhVoltron.groovy b/buildSrc/src/main/groovy/EhVoltron.groovy deleted file mode 100644 index 7c40d28e2a..0000000000 --- a/buildSrc/src/main/groovy/EhVoltron.groovy +++ /dev/null @@ -1,45 +0,0 @@ -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.artifacts.ModuleDependency -import org.gradle.api.plugins.JavaPlugin -import org.gradle.api.tasks.bundling.Jar - -class EhVoltron implements Plugin { - - static String VOLTRON_CONFIGURATION_NAME = 'voltron' - static String SERVICE_CONFIGURATION_NAME = 'service' - - @Override - void apply(Project project) { - project.plugins.withId('java') { - def voltron = project.configurations.create(VOLTRON_CONFIGURATION_NAME) { voltron -> - description "Dependencies provided by Voltron from server/lib" - canBeResolved true - canBeConsumed true - - voltron.dependencies.add(project.dependencies.create(group: 'org.terracotta', name: 'entity-server-api', version: project.terracottaApisVersion)) - voltron.dependencies.add(project.dependencies.create(group: 'org.terracotta', name: 'standard-cluster-services', version: project.terracottaApisVersion)) - voltron.dependencies.add(project.dependencies.create(group: 'org.terracotta', name: 'packaging-support', version: project.terracottaApisVersion)) - voltron.dependencies.add(project.dependencies.create(group: 'org.slf4j', name: 'slf4j-api', version: project.slf4jVersion)) - } - def service = project.configurations.create(SERVICE_CONFIGURATION_NAME) { service -> - description "Services consumed by this plugin" - canBeResolved true - canBeConsumed true - } - - project.configurations.getByName(JavaPlugin.API_CONFIGURATION_NAME) { api -> - api.extendsFrom voltron - api.extendsFrom service - } - - project.tasks.named(JavaPlugin.JAR_TASK_NAME, Jar) { - doFirst { - manifest { - attributes('Class-Path': (project.configurations.runtimeClasspath - voltron - service).collect { it.getName() }.join(' ')) - } - } - } - } - } -} diff --git a/buildSrc/src/main/groovy/scripts/Utils.groovy b/buildSrc/src/main/groovy/scripts/Utils.groovy deleted file mode 100644 index 1bcec0c570..0000000000 --- a/buildSrc/src/main/groovy/scripts/Utils.groovy +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package scripts - -import org.gradle.api.JavaVersion -import org.gradle.internal.jvm.Jvm - -class Utils { - - String version - String revision - boolean isReleaseVersion - - Utils(version, logger) { - this.version = version - this.isReleaseVersion = !version.endsWith('SNAPSHOT') - def tmp = System.getenv("GIT_COMMIT") - if(tmp != null) { - revision = tmp - } else { - logger.debug('Revision not found in system properties, trying command line') - def cmd = 'git rev-parse HEAD' - try { - def proc = cmd.execute() - revision = proc.text.trim() - } catch (IOException) { - revision = 'Unknown' - } - } - logger.debug(revision) - } - - def fillManifest(manifest, group, title) { - manifest.attributes( - 'provider': 'gradle', - 'Implementation-Title': title, - 'Implementation-Vendor-Id': group, - 'Implementation-Version': "$version", - 'Implementation-Revision': "$revision", - 'Built-By': System.getProperty('user.name'), - 'Built-JDK': System.getProperty('java.version')) - if (isReleaseVersion) { - manifest.attributes('Build-Time': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")) - } - } - - def pomFiller(pom, nameVar, descriptionVar) { - pom.withXml { - asNode().version[0] + { - name nameVar - description descriptionVar - url 'http://ehcache.org' - organization { - name 'Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.' - url 'http://terracotta.org' - } - issueManagement { - system 'Github' - url 'https://github.com/ehcache/ehcache3/issues' - } - scm { - url 'https://github.com/ehcache/ehcache3' - connection 'scm:git:https://github.com/ehcache/ehcache3.git' - developerConnection 'scm:git:git@github.com:ehcache/ehcache3.git' - } - licenses { - license { - name 'The Apache Software License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - distribution 'repo' - } - } - developers { - developer { - name 'Terracotta Engineers' - email 'tc-oss@softwareag.com' - organization 'Terracotta Inc., a wholly-owned subsidiary of Software AG USA, Inc.' - organizationUrl 'http://ehcache.org' - } - } - } - } - } - - static def jvmForHome(File home) { - def java = Jvm.forHome(home).javaExecutable - def versionCommand = "$java -version".execute() - def version = JavaVersion.toVersion((versionCommand.err.text =~ /\w+ version "(.+)"/)[0][1]) - return Jvm.discovered(home, version) - } -} diff --git a/clustered/build.gradle b/clustered/build.gradle deleted file mode 100644 index 5809a2cbcb..0000000000 --- a/clustered/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -subprojects { - group = 'org.ehcache.modules.clustered' -} diff --git a/clustered/client/gradle.properties b/clustered/client/gradle.properties deleted file mode 100644 index 8531fcc395..0000000000 --- a/clustered/client/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache 3 Client Side Clustering module -subPomDesc = The Client Side Clustering module of Ehcache 3 diff --git a/clustered/clustered-dist/gradle.properties b/clustered/clustered-dist/gradle.properties deleted file mode 100644 index 4d52981583..0000000000 --- a/clustered/clustered-dist/gradle.properties +++ /dev/null @@ -1,22 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache 3 Clustered Module -subPomDesc = Ehcache 3 Clustered: Defines the client jar and the kit containing the Terracotta server -javadocExclude = **/core/**, **/impl/**, **/xml/**, **/jsr107/**, **/transactions/**, **/management/**, **/tck/** - -# Set to anything to disable SPI doc and jar generation -spiJavadocDisable = true diff --git a/clustered/common-api/gradle.properties b/clustered/common-api/gradle.properties deleted file mode 100644 index 3454901bb0..0000000000 --- a/clustered/common-api/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache 3 Common Clustering API module -subPomDesc = The Common Clustering API module of Ehcache 3 diff --git a/clustered/common/gradle.properties b/clustered/common/gradle.properties deleted file mode 100644 index 6dda235a04..0000000000 --- a/clustered/common/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache 3 Common Clustering module -subPomDesc = The Common Clustering module of Ehcache 3 diff --git a/clustered/client/build.gradle b/clustered/ehcache-client/build.gradle similarity index 57% rename from clustered/client/build.gradle rename to clustered/ehcache-client/build.gradle index 33474da992..bff6116577 100644 --- a/clustered/client/build.gradle +++ b/clustered/ehcache-client/build.gradle @@ -15,29 +15,38 @@ */ plugins { - id 'org.ehcache.build.deploy' - id 'org.jayware.osgi-ds' + id 'org.ehcache.build.clustered-module' +} + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache 3 Client Side Clustering module' + description = 'The Client Side Clustering module of Ehcache 3' + } } dependencies { - compileOnly project(':impl') - compileOnly project(':xml') - implementation project(':clustered:common') - providedImplementation "org.terracotta:entity-client-api:$terracottaApisVersion" - providedImplementation "org.terracotta:runnel:$terracottaPlatformVersion" - providedImplementation "org.terracotta:lease-api:$terracottaPlatformVersion" - providedImplementation "org.terracotta.dynamic-config.entities:dynamic-config-topology-entity-client:$terracottaPlatformVersion" - providedImplementation "org.terracotta:connection-api:$terracottaApisVersion" + api project(':ehcache-impl') + api project(':ehcache-xml') + + implementation project(':clustered:ehcache-common') + implementation "org.terracotta:entity-client-api:$terracottaApisVersion" + implementation "org.terracotta:runnel:$terracottaPlatformVersion" + implementation "org.terracotta:lease-api:$terracottaPlatformVersion" + implementation "org.terracotta.dynamic-config.entities:dynamic-config-topology-entity-client:$terracottaPlatformVersion" + implementation "org.terracotta:connection-api:$terracottaApisVersion" + compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' - testImplementation project(':api') - testImplementation project(':impl') - testImplementation project(':xml') - testImplementation project(':transactions') - testImplementation(project(':clustered:server:entity')) { + testImplementation(project(':ehcache-transactions')) { + capabilities { + requireCapability("org.ehcache:ehcache-transactions-modules") + } + } + testImplementation(project(':clustered:server:ehcache-entity')) { exclude group: 'org.terracotta.internal', module: 'tc-config-parser' } - testImplementation project(':clustered:server:service') + testImplementation project(':clustered:server:ehcache-service') testImplementation "org.terracotta:client-message-tracker:$terracottaPlatformVersion" testImplementation project(':clustered:test-utils') testImplementation "org.terracotta:entity-test-lib:$terracottaPassthroughTestingVersion" @@ -47,6 +56,6 @@ dependencies { testImplementation (group: 'org.codehaus.btm', name: 'btm', version: '2.1.4') { exclude group:'org.slf4j', module:'slf4j-api' } - testImplementation testFixtures(project(':xml')) + testImplementation testFixtures(project(':ehcache-xml')) testImplementation ("org.terracotta:statistics:$parent.statisticVersion") } diff --git a/clustered/client/config/checkstyle-suppressions.xml b/clustered/ehcache-client/config/checkstyle-suppressions.xml similarity index 100% rename from clustered/client/config/checkstyle-suppressions.xml rename to clustered/ehcache-client/config/checkstyle-suppressions.xml diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteredResourcePool.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/ClusteredResourcePool.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteredResourcePool.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/ClusteredResourcePool.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteredResourceType.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/ClusteredResourceType.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteredResourceType.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/ClusteredResourceType.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteredStoreConfiguration.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/ClusteredStoreConfiguration.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteredStoreConfiguration.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/ClusteredStoreConfiguration.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/ClusteringServiceConfiguration.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/DedicatedClusteredResourcePool.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/DedicatedClusteredResourcePool.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/config/DedicatedClusteredResourcePool.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/DedicatedClusteredResourcePool.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/SharedClusteredResourcePool.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/SharedClusteredResourcePool.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/config/SharedClusteredResourcePool.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/SharedClusteredResourcePool.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/Timeouts.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/Timeouts.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/config/Timeouts.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/Timeouts.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteredResourcePoolBuilder.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteredResourcePoolBuilder.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteredResourcePoolBuilder.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteredResourcePoolBuilder.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteredStoreConfigurationBuilder.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteredStoreConfigurationBuilder.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteredStoreConfigurationBuilder.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteredStoreConfigurationBuilder.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteringServiceConfigurationBuilder.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteringServiceConfigurationBuilder.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteringServiceConfigurationBuilder.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/builders/ClusteringServiceConfigurationBuilder.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ServerSideConfigurationBuilder.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/builders/ServerSideConfigurationBuilder.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/ServerSideConfigurationBuilder.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/builders/ServerSideConfigurationBuilder.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/TimeoutsBuilder.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/builders/TimeoutsBuilder.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/config/builders/TimeoutsBuilder.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/config/builders/TimeoutsBuilder.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntity.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntity.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntity.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntity.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactory.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityService.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityService.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityService.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityService.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerCreationException.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerCreationException.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerCreationException.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerCreationException.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerNotFoundException.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerNotFoundException.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerNotFoundException.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerNotFoundException.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerValidationException.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerValidationException.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerValidationException.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/ClusterTierManagerValidationException.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/ConnectionSource.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/PerpetualCachePersistenceException.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/PerpetualCachePersistenceException.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/PerpetualCachePersistenceException.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/PerpetualCachePersistenceException.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/SimpleClusterTierManagerClientEntity.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/SimpleClusterTierManagerClientEntity.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/SimpleClusterTierManagerClientEntity.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/SimpleClusterTierManagerClientEntity.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/ClusteredResourcePoolImpl.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/ClusteredResourcePoolImpl.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/ClusteredResourcePoolImpl.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/ClusteredResourcePoolImpl.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/DedicatedClusteredResourcePoolImpl.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/DedicatedClusteredResourcePoolImpl.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/DedicatedClusteredResourcePoolImpl.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/DedicatedClusteredResourcePoolImpl.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/SharedClusteredResourcePoolImpl.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/SharedClusteredResourcePoolImpl.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/SharedClusteredResourcePoolImpl.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/SharedClusteredResourcePoolImpl.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConstants.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConstants.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConstants.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConstants.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParser.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParser.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStore.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderFactory.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderFactory.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderFactory.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderFactory.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProvider.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProviderFactory.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProviderFactory.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProviderFactory.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStoreProviderFactory.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStore.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderFactory.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderFactory.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderFactory.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderFactory.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLock.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLock.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLock.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLock.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockClient.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockClient.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockClient.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockClient.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockEntityClientService.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockEntityClientService.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockEntityClientService.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockEntityClientService.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/AbstractClientEntityFactory.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/AbstractClientEntityFactory.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/AbstractClientEntityFactory.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/AbstractClientEntityFactory.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterStateRepository.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterStateRepository.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterStateRepository.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterStateRepository.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierCreationException.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierCreationException.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierCreationException.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierCreationException.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierDestructionException.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierDestructionException.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierDestructionException.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierDestructionException.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierException.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierException.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierException.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierException.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerConfigurationException.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerConfigurationException.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerConfigurationException.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerConfigurationException.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierReleaseException.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierReleaseException.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierReleaseException.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierReleaseException.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierValidationException.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierValidationException.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierValidationException.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusterTierValidationException.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteredMapException.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteredMapException.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteredMapException.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteredMapException.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteredStateHolder.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteredStateHolder.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteredStateHolder.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteredStateHolder.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactory.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java similarity index 99% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java index 9c152b3f9d..d6d92a04f4 100644 --- a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java +++ b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ConnectionState.java @@ -45,6 +45,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.Executor; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; @@ -186,7 +187,7 @@ private void silentDestroy() { LOGGER.debug("Found a broken ClusterTierManager - trying to clean it up"); try { // Random sleep to enable racing clients to have a window to do the cleanup - Thread.sleep(new Random().nextInt(1000)); + Thread.sleep(ThreadLocalRandom.current().nextInt(1000)); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ValueCodec.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ValueCodec.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ValueCodec.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ValueCodec.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ValueCodecFactory.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ValueCodecFactory.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ValueCodecFactory.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/ValueCodecFactory.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntity.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntity.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntity.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntity.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierClientEntityService.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierUserData.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierUserData.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierUserData.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusterTierUserData.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderFactory.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredValueHolder.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredValueHolder.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredValueHolder.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredValueHolder.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxy.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/FailedReconnectStoreProxy.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/FailedReconnectStoreProxy.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/FailedReconnectStoreProxy.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/FailedReconnectStoreProxy.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/InternalClusterTierClientEntity.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectInProgressException.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectInProgressException.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectInProgressException.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectInProgressException.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxy.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxy.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxy.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxy.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxy.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxyException.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxyException.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxyException.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ServerStoreProxyException.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/SimpleClusterTierClientEntity.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxy.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManager.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManager.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManager.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockManager.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxy.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/lock/LockingServerStoreProxyImpl.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ChainResolver.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/EternalChainResolver.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/operations/EternalChainResolver.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/EternalChainResolver.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/operations/EternalChainResolver.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/operations/ExpiryChainResolver.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/service/ClientEntityFactory.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/service/ClientEntityFactory.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/service/ClientEntityFactory.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/service/ClientEntityFactory.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/service/ClusteringService.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/service/ClusteringService.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/service/ClusteringService.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/service/ClusteringService.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/service/EntityBusyException.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/service/EntityBusyException.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/service/EntityBusyException.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/service/EntityBusyException.java diff --git a/clustered/client/src/main/java/org/ehcache/clustered/client/service/EntityService.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/service/EntityService.java similarity index 100% rename from clustered/client/src/main/java/org/ehcache/clustered/client/service/EntityService.java rename to clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/service/EntityService.java diff --git a/clustered/client/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory b/clustered/ehcache-client/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory similarity index 100% rename from clustered/client/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory rename to clustered/ehcache-client/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory diff --git a/clustered/client/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser b/clustered/ehcache-client/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser similarity index 100% rename from clustered/client/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser rename to clustered/ehcache-client/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser diff --git a/clustered/client/src/main/resources/META-INF/services/org.ehcache.xml.CacheResourceConfigurationParser b/clustered/ehcache-client/src/main/resources/META-INF/services/org.ehcache.xml.CacheResourceConfigurationParser similarity index 100% rename from clustered/client/src/main/resources/META-INF/services/org.ehcache.xml.CacheResourceConfigurationParser rename to clustered/ehcache-client/src/main/resources/META-INF/services/org.ehcache.xml.CacheResourceConfigurationParser diff --git a/clustered/client/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser b/clustered/ehcache-client/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser similarity index 100% rename from clustered/client/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser rename to clustered/ehcache-client/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser diff --git a/clustered/client/src/main/resources/META-INF/services/org.terracotta.entity.EntityClientService b/clustered/ehcache-client/src/main/resources/META-INF/services/org.terracotta.entity.EntityClientService similarity index 100% rename from clustered/client/src/main/resources/META-INF/services/org.terracotta.entity.EntityClientService rename to clustered/ehcache-client/src/main/resources/META-INF/services/org.terracotta.entity.EntityClientService diff --git a/clustered/client/src/main/resources/ehcache-clustered-ext.xsd b/clustered/ehcache-client/src/main/resources/ehcache-clustered-ext.xsd similarity index 100% rename from clustered/client/src/main/resources/ehcache-clustered-ext.xsd rename to clustered/ehcache-client/src/main/resources/ehcache-clustered-ext.xsd diff --git a/clustered/client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/ClusteredResourcePoolUpdationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheExpiryTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/BasicClusteredCacheTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/CacheManagerDestroyTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/ClusteredCacheDestroyTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/ClusteredCacheExpirationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/ClusteredConcurrencyTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/ClusteredEventsTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/EntityServiceTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/NonClusteredCacheTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/SimpleClusteredCacheByXmlTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/SimpleClusteredCacheByXmlTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/SimpleClusteredCacheByXmlTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/SimpleClusteredCacheByXmlTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/TerracottaUriXmlTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/TerracottaUriXmlTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/TerracottaUriXmlTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/TerracottaUriXmlTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/TestTimeSource.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/TestTimeSource.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/TestTimeSource.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/TestTimeSource.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/UnSupportedCombinationsWithClusteredCacheTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/XmlConsistencyTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/XmlConsistencyTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/XmlConsistencyTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/XmlConsistencyTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/XmlUnknownCacheTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/XmlUnknownCacheTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/XmlUnknownCacheTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/XmlUnknownCacheTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredConfigurationDerivationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/config/ClusteredConfigurationDerivationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredConfigurationDerivationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/config/ClusteredConfigurationDerivationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredStoreConfigurationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/config/ClusteredStoreConfigurationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteredStoreConfigurationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/config/ClusteredStoreConfigurationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/config/ClusteringServiceConfigurationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/config/builders/ClusteredResourcePoolBuilderTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/config/builders/ClusteredResourcePoolBuilderTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/config/builders/ClusteredResourcePoolBuilderTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/config/builders/ClusteredResourcePoolBuilderTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/config/builders/TimeoutsBuilderTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/config/builders/TimeoutsBuilderTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/config/builders/TimeoutsBuilderTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/config/builders/TimeoutsBuilderTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/ClusterTierManagerClientEntityFactoryTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/MockConnectionService.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/MockConnectionService.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/MockConnectionService.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/MockConnectionService.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/UnitTestConnectionService.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/ClusteredResourcePoolImplTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/config/ClusteredResourcePoolImplTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/ClusteredResourcePoolImplTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/config/ClusteredResourcePoolImplTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/DedicatedClusteredResourcePoolImplTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/config/DedicatedClusteredResourcePoolImplTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/DedicatedClusteredResourcePoolImplTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/config/DedicatedClusteredResourcePoolImplTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/SharedClusteredResourcePoolImplTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/config/SharedClusteredResourcePoolImplTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/SharedClusteredResourcePoolImplTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/config/SharedClusteredResourcePoolImplTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredCacheConfigurationParserIT.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParserTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheManagerServiceConfigurationParserTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/config/xml/ClusteringCacheServiceConfigurationParserTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreProviderTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/ClusteredLoaderWriterStoreTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindStoreProviderTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehindTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockClientTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockClientTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockClientTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockClientTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/lock/VoltronReadWriteLockTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterStateRepositoryReplicationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/ClusterTierManagerClientEntityExceptionTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteringServiceFactoryTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionClosedTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/ConnectionStateTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/ReconnectTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/TestServiceProvider.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/TestServiceProvider.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/service/TestServiceProvider.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/TestServiceProvider.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/AbstractServerStoreProxyTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ChainBuilderTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ChainBuilderTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ChainBuilderTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ChainBuilderTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreEventsTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreProviderTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxyTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/EventualServerStoreProxyTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/MultiThreadedStrongServerStoreProxyTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxyTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxyTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxyTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ReconnectingServerStoreProxyTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/StrongServerStoreProxyTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockManagerTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/lock/LockRetentionDuringFailoverTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/replication/ActivePassiveClientIdTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/client/replication/ReplicationUtil.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/replication/ReplicationUtil.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/client/replication/ReplicationUtil.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/replication/ReplicationUtil.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/AbstractChainResolverTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/BaseKeyValueOperationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/BaseKeyValueOperationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/BaseKeyValueOperationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/BaseKeyValueOperationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ConditionalRemoveOperationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ConditionalRemoveOperationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ConditionalRemoveOperationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ConditionalRemoveOperationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/EternalChainResolverTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/EternalChainResolverTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/EternalChainResolverTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/EternalChainResolverTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ExpiryChainResolverTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/LazyValueHolderTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/LazyValueHolderTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/LazyValueHolderTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/LazyValueHolderTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutIfAbsentOperationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutIfAbsentOperationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutIfAbsentOperationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutIfAbsentOperationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutOperationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutOperationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutOperationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutOperationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutWithWriterOperationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutWithWriterOperationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutWithWriterOperationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/PutWithWriterOperationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/RemoveOperationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/RemoveOperationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/RemoveOperationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/RemoveOperationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ReplaceOperationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ReplaceOperationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ReplaceOperationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/ReplaceOperationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperationTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperationTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperationTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperationTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/loaderWriter/BasicClusteredLoaderWriterTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/TestCacheLoaderWriter.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/loaderWriter/TestCacheLoaderWriter.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/TestCacheLoaderWriter.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/loaderWriter/TestCacheLoaderWriter.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/BasicClusteredWriteBehindPassthroughTest.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/RecordingLoaderWriter.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/RecordingLoaderWriter.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/RecordingLoaderWriter.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/loaderWriter/writebehind/RecordingLoaderWriter.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/server/ObservableEhcacheServerEntityService.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/server/ObservableEhcacheServerEntityService.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/server/ObservableEhcacheServerEntityService.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/server/ObservableEhcacheServerEntityService.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/server/package-info.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/server/package-info.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/server/package-info.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/server/package-info.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/server/store/ObservableClusterTierServerEntityService.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/server/store/ObservableClusterTierServerEntityService.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/server/store/ObservableClusterTierServerEntityService.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/server/store/ObservableClusterTierServerEntityService.java diff --git a/clustered/client/src/test/java/org/ehcache/clustered/util/StatisticsTestUtils.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/util/StatisticsTestUtils.java similarity index 100% rename from clustered/client/src/test/java/org/ehcache/clustered/util/StatisticsTestUtils.java rename to clustered/ehcache-client/src/test/java/org/ehcache/clustered/util/StatisticsTestUtils.java diff --git a/clustered/client/src/test/resources/META-INF/services/org.terracotta.connection.ConnectionService b/clustered/ehcache-client/src/test/resources/META-INF/services/org.terracotta.connection.ConnectionService similarity index 100% rename from clustered/client/src/test/resources/META-INF/services/org.terracotta.connection.ConnectionService rename to clustered/ehcache-client/src/test/resources/META-INF/services/org.terracotta.connection.ConnectionService diff --git a/clustered/client/src/test/resources/configs/cluster-ha.xml b/clustered/ehcache-client/src/test/resources/configs/cluster-ha.xml similarity index 100% rename from clustered/client/src/test/resources/configs/cluster-ha.xml rename to clustered/ehcache-client/src/test/resources/configs/cluster-ha.xml diff --git a/clustered/client/src/test/resources/configs/cluster-invalid-uri.xml b/clustered/ehcache-client/src/test/resources/configs/cluster-invalid-uri.xml similarity index 100% rename from clustered/client/src/test/resources/configs/cluster-invalid-uri.xml rename to clustered/ehcache-client/src/test/resources/configs/cluster-invalid-uri.xml diff --git a/clustered/client/src/test/resources/configs/clustered-cache.xml b/clustered/ehcache-client/src/test/resources/configs/clustered-cache.xml similarity index 100% rename from clustered/client/src/test/resources/configs/clustered-cache.xml rename to clustered/ehcache-client/src/test/resources/configs/clustered-cache.xml diff --git a/clustered/client/src/test/resources/configs/consistency.xml b/clustered/ehcache-client/src/test/resources/configs/consistency.xml similarity index 86% rename from clustered/client/src/test/resources/configs/consistency.xml rename to clustered/ehcache-client/src/test/resources/configs/consistency.xml index a32851c490..4f69a9afbb 100644 --- a/clustered/client/src/test/resources/configs/consistency.xml +++ b/clustered/ehcache-client/src/test/resources/configs/consistency.xml @@ -16,12 +16,8 @@ --> + xmlns:tc='http://www.ehcache.org/v3/clustered'> diff --git a/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml b/clustered/ehcache-client/src/test/resources/configs/docs/ehcache-clustered.xml similarity index 82% rename from clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml rename to clustered/ehcache-client/src/test/resources/configs/docs/ehcache-clustered.xml index fc34ea80f5..84f263a0a7 100644 --- a/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml +++ b/clustered/ehcache-client/src/test/resources/configs/docs/ehcache-clustered.xml @@ -15,12 +15,8 @@ --> + xmlns:tc='http://www.ehcache.org/v3/clustered'> diff --git a/clustered/client/src/test/resources/configs/offheap-resource.xml b/clustered/ehcache-client/src/test/resources/configs/offheap-resource.xml similarity index 94% rename from clustered/client/src/test/resources/configs/offheap-resource.xml rename to clustered/ehcache-client/src/test/resources/configs/offheap-resource.xml index 5018f2226c..b805e5dca2 100644 --- a/clustered/client/src/test/resources/configs/offheap-resource.xml +++ b/clustered/ehcache-client/src/test/resources/configs/offheap-resource.xml @@ -17,7 +17,6 @@ --> 64 diff --git a/clustered/client/src/test/resources/configs/simple-cluster.xml b/clustered/ehcache-client/src/test/resources/configs/simple-cluster.xml similarity index 100% rename from clustered/client/src/test/resources/configs/simple-cluster.xml rename to clustered/ehcache-client/src/test/resources/configs/simple-cluster.xml diff --git a/clustered/client/src/test/resources/configs/unknown-cluster-cache-invalid-attribute.xml b/clustered/ehcache-client/src/test/resources/configs/unknown-cluster-cache-invalid-attribute.xml similarity index 94% rename from clustered/client/src/test/resources/configs/unknown-cluster-cache-invalid-attribute.xml rename to clustered/ehcache-client/src/test/resources/configs/unknown-cluster-cache-invalid-attribute.xml index 80392dddd8..5b39fa2d8a 100644 --- a/clustered/client/src/test/resources/configs/unknown-cluster-cache-invalid-attribute.xml +++ b/clustered/ehcache-client/src/test/resources/configs/unknown-cluster-cache-invalid-attribute.xml @@ -16,7 +16,6 @@ --> diff --git a/clustered/client/src/test/resources/configs/unknown-cluster-cache-invalid-element.xml b/clustered/ehcache-client/src/test/resources/configs/unknown-cluster-cache-invalid-element.xml similarity index 94% rename from clustered/client/src/test/resources/configs/unknown-cluster-cache-invalid-element.xml rename to clustered/ehcache-client/src/test/resources/configs/unknown-cluster-cache-invalid-element.xml index f200afde6b..642b8a3d1f 100644 --- a/clustered/client/src/test/resources/configs/unknown-cluster-cache-invalid-element.xml +++ b/clustered/ehcache-client/src/test/resources/configs/unknown-cluster-cache-invalid-element.xml @@ -16,7 +16,6 @@ --> diff --git a/clustered/client/src/test/resources/configs/unknown-cluster-cache.xml b/clustered/ehcache-client/src/test/resources/configs/unknown-cluster-cache.xml similarity index 94% rename from clustered/client/src/test/resources/configs/unknown-cluster-cache.xml rename to clustered/ehcache-client/src/test/resources/configs/unknown-cluster-cache.xml index 80f4f54963..0ee2f72f42 100644 --- a/clustered/client/src/test/resources/configs/unknown-cluster-cache.xml +++ b/clustered/ehcache-client/src/test/resources/configs/unknown-cluster-cache.xml @@ -16,7 +16,6 @@ --> diff --git a/clustered/clustered-dist/build.gradle b/clustered/ehcache-clustered/build.gradle similarity index 62% rename from clustered/clustered-dist/build.gradle rename to clustered/ehcache-clustered/build.gradle index 7ae071ad64..92ddb8616e 100644 --- a/clustered/clustered-dist/build.gradle +++ b/clustered/ehcache-clustered/build.gradle @@ -14,6 +14,8 @@ * limitations under the License. */ +import aQute.bnd.osgi.Constants + /** * NOTE: this directory had to be named clustered-dist instead of just dist * because gradle creatively substitutes :dist for :clustered:dist or vice versa @@ -22,23 +24,42 @@ */ plugins { + id 'org.ehcache.build.package' id 'distribution' - id 'org.ehcache.build.distribute' } -group = 'org.ehcache' -archivesBaseName = 'ehcache-clustered' + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache 3 Clustered Module' + description = 'Ehcache 3 Clustered: Defines the client jar and the kit containing the Terracotta server' + } +} ext { docsFolder = "$buildDir/docs/asciidoc" } -dependencies { - compileOnly(project(':clustered:client')) { - exclude group: 'org.ehcache.modules', module: 'api' - exclude group: 'org.terracotta', module: 'statistics' +configurations { + [apiElements, runtimeElements].each { + it.outgoing { + variants.removeIf { it.name == 'classes' || it.name == 'resources' } + capability "org.ehcache:ehcache-clustered:$version" + capability "org.ehcache.modules.clustered:ehcache-client:$version" + } + } + + contents { + exclude group:'org.ehcache.modules' + exclude group:'org.slf4j' } - // Needed because declared as provided in the different projects - compileOnly "org.terracotta:runnel:$parent.terracottaPlatformVersion" +} + +dependencies { + contents project(':clustered:ehcache-client') + contents "org.terracotta.internal:client-runtime:$terracottaCoreVersion" + + implementation "org.slf4j:slf4j-api:$parent.slf4jVersion" + implementation project(':ehcache') } def kitProvides = { Configuration c -> @@ -64,38 +85,34 @@ configurations { } dependencies { - compileOnly "org.terracotta.internal:client-runtime:$terracottaCoreVersion" - compileOnly "org.terracotta:lease-api:$terracottaPlatformVersion" - compileOnly "org.terracotta.dynamic-config.entities:dynamic-config-topology-entity-client:$terracottaPlatformVersion" - - serverApis project(':clustered:server:service-api') - serverLibs project(':clustered:server:entity') - serverLibs project(':clustered:server:service') + serverApis project(':clustered:server:ehcache-service-api') + serverLibs project(':clustered:server:ehcache-entity') + serverLibs project(':clustered:server:ehcache-service') kit "org.terracotta:platform-kit:$terracottaPlatformVersion@tar.gz" - - shadowCompile "org.slf4j:slf4j-api:$parent.slf4jVersion" - pomOnlyCompile "org.ehcache:ehcache:$parent.baseVersion" } -task copyDocs(type: Copy) { +task copyDocs(type: Sync) { dependsOn asciidocZip from zipTree(asciidocZip.archivePath) into docsFolder } -jar { - bnd ( - 'Bundle-SymbolicName': 'org.ehcache.clustered', - 'Export-Package': '!com.tc.*, !com.terracotta.*, !org.terracotta.*, !org.ehcache.*.internal.*, !sun.misc, ' + - 'org.ehcache.clustered.client.*, org.ehcache.clustered.common.*', - 'Import-Package': '!sun.misc.*, org.ehcache.xml.*;resolution:=optional, jdk.jfr.*;resolution:=optional, !com.fasterxml.jackson.*, !org.terracotta.json, *' - ) +javadoc { + exclude '**/core/**', '**/impl/**', '**/xml/**', '**/jsr107/**', '**/transactions/**', '**/management/**', '**/tck/**' +} + +tasks.named('jar') { + osgi { + instruction Constants.BUNDLE_SYMBOLICNAME, 'org.ehcache.clustered' + instruction Constants.EXPORT_PACKAGE, '!com.tc.*, !com.terracotta.*, !org.terracotta.*, !org.ehcache.*.internal.*, !sun.misc, org.ehcache.clustered.client.*, org.ehcache.clustered.common.*' + instruction Constants.IMPORT_PACKAGE, '!sun.misc.*, org.ehcache.xml.*;resolution:=optional, jdk.jfr.*;resolution:=optional, !com.fasterxml.jackson.*, !org.terracotta.json, javax.xml.bind*;version="[2.2,3)", *' + } } distributions { main { - baseName = archivesBaseName + distributionBaseName = archivesBaseName contents { filesMatching('**/*.jar') { // We can safely exclude JAR duplicates as our dependency strategy is fail on conflict @@ -103,7 +120,9 @@ distributions { } //tc kit into ('') { - from configurations.kit.files.collect { tarTree(it) } + from configurations.kit.elements.map { + files -> files.collect { tarTree(it) } + } eachFile { f -> // remove top level directory from the kit f.path = f.path.replace("platform-kit-$terracottaPlatformVersion/", "") @@ -122,7 +141,7 @@ distributions { } into ('client/ehcache') { from jar - from project(':dist').jar.archivePath.getPath() + from project(':ehcache').jar exclude { f -> !f.path.contains('ehcache') // do not add any transitives in this directory } @@ -131,11 +150,11 @@ distributions { from "$docsFolder/user" } into ('client/ehcache/javadoc') { - from javadocJar.archivePath.getPath() - from project(':dist').javadocJar.archivePath.getPath() + from tasks.named('javadocJar') + from project(':ehcache').javadocJar } into ('client/lib') { - from configurations.shadowCompile + from configurations.runtimeClasspath } into ('') { from 'src/assemble' @@ -153,4 +172,9 @@ distZip { archiveClassifier = 'kit' } -[distTar, distZip, installDist]*.dependsOn copyDocs, javadocJar, project(':dist').jar, project(':dist').javadocJar +publishing.publications.withType(MavenPublication) { + artifact distZip + artifact distTar +} + +[distTar, distZip, installDist]*.dependsOn copyDocs, javadocJar, project(':ehcache').jar, project(':ehcache').javadocJar diff --git a/clustered/clustered-dist/src/assemble/README.txt b/clustered/ehcache-clustered/src/assemble/README.txt similarity index 100% rename from clustered/clustered-dist/src/assemble/README.txt rename to clustered/ehcache-clustered/src/assemble/README.txt diff --git a/clustered/clustered-dist/src/assemble/legal/APACHE_PUBLIC_LICENSE.txt b/clustered/ehcache-clustered/src/assemble/legal/APACHE_PUBLIC_LICENSE.txt similarity index 100% rename from clustered/clustered-dist/src/assemble/legal/APACHE_PUBLIC_LICENSE.txt rename to clustered/ehcache-clustered/src/assemble/legal/APACHE_PUBLIC_LICENSE.txt diff --git a/clustered/clustered-dist/src/assemble/legal/LICENSE b/clustered/ehcache-clustered/src/assemble/legal/LICENSE similarity index 100% rename from clustered/clustered-dist/src/assemble/legal/LICENSE rename to clustered/ehcache-clustered/src/assemble/legal/LICENSE diff --git a/clustered/clustered-dist/src/assemble/server/conf/cluster.cfg b/clustered/ehcache-clustered/src/assemble/server/conf/cluster.cfg similarity index 100% rename from clustered/clustered-dist/src/assemble/server/conf/cluster.cfg rename to clustered/ehcache-clustered/src/assemble/server/conf/cluster.cfg diff --git a/clustered/common-api/build.gradle b/clustered/ehcache-common-api/build.gradle similarity index 75% rename from clustered/common-api/build.gradle rename to clustered/ehcache-common-api/build.gradle index 29537eb300..e748bfe3be 100644 --- a/clustered/common-api/build.gradle +++ b/clustered/ehcache-common-api/build.gradle @@ -15,7 +15,14 @@ */ plugins { - id 'org.ehcache.build.deploy' + id 'org.ehcache.build.clustered-module' +} + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache 3 Common Clustering API module' + description = 'The Common Clustering API module of Ehcache 3' + } } dependencies { diff --git a/clustered/common-api/config/checkstyle-suppressions.xml b/clustered/ehcache-common-api/config/checkstyle-suppressions.xml similarity index 100% rename from clustered/common-api/config/checkstyle-suppressions.xml rename to clustered/ehcache-common-api/config/checkstyle-suppressions.xml diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/Consistency.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/Consistency.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/Consistency.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/Consistency.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/PoolAllocation.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/PoolAllocation.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/PoolAllocation.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/PoolAllocation.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/ServerSideConfiguration.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/ServerSideConfiguration.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/ServerSideConfiguration.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/ServerSideConfiguration.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/ClusterTierManagerConfiguration.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/ClusterTierManagerConfiguration.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/ClusterTierManagerConfiguration.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/ClusterTierManagerConfiguration.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/ServerStoreConfiguration.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/ServerStoreConfiguration.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/ServerStoreConfiguration.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/ServerStoreConfiguration.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/ClusterException.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/ClusterException.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/ClusterException.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/ClusterException.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/DestroyInProgressException.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/DestroyInProgressException.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/DestroyInProgressException.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/DestroyInProgressException.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationException.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationException.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationException.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationException.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreException.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreException.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreException.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreException.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/LifecycleException.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/LifecycleException.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/LifecycleException.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/exceptions/LifecycleException.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityMessage.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityMessage.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityMessage.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityMessage.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheEntityResponse.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheMessageType.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheOperationMessage.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheOperationMessage.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheOperationMessage.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheOperationMessage.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheResponseType.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpMessage.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpMessage.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpMessage.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpMessage.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/Chain.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/Chain.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/Chain.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/Chain.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/Element.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/Element.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/Element.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/Element.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/ServerStore.java diff --git a/clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java similarity index 100% rename from clustered/common-api/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java rename to clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java diff --git a/clustered/common-api/src/test/java/org/ehcache/clustered/common/ServerSideConfigurationTest.java b/clustered/ehcache-common-api/src/test/java/org/ehcache/clustered/common/ServerSideConfigurationTest.java similarity index 100% rename from clustered/common-api/src/test/java/org/ehcache/clustered/common/ServerSideConfigurationTest.java rename to clustered/ehcache-common-api/src/test/java/org/ehcache/clustered/common/ServerSideConfigurationTest.java diff --git a/clustered/common/build.gradle b/clustered/ehcache-common/build.gradle similarity index 60% rename from clustered/common/build.gradle rename to clustered/ehcache-common/build.gradle index 5675a157e6..0a5f41937d 100644 --- a/clustered/common/build.gradle +++ b/clustered/ehcache-common/build.gradle @@ -15,15 +15,22 @@ */ plugins { - id 'org.ehcache.build.deploy' + id 'org.ehcache.build.clustered-module' +} + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache 3 Common Clustering module' + description = 'The Common Clustering module of Ehcache 3' + } } dependencies { - api project(':clustered:common-api') + api project(':ehcache-api') + api project(':clustered:ehcache-common-api') - providedImplementation project(':api') - providedImplementation "org.terracotta:entity-common-api:$terracottaApisVersion" - providedImplementation "org.terracotta:runnel:$terracottaPlatformVersion" + implementation "org.terracotta:entity-common-api:$terracottaApisVersion" + implementation "org.terracotta:runnel:$terracottaPlatformVersion" testImplementation project(':clustered:test-utils') } diff --git a/clustered/common/config/checkstyle-suppressions.xml b/clustered/ehcache-common/config/checkstyle-suppressions.xml similarity index 100% rename from clustered/common/config/checkstyle-suppressions.xml rename to clustered/ehcache-common/config/checkstyle-suppressions.xml diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/EhcacheEntityVersion.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/EhcacheEntityVersion.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/EhcacheEntityVersion.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/EhcacheEntityVersion.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/IllegalMessageException.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/exceptions/IllegalMessageException.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/IllegalMessageException.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/exceptions/IllegalMessageException.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidOperationException.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidOperationException.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidOperationException.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidOperationException.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerStoreConfigurationException.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerStoreConfigurationException.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerStoreConfigurationException.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerStoreConfigurationException.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/UnknownClusterException.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/exceptions/UnknownClusterException.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/exceptions/UnknownClusterException.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/exceptions/UnknownClusterException.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/lock/LockMessaging.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/lock/LockMessaging.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/lock/LockMessaging.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/lock/LockMessaging.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/BaseCodec.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/BaseCodec.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/BaseCodec.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/BaseCodec.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ChainCodec.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ClusterTierReconnectMessage.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ClusterTierReconnectMessage.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ClusterTierReconnectMessage.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ClusterTierReconnectMessage.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/CodecUtil.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/CodecUtil.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/CodecUtil.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/CodecUtil.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodec.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodec.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodec.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodec.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ConcurrentEntityMessage.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ConcurrentEntityMessage.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ConcurrentEntityMessage.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ConcurrentEntityMessage.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ConfigCodec.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ConfigCodec.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ConfigCodec.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ConfigCodec.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheCodec.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheCodec.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheCodec.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/EhcacheCodec.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EntityConfigurationCodec.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/EntityConfigurationCodec.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/EntityConfigurationCodec.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/EntityConfigurationCodec.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ExceptionCodec.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ExceptionCodec.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ExceptionCodec.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ExceptionCodec.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodec.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodec.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodec.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodec.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageFactory.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageFactory.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageFactory.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageFactory.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/LifecycleMessage.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/LifecycleMessage.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/LifecycleMessage.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/LifecycleMessage.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/MessageCodecUtils.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/MessageCodecUtils.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/MessageCodecUtils.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/MessageCodecUtils.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodec.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodec.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodec.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodec.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ResponseCodec.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodec.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessage.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessage.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessage.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessage.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryMessageFactory.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryMessageFactory.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryMessageFactory.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryMessageFactory.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpCodec.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpCodec.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpCodec.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/messages/StateRepositoryOpCodec.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/ClusterTierEntityConfiguration.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/ClusterTierEntityConfiguration.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/ClusterTierEntityConfiguration.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/ClusterTierEntityConfiguration.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/CustomLoaderBasedObjectInputStream.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/CustomLoaderBasedObjectInputStream.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/CustomLoaderBasedObjectInputStream.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/CustomLoaderBasedObjectInputStream.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/FilteredObjectInputStream.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/FilteredObjectInputStream.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/FilteredObjectInputStream.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/FilteredObjectInputStream.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/SequencedElement.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/SequencedElement.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/SequencedElement.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/SequencedElement.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/Util.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/Util.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/Util.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/Util.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/BaseKeyValueOperation.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/BaseKeyValueOperation.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/BaseKeyValueOperation.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/BaseKeyValueOperation.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ConditionalRemoveOperation.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ConditionalRemoveOperation.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ConditionalRemoveOperation.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ConditionalRemoveOperation.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperation.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperation.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperation.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ConditionalReplaceOperation.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/LazyValueHolder.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/LazyValueHolder.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/LazyValueHolder.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/LazyValueHolder.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/Operation.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/Operation.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/Operation.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/Operation.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/OperationCode.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/OperationCode.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/OperationCode.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/OperationCode.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutIfAbsentOperation.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutIfAbsentOperation.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutIfAbsentOperation.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutIfAbsentOperation.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutOperation.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutOperation.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutOperation.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutOperation.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutWithWriterOperation.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutWithWriterOperation.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutWithWriterOperation.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/PutWithWriterOperation.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/RemoveOperation.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/RemoveOperation.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/RemoveOperation.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/RemoveOperation.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ReplaceOperation.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ReplaceOperation.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ReplaceOperation.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/ReplaceOperation.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/Result.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/Result.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/Result.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/Result.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperation.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperation.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperation.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/TimestampOperation.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/codecs/CodecException.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/codecs/CodecException.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/codecs/CodecException.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/codecs/CodecException.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/codecs/OperationsCodec.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/codecs/OperationsCodec.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/operations/codecs/OperationsCodec.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/store/operations/codecs/OperationsCodec.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/util/ByteBufferInputStream.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/util/ByteBufferInputStream.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/util/ByteBufferInputStream.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/util/ByteBufferInputStream.java diff --git a/clustered/common/src/main/java/org/ehcache/clustered/common/internal/util/ChainBuilder.java b/clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/util/ChainBuilder.java similarity index 100% rename from clustered/common/src/main/java/org/ehcache/clustered/common/internal/util/ChainBuilder.java rename to clustered/ehcache-common/src/main/java/org/ehcache/clustered/common/internal/util/ChainBuilder.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/operations/OperationCodeTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/Store/operations/OperationCodeTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/Store/operations/OperationCodeTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/Store/operations/OperationCodeTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/BaseClusteredEhcacheExceptionTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/exceptions/BaseClusteredEhcacheExceptionTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/BaseClusteredEhcacheExceptionTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/exceptions/BaseClusteredEhcacheExceptionTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/IllegalMessageExceptionTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/exceptions/IllegalMessageExceptionTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/IllegalMessageExceptionTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/exceptions/IllegalMessageExceptionTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidOperationExceptionTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidOperationExceptionTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidOperationExceptionTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidOperationExceptionTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationExceptionTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationExceptionTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationExceptionTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerSideConfigurationExceptionTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerStoreConfigurationExceptionTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerStoreConfigurationExceptionTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerStoreConfigurationExceptionTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidServerStoreConfigurationExceptionTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreExceptionTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreExceptionTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreExceptionTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/exceptions/InvalidStoreExceptionTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/LifecycleExceptionTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/exceptions/LifecycleExceptionTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/exceptions/LifecycleExceptionTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/exceptions/LifecycleExceptionTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodecTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodecTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodecTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/CommonConfigCodecTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/EhcacheCodecTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/EhcacheCodecTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/EhcacheCodecTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/EhcacheCodecTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodecTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodecTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodecTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/LifeCycleMessageCodecTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodecTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodecTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodecTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ReconnectMessageCodecTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpCodecTest.java diff --git a/clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessageTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessageTest.java similarity index 100% rename from clustered/common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessageTest.java rename to clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ServerStoreOpMessageTest.java diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index 055dd129de..56aab2750d 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -14,16 +14,20 @@ * limitations under the License. */ +plugins { + id 'org.ehcache.build.conventions.java' +} + configurations { serverLibs } dependencies { - testImplementation project(':clustered:client') - testImplementation project(':clustered:common') - testImplementation project(':impl') - testImplementation project(':xml') - testImplementation project(':107') + testImplementation project(':clustered:ehcache-client') + testImplementation project(':clustered:ehcache-common') + testImplementation project(':ehcache-impl') + testImplementation project(':ehcache-xml') + testImplementation project(':ehcache-107') testImplementation "org.terracotta.internal:client-runtime:$terracottaCoreVersion" testImplementation "org.terracotta:runnel:$terracottaPlatformVersion" testImplementation "org.terracotta:lease-api:$terracottaPlatformVersion" @@ -34,28 +38,24 @@ dependencies { exclude group:'junit', module:'junit' } - testImplementation project(':management') + testImplementation project(':ehcache-management') testImplementation "org.terracotta.management:nms-entity-client:$terracottaPlatformVersion" testImplementation "org.terracotta.management:nms-agent-entity-client:$terracottaPlatformVersion" testImplementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" - - testRuntimeOnly "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" - testRuntimeOnly project(':clustered:clustered-dist') - - testImplementation (group:'org.terracotta', name:'galvan-platform-support', version: terracottaPlatformVersion) - testImplementation group: 'javax.cache', name: 'cache-api', version: jcacheVersion + testImplementation "org.terracotta:galvan-platform-support:$terracottaPlatformVersion" + testImplementation "javax.cache:cache-api:$jcacheVersion" } -task unzipKit(type: Copy) { - dependsOn project(':clustered:clustered-dist').distZip - from zipTree(project(':clustered:clustered-dist').distZip.archivePath) +task unzipKit(type: Sync) { + dependsOn project(':clustered:ehcache-clustered').distZip + from zipTree(project(':clustered:ehcache-clustered').distZip.archivePath) into 'build/ehcache-kit' } -task copyServerLibs(type: Copy) { +task copyServerLibs(type: Sync) { dependsOn unzipKit from project.configurations.serverLibs - into "$unzipKit.destinationDir/${project(':clustered:clustered-dist').archivesBaseName}-$project.version-kit/server/plugins/lib" + into "$unzipKit.destinationDir/${project(':clustered:ehcache-clustered').archivesBaseName}-$project.version-kit/server/plugins/lib" } test { @@ -64,7 +64,7 @@ test { dependsOn copyServerLibs environment 'JAVA_HOME', testJava.javaHome //If this directory does not exist, tests will fail with a cryptic assert failure - systemProperty 'kitInstallationPath', "$unzipKit.destinationDir/${project(':clustered:clustered-dist').archivesBaseName}-$project.version-kit" + systemProperty 'kitInstallationPath', "$unzipKit.destinationDir/${project(':clustered:ehcache-clustered').archivesBaseName}-$project.version-kit" // Uncomment to include client logging in console output // testLogging.showStandardStreams = true } diff --git a/clustered/integration-test/gradle.properties b/clustered/integration-test/gradle.properties deleted file mode 100644 index bdb75fe1c9..0000000000 --- a/clustered/integration-test/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache 3 Clustered Integration Test module -subPomDesc = The Clustering Integration Test module of Ehcache 3 diff --git a/clustered/integration-test/src/test/resources/configs/offheap-resource.xml b/clustered/integration-test/src/test/resources/configs/offheap-resource.xml index 2b2ab18a3c..fab9f0273e 100644 --- a/clustered/integration-test/src/test/resources/configs/offheap-resource.xml +++ b/clustered/integration-test/src/test/resources/configs/offheap-resource.xml @@ -17,7 +17,6 @@ --> 64 diff --git a/clustered/ops-tool/build.gradle b/clustered/ops-tool/build.gradle index 7499269244..0963f3352c 100644 --- a/clustered/ops-tool/build.gradle +++ b/clustered/ops-tool/build.gradle @@ -14,6 +14,10 @@ * limitations under the License. */ +plugins { + id 'org.ehcache.build.conventions.java-library' +} + dependencies { implementation 'com.beust:jcommander:1.47' } diff --git a/clustered/ops-tool/gradle.properties b/clustered/ops-tool/gradle.properties deleted file mode 100644 index 86aa0f75bb..0000000000 --- a/clustered/ops-tool/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache 3 Clustered Ops Tooling -subPomDesc = Operations Tools for Clustered Ehcache 3 diff --git a/clustered/osgi-test/build.gradle b/clustered/osgi-test/build.gradle index e8cc65a819..57909678f5 100644 --- a/clustered/osgi-test/build.gradle +++ b/clustered/osgi-test/build.gradle @@ -14,20 +14,25 @@ * limitations under the License. */ +plugins { + id 'org.ehcache.build.conventions.java' +} + configurations { + modularOsgiModule osgiModule lowerBoundOsgiModule.extendsFrom osgiModule testCompileOnly.extendsFrom osgiModule } dependencies { - osgiModule project(':api') - osgiModule project(':core') - osgiModule project(':impl') - osgiModule project(':xml') + modularOsgiModule project(':ehcache-api') + modularOsgiModule project(':ehcache-core') + modularOsgiModule project(':ehcache-impl') + modularOsgiModule project(':ehcache-xml') - osgiModule project(':dist') - osgiModule project(':clustered:clustered-dist') + osgiModule project(':ehcache') + osgiModule project(':clustered:ehcache-clustered') osgiModule "javax.cache:cache-api:$parent.jcacheVersion" osgiModule "org.slf4j:slf4j-simple:$parent.slf4jVersion" osgiModule "org.terracotta:terracotta-utilities-test-tools:$terracottaUtilitiesVersion" @@ -36,10 +41,6 @@ dependencies { osgiModule 'com.sun.activation:javax.activation:1.2.0' osgiModule 'org.glassfish.hk2:osgi-resource-locator:1.0.2' - //IDEs cannot handle the :dist or :clustered:clustered-dist dependencies - testCompileOnly project(':clustered:client') - testCompileOnly project(':clustered:common') - testImplementation project(':osgi-test') testImplementation 'org.osgi:osgi.core:6.0.0' } @@ -58,6 +59,9 @@ configurations.all { .because('https://ops4j1.jira.com/browse/PAXURL-341') .with(module('org.ops4j.pax.url:pax-url-link:2.6.1')) + substitute(module('biz.aQute.bnd:bndlib:2.4.0')) + .because('Java 9 Stuff') + .with(module('biz.aQute.bnd:biz.aQute.bndlib:5.2.0')) substitute(module('junit:junit:4.12')) .because('CVE-2020-15250') .with(module('junit:junit:4.13.1')) @@ -73,21 +77,21 @@ sourceSets { } } -task unzipKit(type: Copy) { - dependsOn project(':clustered:clustered-dist').distZip - from zipTree(project(':clustered:clustered-dist').distZip.archivePath) +task unzipKit(type: Sync) { + dependsOn project(':clustered:ehcache-clustered').distZip + from zipTree(project(':clustered:ehcache-clustered').distZip.archivePath) into 'build/ehcache-kit' } tasks.withType(Test) { dependsOn unzipKit - systemProperty 'kitInstallationPath', "$unzipKit.destinationDir/${project(':clustered:clustered-dist').archivesBaseName}-$project.version-kit" + systemProperty 'kitInstallationPath', "$unzipKit.destinationDir/${project(':clustered:ehcache-clustered').archivesBaseName}-$project.version-kit" } test { - dependsOn configurations.osgiModule + dependsOn configurations.osgiModule, configurations.modularOsgiModule doFirst { - configurations.osgiModule.resolvedConfiguration.resolvedArtifacts.forEach({ + [configurations.modularOsgiModule, configurations.osgiModule]*.resolvedConfiguration*.resolvedArtifacts*.forEach({ systemProperty "$it.moduleVersion.id.module:osgi-path", it.file }) } @@ -106,9 +110,9 @@ dependencies { tasks.register('lowerBoundTest', Test) { group = JavaBasePlugin.VERIFICATION_GROUP - dependsOn configurations.lowerBoundOsgiModule + dependsOn configurations.lowerBoundOsgiModule, configurations.modularOsgiModule doFirst { - configurations.lowerBoundOsgiModule.resolvedConfiguration.resolvedArtifacts.forEach({ + [configurations.modularOsgiModule, configurations.lowerBoundOsgiModule]*.resolvedConfiguration*.resolvedArtifacts*.forEach({ systemProperty "$it.moduleVersion.id.module:osgi-path", it.file }) } diff --git a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java index 0fba7b725d..af954049df 100644 --- a/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java +++ b/clustered/osgi-test/src/test/java/org/ehcache/osgi/ClusteredOsgiTest.java @@ -84,11 +84,11 @@ public class ClusteredOsgiTest { @Configuration public Option[] individualModules() { return options( - gradleBundle("org.ehcache.modules:api"), - gradleBundle("org.ehcache.modules:core"), - gradleBundle("org.ehcache.modules:impl"), - gradleBundle("org.ehcache.modules:xml"), jaxbConfiguration(), - gradleBundle("org.ehcache:clustered-dist"), + gradleBundle("org.ehcache.modules:ehcache-api"), + gradleBundle("org.ehcache.modules:ehcache-core"), + gradleBundle("org.ehcache.modules:ehcache-impl"), + gradleBundle("org.ehcache.modules:ehcache-xml"), jaxbConfiguration(), + gradleBundle("org.ehcache:ehcache-clustered"), gradleBundle("org.terracotta:statistics"), gradleBundle("org.ehcache:sizeof"), @@ -104,8 +104,8 @@ public Option[] individualModules() { @Configuration public Option[] uberJar() { return options( - gradleBundle("org.ehcache:dist"), jaxbConfiguration(), - gradleBundle("org.ehcache:clustered-dist"), + gradleBundle("org.ehcache:ehcache"), jaxbConfiguration(), + gradleBundle("org.ehcache:ehcache-clustered"), baseConfiguration("ClusteredOsgiTest", "uberJar"), gradleBundle("org.terracotta:terracotta-utilities-tools"), diff --git a/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml b/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml index 9444bf37f0..13db0d6848 100644 --- a/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml +++ b/clustered/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-clustered-osgi.xml @@ -16,10 +16,7 @@ + xmlns:tc='http://www.ehcache.org/v3/clustered'> diff --git a/clustered/server/entity/build.gradle b/clustered/server/ehcache-entity/build.gradle similarity index 72% rename from clustered/server/entity/build.gradle rename to clustered/server/ehcache-entity/build.gradle index 3fc3ad6d33..2d88b49de3 100644 --- a/clustered/server/entity/build.gradle +++ b/clustered/server/ehcache-entity/build.gradle @@ -15,20 +15,26 @@ */ plugins { - id 'org.ehcache.build.deploy' - id 'org.ehcache.build.voltron' + id 'org.ehcache.build.clustered-server-module' +} + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache 3 Clustering Server Entity module' + description = 'The Server Entity module of Ehcache 3' + } } dependencies { - service project(':clustered:server:service-api') + service project(':clustered:server:ehcache-service-api') service "org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion" service "org.terracotta.management:management-registry:$terracottaPlatformVersion" - api project(':clustered:common') + api project(':clustered:ehcache-common') implementation "org.terracotta:runnel:$terracottaPlatformVersion" implementation "org.terracotta:offheap-store:$offheapVersion" implementation "org.terracotta:client-message-tracker:$terracottaPlatformVersion" - testImplementation project(':clustered:server:service') + testImplementation project(':clustered:server:ehcache-service') testImplementation project(':clustered:test-utils') } diff --git a/clustered/server/entity/config/checkstyle-suppressions.xml b/clustered/server/ehcache-entity/config/checkstyle-suppressions.xml similarity index 100% rename from clustered/server/entity/config/checkstyle-suppressions.xml rename to clustered/server/ehcache-entity/config/checkstyle-suppressions.xml diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntity.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntity.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntity.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntity.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockPassiveEntity.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockPassiveEntity.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockPassiveEntity.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockPassiveEntity.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockServerEntityService.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockServerEntityService.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockServerEntityService.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockServerEntityService.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/messages/LockSyncMessaging.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/lock/server/messages/LockSyncMessaging.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/lock/server/messages/LockSyncMessaging.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/lock/server/messages/LockSyncMessaging.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntity.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntity.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntity.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntity.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerDump.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerDump.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerDump.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerDump.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntity.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntity.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntity.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntity.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerServerEntityService.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerServerEntityService.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerServerEntityService.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/ClusterTierManagerServerEntityService.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/CommunicatorServiceConfiguration.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/CommunicatorServiceConfiguration.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/CommunicatorServiceConfiguration.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/CommunicatorServiceConfiguration.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ConcurrencyStrategies.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/ConcurrencyStrategies.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/ConcurrencyStrategies.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/ConcurrencyStrategies.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/EhcacheExecutionStrategy.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/EhcacheExecutionStrategy.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/EhcacheExecutionStrategy.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/EhcacheExecutionStrategy.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/ServerStoreCompatibility.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/ServerStoreCompatibility.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/ServerStoreCompatibility.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/ServerStoreCompatibility.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheDataSyncMessage.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheDataSyncMessage.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheDataSyncMessage.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheDataSyncMessage.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerCatchup.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerCatchup.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerCatchup.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerCatchup.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessage.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodec.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodec.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessage.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessage.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessage.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessage.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodec.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagement.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagement.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagement.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagement.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerBinding.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerBinding.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerBinding.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerBinding.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerSettingsManagementProvider.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerSettingsManagementProvider.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerSettingsManagementProvider.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/ClusterTierManagerSettingsManagementProvider.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/Management.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/Management.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/Management.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/Management.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/Notification.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/Notification.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/Notification.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/Notification.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/PoolBinding.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/PoolBinding.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/PoolBinding.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/PoolBinding.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/PoolSettingsManagementProvider.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/PoolSettingsManagementProvider.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/PoolSettingsManagementProvider.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/PoolSettingsManagementProvider.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/PoolStatisticsManagementProvider.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/PoolStatisticsManagementProvider.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/PoolStatisticsManagementProvider.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/PoolStatisticsManagementProvider.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreBinding.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreBinding.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreBinding.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreBinding.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreSettingsManagementProvider.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreStatisticsManagementProvider.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreStatisticsManagementProvider.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreStatisticsManagementProvider.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/management/ServerStoreStatisticsManagementProvider.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierActiveEntity.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierDump.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierDump.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierDump.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierDump.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntity.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/ClusterTierServerEntityService.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/LockManagerImpl.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/LockManagerImpl.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/LockManagerImpl.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/LockManagerImpl.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/MessageToTrackerSegmentFunction.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/MessageToTrackerSegmentFunction.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/MessageToTrackerSegmentFunction.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/MessageToTrackerSegmentFunction.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/NoopLockManager.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/NoopLockManager.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/NoopLockManager.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/NoopLockManager.java diff --git a/clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ServerLockManager.java b/clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/ServerLockManager.java similarity index 100% rename from clustered/server/entity/src/main/java/org/ehcache/clustered/server/store/ServerLockManager.java rename to clustered/server/ehcache-entity/src/main/java/org/ehcache/clustered/server/store/ServerLockManager.java diff --git a/clustered/server/entity/src/main/resources/META-INF/services/org.terracotta.entity.EntityServerService b/clustered/server/ehcache-entity/src/main/resources/META-INF/services/org.terracotta.entity.EntityServerService similarity index 100% rename from clustered/server/entity/src/main/resources/META-INF/services/org.terracotta.entity.EntityServerService rename to clustered/server/ehcache-entity/src/main/resources/META-INF/services/org.terracotta.entity.EntityServerService diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/lock/server/VoltronReadWriteLockActiveEntityTest.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerActiveEntityTest.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/ClusterTierManagerPassiveEntityTest.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/DefaultConcurrencyStrategyTest.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/DefaultConcurrencyStrategyTest.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/DefaultConcurrencyStrategyTest.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/DefaultConcurrencyStrategyTest.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/ServerStoreCompatibilityTest.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/TestClientDescriptor.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientSourceId.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/TestClientSourceId.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestClientSourceId.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/TestClientSourceId.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestInvokeContext.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/TestInvokeContext.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/TestInvokeContext.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/TestInvokeContext.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessageTest.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessageTest.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessageTest.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheMessageTrackerMessageTest.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodecTest.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodecTest.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodecTest.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheServerCodecTest.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessageCodecTest.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/internal/messages/PassiveReplicationMessageCodecTest.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierActiveEntityTest.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/store/ClusterTierPassiveEntityTest.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/InvalidMessage.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/store/InvalidMessage.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/InvalidMessage.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/store/InvalidMessage.java diff --git a/clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java b/clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java similarity index 100% rename from clustered/server/entity/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java rename to clustered/server/ehcache-entity/src/test/java/org/ehcache/clustered/server/store/LockManagerImplTest.java diff --git a/clustered/server/service-api/build.gradle b/clustered/server/ehcache-service-api/build.gradle similarity index 68% rename from clustered/server/service-api/build.gradle rename to clustered/server/ehcache-service-api/build.gradle index dddbdfa46b..ada3ceba19 100644 --- a/clustered/server/service-api/build.gradle +++ b/clustered/server/ehcache-service-api/build.gradle @@ -15,10 +15,16 @@ */ plugins { - id 'org.ehcache.build.deploy' - id 'org.ehcache.build.voltron' + id 'org.ehcache.build.clustered-server-module' +} + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache 3 Clustering Server Storage API module' + description = 'The Server Storage API module of Ehcache 3' + } } dependencies { - api project(':clustered:common-api') + api project(':clustered:ehcache-common-api') } diff --git a/clustered/server/service-api/config/checkstyle-suppressions.xml b/clustered/server/ehcache-service-api/config/checkstyle-suppressions.xml similarity index 100% rename from clustered/server/service-api/config/checkstyle-suppressions.xml rename to clustered/server/ehcache-service-api/config/checkstyle-suppressions.xml diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/KeySegmentMapper.java b/clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/KeySegmentMapper.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/KeySegmentMapper.java rename to clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/KeySegmentMapper.java diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java b/clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java rename to clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/ServerSideServerStore.java diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java b/clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java rename to clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/ServerStoreEventListener.java diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java b/clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java rename to clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheStateRepoSyncMessage.java diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessage.java b/clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessage.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessage.java rename to clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/internal/messages/EhcacheSyncMessage.java diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java b/clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java rename to clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/internal/messages/SyncMessageType.java diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java b/clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java rename to clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/offheap/InternalChain.java diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/repo/ServerStateRepository.java b/clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/repo/ServerStateRepository.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/repo/ServerStateRepository.java rename to clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/repo/ServerStateRepository.java diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/repo/StateRepositoryManager.java b/clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/repo/StateRepositoryManager.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/repo/StateRepositoryManager.java rename to clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/repo/StateRepositoryManager.java diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateContext.java b/clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateContext.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateContext.java rename to clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateContext.java diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java b/clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java rename to clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/state/EhcacheStateService.java diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/InvalidationTracker.java b/clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/state/InvalidationTracker.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/InvalidationTracker.java rename to clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/state/InvalidationTracker.java diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStateServiceConfig.java b/clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStateServiceConfig.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStateServiceConfig.java rename to clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStateServiceConfig.java diff --git a/clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStoreStateServiceConfig.java b/clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStoreStateServiceConfig.java similarity index 100% rename from clustered/server/service-api/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStoreStateServiceConfig.java rename to clustered/server/ehcache-service-api/src/main/java/org/ehcache/clustered/server/state/config/EhcacheStoreStateServiceConfig.java diff --git a/clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/ServerStateRepositoryTest.java b/clustered/server/ehcache-service-api/src/test/java/org/ehcache/clustered/server/repo/ServerStateRepositoryTest.java similarity index 100% rename from clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/ServerStateRepositoryTest.java rename to clustered/server/ehcache-service-api/src/test/java/org/ehcache/clustered/server/repo/ServerStateRepositoryTest.java diff --git a/clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/StateRepositoryManagerTest.java b/clustered/server/ehcache-service-api/src/test/java/org/ehcache/clustered/server/repo/StateRepositoryManagerTest.java similarity index 100% rename from clustered/server/service-api/src/test/java/org/ehcache/clustered/server/repo/StateRepositoryManagerTest.java rename to clustered/server/ehcache-service-api/src/test/java/org/ehcache/clustered/server/repo/StateRepositoryManagerTest.java diff --git a/clustered/server/service/build.gradle b/clustered/server/ehcache-service/build.gradle similarity index 73% rename from clustered/server/service/build.gradle rename to clustered/server/ehcache-service/build.gradle index c529c92602..c26735f52f 100644 --- a/clustered/server/service/build.gradle +++ b/clustered/server/ehcache-service/build.gradle @@ -15,16 +15,22 @@ */ plugins { - id 'org.ehcache.build.deploy' - id 'org.ehcache.build.voltron' + id 'org.ehcache.build.clustered-server-module' +} + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache 3 Clustering Server Storage Implementation module' + description = 'The Server Storage Implementation module of Ehcache 3' + } } dependencies { - service project(':clustered:server:service-api') + service project(':clustered:server:ehcache-service-api') service "org.terracotta:offheap-resource:$terracottaPlatformVersion" service "org.terracotta:statistics:$statisticVersion" - implementation project(':clustered:common') + implementation project(':clustered:ehcache-common') implementation "org.terracotta:offheap-store:$offheapVersion" testImplementation project(':clustered:test-utils') diff --git a/clustered/server/service/config/checkstyle-suppressions.xml b/clustered/server/ehcache-service/config/checkstyle-suppressions.xml similarity index 100% rename from clustered/server/service/config/checkstyle-suppressions.xml rename to clustered/server/ehcache-service/config/checkstyle-suppressions.xml diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/EhcacheStateServiceImpl.java b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/EhcacheStateServiceImpl.java similarity index 100% rename from clustered/server/service/src/main/java/org/ehcache/clustered/server/EhcacheStateServiceImpl.java rename to clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/EhcacheStateServiceImpl.java diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java similarity index 100% rename from clustered/server/service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java rename to clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/ServerStoreImpl.java diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/ChainStorageEngine.java b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/ChainStorageEngine.java similarity index 100% rename from clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/ChainStorageEngine.java rename to clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/ChainStorageEngine.java diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/LongPortability.java b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/LongPortability.java similarity index 100% rename from clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/LongPortability.java rename to clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/LongPortability.java diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java similarity index 100% rename from clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java rename to clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainMap.java diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java similarity index 100% rename from clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java rename to clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java similarity index 100% rename from clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java rename to clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapServerStore.java diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMap.java b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMap.java similarity index 100% rename from clustered/server/service/src/main/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMap.java rename to clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMap.java diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceDump.java b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceDump.java similarity index 100% rename from clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceDump.java rename to clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceDump.java diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java similarity index 100% rename from clustered/server/service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java rename to clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/state/EhcacheStateServiceProvider.java diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/InvalidationTrackerImpl.java b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/state/InvalidationTrackerImpl.java similarity index 100% rename from clustered/server/service/src/main/java/org/ehcache/clustered/server/state/InvalidationTrackerImpl.java rename to clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/state/InvalidationTrackerImpl.java diff --git a/clustered/server/service/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java similarity index 100% rename from clustered/server/service/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java rename to clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/state/ResourcePageSource.java diff --git a/clustered/server/service/src/main/resources/META-INF/services/org.terracotta.entity.ServiceProvider b/clustered/server/ehcache-service/src/main/resources/META-INF/services/org.terracotta.entity.ServiceProvider similarity index 100% rename from clustered/server/service/src/main/resources/META-INF/services/org.terracotta.entity.ServiceProvider rename to clustered/server/ehcache-service/src/main/resources/META-INF/services/org.terracotta.entity.ServiceProvider diff --git a/clustered/server/service/src/main/resources/offheap-message.properties b/clustered/server/ehcache-service/src/main/resources/offheap-message.properties similarity index 100% rename from clustered/server/service/src/main/resources/offheap-message.properties rename to clustered/server/ehcache-service/src/main/resources/offheap-message.properties diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/EhcacheStateServiceImplTest.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/EhcacheStateServiceImplTest.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/EhcacheStateServiceImplTest.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/EhcacheStateServiceImplTest.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/OffHeapServerStoreTest.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/PinningOffHeapChainMapTest.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/state/EhcacheStateServiceProviderTest.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/state/EhcacheStateServiceProviderTest.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/state/EhcacheStateServiceProviderTest.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/state/EhcacheStateServiceProviderTest.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/state/InvalidationTrackerImplTest.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/state/InvalidationTrackerImplTest.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/state/InvalidationTrackerImplTest.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/state/InvalidationTrackerImplTest.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ChainBuilder.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/ChainBuilder.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ChainBuilder.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/ChainBuilder.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ElementBuilder.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/ElementBuilder.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ElementBuilder.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/ElementBuilder.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/ServerStoreTest.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainBuilder.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainBuilder.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainBuilder.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainBuilder.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainImpl.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainImpl.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainImpl.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/impl/HeapChainImpl.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementBuilder.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementBuilder.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementBuilder.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementBuilder.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementImpl.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementImpl.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementImpl.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/impl/HeapElementImpl.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreImpl.java diff --git a/clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreTest.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreTest.java similarity index 100% rename from clustered/server/service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreTest.java rename to clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/store/impl/ReferenceStoreTest.java diff --git a/clustered/server/entity/gradle.properties b/clustered/server/entity/gradle.properties deleted file mode 100644 index 0f411f1061..0000000000 --- a/clustered/server/entity/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache 3 Clustering Server Entity module -subPomDesc = The Server Entity module of Ehcache 3 diff --git a/clustered/server/service-api/gradle.properties b/clustered/server/service-api/gradle.properties deleted file mode 100644 index b45711e33d..0000000000 --- a/clustered/server/service-api/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache 3 Clustering Server Storage API module -subPomDesc = The Server Storage API module of Ehcache 3 diff --git a/clustered/server/service/gradle.properties b/clustered/server/service/gradle.properties deleted file mode 100644 index 7a8edd6a46..0000000000 --- a/clustered/server/service/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache 3 Clustering Server Storage Implementation module -subPomDesc = The Server Storage Implementation module of Ehcache 3 diff --git a/clustered/test-utils/build.gradle b/clustered/test-utils/build.gradle index b4a17f93c7..067d92bd33 100644 --- a/clustered/test-utils/build.gradle +++ b/clustered/test-utils/build.gradle @@ -1,4 +1,8 @@ +plugins { + id 'org.ehcache.build.conventions.java-library' +} + dependencies { - api project(':clustered:common') + api project(':clustered:ehcache-common') api "org.hamcrest:hamcrest-core:$hamcrestVersion" } diff --git a/config/owasp-supressions.xml b/config/owasp-supressions.xml index 5718b311b8..8a5a28b93e 100644 --- a/config/owasp-supressions.xml +++ b/config/owasp-supressions.xml @@ -5,28 +5,32 @@ They are then flagged as being vulnerable to https://nvd.nist.gov/vuln/detail/CVE-2019-11065. --> - + Ehcache modules are not Gradle! ^pkg:maven/org\.ehcache.*@.*$ CVE-2019-11065 - + Ehcache modules are not Gradle! ^pkg:maven/org\.ehcache.*@.*$ CVE-2019-15052 - + Ehcache modules are not Gradle! ^pkg:maven/org\.ehcache.*@.*$ CVE-2019-16370 - + TC Tripwire is unrelated to the other Tripwire ^pkg:maven/org\.terracotta/tc\-tripwire\-plugin@.*$ cpe:/a:tripwire:tripwire - - Ehcache 3 builds require with Java 8+ : 4.13.1 is safe + BND isn't Eclipse + ^pkg:maven/biz\.aQute\.bnd/biz\.aQute\.bndlib@.*$ + cpe:/a:eclipse:eclipse_ide + + + Ehcache 3 builds require Java 8+ : 4.13.1 is safe pkg:maven/junit/junit@4.13.1 CVE-2020-15250 @@ -36,4 +40,14 @@ db40edda8b95d880d2a810560fd5e46eb4fa6909 CVE-2020-13956 + + PAX URL Aether repackages commons-io and isn't (yet) fixed + 5060835593e5b6ed18c82fc2e782f0a3c30a00b1 + CVE-2021-29425 + + + PAX Exame JUnit4 doesn't have a 4.13.1 depending release + ^pkg:maven/org\.ops4j\.pax\.exam/pax\-exam\-junit4@.*$ + CVE-2020-15250 + diff --git a/core-spi-test/.gitignore b/core-spi-test/.gitignore deleted file mode 100755 index ae3c172604..0000000000 --- a/core-spi-test/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/core-spi-test/build.gradle b/core-spi-test/build.gradle index 5f7ff037f7..0b8db145f4 100644 --- a/core-spi-test/build.gradle +++ b/core-spi-test/build.gradle @@ -13,11 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +plugins { + id 'org.ehcache.build.conventions.java-library' +} dependencies { api project(':spi-tester') - implementation project(':core') - implementation project(':impl') + implementation project(':ehcache-core') + implementation project(':ehcache-impl') implementation "junit:junit:$junitVersion" implementation "org.mockito:mockito-core:$mockitoVersion" implementation "org.hamcrest:hamcrest-library:$hamcrestVersion" diff --git a/core-spi-test/gradle.properties b/core-spi-test/gradle.properties deleted file mode 100644 index 38ab6ff6e6..0000000000 --- a/core-spi-test/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache 3 Core SPI test module -subPomDesc = The Core SPI test module of Ehcache 3 diff --git a/core/.gitignore b/core/.gitignore deleted file mode 100755 index ae3c172604..0000000000 --- a/core/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/core/gradle.properties b/core/gradle.properties deleted file mode 100644 index d33b3d08d9..0000000000 --- a/core/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -subPomName = Ehcache 3 Core module -subPomDesc = The Core module of Ehcache 3 diff --git a/demos/00-NoCache/gradle.properties b/demos/00-NoCache/gradle.properties deleted file mode 100755 index 83967b0dd6..0000000000 --- a/demos/00-NoCache/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache 3 no cache demo module -subPomDesc = The no cache demo module of Ehcache 3 diff --git a/demos/01-CacheAside/gradle.properties b/demos/01-CacheAside/gradle.properties deleted file mode 100755 index 2f155acc0b..0000000000 --- a/demos/01-CacheAside/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache 3 cache aside demo module -subPomDesc = The cache aside demo module of Ehcache 3 diff --git a/demos/build.gradle b/demos/build.gradle index 17fa97b7dd..fbf81c9647 100644 --- a/demos/build.gradle +++ b/demos/build.gradle @@ -1,9 +1,10 @@ plugins { + id 'org.ehcache.build.conventions.war' apply false id 'org.gretty' apply false } subprojects { - apply plugin: 'war' + apply plugin: 'org.ehcache.build.conventions.war' apply plugin: 'org.gretty' repositories { @@ -17,7 +18,7 @@ subprojects { } dependencies { - implementation project(':impl') + implementation project(':ehcache-impl') implementation 'javax.servlet:javax.servlet-api:3.1.0' runtimeOnly 'ch.qos.logback:logback-classic:1.2.3' runtimeOnly 'com.h2database:h2:1.4.196' diff --git a/deploy.sh b/deploy.sh index 5c5c03ca6c..6e15781ff5 100755 --- a/deploy.sh +++ b/deploy.sh @@ -169,14 +169,14 @@ fi if [ $is_major ]; then echo "Adding XSDs since this is a major version" - cp xml/src/main/resources/ehcache-core.xsd $site_dir/schema/ehcache-core.xsd - cp xml/src/main/resources/ehcache-core.xsd $site_dir/schema/ehcache-core-${major_version}.xsd - cp 107/src/main/resources/ehcache-107-ext.xsd $site_dir/schema/ehcache-107-ext.xsd - cp 107/src/main/resources/ehcache-107-ext.xsd $site_dir/schema/ehcache-107-ext-${major_version}.xsd - cp clustered/client/src/main/resources/ehcache-clustered-ext.xsd $site_dir/schema/ehcache-clustered-ext.xsd - cp clustered/client/src/main/resources/ehcache-clustered-ext.xsd $site_dir/schema/ehcache-clustered-ext-${major_version}.xsd - cp transactions/src/main/resources/ehcache-tx-ext.xsd $site_dir/schema/ehcache-tx-ext.xsd - cp transactions/src/main/resources/ehcache-tx-ext.xsd $site_dir/schema/ehcache-tx-ext-${major_version}.xsd + cp ehcache-xml/src/main/schema/ehcache-core.xsd $site_dir/schema/ehcache-core.xsd + cp ehcache-xml/src/main/schema/ehcache-core.xsd $site_dir/schema/ehcache-core-${major_version}.xsd + cp ehcache-107/src/main/resources/ehcache-107-ext.xsd $site_dir/schema/ehcache-107-ext.xsd + cp ehcache-107/src/main/resources/ehcache-107-ext.xsd $site_dir/schema/ehcache-107-ext-${major_version}.xsd + cp clustered/ehcache-client/src/main/resources/ehcache-clustered-ext.xsd $site_dir/schema/ehcache-clustered-ext.xsd + cp clustered/ehcache-client/src/main/resources/ehcache-clustered-ext.xsd $site_dir/schema/ehcache-clustered-ext-${major_version}.xsd + cp ehcache-transactions/src/main/resources/ehcache-tx-ext.xsd $site_dir/schema/ehcache-tx-ext.xsd + cp ehcache-transactions/src/main/resources/ehcache-tx-ext.xsd $site_dir/schema/ehcache-tx-ext-${major_version}.xsd fi echo "Copy the javadoc from Maven central" diff --git a/dist/.gitignore b/dist/.gitignore deleted file mode 100755 index ae3c172604..0000000000 --- a/dist/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/dist/build.gradle b/dist/build.gradle deleted file mode 100644 index 732bfe9955..0000000000 --- a/dist/build.gradle +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -plugins { - id 'org.ehcache.build.distribute' -} - -group = 'org.ehcache' -archivesBaseName = 'ehcache' - -dependencies { - compileOnly project(':api') - compileOnly project(':core') - compileOnly project(':impl') - compileOnly project(':107') - compileOnly project(':xml') -} - -dependencies { - shadowCompile "org.slf4j:slf4j-api:$parent.slf4jVersion" - shadowProvided "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" - shadowProvided "javax.cache:cache-api:$parent.jcacheVersion" -} - -jar { - bnd ( - 'Bundle-Name': 'Ehcache 3', - 'Bundle-SymbolicName': 'org.ehcache', - 'Bundle-Description': 'Ehcache is an open-source caching library, compliant with the JSR-107 standard.', - - 'Bundle-Activator': 'org.ehcache.core.osgi.EhcacheActivator', - 'Export-Package': '!org.ehcache.jsr107.tck, !org.ehcache.*.internal.*, org.ehcache.*', - 'Import-Package': "javax.cache.*;resolution:=optional, !javax.annotation, !sun.misc, javax.xml.bind*;version=\"${parent.jaxbVersion}\", *" - ) -} diff --git a/dist/gradle.properties b/dist/gradle.properties deleted file mode 100644 index 944561ba5a..0000000000 --- a/dist/gradle.properties +++ /dev/null @@ -1,19 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache -subPomDesc = End-user ehcache3 jar artifact -javadocExclude = **/core/**, **/impl/**, **/xml/**, **/jsr107/**, **/transactions/**, **/management/**, **/tck/** diff --git a/docs/build.gradle b/docs/build.gradle index 69b7943e39..42563d66f0 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -18,6 +18,7 @@ import org.asciidoctor.gradle.jvm.AsciidoctorJBasePlugin import org.asciidoctor.gradle.jvm.AsciidoctorTask plugins { + id 'org.ehcache.build.conventions.base' id 'org.asciidoctor.jvm.base' } @@ -31,7 +32,7 @@ asciidoctorj { } def createCopyCssTask(def asciidocTask) { - return tasks.register("copy${asciidocTask.name}CSS", Copy) { + return tasks.register("copy${asciidocTask.name}CSS", Sync) { from ('css') { include '**' } into("${asciidocTask.outputDir}/css") diff --git a/docs/gradle.properties b/docs/gradle.properties deleted file mode 100644 index 63ef54e3be..0000000000 --- a/docs/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -subPomName = Ehcache 3 Documentation module -subPomDesc = The Documentation module of Ehcache 3 \ No newline at end of file diff --git a/docs/src/docs/asciidoc/user/107.adoc b/docs/src/docs/asciidoc/user/107.adoc index d4a471cba5..6c627a94af 100644 --- a/docs/src/docs/asciidoc/user/107.adoc +++ b/docs/src/docs/asciidoc/user/107.adoc @@ -59,7 +59,7 @@ Here is a code sample that demonstrates the usage of the basic JCache configurat [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=basicConfigurationExample] +include::{sourcedir39}/ehcache-107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=basicConfigurationExample] ---- <1> Retrieves the default CachingProvider implementation from the application's classpath. @@ -91,7 +91,7 @@ you can still get to the underlying Ehcache `CacheRuntimeConfiguration`: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=mutableConfigurationExample] +include::{sourcedir39}/ehcache-107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=mutableConfigurationExample] ---- <1> Create a JCache cache using the `MutableConfiguration` interface from the JCache specification. @@ -109,7 +109,7 @@ The way you do this is as follows: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheCacheManagerConfigurationExample] +include::{sourcedir39}/ehcache-107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheCacheManagerConfigurationExample] ---- <1> Cast the `CachingProvider` into the Ehcache specific implementation `org.ehcache.jsr107.EhcacheCachingProvider`, <2> Create a configuration using the specific Ehcache `DefaultConfiguration` and pass it some `CacheManager` level configurations, @@ -122,7 +122,7 @@ When using this mechanism, no JCache `CompleteConfiguration` is used and so you [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheBasedConfigurationExample] +include::{sourcedir39}/ehcache-107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=ehcacheBasedConfigurationExample] ---- <1> Create an Ehcache `CacheConfiguration`. @@ -142,14 +142,14 @@ The following is an example of an XML configuration: [source%nowrap,xml,indent=0] ---- -include::{sourcedir39}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml[] +include::{sourcedir39}/ehcache-107/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml[] ---- Here is an example of how to access the XML configuration using JCache: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107UsingXMLConfigExample] +include::{sourcedir39}/ehcache-107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107UsingXMLConfigExample] ---- <1> Invoke `javax.cache.spi.CachingProvider.getCacheManager(java.net.URI, java.lang.ClassLoader)` @@ -179,7 +179,7 @@ You can do this at two different levels: [source%nowrap,xml,indent=0] ---- -include::{sourcedir39}/107/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml[lines=17..-1] +include::{sourcedir39}/ehcache-107/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml[lines=17..-1] ---- <1> Using the JCache service extension, you can enable MBeans by default. @@ -202,7 +202,7 @@ To do this, add a `jsr107` service in your XML configuration file: [source%nowrap,xml,indent=0] ---- -include::{sourcedir39}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml[] +include::{sourcedir39}/ehcache-107/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml[] ---- <1> First, declare a namespace for the JCache extension, e.g. `jsr107`. @@ -219,7 +219,7 @@ Using the above configuration, you can not only supplement but also override the [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107SupplementWithTemplatesExample] +include::{sourcedir39}/ehcache-107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java[tag=jsr107SupplementWithTemplatesExample] ---- <1> Assume existing JCache configuration code, which is store-by-value by default @@ -284,5 +284,5 @@ If you need _Ehcache through JCache_ behaviour, the following shows the relevant [source%nowrap,xml,indent=0] ---- -include::{sourcedir39}/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml[tag=cacheThroughCAS] +include::{sourcedir39}/ehcache-107/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml[tag=cacheThroughCAS] ---- diff --git a/docs/src/docs/asciidoc/user/cache-event-listeners.adoc b/docs/src/docs/asciidoc/user/cache-event-listeners.adoc index 684d473e82..6938d36340 100644 --- a/docs/src/docs/asciidoc/user/cache-event-listeners.adoc +++ b/docs/src/docs/asciidoc/user/cache-event-listeners.adoc @@ -18,7 +18,7 @@ Listeners are registered at the cache level - and therefore only receive events [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEventListener] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEventListener] ---- <1> Create a `CacheEventListenerConfiguration` using the builder indicating the listener and the events to receive (in this case create and update events) @@ -57,7 +57,7 @@ Cache event listeners may also be added and removed while the cache is being use [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=registerListenerAtRuntime] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=registerListenerAtRuntime] ---- <1> Create a `CacheEventListener` implementation instance. @@ -73,7 +73,7 @@ Advanced users may want to tune the level of concurrency which may be used for d [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=configuringEventProcessingQueues] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=configuringEventProcessingQueues] ---- <1> Indicate the level of concurrency desired diff --git a/docs/src/docs/asciidoc/user/clustered-cache.adoc b/docs/src/docs/asciidoc/user/clustered-cache.adoc index d491a2fde0..e16f1e2217 100644 --- a/docs/src/docs/asciidoc/user/clustered-cache.adoc +++ b/docs/src/docs/asciidoc/user/clustered-cache.adoc @@ -157,7 +157,7 @@ Here is a code sample that shows how to configure a cache manager with clusterin [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] +include::{sourcedir39}/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] ---- <1> Returns the `org.ehcache.config.builders.CacheManagerBuilder` instance. @@ -174,7 +174,7 @@ This code sample demonstrates the usage of the concepts explained in the previou [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerWithServerSideConfigExample] +include::{sourcedir39}/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerWithServerSideConfigExample] ---- <1> `defaultServerResource(String)` on `ClusteringServiceConfigurationBuilder` instance sets the default server off-heap resource for the cache manager. @@ -201,7 +201,7 @@ When configuring a cache manager to connect to a cluster tier manager there are [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerLifecycle] +include::{sourcedir39}/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerLifecycle] ---- <1> In auto create mode if no cluster tier manager exists then one is created with the supplied configuration. If it exists and its configuration matches the supplied configuration then a connection is established. @@ -220,7 +220,7 @@ If it does not exist then the cache manager will fail to initialize. [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheTieredExample] +include::{sourcedir39}/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheTieredExample] ---- <1> Configuring the heap tier for cache. @@ -230,7 +230,7 @@ The equivalent XML configuration is as follows: [source%nowrap,xml,indent=0] ---- -include::{sourcedir39}/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=tieringSample] +include::{sourcedir39}/clustered/ehcache-client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=tieringSample] ---- <1> Specify the heap tier for cache. @@ -253,7 +253,7 @@ This comes with a latency penalty on the write operation required to give this g [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheConsistency] +include::{sourcedir39}/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheConsistency] ---- <1> Specify the consistency level through the use of additional service configuration, using _strong_ consistency here. @@ -263,7 +263,7 @@ The equivalent XML configuration is as follows: [source%nowrap,xml,indent=0] ---- -include::{sourcedir39}/clustered/client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=consistencySample] +include::{sourcedir39}/clustered/ehcache-client/src/test/resources/configs/docs/ehcache-clustered.xml[tag=consistencySample] ---- <1> Specify the consistency level through a custom service configuration from the `clustered` namespace. @@ -293,7 +293,7 @@ The example code below shows how this can be implemented. [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=unspecifiedClusteredCacheExample] +include::{sourcedir39}/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=unspecifiedClusteredCacheExample] ---- <1> Configure the first cache manager with auto create on reconnect diff --git a/docs/src/docs/asciidoc/user/config-derive.adoc b/docs/src/docs/asciidoc/user/config-derive.adoc index d53e12547c..dd4f35e94a 100644 --- a/docs/src/docs/asciidoc/user/config-derive.adoc +++ b/docs/src/docs/asciidoc/user/config-derive.adoc @@ -22,7 +22,7 @@ with the configurations values [source,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=deriveContract] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=deriveContract] ---- <1> Creates a builder seeded with the configuration's state. <2> Configurations built using the builder are then functionally identical to the original configuration. @@ -34,13 +34,13 @@ The configuration builder returned by the derive method provide direct methods f .setting a custom classloader: [source,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=customClassLoader] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=customClassLoader] ---- .adding a cache: [source,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withCache] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withCache] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -65,7 +65,7 @@ include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivati .removing a cache: [source,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withoutCache] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withoutCache] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -93,7 +93,7 @@ builder seeded using the existing cache configuration. .updating a cache, by adding a resource: [source,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=updateCache] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=updateCache] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -131,7 +131,7 @@ creation configurations and service configurations: .adding a service creation configuration (constraining the default thread pool) [source,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withServiceCreation] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withServiceCreation] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -155,7 +155,7 @@ include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivati .updating a service creation configuration (changing the persistence path) [source,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=updateServiceCreation] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=updateServiceCreation] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -177,7 +177,7 @@ include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivati .adding a service configuration (setting a resilience strategy) [source,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withService] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java[tag=withService] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -210,7 +210,7 @@ include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ConfigurationDerivati .updating a service configuration (changing a clustered cache's consistency) [source,java,indent=0] ---- -include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java[tag=updateService] +include::{sourcedir39}/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java[tag=updateService] ---- [cols=".^~a,^.^~d,.^~a"] |=== @@ -258,7 +258,7 @@ instance its configuration are usually strongly coupled: .removing a service (making a cache manager non-clustered) [source,java,indent=0] ---- -include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java[tag=removeService] +include::{sourcedir39}/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/ConfigurationDerivation.java[tag=removeService] ---- <1> From all cache configurations... <2> remove any existing `ClusteredStoreConfiguration` instances. diff --git a/docs/src/docs/asciidoc/user/eviction-advisor.adoc b/docs/src/docs/asciidoc/user/eviction-advisor.adoc index 48a7a342b8..e87a8021bf 100644 --- a/docs/src/docs/asciidoc/user/eviction-advisor.adoc +++ b/docs/src/docs/asciidoc/user/eviction-advisor.adoc @@ -29,7 +29,7 @@ If the eviction is advised against, Ehcache will try to honor the preference of [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEvictionAdvisor] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cacheEvictionAdvisor] ---- <1> Configure a constrained heap, as the eviction advisor is only relevant when mappings get evicted from the cache. diff --git a/docs/src/docs/asciidoc/user/examples.adoc b/docs/src/docs/asciidoc/user/examples.adoc index 41cd3af73a..ad9199d418 100644 --- a/docs/src/docs/asciidoc/user/examples.adoc +++ b/docs/src/docs/asciidoc/user/examples.adoc @@ -102,5 +102,5 @@ Note the presence of the +Filling cache with peeps+, +Clearing peeps cache+, and [source,xml,indent=0] ---- -include::{sourcedir39}/107/src/test/resources/ehcache-example.xml[] +include::{sourcedir39}/ehcache-107/src/test/resources/ehcache-example.xml[] ---- diff --git a/docs/src/docs/asciidoc/user/expiry.adoc b/docs/src/docs/asciidoc/user/expiry.adoc index e25bb9a40f..5eae004e1a 100644 --- a/docs/src/docs/asciidoc/user/expiry.adoc +++ b/docs/src/docs/asciidoc/user/expiry.adoc @@ -20,7 +20,7 @@ Expiry is configured at the cache level, in Java or in XML: [source,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] ---- <1> Expiry policy is configured at the cache level, so start by defining a cache configuration, @@ -28,7 +28,7 @@ include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[t [source,xml,indent=0] ---- -include::{sourcedir39}/xml/src/test/resources/configs/docs/expiry.xml[tags=expiry] +include::{sourcedir39}/ehcache-xml/src/test/resources/configs/docs/expiry.xml[tags=expiry] ---- <1> At the cache level, using the predefined _time-to-live_ again. @@ -50,7 +50,7 @@ Supporting your own expiration scheme simply means implementing the `ExpiryPolic [source,java,indent=0] ---- -include::{sourcedir39}/api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java[lines=21..-1] +include::{sourcedir39}/ehcache-api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java[lines=21..-1] ---- The main points to remember on the return value from these methods: @@ -71,7 +71,7 @@ In Java: [source,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=customExpiry] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=customExpiry] ---- <1> Simply pass your custom expiry instance into the cache builder. @@ -80,7 +80,7 @@ In XML: [source,xml,indent=0] ---- -include::{sourcedir39}/xml/src/test/resources/configs/docs/expiry.xml[tags=customExpiry] +include::{sourcedir39}/ehcache-xml/src/test/resources/configs/docs/expiry.xml[tags=customExpiry] ---- <1> Simply pass the fully qualified class name of your custom expiry. diff --git a/docs/src/docs/asciidoc/user/getting-started.adoc b/docs/src/docs/asciidoc/user/getting-started.adoc index 98c4b32e17..6721782379 100644 --- a/docs/src/docs/asciidoc/user/getting-started.adoc +++ b/docs/src/docs/asciidoc/user/getting-started.adoc @@ -25,7 +25,7 @@ As with the previous versions of Ehcache, the canonical way of dealing with `Cac [source,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cachemanagerExample] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=cachemanagerExample] ---- <1> The static method `org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder` returns a new `org.ehcache.config.builders.CacheManagerBuilder` instance. @@ -74,7 +74,7 @@ You can create an XML file to configure a `CacheManager`. [source,xml,indent=0] ---- -include::{sourcedir39}/xml/src/test/resources/configs/docs/getting-started.xml[tags=gettingStarted] +include::{sourcedir39}/ehcache-xml/src/test/resources/configs/docs/getting-started.xml[tags=gettingStarted] ---- <1> Declares a `Cache` aliased to `foo`. @@ -108,7 +108,7 @@ In addition, for creating the cache manager with clustering support, you will ne [source,java,indent=0] ---- -include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] +include::{sourcedir39}/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/GettingStarted.java[tag=clusteredCacheManagerExample] ---- <1> Returns the `org.ehcache.config.builders.CacheManagerBuilder` instance; @@ -137,7 +137,7 @@ A classical example would be using 3 tiers with a persistent disk storage. [source,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=threeTiersCacheManager] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=threeTiersCacheManager] ---- <1> If you wish to use disk storage (like for persistent `Cache` instances), you'll have to provide a @@ -156,7 +156,7 @@ The following illustrates how to configure a _time-to-live_ expiry. [source,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=expiry] ---- <1> Expiry is configured at the cache level, so start by defining a cache configuration, diff --git a/docs/src/docs/asciidoc/user/management.adoc b/docs/src/docs/asciidoc/user/management.adoc index 87323351c6..14b2c33069 100644 --- a/docs/src/docs/asciidoc/user/management.adoc +++ b/docs/src/docs/asciidoc/user/management.adoc @@ -30,7 +30,7 @@ cache manager builder as a service: [source,java,indent=0] ---- -include::{sourcedir39}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=usingManagementRegistry] +include::{sourcedir39}/ehcache-management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=usingManagementRegistry] ---- <1> Optional: give a name to your cache manager by using a custom configuration <2> Create an instance of `org.ehcache.management.registry.DefaultManagementRegistryService`. This is only required because the service is used below. @@ -50,7 +50,7 @@ and a cache name to uniquely identify the cache on which you want to query stats [source,java,indent=0] ---- -include::{sourcedir39}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=capabilitiesAndContexts] +include::{sourcedir39}/ehcache-management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=capabilitiesAndContexts] ---- <1> Query the `ManagementRegistry` for the registered managed objects' capabilities. <2> Each capability has a unique name you will need to refer to it. @@ -74,7 +74,7 @@ a managed object. Examples of actions could be: clear caches, get their configur [source,java,indent=0] ---- -include::{sourcedir39}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=actionCall] +include::{sourcedir39}/ehcache-management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=actionCall] ---- <1> Put something in a cache. <2> Call the 'clear' action on the managed cache. Refer to the descriptors of the provider to get the exact list of @@ -92,7 +92,7 @@ manager by default, but sometimes you may want one `ManagementRegistry` to manag [source,java,indent=0] ---- -include::{sourcedir39}/management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=managingMultipleCacheManagers] +include::{sourcedir39}/ehcache-management/src/test/java/org/ehcache/docs/ManagementTest.java[tag=managingMultipleCacheManagers] ---- <1> Create an instance of `org.ehcache.management.SharedManagementService` <2> Pass it as a service to the first cache manager diff --git a/docs/src/docs/asciidoc/user/migration-guide.adoc b/docs/src/docs/asciidoc/user/migration-guide.adoc index 11dd00aa43..324684b5a3 100644 --- a/docs/src/docs/asciidoc/user/migration-guide.adoc +++ b/docs/src/docs/asciidoc/user/migration-guide.adoc @@ -65,7 +65,7 @@ having dedicated logic in the methods called during the lifecycle of added and u [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Ehcache3.java[tag=CustomExpiryEhcache3] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/Ehcache3.java[tag=CustomExpiryEhcache3] ---- <1> Defining custom expiry to be called during the lifecycle of added mappings. diff --git a/docs/src/docs/asciidoc/user/resilience.adoc b/docs/src/docs/asciidoc/user/resilience.adoc index bbe653443f..977fce5a7c 100644 --- a/docs/src/docs/asciidoc/user/resilience.adoc +++ b/docs/src/docs/asciidoc/user/resilience.adoc @@ -64,7 +64,7 @@ Timeouts can be configured using a dedicated builder or in XML. [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java[tag=timeoutsExample] +include::{sourcedir39}/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/Resilience.java[tag=timeoutsExample] ---- <1> Start setting timeouts using the build diff --git a/docs/src/docs/asciidoc/user/serializers-copiers.adoc b/docs/src/docs/asciidoc/user/serializers-copiers.adoc index a59231cddd..d91664e230 100644 --- a/docs/src/docs/asciidoc/user/serializers-copiers.adoc +++ b/docs/src/docs/asciidoc/user/serializers-copiers.adoc @@ -119,7 +119,7 @@ Implement the following interface, from package `org.ehcache.spi.serialization`: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/api/src/main/java/org/ehcache/spi/serialization/Serializer.java[lines=20..-1] +include::{sourcedir39}/ehcache-api/src/main/java/org/ehcache/spi/serialization/Serializer.java[lines=20..-1] ---- As the Javadoc states, there are some constructor rules, see the section <> for that. @@ -256,7 +256,7 @@ Implement the following interface: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/api/src/main/java/org/ehcache/spi/copy/Copier.java[lines=19..-1] +include::{sourcedir39}/ehcache-api/src/main/java/org/ehcache/spi/copy/Copier.java[lines=19..-1] ---- * `T copyForRead(T obj)` is invoked when a copy must be made upon a read operation (like a cache `get()`), diff --git a/docs/src/docs/asciidoc/user/thread-pools.adoc b/docs/src/docs/asciidoc/user/thread-pools.adoc index 446880013f..d3967f4a6f 100644 --- a/docs/src/docs/asciidoc/user/thread-pools.adoc +++ b/docs/src/docs/asciidoc/user/thread-pools.adoc @@ -88,7 +88,7 @@ Following are examples of describing how to configure the thread pools the diffe [source%nowrap,java] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=diskStore] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=diskStore] ---- <1> Configure the thread pools. Note that the default one (`dflt`) is required for the events even when no event listener is configured. @@ -99,7 +99,7 @@ include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag= [source%nowrap,java] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=writeBehind] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=writeBehind] ---- <1> Configure the thread pools. Note that the default one (`dflt`) is required for the events even when no event listener is configured. @@ -110,7 +110,7 @@ include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag= [source%nowrap,java] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=events] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/ThreadPools.java[tag=events] ---- <1> Configure the thread pools. Note that there is no default one so all thread-using services must be configured with explicit defaults. @@ -124,7 +124,7 @@ Following is an example describing how to configure the thread pools the differe [source%nowrap,xml] ---- -include::{sourcedir39}/xml/src/test/resources/configs/docs/thread-pools.xml[tags=threadPools] +include::{sourcedir39}/ehcache-xml/src/test/resources/configs/docs/thread-pools.xml[tags=threadPools] ---- <1> Configure the thread pools. Note that there is no default one. diff --git a/docs/src/docs/asciidoc/user/tiering.adoc b/docs/src/docs/asciidoc/user/tiering.adoc index e62706b29a..2f63824594 100644 --- a/docs/src/docs/asciidoc/user/tiering.adoc +++ b/docs/src/docs/asciidoc/user/tiering.adoc @@ -49,7 +49,7 @@ For this, simply define the single resource in the cache configuration: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheapOnly] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheapOnly] ---- <1> Start with defining the key and value type in the configuration builder. @@ -66,7 +66,7 @@ A heap tier can be sized by entries or by size. [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=heap] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/Tiering.java[tag=heap] ---- <1> Only 10 entries allowed on heap. Eviction will occur when full. @@ -84,7 +84,7 @@ NOTE: Byte sizing has a runtime performance impact that depends on the size and [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=byteSizedTieredCache] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/Tiering.java[tag=byteSizedTieredCache] ---- <1> This will limit the amount of memory used by the heap tier for storing key-value pairs. @@ -104,7 +104,7 @@ If you wish to use off-heap, you'll have to define a resource pool, giving the m [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheap] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/Tiering.java[tag=offheap] ---- <1> Only 10 MB allowed off-heap. @@ -127,7 +127,7 @@ The faster and more dedicated the disk is, the faster accessing the data will be [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=persistentCacheManager] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/Tiering.java[tag=persistentCacheManager] ---- <1> To obtain a `PersistentCacheManager` which is a normal `CacheManager` but with the ability to @@ -167,7 +167,7 @@ In some cases, you might want to reduce the concurrency and save resources by re [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=diskSegments] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/Tiering.java[tag=diskSegments] ---- <1> Define an `OffHeapDiskStoreConfiguration` instance specifying the required number of segments. @@ -235,7 +235,7 @@ Here is an example using heap, offheap and clustered. [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/clustered/client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java[tag=threeTiersCacheManager] +include::{sourcedir39}/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/docs/Tiering.java[tag=threeTiersCacheManager] ---- <1> Clustered specific information telling how to connect to the Terracotta cluster @@ -254,7 +254,7 @@ Let's revisit an example used earlier: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=threeTiersCacheManager] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/Tiering.java[tag=threeTiersCacheManager] ---- This is a cache using 3 tiers (heap, offheap, disk). @@ -268,7 +268,7 @@ Consider for instance this code: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=notShared] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/Tiering.java[tag=notShared] ---- You will end up with two caches that can contain 10 entries each. @@ -285,7 +285,7 @@ Thus you can't change the sizing of off-heap or disk tiers. [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/Tiering.java[tag=updateResourcesAtRuntime] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/Tiering.java[tag=updateResourcesAtRuntime] ---- <1> You will need to create a new `ResourcePools` object with resources of the required size, using `ResourcePoolsBuilder`. diff --git a/docs/src/docs/asciidoc/user/usermanaged.adoc b/docs/src/docs/asciidoc/user/usermanaged.adoc index 9f78d5c165..87aac48e79 100644 --- a/docs/src/docs/asciidoc/user/usermanaged.adoc +++ b/docs/src/docs/asciidoc/user/usermanaged.adoc @@ -44,7 +44,7 @@ The interface definition is shown in this code: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/api/src/main/java/org/ehcache/UserManagedCache.java[lines=17..-1] +include::{sourcedir39}/ehcache-api/src/main/java/org/ehcache/UserManagedCache.java[lines=17..-1] ---- === User Managed Persistent Cache @@ -63,7 +63,7 @@ The interface definition is shown in this code: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/api/src/main/java/org/ehcache/PersistentUserManagedCache.java[lines=17..-1] +include::{sourcedir39}/ehcache-api/src/main/java/org/ehcache/PersistentUserManagedCache.java[lines=17..-1] ---- [[code-examples]] @@ -75,7 +75,7 @@ Here is a simple example showing a basic lifecycle of a user managed cache: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=userManagedCacheExample] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=userManagedCacheExample] ---- <1> Create a `UserManagedCache` instance. You can either pass `true` to have the builder `init()` it for you, @@ -102,7 +102,7 @@ If you want to use disk persistent cache, you will need to create and lifecycle [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=persistentUserManagedCache] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/UserManagedCaches.java[tag=persistentUserManagedCache] ---- <1> Create the persistence service to be used by the cache for storing data on disk. @@ -125,7 +125,7 @@ For more information on cache event listeners, see the section < Provide the `ExecutorService` for ordered and unordered event delivery. diff --git a/docs/src/docs/asciidoc/user/writers.adoc b/docs/src/docs/asciidoc/user/writers.adoc index 28b56dcfad..e180f52f8e 100644 --- a/docs/src/docs/asciidoc/user/writers.adoc +++ b/docs/src/docs/asciidoc/user/writers.adoc @@ -74,7 +74,7 @@ After this time has elapsed, the batch is processed even if incomplete. [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeThroughCache] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeThroughCache] ---- <1> We register a sample `CacheLoaderWriter` that knows about the mapping ("41L" maps to "zero"). @@ -86,7 +86,7 @@ The returned mapping will populate the cache and be returned to the caller. [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeBehindCache] +include::{sourcedir39}/ehcache-impl/src/test/java/org/ehcache/docs/GettingStarted.java[tag=writeBehindCache] ---- <1> For write-behind you need a configured `CacheLoaderWriter`. diff --git a/docs/src/docs/asciidoc/user/xa.adoc b/docs/src/docs/asciidoc/user/xa.adoc index 0271d02928..e03fb2b3d9 100644 --- a/docs/src/docs/asciidoc/user/xa.adoc +++ b/docs/src/docs/asciidoc/user/xa.adoc @@ -65,7 +65,7 @@ Here is an example: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testSimpleXACache] +include::{sourcedir39}/ehcache-transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testSimpleXACache] ---- <1> First start the Bitronix transaction manager. By default, Ehcache will auto-detect it but will throw an exception during the cache manager initialization if BTM isn't started. @@ -96,7 +96,7 @@ Nothing special needs to be configured for this to happen, just ensure that the [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithWriteThrough] +include::{sourcedir39}/ehcache-transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithWriteThrough] ---- <1> First start the Bitronix transaction manager. @@ -122,7 +122,7 @@ Any attempt to access one outside of such context will result in `XACacheExcepti [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testNonTransactionalAccess] +include::{sourcedir39}/ehcache-transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testNonTransactionalAccess] ---- <1> First start the Bitronix transaction manager. @@ -151,7 +151,7 @@ Here is an example: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithThreeTiers] +include::{sourcedir39}/ehcache-transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithThreeTiers] ---- <1> First start the Bitronix transaction manager. @@ -174,7 +174,7 @@ You can create a XML file to configure a `CacheManager`, lookup a specific trans [source%nowrap,xml,indent=0] ---- -include::{sourcedir39}/transactions/src/test/resources/docs/configs/xa-getting-started.xml[tags=gettingStarted] +include::{sourcedir39}/ehcache-transactions/src/test/resources/docs/configs/xa-getting-started.xml[tags=gettingStarted] ---- <1> Declare a `TransactionManagerLookup` that will lookup your transaction manager. @@ -185,7 +185,7 @@ In order to parse an XML configuration, you can use the XmlConfiguration type: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithXMLConfig] +include::{sourcedir39}/ehcache-transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java[tag=testXACacheWithXMLConfig] ---- <1> The Bitronix transaction manager must be started before the cache manager is initialized. @@ -198,7 +198,7 @@ And here is what the BitronixTransactionManagerLookup implementation looks like: [source%nowrap,java,indent=0] ---- -include::{sourcedir39}/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixTransactionManagerLookup.java[tag=BitronixLookup] +include::{sourcedir39}/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixTransactionManagerLookup.java[tag=BitronixLookup] ---- <1> The `TransactionManagerLookup` interface must be implemented and the offer a `no-arg` constructor. diff --git a/docs/src/docs/asciidoc/user/xml.adoc b/docs/src/docs/asciidoc/user/xml.adoc index 0ed5c10431..622e4d15b9 100644 --- a/docs/src/docs/asciidoc/user/xml.adoc +++ b/docs/src/docs/asciidoc/user/xml.adoc @@ -113,7 +113,7 @@ NOTE: If you are obtaining your `CacheManager` through the JSR-107 API, what fol [source,java,indent=0] ---- -include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlConfig] +include::{sourcedir39}/ehcache-xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlConfig] ---- <1> Obtain a `URL` to your XML file's location <2> Instantiate an `XmlConfiguration` passing the XML file's URL to it @@ -126,14 +126,14 @@ to use a `` element from an XML file, e.g. the `/my-config.xml` [source,xml,indent=0] ---- -include::{sourcedir39}/xml/src/test/resources/configs/docs/template-sample.xml[tag=templateSample] +include::{sourcedir39}/ehcache-xml/src/test/resources/configs/docs/template-sample.xml[tag=templateSample] ---- Creating a `CacheConfigurationBuilder` of that `example` `` element, would be done as follows: [source,java,indent=0] ---- -include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] +include::{sourcedir39}/ehcache-xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] ---- <1> Creates a builder, inheriting the capacity constraint of 200 entries <2> The inherent properties can be overridden by simply providing a different value prior to building the `CacheConfiguration` @@ -146,14 +146,14 @@ and the string representation of that object will give you the XML equivalent of [source,java,indent=0] ---- -include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] +include::{sourcedir39}/ehcache-xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTemplate] ---- <1> Creates a builder, inheriting the capacity constraint of 200 entries <2> The inherent properties can be overridden by simply providing a different value prior to building the `CacheConfiguration` [source,java,indent=0] ---- -include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTranslation] +include::{sourcedir39}/ehcache-xml/src/test/java/org/ehcache/docs/GettingStarted.java[tag=xmlTranslation] ---- <1> Instantiate an `XmlConfiguration` passing the cache manager `Configuration` <2> Retrieve the XML representation using the `toString` method. @@ -181,7 +181,7 @@ The simplest use of the multi-configuration features is to embed multiple cache file: [source,xml,indent=0] ---- -include::{sourcedir39}/xml/src/test/resources/configs/docs/multi/multiple-managers.xml[] +include::{sourcedir39}/ehcache-xml/src/test/resources/configs/docs/multi/multiple-managers.xml[] ---- <1> A top-level `` container with namespace declarations for the `multi` and core schemas <2> Each Ehcache configuration is embedded inside a `configuration` tag with a required (unique) `identity` attribute @@ -189,7 +189,7 @@ include::{sourcedir39}/xml/src/test/resources/configs/docs/multi/multiple-manage These embedded configurations can then be retrieved via an `XmlMultiConfiguration` instance built from the XML document. [source,java,indent=0] ---- -include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleManagers] +include::{sourcedir39}/ehcache-xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleManagers] ---- <1> The `XmlMultiConfiguration` is assembled from the XML resource. <2> Once assembled the configuration is built. @@ -201,13 +201,13 @@ Multiple variant configurations for a given manager can be provided by including with a required `type` attribute: [source,xml,indent=0] ---- -include::{sourcedir39}/xml/src/test/resources/configs/docs/multi/multiple-variants.xml[tag=variants] +include::{sourcedir39}/ehcache-xml/src/test/resources/configs/docs/multi/multiple-variants.xml[tag=variants] ---- A specific cache configuration can then be retrieved by choosing both a variant and an identity explicitly on retrieval. [source,java,indent=0] ---- -include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleVariants] +include::{sourcedir39}/ehcache-xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleVariants] ---- The samples above are just samples, variant types can be used to represent any kind of variation: development vs production, clustered vs unclustered, red vs blue, etc. @@ -223,7 +223,7 @@ Multiple cache managers can be retrieved from an `XmlMultiConfiguration` by iter `identities()`: [source,java,indent=0] ---- -include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleRetrieval] +include::{sourcedir39}/ehcache-xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=multipleRetrieval] ---- <1> From a stream over the set of identities in a mult-configuration. <2> Map each identity to it's unique (non-varianted) configuration. @@ -237,7 +237,7 @@ of parsing XML multi-configuration documents are all just simple invocations of Configurations can be built from scratch as show below: [source,java,indent=0] ---- -include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=building] +include::{sourcedir39}/ehcache-xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=building] ---- <1> Starting with an initially empty set of configurations. <2> Add a configuration without variants. @@ -247,7 +247,7 @@ include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.ja They can also be built from existing configurations: [source,java,indent=0] ---- -include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=modifying] +include::{sourcedir39}/ehcache-xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=modifying] ---- <1> Starting with an existing `XmlMultiConfiguration`. <2> Remove the configuration with identity `"foo"`. @@ -255,7 +255,7 @@ include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.ja Once built a multi-configuration can be retrieved in XML form: [source,java,indent=0] ---- -include::{sourcedir39}/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=rendering] +include::{sourcedir39}/ehcache-xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java[tag=rendering] ---- <1> Retrieving the XML as a rendered string. <2> Retrieving the XML as a DOM (`org.w3c.Document`). diff --git a/docs/src/docs/asciidoc/user/xsds.adoc b/docs/src/docs/asciidoc/user/xsds.adoc index 75efb3acb4..879fc7c3e7 100644 --- a/docs/src/docs/asciidoc/user/xsds.adoc +++ b/docs/src/docs/asciidoc/user/xsds.adoc @@ -63,7 +63,7 @@ endif::notBuildingForSite[] [source,xml,indent=0] ---- -include::{sourcedir39}/107/src/test/resources/org/ehcache/docs/public-xsds-location.xml[tag=xsdLocations] +include::{sourcedir39}/ehcache-107/src/test/resources/org/ehcache/docs/public-xsds-location.xml[tag=xsdLocations] ---- [[core]] @@ -71,7 +71,7 @@ include::{sourcedir39}/107/src/test/resources/org/ehcache/docs/public-xsds-locat [source,xsd,indent=0] ---- -include::{sourcedir39}/xml/src/main/resources/ehcache-core.xsd[lines=18..-1] +include::{sourcedir39}/ehcache-xml/src/main/schema/ehcache-core.xsd[lines=18..-1] ---- [[jsr-107-extension]] @@ -79,12 +79,12 @@ include::{sourcedir39}/xml/src/main/resources/ehcache-core.xsd[lines=18..-1] [source,xsd,indent=0] ---- -include::{sourcedir39}/107/src/main/resources/ehcache-107-ext.xsd[lines=18..-1] +include::{sourcedir39}/ehcache-107/src/main/resources/ehcache-107-ext.xsd[lines=18..-1] ---- == XA transactions extension [source,xsd,indent=0] ---- -include::{sourcedir39}/transactions/src/main/resources/ehcache-tx-ext.xsd[lines=18..-1] +include::{sourcedir39}/ehcache-transactions/src/main/resources/ehcache-tx-ext.xsd[lines=18..-1] ---- diff --git a/107/README.adoc b/ehcache-107/README.adoc similarity index 98% rename from 107/README.adoc rename to ehcache-107/README.adoc index c9d4e422a3..65e8d93be6 100644 --- a/107/README.adoc +++ b/ehcache-107/README.adoc @@ -54,7 +54,6 @@ constraint. All is needed is adding a jsr107 service in your XML configuration f [source,xml] ---- diff --git a/107/build.gradle b/ehcache-107/build.gradle similarity index 86% rename from 107/build.gradle rename to ehcache-107/build.gradle index a976458daa..035a2dd193 100644 --- a/107/build.gradle +++ b/ehcache-107/build.gradle @@ -15,9 +15,14 @@ */ plugins { - id 'biz.aQute.bnd.builder' - id 'org.jayware.osgi-ds' - id 'org.ehcache.build.deploy' + id 'org.ehcache.build.internal-module' +} + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache 3 JSR-107 module' + description = 'The JSR-107 compatibility module of Ehcache 3' + } } configurations { @@ -44,11 +49,11 @@ sourceSets { } dependencies { - api project(':api') - providedApi "javax.cache:cache-api:$parent.jcacheVersion" + api project(':ehcache-api') + api "javax.cache:cache-api:$parent.jcacheVersion" - implementation project(':impl') - implementation project(':xml') + implementation project(':ehcache-impl') + implementation project(':ehcache-xml') implementation "org.terracotta:statistics:$statisticVersion" compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' @@ -70,7 +75,7 @@ jar { ) } -task unpackTckTests(type: Copy) { +task unpackTckTests(type: Sync) { from { configurations.tckTestClasses.collect {zipTree(it)} } diff --git a/107/config/checkstyle-suppressions.xml b/ehcache-107/config/checkstyle-suppressions.xml similarity index 100% rename from 107/config/checkstyle-suppressions.xml rename to ehcache-107/config/checkstyle-suppressions.xml diff --git a/107/src/main/java/org/ehcache/jsr107/CacheResources.java b/ehcache-107/src/main/java/org/ehcache/jsr107/CacheResources.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/CacheResources.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/CacheResources.java diff --git a/107/src/main/java/org/ehcache/jsr107/CloseUtil.java b/ehcache-107/src/main/java/org/ehcache/jsr107/CloseUtil.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/CloseUtil.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/CloseUtil.java diff --git a/107/src/main/java/org/ehcache/jsr107/ConfigurationMerger.java b/ehcache-107/src/main/java/org/ehcache/jsr107/ConfigurationMerger.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/ConfigurationMerger.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/ConfigurationMerger.java diff --git a/107/src/main/java/org/ehcache/jsr107/DefaultConfigurationResolver.java b/ehcache-107/src/main/java/org/ehcache/jsr107/DefaultConfigurationResolver.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/DefaultConfigurationResolver.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/DefaultConfigurationResolver.java diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107Cache.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Eh107Cache.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Eh107Cache.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Eh107Cache.java diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107CacheEntryEvent.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Eh107CacheEntryEvent.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Eh107CacheEntryEvent.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Eh107CacheEntryEvent.java diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107CacheLoaderWriter.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Eh107CacheLoaderWriter.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Eh107CacheLoaderWriter.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Eh107CacheLoaderWriter.java diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107CacheLoaderWriterProvider.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Eh107CacheLoaderWriterProvider.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Eh107CacheLoaderWriterProvider.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Eh107CacheLoaderWriterProvider.java diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107CacheMXBean.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Eh107CacheMXBean.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Eh107CacheMXBean.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Eh107CacheMXBean.java diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107CacheManager.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Eh107CacheManager.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Eh107CacheManager.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Eh107CacheManager.java diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Eh107CacheStatisticsMXBean.java diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107CompleteConfiguration.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Eh107CompleteConfiguration.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Eh107CompleteConfiguration.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Eh107CompleteConfiguration.java diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107Configuration.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Eh107Configuration.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Eh107Configuration.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Eh107Configuration.java diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107Expiry.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Eh107Expiry.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Eh107Expiry.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Eh107Expiry.java diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107IdentityCopier.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Eh107IdentityCopier.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Eh107IdentityCopier.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Eh107IdentityCopier.java diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107MXBean.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Eh107MXBean.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Eh107MXBean.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Eh107MXBean.java diff --git a/107/src/main/java/org/ehcache/jsr107/Eh107ReverseConfiguration.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Eh107ReverseConfiguration.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Eh107ReverseConfiguration.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Eh107ReverseConfiguration.java diff --git a/107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java b/ehcache-107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/EhcacheCachingProvider.java diff --git a/107/src/main/java/org/ehcache/jsr107/EhcacheExpiryWrapper.java b/ehcache-107/src/main/java/org/ehcache/jsr107/EhcacheExpiryWrapper.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/EhcacheExpiryWrapper.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/EhcacheExpiryWrapper.java diff --git a/107/src/main/java/org/ehcache/jsr107/EventListenerAdaptors.java b/ehcache-107/src/main/java/org/ehcache/jsr107/EventListenerAdaptors.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/EventListenerAdaptors.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/EventListenerAdaptors.java diff --git a/107/src/main/java/org/ehcache/jsr107/ExpiryPolicyToEhcacheExpiry.java b/ehcache-107/src/main/java/org/ehcache/jsr107/ExpiryPolicyToEhcacheExpiry.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/ExpiryPolicyToEhcacheExpiry.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/ExpiryPolicyToEhcacheExpiry.java diff --git a/107/src/main/java/org/ehcache/jsr107/Jsr107Service.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Jsr107Service.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Jsr107Service.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Jsr107Service.java diff --git a/107/src/main/java/org/ehcache/jsr107/ListenerResources.java b/ehcache-107/src/main/java/org/ehcache/jsr107/ListenerResources.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/ListenerResources.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/ListenerResources.java diff --git a/107/src/main/java/org/ehcache/jsr107/NullCompletionListener.java b/ehcache-107/src/main/java/org/ehcache/jsr107/NullCompletionListener.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/NullCompletionListener.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/NullCompletionListener.java diff --git a/107/src/main/java/org/ehcache/jsr107/Unwrap.java b/ehcache-107/src/main/java/org/ehcache/jsr107/Unwrap.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/Unwrap.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/Unwrap.java diff --git a/107/src/main/java/org/ehcache/jsr107/config/ConfigurationElementState.java b/ehcache-107/src/main/java/org/ehcache/jsr107/config/ConfigurationElementState.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/config/ConfigurationElementState.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/config/ConfigurationElementState.java diff --git a/107/src/main/java/org/ehcache/jsr107/config/Jsr107CacheConfiguration.java b/ehcache-107/src/main/java/org/ehcache/jsr107/config/Jsr107CacheConfiguration.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/config/Jsr107CacheConfiguration.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/config/Jsr107CacheConfiguration.java diff --git a/107/src/main/java/org/ehcache/jsr107/config/Jsr107Configuration.java b/ehcache-107/src/main/java/org/ehcache/jsr107/config/Jsr107Configuration.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/config/Jsr107Configuration.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/config/Jsr107Configuration.java diff --git a/107/src/main/java/org/ehcache/jsr107/config/package-info.java b/ehcache-107/src/main/java/org/ehcache/jsr107/config/package-info.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/config/package-info.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/config/package-info.java diff --git a/107/src/main/java/org/ehcache/jsr107/internal/DefaultJsr107Service.java b/ehcache-107/src/main/java/org/ehcache/jsr107/internal/DefaultJsr107Service.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/internal/DefaultJsr107Service.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/internal/DefaultJsr107Service.java diff --git a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java b/ehcache-107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParser.java diff --git a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheLoaderWriter.java b/ehcache-107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheLoaderWriter.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheLoaderWriter.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/internal/Jsr107CacheLoaderWriter.java diff --git a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107LatencyMonitor.java b/ehcache-107/src/main/java/org/ehcache/jsr107/internal/Jsr107LatencyMonitor.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/internal/Jsr107LatencyMonitor.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/internal/Jsr107LatencyMonitor.java diff --git a/107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java b/ehcache-107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParser.java diff --git a/107/src/main/java/org/ehcache/jsr107/internal/WrappedCacheLoaderWriter.java b/ehcache-107/src/main/java/org/ehcache/jsr107/internal/WrappedCacheLoaderWriter.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/internal/WrappedCacheLoaderWriter.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/internal/WrappedCacheLoaderWriter.java diff --git a/107/src/main/java/org/ehcache/jsr107/internal/tck/Eh107MBeanServerBuilder.java b/ehcache-107/src/main/java/org/ehcache/jsr107/internal/tck/Eh107MBeanServerBuilder.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/internal/tck/Eh107MBeanServerBuilder.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/internal/tck/Eh107MBeanServerBuilder.java diff --git a/107/src/main/java/org/ehcache/jsr107/package-info.java b/ehcache-107/src/main/java/org/ehcache/jsr107/package-info.java similarity index 100% rename from 107/src/main/java/org/ehcache/jsr107/package-info.java rename to ehcache-107/src/main/java/org/ehcache/jsr107/package-info.java diff --git a/107/src/main/resources/META-INF/services/javax.cache.spi.CachingProvider b/ehcache-107/src/main/resources/META-INF/services/javax.cache.spi.CachingProvider similarity index 100% rename from 107/src/main/resources/META-INF/services/javax.cache.spi.CachingProvider rename to ehcache-107/src/main/resources/META-INF/services/javax.cache.spi.CachingProvider diff --git a/107/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser b/ehcache-107/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser similarity index 100% rename from 107/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser rename to ehcache-107/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser diff --git a/107/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser b/ehcache-107/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser similarity index 100% rename from 107/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser rename to ehcache-107/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser diff --git a/107/src/main/resources/ehcache-107-ext.xsd b/ehcache-107/src/main/resources/ehcache-107-ext.xsd similarity index 100% rename from 107/src/main/resources/ehcache-107-ext.xsd rename to ehcache-107/src/main/resources/ehcache-107-ext.xsd diff --git a/107/src/tck/resources/ExcludeList b/ehcache-107/src/tck/resources/ExcludeList similarity index 100% rename from 107/src/tck/resources/ExcludeList rename to ehcache-107/src/tck/resources/ExcludeList diff --git a/107/src/test/java/com/pany/domain/Client.java b/ehcache-107/src/test/java/com/pany/domain/Client.java similarity index 100% rename from 107/src/test/java/com/pany/domain/Client.java rename to ehcache-107/src/test/java/com/pany/domain/Client.java diff --git a/107/src/test/java/com/pany/domain/Customer.java b/ehcache-107/src/test/java/com/pany/domain/Customer.java similarity index 100% rename from 107/src/test/java/com/pany/domain/Customer.java rename to ehcache-107/src/test/java/com/pany/domain/Customer.java diff --git a/107/src/test/java/com/pany/domain/Product.java b/ehcache-107/src/test/java/com/pany/domain/Product.java similarity index 100% rename from 107/src/test/java/com/pany/domain/Product.java rename to ehcache-107/src/test/java/com/pany/domain/Product.java diff --git a/107/src/test/java/com/pany/ehcache/ClientCopier.java b/ehcache-107/src/test/java/com/pany/ehcache/ClientCopier.java similarity index 100% rename from 107/src/test/java/com/pany/ehcache/ClientCopier.java rename to ehcache-107/src/test/java/com/pany/ehcache/ClientCopier.java diff --git a/107/src/test/java/com/pany/ehcache/MyEvictionAdvisor.java b/ehcache-107/src/test/java/com/pany/ehcache/MyEvictionAdvisor.java similarity index 100% rename from 107/src/test/java/com/pany/ehcache/MyEvictionAdvisor.java rename to ehcache-107/src/test/java/com/pany/ehcache/MyEvictionAdvisor.java diff --git a/107/src/test/java/com/pany/ehcache/Test107CacheEntryListener.java b/ehcache-107/src/test/java/com/pany/ehcache/Test107CacheEntryListener.java similarity index 100% rename from 107/src/test/java/com/pany/ehcache/Test107CacheEntryListener.java rename to ehcache-107/src/test/java/com/pany/ehcache/Test107CacheEntryListener.java diff --git a/107/src/test/java/com/pany/ehcache/TestCacheEventListener.java b/ehcache-107/src/test/java/com/pany/ehcache/TestCacheEventListener.java similarity index 100% rename from 107/src/test/java/com/pany/ehcache/TestCacheEventListener.java rename to ehcache-107/src/test/java/com/pany/ehcache/TestCacheEventListener.java diff --git a/107/src/test/java/com/pany/ehcache/integration/ProductCacheLoaderWriter.java b/ehcache-107/src/test/java/com/pany/ehcache/integration/ProductCacheLoaderWriter.java similarity index 100% rename from 107/src/test/java/com/pany/ehcache/integration/ProductCacheLoaderWriter.java rename to ehcache-107/src/test/java/com/pany/ehcache/integration/ProductCacheLoaderWriter.java diff --git a/107/src/test/java/org/ehcache/ParsesConfigurationExtensionTest.java b/ehcache-107/src/test/java/org/ehcache/ParsesConfigurationExtensionTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/ParsesConfigurationExtensionTest.java rename to ehcache-107/src/test/java/org/ehcache/ParsesConfigurationExtensionTest.java diff --git a/107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java b/ehcache-107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java rename to ehcache-107/src/test/java/org/ehcache/docs/EhCache107ConfigurationIntegrationDocTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/CacheResourcesTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/CacheResourcesTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/CacheResourcesTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/CacheResourcesTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/ConfigStatsManagementActivationTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/ConfigStatsManagementActivationTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/ConfigStatsManagementActivationTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/ConfigStatsManagementActivationTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/ConfigurationMergerTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/DefaultConfigurationResolverTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/DefaultConfigurationResolverTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/DefaultConfigurationResolverTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/DefaultConfigurationResolverTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/Eh107CacheTypeTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/Eh107CacheTypeTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/Eh107CacheTypeTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/Eh107CacheTypeTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/Eh107XmlIntegrationTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/Eh107XmlIntegrationTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/Eh107XmlIntegrationTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/Eh107XmlIntegrationTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/EhCachingProviderTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/EhCachingProviderTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/EhCachingProviderTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/EhCachingProviderTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/IteratorTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/IteratorTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/IteratorTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/IteratorTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/Jsr107CacheParserIT.java b/ehcache-107/src/test/java/org/ehcache/jsr107/Jsr107CacheParserIT.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/Jsr107CacheParserIT.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/Jsr107CacheParserIT.java diff --git a/107/src/test/java/org/ehcache/jsr107/LoadAtomicsWith107Test.java b/ehcache-107/src/test/java/org/ehcache/jsr107/LoadAtomicsWith107Test.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/LoadAtomicsWith107Test.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/LoadAtomicsWith107Test.java diff --git a/107/src/test/java/org/ehcache/jsr107/LoaderWriterConfigTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/LoaderWriterConfigTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/LoaderWriterConfigTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/LoaderWriterConfigTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/LoaderWriterTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/LoaderWriterTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/LoaderWriterTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/LoaderWriterTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/LongSerializer.java b/ehcache-107/src/test/java/org/ehcache/jsr107/LongSerializer.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/LongSerializer.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/LongSerializer.java diff --git a/107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/ResourceCombinationsTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/SerializerTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/SerializerTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/SerializerTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/SerializerTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/SimpleEh107ConfigTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/SimpleEh107ConfigTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/SimpleEh107ConfigTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/SimpleEh107ConfigTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/StatisticsTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/StatisticsTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/StatisticsTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/StatisticsTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/StringSerializer.java b/ehcache-107/src/test/java/org/ehcache/jsr107/StringSerializer.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/StringSerializer.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/StringSerializer.java diff --git a/107/src/test/java/org/ehcache/jsr107/UnwrapTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/UnwrapTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/UnwrapTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/UnwrapTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParserTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParserTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParserTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/internal/Jsr107CacheConfigurationParserTest.java diff --git a/107/src/test/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParserTest.java b/ehcache-107/src/test/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParserTest.java similarity index 100% rename from 107/src/test/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParserTest.java rename to ehcache-107/src/test/java/org/ehcache/jsr107/internal/Jsr107ServiceConfigurationParserTest.java diff --git a/107/src/test/resources/ehcache-107-copiers-immutable-types.xml b/ehcache-107/src/test/resources/ehcache-107-copiers-immutable-types.xml similarity index 97% rename from 107/src/test/resources/ehcache-107-copiers-immutable-types.xml rename to ehcache-107/src/test/resources/ehcache-107-copiers-immutable-types.xml index d2499af468..366d4f5127 100644 --- a/107/src/test/resources/ehcache-107-copiers-immutable-types.xml +++ b/ehcache-107/src/test/resources/ehcache-107-copiers-immutable-types.xml @@ -15,7 +15,6 @@ --> diff --git a/107/src/test/resources/ehcache-107-default-copiers.xml b/ehcache-107/src/test/resources/ehcache-107-default-copiers.xml similarity index 95% rename from 107/src/test/resources/ehcache-107-default-copiers.xml rename to ehcache-107/src/test/resources/ehcache-107-default-copiers.xml index a484c01976..5c707f0335 100644 --- a/107/src/test/resources/ehcache-107-default-copiers.xml +++ b/ehcache-107/src/test/resources/ehcache-107-default-copiers.xml @@ -15,7 +15,6 @@ --> diff --git a/107/src/test/resources/ehcache-107-immutable-types-cm-level-copiers.xml b/ehcache-107/src/test/resources/ehcache-107-immutable-types-cm-level-copiers.xml similarity index 97% rename from 107/src/test/resources/ehcache-107-immutable-types-cm-level-copiers.xml rename to ehcache-107/src/test/resources/ehcache-107-immutable-types-cm-level-copiers.xml index db38f60436..8882458718 100644 --- a/107/src/test/resources/ehcache-107-immutable-types-cm-level-copiers.xml +++ b/ehcache-107/src/test/resources/ehcache-107-immutable-types-cm-level-copiers.xml @@ -15,7 +15,6 @@ --> diff --git a/107/src/test/resources/ehcache-107-integration.xml b/ehcache-107/src/test/resources/ehcache-107-integration.xml similarity index 100% rename from 107/src/test/resources/ehcache-107-integration.xml rename to ehcache-107/src/test/resources/ehcache-107-integration.xml diff --git a/107/src/test/resources/ehcache-107-listeners.xml b/ehcache-107/src/test/resources/ehcache-107-listeners.xml similarity index 80% rename from 107/src/test/resources/ehcache-107-listeners.xml rename to ehcache-107/src/test/resources/ehcache-107-listeners.xml index 27cd72c308..eb460261ee 100644 --- a/107/src/test/resources/ehcache-107-listeners.xml +++ b/ehcache-107/src/test/resources/ehcache-107-listeners.xml @@ -16,11 +16,8 @@ --> + xmlns:jsr107='http://www.ehcache.org/v3/jsr107'> diff --git a/107/src/test/resources/ehcache-107-mbeans-cache-config.xml b/ehcache-107/src/test/resources/ehcache-107-mbeans-cache-config.xml similarity index 74% rename from 107/src/test/resources/ehcache-107-mbeans-cache-config.xml rename to ehcache-107/src/test/resources/ehcache-107-mbeans-cache-config.xml index 8310e2c1fe..ca599c2396 100644 --- a/107/src/test/resources/ehcache-107-mbeans-cache-config.xml +++ b/ehcache-107/src/test/resources/ehcache-107-mbeans-cache-config.xml @@ -15,11 +15,8 @@ --> + xmlns:jsr107='http://www.ehcache.org/v3/jsr107'> java.lang.String diff --git a/107/src/test/resources/ehcache-107-mbeans-template-config.xml b/ehcache-107/src/test/resources/ehcache-107-mbeans-template-config.xml similarity index 78% rename from 107/src/test/resources/ehcache-107-mbeans-template-config.xml rename to ehcache-107/src/test/resources/ehcache-107-mbeans-template-config.xml index dd34c9d2c3..430984105e 100644 --- a/107/src/test/resources/ehcache-107-mbeans-template-config.xml +++ b/ehcache-107/src/test/resources/ehcache-107-mbeans-template-config.xml @@ -15,11 +15,8 @@ --> + xmlns:jsr107='http://www.ehcache.org/v3/jsr107'> diff --git a/107/src/test/resources/ehcache-107-serializer.xml b/ehcache-107/src/test/resources/ehcache-107-serializer.xml similarity index 69% rename from 107/src/test/resources/ehcache-107-serializer.xml rename to ehcache-107/src/test/resources/ehcache-107-serializer.xml index b46cf8f7d4..8d8deec44e 100644 --- a/107/src/test/resources/ehcache-107-serializer.xml +++ b/ehcache-107/src/test/resources/ehcache-107-serializer.xml @@ -1,10 +1,6 @@ + xmlns:ehcache='http://www.ehcache.org/v3'> org.ehcache.impl.serialization.CompactJavaSerializer diff --git a/107/src/test/resources/ehcache-107-stats.xml b/ehcache-107/src/test/resources/ehcache-107-stats.xml similarity index 73% rename from 107/src/test/resources/ehcache-107-stats.xml rename to ehcache-107/src/test/resources/ehcache-107-stats.xml index 2d66203801..909732857e 100644 --- a/107/src/test/resources/ehcache-107-stats.xml +++ b/ehcache-107/src/test/resources/ehcache-107-stats.xml @@ -1,9 +1,6 @@ + xmlns:jsr107='http://www.ehcache.org/v3/jsr107'> diff --git a/107/src/test/resources/ehcache-107-types.xml b/ehcache-107/src/test/resources/ehcache-107-types.xml similarity index 100% rename from 107/src/test/resources/ehcache-107-types.xml rename to ehcache-107/src/test/resources/ehcache-107-types.xml diff --git a/107/src/test/resources/ehcache-107.xml b/ehcache-107/src/test/resources/ehcache-107.xml similarity index 61% rename from 107/src/test/resources/ehcache-107.xml rename to ehcache-107/src/test/resources/ehcache-107.xml index fa18f703e4..cd32783126 100644 --- a/107/src/test/resources/ehcache-107.xml +++ b/ehcache-107/src/test/resources/ehcache-107.xml @@ -1,9 +1,6 @@ + xmlns:jsr107='http://www.ehcache.org/v3/jsr107'> diff --git a/107/src/test/resources/ehcache-example.xml b/ehcache-107/src/test/resources/ehcache-example.xml similarity index 100% rename from 107/src/test/resources/ehcache-example.xml rename to ehcache-107/src/test/resources/ehcache-example.xml diff --git a/107/src/test/resources/ehcache-loader-writer-107-load-atomics.xml b/ehcache-107/src/test/resources/ehcache-loader-writer-107-load-atomics.xml similarity index 89% rename from 107/src/test/resources/ehcache-loader-writer-107-load-atomics.xml rename to ehcache-107/src/test/resources/ehcache-loader-writer-107-load-atomics.xml index 3cf28037f4..b8febe0ce1 100644 --- a/107/src/test/resources/ehcache-loader-writer-107-load-atomics.xml +++ b/ehcache-107/src/test/resources/ehcache-loader-writer-107-load-atomics.xml @@ -1,5 +1,4 @@ diff --git a/107/src/test/resources/ehcache-loader-writer-107.xml b/ehcache-107/src/test/resources/ehcache-loader-writer-107.xml similarity index 88% rename from 107/src/test/resources/ehcache-loader-writer-107.xml rename to ehcache-107/src/test/resources/ehcache-loader-writer-107.xml index ee84dd73ba..01a332c67b 100644 --- a/107/src/test/resources/ehcache-loader-writer-107.xml +++ b/ehcache-107/src/test/resources/ehcache-loader-writer-107.xml @@ -1,5 +1,4 @@ diff --git a/107/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml b/ehcache-107/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml similarity index 81% rename from 107/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml rename to ehcache-107/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml index bebec36a39..5bf3687b4e 100644 --- a/107/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml +++ b/ehcache-107/src/test/resources/org/ehcache/docs/ehcache-107-mbeans-cache-manager-config.xml @@ -15,12 +15,8 @@ --> + xmlns:jsr107='http://www.ehcache.org/v3/jsr107'> diff --git a/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml b/ehcache-107/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml similarity index 93% rename from 107/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml rename to ehcache-107/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml index 1061bc0b6d..f587c97f35 100644 --- a/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml +++ b/ehcache-107/src/test/resources/org/ehcache/docs/ehcache-jsr107-cache-through.xml @@ -15,7 +15,6 @@ --> diff --git a/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml b/ehcache-107/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml similarity index 57% rename from 107/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml rename to ehcache-107/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml index b52a370326..2a38ad11f9 100644 --- a/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml +++ b/ehcache-107/src/test/resources/org/ehcache/docs/ehcache-jsr107-config.xml @@ -1,8 +1,4 @@ - + java.lang.Long diff --git a/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml b/ehcache-107/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml similarity index 85% rename from 107/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml rename to ehcache-107/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml index c50dc33616..1e2599caf6 100644 --- a/107/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml +++ b/ehcache-107/src/test/resources/org/ehcache/docs/ehcache-jsr107-template-override.xml @@ -1,10 +1,6 @@ + xmlns:jsr107='http://www.ehcache.org/v3/jsr107'> diff --git a/107/src/test/resources/org/ehcache/docs/public-xsds-location.xml b/ehcache-107/src/test/resources/org/ehcache/docs/public-xsds-location.xml similarity index 100% rename from 107/src/test/resources/org/ehcache/docs/public-xsds-location.xml rename to ehcache-107/src/test/resources/org/ehcache/docs/public-xsds-location.xml diff --git a/api/build.gradle b/ehcache-api/build.gradle similarity index 72% rename from api/build.gradle rename to ehcache-api/build.gradle index 0ea554e654..c32a4fa5e2 100644 --- a/api/build.gradle +++ b/ehcache-api/build.gradle @@ -15,8 +15,14 @@ */ plugins { - id 'org.ehcache.build.deploy' - id 'biz.aQute.bnd.builder' + id 'org.ehcache.build.internal-module' +} + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache 3 API module' + description = 'The API module of Ehcache 3' + } } checkstyle { @@ -30,4 +36,5 @@ jar { ) } -check.dependsOn(baseline) +//TODO : Baseline task is broken pending Gradle artifact resolution fixes +//check.dependsOn(baseline) diff --git a/api/config/checkstyle-suppressions.xml b/ehcache-api/config/checkstyle-suppressions.xml similarity index 100% rename from api/config/checkstyle-suppressions.xml rename to ehcache-api/config/checkstyle-suppressions.xml diff --git a/api/config/checkstyle.xml b/ehcache-api/config/checkstyle.xml similarity index 97% rename from api/config/checkstyle.xml rename to ehcache-api/config/checkstyle.xml index 796ef315bc..945a03c384 100644 --- a/api/config/checkstyle.xml +++ b/ehcache-api/config/checkstyle.xml @@ -45,7 +45,6 @@ - diff --git a/api/src/main/java/org/ehcache/Cache.java b/ehcache-api/src/main/java/org/ehcache/Cache.java similarity index 100% rename from api/src/main/java/org/ehcache/Cache.java rename to ehcache-api/src/main/java/org/ehcache/Cache.java diff --git a/api/src/main/java/org/ehcache/CacheIterationException.java b/ehcache-api/src/main/java/org/ehcache/CacheIterationException.java similarity index 100% rename from api/src/main/java/org/ehcache/CacheIterationException.java rename to ehcache-api/src/main/java/org/ehcache/CacheIterationException.java diff --git a/api/src/main/java/org/ehcache/CacheManager.java b/ehcache-api/src/main/java/org/ehcache/CacheManager.java similarity index 100% rename from api/src/main/java/org/ehcache/CacheManager.java rename to ehcache-api/src/main/java/org/ehcache/CacheManager.java diff --git a/api/src/main/java/org/ehcache/CachePersistenceException.java b/ehcache-api/src/main/java/org/ehcache/CachePersistenceException.java similarity index 100% rename from api/src/main/java/org/ehcache/CachePersistenceException.java rename to ehcache-api/src/main/java/org/ehcache/CachePersistenceException.java diff --git a/api/src/main/java/org/ehcache/PersistentCacheManager.java b/ehcache-api/src/main/java/org/ehcache/PersistentCacheManager.java similarity index 100% rename from api/src/main/java/org/ehcache/PersistentCacheManager.java rename to ehcache-api/src/main/java/org/ehcache/PersistentCacheManager.java diff --git a/api/src/main/java/org/ehcache/PersistentUserManagedCache.java b/ehcache-api/src/main/java/org/ehcache/PersistentUserManagedCache.java similarity index 100% rename from api/src/main/java/org/ehcache/PersistentUserManagedCache.java rename to ehcache-api/src/main/java/org/ehcache/PersistentUserManagedCache.java diff --git a/api/src/main/java/org/ehcache/StateTransitionException.java b/ehcache-api/src/main/java/org/ehcache/StateTransitionException.java similarity index 100% rename from api/src/main/java/org/ehcache/StateTransitionException.java rename to ehcache-api/src/main/java/org/ehcache/StateTransitionException.java diff --git a/api/src/main/java/org/ehcache/Status.java b/ehcache-api/src/main/java/org/ehcache/Status.java similarity index 100% rename from api/src/main/java/org/ehcache/Status.java rename to ehcache-api/src/main/java/org/ehcache/Status.java diff --git a/api/src/main/java/org/ehcache/UserManagedCache.java b/ehcache-api/src/main/java/org/ehcache/UserManagedCache.java similarity index 100% rename from api/src/main/java/org/ehcache/UserManagedCache.java rename to ehcache-api/src/main/java/org/ehcache/UserManagedCache.java diff --git a/api/src/main/java/org/ehcache/ValueSupplier.java b/ehcache-api/src/main/java/org/ehcache/ValueSupplier.java similarity index 100% rename from api/src/main/java/org/ehcache/ValueSupplier.java rename to ehcache-api/src/main/java/org/ehcache/ValueSupplier.java diff --git a/api/src/main/java/org/ehcache/config/Builder.java b/ehcache-api/src/main/java/org/ehcache/config/Builder.java similarity index 100% rename from api/src/main/java/org/ehcache/config/Builder.java rename to ehcache-api/src/main/java/org/ehcache/config/Builder.java diff --git a/api/src/main/java/org/ehcache/config/CacheConfiguration.java b/ehcache-api/src/main/java/org/ehcache/config/CacheConfiguration.java similarity index 100% rename from api/src/main/java/org/ehcache/config/CacheConfiguration.java rename to ehcache-api/src/main/java/org/ehcache/config/CacheConfiguration.java diff --git a/api/src/main/java/org/ehcache/config/CacheRuntimeConfiguration.java b/ehcache-api/src/main/java/org/ehcache/config/CacheRuntimeConfiguration.java similarity index 100% rename from api/src/main/java/org/ehcache/config/CacheRuntimeConfiguration.java rename to ehcache-api/src/main/java/org/ehcache/config/CacheRuntimeConfiguration.java diff --git a/api/src/main/java/org/ehcache/config/Configuration.java b/ehcache-api/src/main/java/org/ehcache/config/Configuration.java similarity index 100% rename from api/src/main/java/org/ehcache/config/Configuration.java rename to ehcache-api/src/main/java/org/ehcache/config/Configuration.java diff --git a/api/src/main/java/org/ehcache/config/Eviction.java b/ehcache-api/src/main/java/org/ehcache/config/Eviction.java similarity index 100% rename from api/src/main/java/org/ehcache/config/Eviction.java rename to ehcache-api/src/main/java/org/ehcache/config/Eviction.java diff --git a/api/src/main/java/org/ehcache/config/EvictionAdvisor.java b/ehcache-api/src/main/java/org/ehcache/config/EvictionAdvisor.java similarity index 100% rename from api/src/main/java/org/ehcache/config/EvictionAdvisor.java rename to ehcache-api/src/main/java/org/ehcache/config/EvictionAdvisor.java diff --git a/api/src/main/java/org/ehcache/config/FluentCacheConfigurationBuilder.java b/ehcache-api/src/main/java/org/ehcache/config/FluentCacheConfigurationBuilder.java similarity index 100% rename from api/src/main/java/org/ehcache/config/FluentCacheConfigurationBuilder.java rename to ehcache-api/src/main/java/org/ehcache/config/FluentCacheConfigurationBuilder.java diff --git a/api/src/main/java/org/ehcache/config/FluentConfigurationBuilder.java b/ehcache-api/src/main/java/org/ehcache/config/FluentConfigurationBuilder.java similarity index 100% rename from api/src/main/java/org/ehcache/config/FluentConfigurationBuilder.java rename to ehcache-api/src/main/java/org/ehcache/config/FluentConfigurationBuilder.java diff --git a/api/src/main/java/org/ehcache/config/ResourcePool.java b/ehcache-api/src/main/java/org/ehcache/config/ResourcePool.java similarity index 100% rename from api/src/main/java/org/ehcache/config/ResourcePool.java rename to ehcache-api/src/main/java/org/ehcache/config/ResourcePool.java diff --git a/api/src/main/java/org/ehcache/config/ResourcePools.java b/ehcache-api/src/main/java/org/ehcache/config/ResourcePools.java similarity index 100% rename from api/src/main/java/org/ehcache/config/ResourcePools.java rename to ehcache-api/src/main/java/org/ehcache/config/ResourcePools.java diff --git a/api/src/main/java/org/ehcache/config/ResourceType.java b/ehcache-api/src/main/java/org/ehcache/config/ResourceType.java similarity index 100% rename from api/src/main/java/org/ehcache/config/ResourceType.java rename to ehcache-api/src/main/java/org/ehcache/config/ResourceType.java diff --git a/api/src/main/java/org/ehcache/config/ResourceUnit.java b/ehcache-api/src/main/java/org/ehcache/config/ResourceUnit.java similarity index 100% rename from api/src/main/java/org/ehcache/config/ResourceUnit.java rename to ehcache-api/src/main/java/org/ehcache/config/ResourceUnit.java diff --git a/api/src/main/java/org/ehcache/config/SizedResourcePool.java b/ehcache-api/src/main/java/org/ehcache/config/SizedResourcePool.java similarity index 100% rename from api/src/main/java/org/ehcache/config/SizedResourcePool.java rename to ehcache-api/src/main/java/org/ehcache/config/SizedResourcePool.java diff --git a/api/src/main/java/org/ehcache/config/package-info.java b/ehcache-api/src/main/java/org/ehcache/config/package-info.java similarity index 100% rename from api/src/main/java/org/ehcache/config/package-info.java rename to ehcache-api/src/main/java/org/ehcache/config/package-info.java diff --git a/api/src/main/java/org/ehcache/config/units/EntryUnit.java b/ehcache-api/src/main/java/org/ehcache/config/units/EntryUnit.java similarity index 100% rename from api/src/main/java/org/ehcache/config/units/EntryUnit.java rename to ehcache-api/src/main/java/org/ehcache/config/units/EntryUnit.java diff --git a/api/src/main/java/org/ehcache/config/units/MemoryUnit.java b/ehcache-api/src/main/java/org/ehcache/config/units/MemoryUnit.java similarity index 100% rename from api/src/main/java/org/ehcache/config/units/MemoryUnit.java rename to ehcache-api/src/main/java/org/ehcache/config/units/MemoryUnit.java diff --git a/api/src/main/java/org/ehcache/config/units/package-info.java b/ehcache-api/src/main/java/org/ehcache/config/units/package-info.java similarity index 100% rename from api/src/main/java/org/ehcache/config/units/package-info.java rename to ehcache-api/src/main/java/org/ehcache/config/units/package-info.java diff --git a/api/src/main/java/org/ehcache/event/CacheEvent.java b/ehcache-api/src/main/java/org/ehcache/event/CacheEvent.java similarity index 100% rename from api/src/main/java/org/ehcache/event/CacheEvent.java rename to ehcache-api/src/main/java/org/ehcache/event/CacheEvent.java diff --git a/api/src/main/java/org/ehcache/event/CacheEventListener.java b/ehcache-api/src/main/java/org/ehcache/event/CacheEventListener.java similarity index 100% rename from api/src/main/java/org/ehcache/event/CacheEventListener.java rename to ehcache-api/src/main/java/org/ehcache/event/CacheEventListener.java diff --git a/api/src/main/java/org/ehcache/event/EventFiring.java b/ehcache-api/src/main/java/org/ehcache/event/EventFiring.java similarity index 100% rename from api/src/main/java/org/ehcache/event/EventFiring.java rename to ehcache-api/src/main/java/org/ehcache/event/EventFiring.java diff --git a/api/src/main/java/org/ehcache/event/EventOrdering.java b/ehcache-api/src/main/java/org/ehcache/event/EventOrdering.java similarity index 100% rename from api/src/main/java/org/ehcache/event/EventOrdering.java rename to ehcache-api/src/main/java/org/ehcache/event/EventOrdering.java diff --git a/api/src/main/java/org/ehcache/event/EventType.java b/ehcache-api/src/main/java/org/ehcache/event/EventType.java similarity index 100% rename from api/src/main/java/org/ehcache/event/EventType.java rename to ehcache-api/src/main/java/org/ehcache/event/EventType.java diff --git a/api/src/main/java/org/ehcache/event/package-info.java b/ehcache-api/src/main/java/org/ehcache/event/package-info.java similarity index 100% rename from api/src/main/java/org/ehcache/event/package-info.java rename to ehcache-api/src/main/java/org/ehcache/event/package-info.java diff --git a/api/src/main/java/org/ehcache/expiry/Duration.java b/ehcache-api/src/main/java/org/ehcache/expiry/Duration.java similarity index 100% rename from api/src/main/java/org/ehcache/expiry/Duration.java rename to ehcache-api/src/main/java/org/ehcache/expiry/Duration.java diff --git a/api/src/main/java/org/ehcache/expiry/Expirations.java b/ehcache-api/src/main/java/org/ehcache/expiry/Expirations.java similarity index 100% rename from api/src/main/java/org/ehcache/expiry/Expirations.java rename to ehcache-api/src/main/java/org/ehcache/expiry/Expirations.java diff --git a/api/src/main/java/org/ehcache/expiry/Expiry.java b/ehcache-api/src/main/java/org/ehcache/expiry/Expiry.java similarity index 100% rename from api/src/main/java/org/ehcache/expiry/Expiry.java rename to ehcache-api/src/main/java/org/ehcache/expiry/Expiry.java diff --git a/api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java b/ehcache-api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java similarity index 100% rename from api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java rename to ehcache-api/src/main/java/org/ehcache/expiry/ExpiryPolicy.java diff --git a/api/src/main/java/org/ehcache/expiry/package-info.java b/ehcache-api/src/main/java/org/ehcache/expiry/package-info.java similarity index 100% rename from api/src/main/java/org/ehcache/expiry/package-info.java rename to ehcache-api/src/main/java/org/ehcache/expiry/package-info.java diff --git a/api/src/main/java/org/ehcache/package-info.java b/ehcache-api/src/main/java/org/ehcache/package-info.java similarity index 100% rename from api/src/main/java/org/ehcache/package-info.java rename to ehcache-api/src/main/java/org/ehcache/package-info.java diff --git a/api/src/main/java/org/ehcache/spi/copy/Copier.java b/ehcache-api/src/main/java/org/ehcache/spi/copy/Copier.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/copy/Copier.java rename to ehcache-api/src/main/java/org/ehcache/spi/copy/Copier.java diff --git a/api/src/main/java/org/ehcache/spi/copy/CopyProvider.java b/ehcache-api/src/main/java/org/ehcache/spi/copy/CopyProvider.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/copy/CopyProvider.java rename to ehcache-api/src/main/java/org/ehcache/spi/copy/CopyProvider.java diff --git a/api/src/main/java/org/ehcache/spi/copy/package-info.java b/ehcache-api/src/main/java/org/ehcache/spi/copy/package-info.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/copy/package-info.java rename to ehcache-api/src/main/java/org/ehcache/spi/copy/package-info.java diff --git a/api/src/main/java/org/ehcache/spi/loaderwriter/BulkCacheLoadingException.java b/ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/BulkCacheLoadingException.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/loaderwriter/BulkCacheLoadingException.java rename to ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/BulkCacheLoadingException.java diff --git a/api/src/main/java/org/ehcache/spi/loaderwriter/BulkCacheWritingException.java b/ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/BulkCacheWritingException.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/loaderwriter/BulkCacheWritingException.java rename to ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/BulkCacheWritingException.java diff --git a/api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriter.java b/ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriter.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriter.java rename to ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriter.java diff --git a/api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterConfiguration.java b/ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterConfiguration.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterConfiguration.java rename to ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterConfiguration.java diff --git a/api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterProvider.java b/ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterProvider.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterProvider.java rename to ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoaderWriterProvider.java diff --git a/api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoadingException.java b/ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoadingException.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoadingException.java rename to ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/CacheLoadingException.java diff --git a/api/src/main/java/org/ehcache/spi/loaderwriter/CacheWritingException.java b/ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/CacheWritingException.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/loaderwriter/CacheWritingException.java rename to ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/CacheWritingException.java diff --git a/api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindConfiguration.java b/ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindConfiguration.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindConfiguration.java rename to ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindConfiguration.java diff --git a/api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindProvider.java b/ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindProvider.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindProvider.java rename to ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/WriteBehindProvider.java diff --git a/api/src/main/java/org/ehcache/spi/loaderwriter/package-info.java b/ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/package-info.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/loaderwriter/package-info.java rename to ehcache-api/src/main/java/org/ehcache/spi/loaderwriter/package-info.java diff --git a/api/src/main/java/org/ehcache/spi/persistence/PersistableResourceService.java b/ehcache-api/src/main/java/org/ehcache/spi/persistence/PersistableResourceService.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/persistence/PersistableResourceService.java rename to ehcache-api/src/main/java/org/ehcache/spi/persistence/PersistableResourceService.java diff --git a/api/src/main/java/org/ehcache/spi/persistence/StateHolder.java b/ehcache-api/src/main/java/org/ehcache/spi/persistence/StateHolder.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/persistence/StateHolder.java rename to ehcache-api/src/main/java/org/ehcache/spi/persistence/StateHolder.java diff --git a/api/src/main/java/org/ehcache/spi/persistence/StateRepository.java b/ehcache-api/src/main/java/org/ehcache/spi/persistence/StateRepository.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/persistence/StateRepository.java rename to ehcache-api/src/main/java/org/ehcache/spi/persistence/StateRepository.java diff --git a/api/src/main/java/org/ehcache/spi/persistence/package-info.java b/ehcache-api/src/main/java/org/ehcache/spi/persistence/package-info.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/persistence/package-info.java rename to ehcache-api/src/main/java/org/ehcache/spi/persistence/package-info.java diff --git a/api/src/main/java/org/ehcache/spi/resilience/RecoveryStore.java b/ehcache-api/src/main/java/org/ehcache/spi/resilience/RecoveryStore.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/resilience/RecoveryStore.java rename to ehcache-api/src/main/java/org/ehcache/spi/resilience/RecoveryStore.java diff --git a/api/src/main/java/org/ehcache/spi/resilience/ResilienceStrategy.java b/ehcache-api/src/main/java/org/ehcache/spi/resilience/ResilienceStrategy.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/resilience/ResilienceStrategy.java rename to ehcache-api/src/main/java/org/ehcache/spi/resilience/ResilienceStrategy.java diff --git a/api/src/main/java/org/ehcache/spi/resilience/ResilienceStrategyProvider.java b/ehcache-api/src/main/java/org/ehcache/spi/resilience/ResilienceStrategyProvider.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/resilience/ResilienceStrategyProvider.java rename to ehcache-api/src/main/java/org/ehcache/spi/resilience/ResilienceStrategyProvider.java diff --git a/api/src/main/java/org/ehcache/spi/resilience/StoreAccessException.java b/ehcache-api/src/main/java/org/ehcache/spi/resilience/StoreAccessException.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/resilience/StoreAccessException.java rename to ehcache-api/src/main/java/org/ehcache/spi/resilience/StoreAccessException.java diff --git a/api/src/main/java/org/ehcache/spi/resilience/package-info.java b/ehcache-api/src/main/java/org/ehcache/spi/resilience/package-info.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/resilience/package-info.java rename to ehcache-api/src/main/java/org/ehcache/spi/resilience/package-info.java diff --git a/api/src/main/java/org/ehcache/spi/serialization/SerializationProvider.java b/ehcache-api/src/main/java/org/ehcache/spi/serialization/SerializationProvider.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/serialization/SerializationProvider.java rename to ehcache-api/src/main/java/org/ehcache/spi/serialization/SerializationProvider.java diff --git a/api/src/main/java/org/ehcache/spi/serialization/Serializer.java b/ehcache-api/src/main/java/org/ehcache/spi/serialization/Serializer.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/serialization/Serializer.java rename to ehcache-api/src/main/java/org/ehcache/spi/serialization/Serializer.java diff --git a/api/src/main/java/org/ehcache/spi/serialization/SerializerException.java b/ehcache-api/src/main/java/org/ehcache/spi/serialization/SerializerException.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/serialization/SerializerException.java rename to ehcache-api/src/main/java/org/ehcache/spi/serialization/SerializerException.java diff --git a/api/src/main/java/org/ehcache/spi/serialization/StatefulSerializer.java b/ehcache-api/src/main/java/org/ehcache/spi/serialization/StatefulSerializer.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/serialization/StatefulSerializer.java rename to ehcache-api/src/main/java/org/ehcache/spi/serialization/StatefulSerializer.java diff --git a/api/src/main/java/org/ehcache/spi/serialization/UnsupportedTypeException.java b/ehcache-api/src/main/java/org/ehcache/spi/serialization/UnsupportedTypeException.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/serialization/UnsupportedTypeException.java rename to ehcache-api/src/main/java/org/ehcache/spi/serialization/UnsupportedTypeException.java diff --git a/api/src/main/java/org/ehcache/spi/serialization/package-info.java b/ehcache-api/src/main/java/org/ehcache/spi/serialization/package-info.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/serialization/package-info.java rename to ehcache-api/src/main/java/org/ehcache/spi/serialization/package-info.java diff --git a/api/src/main/java/org/ehcache/spi/service/MaintainableService.java b/ehcache-api/src/main/java/org/ehcache/spi/service/MaintainableService.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/service/MaintainableService.java rename to ehcache-api/src/main/java/org/ehcache/spi/service/MaintainableService.java diff --git a/api/src/main/java/org/ehcache/spi/service/OptionalServiceDependencies.java b/ehcache-api/src/main/java/org/ehcache/spi/service/OptionalServiceDependencies.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/service/OptionalServiceDependencies.java rename to ehcache-api/src/main/java/org/ehcache/spi/service/OptionalServiceDependencies.java diff --git a/api/src/main/java/org/ehcache/spi/service/PluralService.java b/ehcache-api/src/main/java/org/ehcache/spi/service/PluralService.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/service/PluralService.java rename to ehcache-api/src/main/java/org/ehcache/spi/service/PluralService.java diff --git a/api/src/main/java/org/ehcache/spi/service/Service.java b/ehcache-api/src/main/java/org/ehcache/spi/service/Service.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/service/Service.java rename to ehcache-api/src/main/java/org/ehcache/spi/service/Service.java diff --git a/api/src/main/java/org/ehcache/spi/service/ServiceConfiguration.java b/ehcache-api/src/main/java/org/ehcache/spi/service/ServiceConfiguration.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/service/ServiceConfiguration.java rename to ehcache-api/src/main/java/org/ehcache/spi/service/ServiceConfiguration.java diff --git a/api/src/main/java/org/ehcache/spi/service/ServiceCreationConfiguration.java b/ehcache-api/src/main/java/org/ehcache/spi/service/ServiceCreationConfiguration.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/service/ServiceCreationConfiguration.java rename to ehcache-api/src/main/java/org/ehcache/spi/service/ServiceCreationConfiguration.java diff --git a/api/src/main/java/org/ehcache/spi/service/ServiceDependencies.java b/ehcache-api/src/main/java/org/ehcache/spi/service/ServiceDependencies.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/service/ServiceDependencies.java rename to ehcache-api/src/main/java/org/ehcache/spi/service/ServiceDependencies.java diff --git a/api/src/main/java/org/ehcache/spi/service/ServiceProvider.java b/ehcache-api/src/main/java/org/ehcache/spi/service/ServiceProvider.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/service/ServiceProvider.java rename to ehcache-api/src/main/java/org/ehcache/spi/service/ServiceProvider.java diff --git a/api/src/main/java/org/ehcache/spi/service/package-info.java b/ehcache-api/src/main/java/org/ehcache/spi/service/package-info.java similarity index 100% rename from api/src/main/java/org/ehcache/spi/service/package-info.java rename to ehcache-api/src/main/java/org/ehcache/spi/service/package-info.java diff --git a/api/src/test/java/org/ehcache/CacheManagerTest.java b/ehcache-api/src/test/java/org/ehcache/CacheManagerTest.java similarity index 100% rename from api/src/test/java/org/ehcache/CacheManagerTest.java rename to ehcache-api/src/test/java/org/ehcache/CacheManagerTest.java diff --git a/api/src/test/java/org/ehcache/UserManagedCacheTest.java b/ehcache-api/src/test/java/org/ehcache/UserManagedCacheTest.java similarity index 100% rename from api/src/test/java/org/ehcache/UserManagedCacheTest.java rename to ehcache-api/src/test/java/org/ehcache/UserManagedCacheTest.java diff --git a/api/src/test/java/org/ehcache/config/units/MemoryUnitTest.java b/ehcache-api/src/test/java/org/ehcache/config/units/MemoryUnitTest.java similarity index 100% rename from api/src/test/java/org/ehcache/config/units/MemoryUnitTest.java rename to ehcache-api/src/test/java/org/ehcache/config/units/MemoryUnitTest.java diff --git a/api/src/test/java/org/ehcache/expiry/DurationTest.java b/ehcache-api/src/test/java/org/ehcache/expiry/DurationTest.java similarity index 100% rename from api/src/test/java/org/ehcache/expiry/DurationTest.java rename to ehcache-api/src/test/java/org/ehcache/expiry/DurationTest.java diff --git a/api/src/test/java/org/ehcache/expiry/ExpirationsTest.java b/ehcache-api/src/test/java/org/ehcache/expiry/ExpirationsTest.java similarity index 100% rename from api/src/test/java/org/ehcache/expiry/ExpirationsTest.java rename to ehcache-api/src/test/java/org/ehcache/expiry/ExpirationsTest.java diff --git a/core/build.gradle b/ehcache-core/build.gradle similarity index 82% rename from core/build.gradle rename to ehcache-core/build.gradle index d342e3d9fa..adf8ced16a 100644 --- a/core/build.gradle +++ b/ehcache-core/build.gradle @@ -15,12 +15,18 @@ */ plugins { - id 'org.ehcache.build.deploy' - id 'biz.aQute.bnd.builder' + id 'org.ehcache.build.internal-module' +} + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache 3 Core module' + description = 'The Core module of Ehcache 3' + } } dependencies { - api project(':api') + api project(':ehcache-api') implementation "org.terracotta:statistics:$parent.statisticVersion" compileOnly 'org.osgi:osgi.core:6.0.0' compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' diff --git a/core/config/checkstyle-suppressions.xml b/ehcache-core/config/checkstyle-suppressions.xml similarity index 100% rename from core/config/checkstyle-suppressions.xml rename to ehcache-core/config/checkstyle-suppressions.xml diff --git a/core/src/main/java/org/ehcache/core/CacheConfigurationChangeEvent.java b/ehcache-core/src/main/java/org/ehcache/core/CacheConfigurationChangeEvent.java similarity index 100% rename from core/src/main/java/org/ehcache/core/CacheConfigurationChangeEvent.java rename to ehcache-core/src/main/java/org/ehcache/core/CacheConfigurationChangeEvent.java diff --git a/core/src/main/java/org/ehcache/core/CacheConfigurationChangeListener.java b/ehcache-core/src/main/java/org/ehcache/core/CacheConfigurationChangeListener.java similarity index 100% rename from core/src/main/java/org/ehcache/core/CacheConfigurationChangeListener.java rename to ehcache-core/src/main/java/org/ehcache/core/CacheConfigurationChangeListener.java diff --git a/core/src/main/java/org/ehcache/core/CacheConfigurationProperty.java b/ehcache-core/src/main/java/org/ehcache/core/CacheConfigurationProperty.java similarity index 100% rename from core/src/main/java/org/ehcache/core/CacheConfigurationProperty.java rename to ehcache-core/src/main/java/org/ehcache/core/CacheConfigurationProperty.java diff --git a/core/src/main/java/org/ehcache/core/DefaultCacheManagerProviderService.java b/ehcache-core/src/main/java/org/ehcache/core/DefaultCacheManagerProviderService.java similarity index 100% rename from core/src/main/java/org/ehcache/core/DefaultCacheManagerProviderService.java rename to ehcache-core/src/main/java/org/ehcache/core/DefaultCacheManagerProviderService.java diff --git a/core/src/main/java/org/ehcache/core/Ehcache.java b/ehcache-core/src/main/java/org/ehcache/core/Ehcache.java similarity index 100% rename from core/src/main/java/org/ehcache/core/Ehcache.java rename to ehcache-core/src/main/java/org/ehcache/core/Ehcache.java diff --git a/core/src/main/java/org/ehcache/core/EhcacheBase.java b/ehcache-core/src/main/java/org/ehcache/core/EhcacheBase.java similarity index 100% rename from core/src/main/java/org/ehcache/core/EhcacheBase.java rename to ehcache-core/src/main/java/org/ehcache/core/EhcacheBase.java diff --git a/core/src/main/java/org/ehcache/core/EhcacheManager.java b/ehcache-core/src/main/java/org/ehcache/core/EhcacheManager.java similarity index 100% rename from core/src/main/java/org/ehcache/core/EhcacheManager.java rename to ehcache-core/src/main/java/org/ehcache/core/EhcacheManager.java diff --git a/core/src/main/java/org/ehcache/core/EhcacheRuntimeConfiguration.java b/ehcache-core/src/main/java/org/ehcache/core/EhcacheRuntimeConfiguration.java similarity index 100% rename from core/src/main/java/org/ehcache/core/EhcacheRuntimeConfiguration.java rename to ehcache-core/src/main/java/org/ehcache/core/EhcacheRuntimeConfiguration.java diff --git a/core/src/main/java/org/ehcache/core/HumanReadable.java b/ehcache-core/src/main/java/org/ehcache/core/HumanReadable.java similarity index 100% rename from core/src/main/java/org/ehcache/core/HumanReadable.java rename to ehcache-core/src/main/java/org/ehcache/core/HumanReadable.java diff --git a/core/src/main/java/org/ehcache/core/InternalCache.java b/ehcache-core/src/main/java/org/ehcache/core/InternalCache.java similarity index 100% rename from core/src/main/java/org/ehcache/core/InternalCache.java rename to ehcache-core/src/main/java/org/ehcache/core/InternalCache.java diff --git a/core/src/main/java/org/ehcache/core/InternalRuntimeConfiguration.java b/ehcache-core/src/main/java/org/ehcache/core/InternalRuntimeConfiguration.java similarity index 100% rename from core/src/main/java/org/ehcache/core/InternalRuntimeConfiguration.java rename to ehcache-core/src/main/java/org/ehcache/core/InternalRuntimeConfiguration.java diff --git a/core/src/main/java/org/ehcache/core/InternalStatus.java b/ehcache-core/src/main/java/org/ehcache/core/InternalStatus.java similarity index 100% rename from core/src/main/java/org/ehcache/core/InternalStatus.java rename to ehcache-core/src/main/java/org/ehcache/core/InternalStatus.java diff --git a/core/src/main/java/org/ehcache/core/Jsr107Cache.java b/ehcache-core/src/main/java/org/ehcache/core/Jsr107Cache.java similarity index 100% rename from core/src/main/java/org/ehcache/core/Jsr107Cache.java rename to ehcache-core/src/main/java/org/ehcache/core/Jsr107Cache.java diff --git a/core/src/main/java/org/ehcache/core/PersistentUserManagedEhcache.java b/ehcache-core/src/main/java/org/ehcache/core/PersistentUserManagedEhcache.java similarity index 100% rename from core/src/main/java/org/ehcache/core/PersistentUserManagedEhcache.java rename to ehcache-core/src/main/java/org/ehcache/core/PersistentUserManagedEhcache.java diff --git a/core/src/main/java/org/ehcache/core/SpecIterator.java b/ehcache-core/src/main/java/org/ehcache/core/SpecIterator.java similarity index 100% rename from core/src/main/java/org/ehcache/core/SpecIterator.java rename to ehcache-core/src/main/java/org/ehcache/core/SpecIterator.java diff --git a/core/src/main/java/org/ehcache/core/StatusTransitioner.java b/ehcache-core/src/main/java/org/ehcache/core/StatusTransitioner.java similarity index 100% rename from core/src/main/java/org/ehcache/core/StatusTransitioner.java rename to ehcache-core/src/main/java/org/ehcache/core/StatusTransitioner.java diff --git a/core/src/main/java/org/ehcache/core/collections/ConcurrentWeakIdentityHashMap.java b/ehcache-core/src/main/java/org/ehcache/core/collections/ConcurrentWeakIdentityHashMap.java similarity index 100% rename from core/src/main/java/org/ehcache/core/collections/ConcurrentWeakIdentityHashMap.java rename to ehcache-core/src/main/java/org/ehcache/core/collections/ConcurrentWeakIdentityHashMap.java diff --git a/core/src/main/java/org/ehcache/core/config/CoreConfigurationBuilder.java b/ehcache-core/src/main/java/org/ehcache/core/config/CoreConfigurationBuilder.java similarity index 100% rename from core/src/main/java/org/ehcache/core/config/CoreConfigurationBuilder.java rename to ehcache-core/src/main/java/org/ehcache/core/config/CoreConfigurationBuilder.java diff --git a/core/src/main/java/org/ehcache/core/config/DefaultConfiguration.java b/ehcache-core/src/main/java/org/ehcache/core/config/DefaultConfiguration.java similarity index 100% rename from core/src/main/java/org/ehcache/core/config/DefaultConfiguration.java rename to ehcache-core/src/main/java/org/ehcache/core/config/DefaultConfiguration.java diff --git a/core/src/main/java/org/ehcache/core/config/ExpiryUtils.java b/ehcache-core/src/main/java/org/ehcache/core/config/ExpiryUtils.java similarity index 100% rename from core/src/main/java/org/ehcache/core/config/ExpiryUtils.java rename to ehcache-core/src/main/java/org/ehcache/core/config/ExpiryUtils.java diff --git a/core/src/main/java/org/ehcache/core/config/package-info.java b/ehcache-core/src/main/java/org/ehcache/core/config/package-info.java similarity index 100% rename from core/src/main/java/org/ehcache/core/config/package-info.java rename to ehcache-core/src/main/java/org/ehcache/core/config/package-info.java diff --git a/core/src/main/java/org/ehcache/core/config/store/StoreEventSourceConfiguration.java b/ehcache-core/src/main/java/org/ehcache/core/config/store/StoreEventSourceConfiguration.java similarity index 100% rename from core/src/main/java/org/ehcache/core/config/store/StoreEventSourceConfiguration.java rename to ehcache-core/src/main/java/org/ehcache/core/config/store/StoreEventSourceConfiguration.java diff --git a/core/src/main/java/org/ehcache/core/config/store/StoreStatisticsConfiguration.java b/ehcache-core/src/main/java/org/ehcache/core/config/store/StoreStatisticsConfiguration.java similarity index 100% rename from core/src/main/java/org/ehcache/core/config/store/StoreStatisticsConfiguration.java rename to ehcache-core/src/main/java/org/ehcache/core/config/store/StoreStatisticsConfiguration.java diff --git a/core/src/main/java/org/ehcache/core/config/store/package-info.java b/ehcache-core/src/main/java/org/ehcache/core/config/store/package-info.java similarity index 100% rename from core/src/main/java/org/ehcache/core/config/store/package-info.java rename to ehcache-core/src/main/java/org/ehcache/core/config/store/package-info.java diff --git a/core/src/main/java/org/ehcache/core/events/CacheEventDispatcher.java b/ehcache-core/src/main/java/org/ehcache/core/events/CacheEventDispatcher.java similarity index 100% rename from core/src/main/java/org/ehcache/core/events/CacheEventDispatcher.java rename to ehcache-core/src/main/java/org/ehcache/core/events/CacheEventDispatcher.java diff --git a/core/src/main/java/org/ehcache/core/events/CacheEventDispatcherFactory.java b/ehcache-core/src/main/java/org/ehcache/core/events/CacheEventDispatcherFactory.java similarity index 100% rename from core/src/main/java/org/ehcache/core/events/CacheEventDispatcherFactory.java rename to ehcache-core/src/main/java/org/ehcache/core/events/CacheEventDispatcherFactory.java diff --git a/core/src/main/java/org/ehcache/core/events/CacheEventListenerConfiguration.java b/ehcache-core/src/main/java/org/ehcache/core/events/CacheEventListenerConfiguration.java similarity index 100% rename from core/src/main/java/org/ehcache/core/events/CacheEventListenerConfiguration.java rename to ehcache-core/src/main/java/org/ehcache/core/events/CacheEventListenerConfiguration.java diff --git a/core/src/main/java/org/ehcache/core/events/CacheEventListenerProvider.java b/ehcache-core/src/main/java/org/ehcache/core/events/CacheEventListenerProvider.java similarity index 100% rename from core/src/main/java/org/ehcache/core/events/CacheEventListenerProvider.java rename to ehcache-core/src/main/java/org/ehcache/core/events/CacheEventListenerProvider.java diff --git a/core/src/main/java/org/ehcache/core/events/CacheEvents.java b/ehcache-core/src/main/java/org/ehcache/core/events/CacheEvents.java similarity index 100% rename from core/src/main/java/org/ehcache/core/events/CacheEvents.java rename to ehcache-core/src/main/java/org/ehcache/core/events/CacheEvents.java diff --git a/core/src/main/java/org/ehcache/core/events/CacheManagerListener.java b/ehcache-core/src/main/java/org/ehcache/core/events/CacheManagerListener.java similarity index 100% rename from core/src/main/java/org/ehcache/core/events/CacheManagerListener.java rename to ehcache-core/src/main/java/org/ehcache/core/events/CacheManagerListener.java diff --git a/core/src/main/java/org/ehcache/core/events/EventListenerWrapper.java b/ehcache-core/src/main/java/org/ehcache/core/events/EventListenerWrapper.java similarity index 100% rename from core/src/main/java/org/ehcache/core/events/EventListenerWrapper.java rename to ehcache-core/src/main/java/org/ehcache/core/events/EventListenerWrapper.java diff --git a/core/src/main/java/org/ehcache/core/events/NullStoreEventDispatcher.java b/ehcache-core/src/main/java/org/ehcache/core/events/NullStoreEventDispatcher.java similarity index 100% rename from core/src/main/java/org/ehcache/core/events/NullStoreEventDispatcher.java rename to ehcache-core/src/main/java/org/ehcache/core/events/NullStoreEventDispatcher.java diff --git a/core/src/main/java/org/ehcache/core/events/StateChangeListener.java b/ehcache-core/src/main/java/org/ehcache/core/events/StateChangeListener.java similarity index 100% rename from core/src/main/java/org/ehcache/core/events/StateChangeListener.java rename to ehcache-core/src/main/java/org/ehcache/core/events/StateChangeListener.java diff --git a/core/src/main/java/org/ehcache/core/events/StoreEventDispatcher.java b/ehcache-core/src/main/java/org/ehcache/core/events/StoreEventDispatcher.java similarity index 100% rename from core/src/main/java/org/ehcache/core/events/StoreEventDispatcher.java rename to ehcache-core/src/main/java/org/ehcache/core/events/StoreEventDispatcher.java diff --git a/core/src/main/java/org/ehcache/core/events/StoreEventSink.java b/ehcache-core/src/main/java/org/ehcache/core/events/StoreEventSink.java similarity index 100% rename from core/src/main/java/org/ehcache/core/events/StoreEventSink.java rename to ehcache-core/src/main/java/org/ehcache/core/events/StoreEventSink.java diff --git a/core/src/main/java/org/ehcache/core/events/package-info.java b/ehcache-core/src/main/java/org/ehcache/core/events/package-info.java similarity index 100% rename from core/src/main/java/org/ehcache/core/events/package-info.java rename to ehcache-core/src/main/java/org/ehcache/core/events/package-info.java diff --git a/core/src/main/java/org/ehcache/core/exceptions/ExceptionFactory.java b/ehcache-core/src/main/java/org/ehcache/core/exceptions/ExceptionFactory.java similarity index 100% rename from core/src/main/java/org/ehcache/core/exceptions/ExceptionFactory.java rename to ehcache-core/src/main/java/org/ehcache/core/exceptions/ExceptionFactory.java diff --git a/core/src/main/java/org/ehcache/core/exceptions/StorePassThroughException.java b/ehcache-core/src/main/java/org/ehcache/core/exceptions/StorePassThroughException.java similarity index 100% rename from core/src/main/java/org/ehcache/core/exceptions/StorePassThroughException.java rename to ehcache-core/src/main/java/org/ehcache/core/exceptions/StorePassThroughException.java diff --git a/core/src/main/java/org/ehcache/core/exceptions/package-info.java b/ehcache-core/src/main/java/org/ehcache/core/exceptions/package-info.java similarity index 100% rename from core/src/main/java/org/ehcache/core/exceptions/package-info.java rename to ehcache-core/src/main/java/org/ehcache/core/exceptions/package-info.java diff --git a/core/src/main/java/org/ehcache/core/internal/resilience/ThrowingResilienceStrategy.java b/ehcache-core/src/main/java/org/ehcache/core/internal/resilience/ThrowingResilienceStrategy.java similarity index 100% rename from core/src/main/java/org/ehcache/core/internal/resilience/ThrowingResilienceStrategy.java rename to ehcache-core/src/main/java/org/ehcache/core/internal/resilience/ThrowingResilienceStrategy.java diff --git a/core/src/main/java/org/ehcache/core/internal/statistics/DefaultCacheStatistics.java b/ehcache-core/src/main/java/org/ehcache/core/internal/statistics/DefaultCacheStatistics.java similarity index 100% rename from core/src/main/java/org/ehcache/core/internal/statistics/DefaultCacheStatistics.java rename to ehcache-core/src/main/java/org/ehcache/core/internal/statistics/DefaultCacheStatistics.java diff --git a/core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsService.java b/ehcache-core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsService.java similarity index 100% rename from core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsService.java rename to ehcache-core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsService.java diff --git a/core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsServiceFactory.java b/ehcache-core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsServiceFactory.java similarity index 100% rename from core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsServiceFactory.java rename to ehcache-core/src/main/java/org/ehcache/core/internal/statistics/DefaultStatisticsServiceFactory.java diff --git a/core/src/main/java/org/ehcache/core/internal/statistics/DefaultTierStatistics.java b/ehcache-core/src/main/java/org/ehcache/core/internal/statistics/DefaultTierStatistics.java similarity index 100% rename from core/src/main/java/org/ehcache/core/internal/statistics/DefaultTierStatistics.java rename to ehcache-core/src/main/java/org/ehcache/core/internal/statistics/DefaultTierStatistics.java diff --git a/core/src/main/java/org/ehcache/core/internal/statistics/DelegatedMappedOperationStatistics.java b/ehcache-core/src/main/java/org/ehcache/core/internal/statistics/DelegatedMappedOperationStatistics.java similarity index 100% rename from core/src/main/java/org/ehcache/core/internal/statistics/DelegatedMappedOperationStatistics.java rename to ehcache-core/src/main/java/org/ehcache/core/internal/statistics/DelegatedMappedOperationStatistics.java diff --git a/core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationObserver.java b/ehcache-core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationObserver.java similarity index 100% rename from core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationObserver.java rename to ehcache-core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationObserver.java diff --git a/core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationStatistic.java b/ehcache-core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationStatistic.java similarity index 100% rename from core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationStatistic.java rename to ehcache-core/src/main/java/org/ehcache/core/internal/statistics/DelegatingOperationStatistic.java diff --git a/core/src/main/java/org/ehcache/core/internal/statistics/StatsUtils.java b/ehcache-core/src/main/java/org/ehcache/core/internal/statistics/StatsUtils.java similarity index 100% rename from core/src/main/java/org/ehcache/core/internal/statistics/StatsUtils.java rename to ehcache-core/src/main/java/org/ehcache/core/internal/statistics/StatsUtils.java diff --git a/core/src/main/java/org/ehcache/core/internal/util/ValueSuppliers.java b/ehcache-core/src/main/java/org/ehcache/core/internal/util/ValueSuppliers.java similarity index 100% rename from core/src/main/java/org/ehcache/core/internal/util/ValueSuppliers.java rename to ehcache-core/src/main/java/org/ehcache/core/internal/util/ValueSuppliers.java diff --git a/core/src/main/java/org/ehcache/core/osgi/EhcacheActivator.java b/ehcache-core/src/main/java/org/ehcache/core/osgi/EhcacheActivator.java similarity index 100% rename from core/src/main/java/org/ehcache/core/osgi/EhcacheActivator.java rename to ehcache-core/src/main/java/org/ehcache/core/osgi/EhcacheActivator.java diff --git a/core/src/main/java/org/ehcache/core/osgi/OsgiServiceLoader.java b/ehcache-core/src/main/java/org/ehcache/core/osgi/OsgiServiceLoader.java similarity index 100% rename from core/src/main/java/org/ehcache/core/osgi/OsgiServiceLoader.java rename to ehcache-core/src/main/java/org/ehcache/core/osgi/OsgiServiceLoader.java diff --git a/core/src/main/java/org/ehcache/core/osgi/SafeOsgi.java b/ehcache-core/src/main/java/org/ehcache/core/osgi/SafeOsgi.java similarity index 100% rename from core/src/main/java/org/ehcache/core/osgi/SafeOsgi.java rename to ehcache-core/src/main/java/org/ehcache/core/osgi/SafeOsgi.java diff --git a/core/src/main/java/org/ehcache/core/package-info.java b/ehcache-core/src/main/java/org/ehcache/core/package-info.java similarity index 100% rename from core/src/main/java/org/ehcache/core/package-info.java rename to ehcache-core/src/main/java/org/ehcache/core/package-info.java diff --git a/core/src/main/java/org/ehcache/core/resilience/DefaultRecoveryStore.java b/ehcache-core/src/main/java/org/ehcache/core/resilience/DefaultRecoveryStore.java similarity index 100% rename from core/src/main/java/org/ehcache/core/resilience/DefaultRecoveryStore.java rename to ehcache-core/src/main/java/org/ehcache/core/resilience/DefaultRecoveryStore.java diff --git a/core/src/main/java/org/ehcache/core/spi/LifeCycled.java b/ehcache-core/src/main/java/org/ehcache/core/spi/LifeCycled.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/LifeCycled.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/LifeCycled.java diff --git a/core/src/main/java/org/ehcache/core/spi/LifeCycledAdapter.java b/ehcache-core/src/main/java/org/ehcache/core/spi/LifeCycledAdapter.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/LifeCycledAdapter.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/LifeCycledAdapter.java diff --git a/core/src/main/java/org/ehcache/core/spi/ServiceLocator.java b/ehcache-core/src/main/java/org/ehcache/core/spi/ServiceLocator.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/ServiceLocator.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/ServiceLocator.java diff --git a/core/src/main/java/org/ehcache/core/spi/package-info.java b/ehcache-core/src/main/java/org/ehcache/core/spi/package-info.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/package-info.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/package-info.java diff --git a/core/src/main/java/org/ehcache/core/spi/service/CacheManagerProviderService.java b/ehcache-core/src/main/java/org/ehcache/core/spi/service/CacheManagerProviderService.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/service/CacheManagerProviderService.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/service/CacheManagerProviderService.java diff --git a/core/src/main/java/org/ehcache/core/spi/service/DiskResourceService.java b/ehcache-core/src/main/java/org/ehcache/core/spi/service/DiskResourceService.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/service/DiskResourceService.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/service/DiskResourceService.java diff --git a/core/src/main/java/org/ehcache/core/spi/service/ExecutionService.java b/ehcache-core/src/main/java/org/ehcache/core/spi/service/ExecutionService.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/service/ExecutionService.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/service/ExecutionService.java diff --git a/core/src/main/java/org/ehcache/core/spi/service/FileBasedPersistenceContext.java b/ehcache-core/src/main/java/org/ehcache/core/spi/service/FileBasedPersistenceContext.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/service/FileBasedPersistenceContext.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/service/FileBasedPersistenceContext.java diff --git a/core/src/main/java/org/ehcache/core/spi/service/LocalPersistenceService.java b/ehcache-core/src/main/java/org/ehcache/core/spi/service/LocalPersistenceService.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/service/LocalPersistenceService.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/service/LocalPersistenceService.java diff --git a/core/src/main/java/org/ehcache/core/spi/service/ServiceFactory.java b/ehcache-core/src/main/java/org/ehcache/core/spi/service/ServiceFactory.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/service/ServiceFactory.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/service/ServiceFactory.java diff --git a/core/src/main/java/org/ehcache/core/spi/service/ServiceUtils.java b/ehcache-core/src/main/java/org/ehcache/core/spi/service/ServiceUtils.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/service/ServiceUtils.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/service/ServiceUtils.java diff --git a/core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java b/ehcache-core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/service/StatisticsService.java diff --git a/core/src/main/java/org/ehcache/core/spi/service/package-info.java b/ehcache-core/src/main/java/org/ehcache/core/spi/service/package-info.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/service/package-info.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/service/package-info.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/AbstractValueHolder.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/AbstractWrapperStoreProvider.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/ConfigurationChangeSupport.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/ConfigurationChangeSupport.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/ConfigurationChangeSupport.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/ConfigurationChangeSupport.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/InternalCacheManager.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/InternalCacheManager.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/InternalCacheManager.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/InternalCacheManager.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/Store.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/Store.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/Store.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/Store.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/WrapperStore.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/WrapperStore.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/WrapperStore.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/WrapperStore.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/events/StoreEvent.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/events/StoreEvent.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/events/StoreEvent.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/events/StoreEvent.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/events/StoreEventFilter.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/events/StoreEventFilter.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/events/StoreEventFilter.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/events/StoreEventFilter.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/events/StoreEventListener.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/events/StoreEventListener.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/events/StoreEventListener.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/events/StoreEventListener.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/events/StoreEventSource.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/events/StoreEventSource.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/events/StoreEventSource.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/events/StoreEventSource.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/events/package-info.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/events/package-info.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/events/package-info.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/events/package-info.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/heap/LimitExceededException.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/heap/LimitExceededException.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/heap/LimitExceededException.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/heap/LimitExceededException.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/heap/SizeOfEngine.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/heap/SizeOfEngine.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/heap/SizeOfEngine.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/heap/SizeOfEngine.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/heap/SizeOfEngineProvider.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/heap/SizeOfEngineProvider.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/heap/SizeOfEngineProvider.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/heap/SizeOfEngineProvider.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/heap/package-info.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/heap/package-info.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/heap/package-info.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/heap/package-info.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/package-info.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/package-info.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/package-info.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/package-info.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/tiering/AuthoritativeTier.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/tiering/AuthoritativeTier.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/tiering/AuthoritativeTier.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/tiering/AuthoritativeTier.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/tiering/CachingTier.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/tiering/CachingTier.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/tiering/CachingTier.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/tiering/CachingTier.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/tiering/HigherCachingTier.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/tiering/HigherCachingTier.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/tiering/HigherCachingTier.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/tiering/HigherCachingTier.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/tiering/LowerCachingTier.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/tiering/LowerCachingTier.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/tiering/LowerCachingTier.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/tiering/LowerCachingTier.java diff --git a/core/src/main/java/org/ehcache/core/spi/store/tiering/package-info.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/tiering/package-info.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/store/tiering/package-info.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/store/tiering/package-info.java diff --git a/core/src/main/java/org/ehcache/core/spi/time/SystemTimeSource.java b/ehcache-core/src/main/java/org/ehcache/core/spi/time/SystemTimeSource.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/time/SystemTimeSource.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/time/SystemTimeSource.java diff --git a/core/src/main/java/org/ehcache/core/spi/time/TickingTimeSource.java b/ehcache-core/src/main/java/org/ehcache/core/spi/time/TickingTimeSource.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/time/TickingTimeSource.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/time/TickingTimeSource.java diff --git a/core/src/main/java/org/ehcache/core/spi/time/TimeSource.java b/ehcache-core/src/main/java/org/ehcache/core/spi/time/TimeSource.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/time/TimeSource.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/time/TimeSource.java diff --git a/core/src/main/java/org/ehcache/core/spi/time/TimeSourceService.java b/ehcache-core/src/main/java/org/ehcache/core/spi/time/TimeSourceService.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/time/TimeSourceService.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/time/TimeSourceService.java diff --git a/core/src/main/java/org/ehcache/core/spi/time/package-info.java b/ehcache-core/src/main/java/org/ehcache/core/spi/time/package-info.java similarity index 100% rename from core/src/main/java/org/ehcache/core/spi/time/package-info.java rename to ehcache-core/src/main/java/org/ehcache/core/spi/time/package-info.java diff --git a/core/src/main/java/org/ehcache/core/statistics/AuthoritativeTierOperationOutcomes.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/AuthoritativeTierOperationOutcomes.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/AuthoritativeTierOperationOutcomes.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/AuthoritativeTierOperationOutcomes.java diff --git a/core/src/main/java/org/ehcache/core/statistics/BulkOps.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/BulkOps.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/BulkOps.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/BulkOps.java diff --git a/core/src/main/java/org/ehcache/core/statistics/CacheOperationOutcomes.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/CacheOperationOutcomes.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/CacheOperationOutcomes.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/CacheOperationOutcomes.java diff --git a/core/src/main/java/org/ehcache/core/statistics/CacheStatistics.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/CacheStatistics.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/CacheStatistics.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/CacheStatistics.java diff --git a/core/src/main/java/org/ehcache/core/statistics/CachingTierOperationOutcomes.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/CachingTierOperationOutcomes.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/CachingTierOperationOutcomes.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/CachingTierOperationOutcomes.java diff --git a/core/src/main/java/org/ehcache/core/statistics/ChainedObserver.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/ChainedObserver.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/ChainedObserver.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/ChainedObserver.java diff --git a/core/src/main/java/org/ehcache/core/statistics/ChainedOperationObserver.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/ChainedOperationObserver.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/ChainedOperationObserver.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/ChainedOperationObserver.java diff --git a/core/src/main/java/org/ehcache/core/statistics/HigherCachingTierOperationOutcomes.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/HigherCachingTierOperationOutcomes.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/HigherCachingTierOperationOutcomes.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/HigherCachingTierOperationOutcomes.java diff --git a/core/src/main/java/org/ehcache/core/statistics/LowerCachingTierOperationsOutcome.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/LowerCachingTierOperationsOutcome.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/LowerCachingTierOperationsOutcome.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/LowerCachingTierOperationsOutcome.java diff --git a/core/src/main/java/org/ehcache/core/statistics/OperationObserver.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/OperationObserver.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/OperationObserver.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/OperationObserver.java diff --git a/core/src/main/java/org/ehcache/core/statistics/OperationStatistic.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/OperationStatistic.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/OperationStatistic.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/OperationStatistic.java diff --git a/core/src/main/java/org/ehcache/core/statistics/SourceStatistic.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/SourceStatistic.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/SourceStatistic.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/SourceStatistic.java diff --git a/core/src/main/java/org/ehcache/core/statistics/StatisticType.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/StatisticType.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/StatisticType.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/StatisticType.java diff --git a/core/src/main/java/org/ehcache/core/statistics/StoreOperationOutcomes.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/StoreOperationOutcomes.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/StoreOperationOutcomes.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/StoreOperationOutcomes.java diff --git a/core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/SuppliedValueStatistic.java diff --git a/core/src/main/java/org/ehcache/core/statistics/TierOperationOutcomes.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/TierOperationOutcomes.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/TierOperationOutcomes.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/TierOperationOutcomes.java diff --git a/core/src/main/java/org/ehcache/core/statistics/TierStatistics.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/TierStatistics.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/TierStatistics.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/TierStatistics.java diff --git a/core/src/main/java/org/ehcache/core/statistics/ValueStatistic.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/ValueStatistic.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/ValueStatistic.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/ValueStatistic.java diff --git a/core/src/main/java/org/ehcache/core/statistics/ZeroOperationStatistic.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/ZeroOperationStatistic.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/ZeroOperationStatistic.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/ZeroOperationStatistic.java diff --git a/core/src/main/java/org/ehcache/core/statistics/package-info.java b/ehcache-core/src/main/java/org/ehcache/core/statistics/package-info.java similarity index 100% rename from core/src/main/java/org/ehcache/core/statistics/package-info.java rename to ehcache-core/src/main/java/org/ehcache/core/statistics/package-info.java diff --git a/core/src/main/java/org/ehcache/core/store/StoreConfigurationImpl.java b/ehcache-core/src/main/java/org/ehcache/core/store/StoreConfigurationImpl.java similarity index 100% rename from core/src/main/java/org/ehcache/core/store/StoreConfigurationImpl.java rename to ehcache-core/src/main/java/org/ehcache/core/store/StoreConfigurationImpl.java diff --git a/core/src/main/java/org/ehcache/core/store/StoreSupport.java b/ehcache-core/src/main/java/org/ehcache/core/store/StoreSupport.java similarity index 100% rename from core/src/main/java/org/ehcache/core/store/StoreSupport.java rename to ehcache-core/src/main/java/org/ehcache/core/store/StoreSupport.java diff --git a/core/src/main/java/org/ehcache/core/util/ByteBufferInputStream.java b/ehcache-core/src/main/java/org/ehcache/core/util/ByteBufferInputStream.java similarity index 100% rename from core/src/main/java/org/ehcache/core/util/ByteBufferInputStream.java rename to ehcache-core/src/main/java/org/ehcache/core/util/ByteBufferInputStream.java diff --git a/core/src/main/java/org/ehcache/core/util/ClassLoading.java b/ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java similarity index 100% rename from core/src/main/java/org/ehcache/core/util/ClassLoading.java rename to ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java diff --git a/core/src/main/java/org/ehcache/core/util/CollectionUtil.java b/ehcache-core/src/main/java/org/ehcache/core/util/CollectionUtil.java similarity index 100% rename from core/src/main/java/org/ehcache/core/util/CollectionUtil.java rename to ehcache-core/src/main/java/org/ehcache/core/util/CollectionUtil.java diff --git a/core/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory b/ehcache-core/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory similarity index 100% rename from core/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory rename to ehcache-core/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory diff --git a/core/src/test/java/org/ehcache/core/CacheConfigurationChangeListenerTest.java b/ehcache-core/src/test/java/org/ehcache/core/CacheConfigurationChangeListenerTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/CacheConfigurationChangeListenerTest.java rename to ehcache-core/src/test/java/org/ehcache/core/CacheConfigurationChangeListenerTest.java diff --git a/core/src/test/java/org/ehcache/core/CacheTest.java b/ehcache-core/src/test/java/org/ehcache/core/CacheTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/CacheTest.java rename to ehcache-core/src/test/java/org/ehcache/core/CacheTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicBulkUtil.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicBulkUtil.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicBulkUtil.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicBulkUtil.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicClearTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicClearTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicClearTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicClearTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicContainsKeyTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicContainsKeyTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicContainsKeyTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicContainsKeyTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicGetAllTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicGetTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicGetTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicGetTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicGetTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicIteratorTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicIteratorTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicIteratorTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicIteratorTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicPutAllTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicPutAllTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicPutAllTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicPutAllTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicPutIfAbsentTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicPutTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicPutTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicPutTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicPutTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveAllTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicRemoveAllTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicRemoveAllTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicRemoveAllTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicRemoveTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicRemoveTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicRemoveTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicRemoveValueTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicRemoveValueTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicRemoveValueTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicRemoveValueTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicReplaceTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicReplaceTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicReplaceTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicReplaceTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBasicReplaceValueTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicReplaceValueTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBasicReplaceValueTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicReplaceValueTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheBulkMethodsTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBulkMethodsTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheBulkMethodsTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheBulkMethodsTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheManagerTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheManagerTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheManagerTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheManagerTest.java diff --git a/core/src/test/java/org/ehcache/core/EhcacheTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/EhcacheTest.java rename to ehcache-core/src/test/java/org/ehcache/core/EhcacheTest.java diff --git a/core/src/test/java/org/ehcache/core/StatusTransitionerTest.java b/ehcache-core/src/test/java/org/ehcache/core/StatusTransitionerTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/StatusTransitionerTest.java rename to ehcache-core/src/test/java/org/ehcache/core/StatusTransitionerTest.java diff --git a/core/src/test/java/org/ehcache/core/UserManagedCacheTest.java b/ehcache-core/src/test/java/org/ehcache/core/UserManagedCacheTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/UserManagedCacheTest.java rename to ehcache-core/src/test/java/org/ehcache/core/UserManagedCacheTest.java diff --git a/core/src/test/java/org/ehcache/core/collections/ConcurrentWeakIdentityHashMapTest.java b/ehcache-core/src/test/java/org/ehcache/core/collections/ConcurrentWeakIdentityHashMapTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/collections/ConcurrentWeakIdentityHashMapTest.java rename to ehcache-core/src/test/java/org/ehcache/core/collections/ConcurrentWeakIdentityHashMapTest.java diff --git a/core/src/test/java/org/ehcache/core/config/CoreConfigurationBuilderTest.java b/ehcache-core/src/test/java/org/ehcache/core/config/CoreConfigurationBuilderTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/config/CoreConfigurationBuilderTest.java rename to ehcache-core/src/test/java/org/ehcache/core/config/CoreConfigurationBuilderTest.java diff --git a/core/src/test/java/org/ehcache/core/config/ExpiryUtilsTest.java b/ehcache-core/src/test/java/org/ehcache/core/config/ExpiryUtilsTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/config/ExpiryUtilsTest.java rename to ehcache-core/src/test/java/org/ehcache/core/config/ExpiryUtilsTest.java diff --git a/core/src/test/java/org/ehcache/core/config/ResourcePoolsHelper.java b/ehcache-core/src/test/java/org/ehcache/core/config/ResourcePoolsHelper.java similarity index 100% rename from core/src/test/java/org/ehcache/core/config/ResourcePoolsHelper.java rename to ehcache-core/src/test/java/org/ehcache/core/config/ResourcePoolsHelper.java diff --git a/core/src/test/java/org/ehcache/core/config/store/StoreStatisticsConfigurationTest.java b/ehcache-core/src/test/java/org/ehcache/core/config/store/StoreStatisticsConfigurationTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/config/store/StoreStatisticsConfigurationTest.java rename to ehcache-core/src/test/java/org/ehcache/core/config/store/StoreStatisticsConfigurationTest.java diff --git a/core/src/test/java/org/ehcache/core/events/CacheEventsTest.java b/ehcache-core/src/test/java/org/ehcache/core/events/CacheEventsTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/events/CacheEventsTest.java rename to ehcache-core/src/test/java/org/ehcache/core/events/CacheEventsTest.java diff --git a/core/src/test/java/org/ehcache/core/exceptions/ExceptionFactoryTest.java b/ehcache-core/src/test/java/org/ehcache/core/exceptions/ExceptionFactoryTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/exceptions/ExceptionFactoryTest.java rename to ehcache-core/src/test/java/org/ehcache/core/exceptions/ExceptionFactoryTest.java diff --git a/core/src/test/java/org/ehcache/core/exceptions/StorePassThroughExceptionTest.java b/ehcache-core/src/test/java/org/ehcache/core/exceptions/StorePassThroughExceptionTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/exceptions/StorePassThroughExceptionTest.java rename to ehcache-core/src/test/java/org/ehcache/core/exceptions/StorePassThroughExceptionTest.java diff --git a/core/src/test/java/org/ehcache/core/internal/util/CollectionUtilTest.java b/ehcache-core/src/test/java/org/ehcache/core/internal/util/CollectionUtilTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/internal/util/CollectionUtilTest.java rename to ehcache-core/src/test/java/org/ehcache/core/internal/util/CollectionUtilTest.java diff --git a/core/src/test/java/org/ehcache/core/spi/ServiceLocatorPluralTest.java b/ehcache-core/src/test/java/org/ehcache/core/spi/ServiceLocatorPluralTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/ServiceLocatorPluralTest.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/ServiceLocatorPluralTest.java diff --git a/core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java b/ehcache-core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/ServiceLocatorTest.java diff --git a/core/src/test/java/org/ehcache/core/spi/service/ServiceUtilsTest.java b/ehcache-core/src/test/java/org/ehcache/core/spi/service/ServiceUtilsTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/service/ServiceUtilsTest.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/service/ServiceUtilsTest.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/DefaultTestProvidedService.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/DefaultTestProvidedService.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/DefaultTestProvidedService.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/DefaultTestProvidedService.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/DefaultTestService.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/DefaultTestService.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/DefaultTestService.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/DefaultTestService.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/FancyCacheProvider.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/FancyCacheProvider.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/FancyCacheProvider.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/FancyCacheProvider.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/FancyCacheProviderFactory.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/FancyCacheProviderFactory.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/FancyCacheProviderFactory.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/FancyCacheProviderFactory.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/TestMandatoryServiceFactory.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/TestMandatoryServiceFactory.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/TestMandatoryServiceFactory.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/TestMandatoryServiceFactory.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/TestProvidedService.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/TestProvidedService.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/TestProvidedService.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/TestProvidedService.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/TestProvidedServiceFactory.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/TestProvidedServiceFactory.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/TestProvidedServiceFactory.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/TestProvidedServiceFactory.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/TestService.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/TestService.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/TestService.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/TestService.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/TestServiceFactory.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/TestServiceFactory.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/TestServiceFactory.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/TestServiceFactory.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/ranking/HighRankServiceAFactory.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/ranking/HighRankServiceAFactory.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/ranking/HighRankServiceAFactory.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/ranking/HighRankServiceAFactory.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/ranking/LowRankServiceBFactory.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/ranking/LowRankServiceBFactory.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/ranking/LowRankServiceBFactory.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/ranking/LowRankServiceBFactory.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryHighRankServiceBFactory.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryHighRankServiceBFactory.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryHighRankServiceBFactory.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryHighRankServiceBFactory.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryLowRankServiceAFactory.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryLowRankServiceAFactory.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryLowRankServiceAFactory.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/ranking/MandatoryLowRankServiceAFactory.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/ranking/RankServiceA.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/ranking/RankServiceA.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/ranking/RankServiceA.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/ranking/RankServiceA.java diff --git a/core/src/test/java/org/ehcache/core/spi/services/ranking/RankServiceB.java b/ehcache-core/src/test/java/org/ehcache/core/spi/services/ranking/RankServiceB.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/services/ranking/RankServiceB.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/services/ranking/RankServiceB.java diff --git a/core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java b/ehcache-core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/store/AbstractValueHolderTest.java diff --git a/core/src/test/java/org/ehcache/core/spi/store/CacheProvider.java b/ehcache-core/src/test/java/org/ehcache/core/spi/store/CacheProvider.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/store/CacheProvider.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/store/CacheProvider.java diff --git a/core/src/test/java/org/ehcache/core/spi/time/TickingTimeSourceTest.java b/ehcache-core/src/test/java/org/ehcache/core/spi/time/TickingTimeSourceTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/spi/time/TickingTimeSourceTest.java rename to ehcache-core/src/test/java/org/ehcache/core/spi/time/TickingTimeSourceTest.java diff --git a/core/src/test/java/org/ehcache/core/store/StoreSupportTest.java b/ehcache-core/src/test/java/org/ehcache/core/store/StoreSupportTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/store/StoreSupportTest.java rename to ehcache-core/src/test/java/org/ehcache/core/store/StoreSupportTest.java diff --git a/core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java b/ehcache-core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java similarity index 100% rename from core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java rename to ehcache-core/src/test/java/org/ehcache/core/util/ClassLoadingTest.java diff --git a/core/src/test/java/org/ehcache/core/util/IsCreated.java b/ehcache-core/src/test/java/org/ehcache/core/util/IsCreated.java similarity index 100% rename from core/src/test/java/org/ehcache/core/util/IsCreated.java rename to ehcache-core/src/test/java/org/ehcache/core/util/IsCreated.java diff --git a/core/src/test/java/org/ehcache/core/util/IsRemoved.java b/ehcache-core/src/test/java/org/ehcache/core/util/IsRemoved.java similarity index 100% rename from core/src/test/java/org/ehcache/core/util/IsRemoved.java rename to ehcache-core/src/test/java/org/ehcache/core/util/IsRemoved.java diff --git a/core/src/test/java/org/ehcache/core/util/IsUpdated.java b/ehcache-core/src/test/java/org/ehcache/core/util/IsUpdated.java similarity index 100% rename from core/src/test/java/org/ehcache/core/util/IsUpdated.java rename to ehcache-core/src/test/java/org/ehcache/core/util/IsUpdated.java diff --git a/core/src/test/java/org/ehcache/core/util/Matchers.java b/ehcache-core/src/test/java/org/ehcache/core/util/Matchers.java similarity index 100% rename from core/src/test/java/org/ehcache/core/util/Matchers.java rename to ehcache-core/src/test/java/org/ehcache/core/util/Matchers.java diff --git a/core/src/test/java/org/ehcache/core/util/TestCacheConfig.java b/ehcache-core/src/test/java/org/ehcache/core/util/TestCacheConfig.java similarity index 100% rename from core/src/test/java/org/ehcache/core/util/TestCacheConfig.java rename to ehcache-core/src/test/java/org/ehcache/core/util/TestCacheConfig.java diff --git a/core/src/test/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory b/ehcache-core/src/test/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory similarity index 100% rename from core/src/test/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory rename to ehcache-core/src/test/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory diff --git a/impl/build.gradle b/ehcache-impl/build.gradle similarity index 66% rename from impl/build.gradle rename to ehcache-impl/build.gradle index 303d31c72e..3d338a724a 100644 --- a/impl/build.gradle +++ b/ehcache-impl/build.gradle @@ -15,21 +15,41 @@ */ plugins { - id 'org.ehcache.build.deploy' - id 'biz.aQute.bnd.builder' - id 'org.jayware.osgi-ds' + id 'org.ehcache.build.internal-module' +} + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache 3 Implementation module' + description = 'The implementation module of Ehcache 3' + } +} + +sourceSets { + unsafe } sourceSets { - unsafe { - java { - srcDir 'src/unsafe/java' - } + slowTest { + java.srcDir 'src/slow-test/java' + resources.srcDir 'src/slow-test/resources' + compileClasspath += sourceSets.test.compileClasspath + runtimeClasspath += sourceSets.test.runtimeClasspath } } +task slowTest(type: Test) { + testClassesDirs = sourceSets.slowTest.output.classesDirs + classpath += sourceSets.slowTest.runtimeClasspath + + binResultsDir file("$buildDir/slow-tests-results/binary/$name") + reports.junitXml.destination = file("$buildDir/slow-tests-results") + reports.html.destination = file("$buildDir/reports/slow-tests") +} + + dependencies { - api project(':core') + api project(':ehcache-core') implementation group: 'org.terracotta', name: 'offheap-store', version: parent.offheapVersion implementation group: 'org.ehcache', name: 'sizeof', version: parent.sizeofVersion implementation group: 'org.terracotta', name: 'terracotta-utilities-tools', version: parent.terracottaUtilitiesVersion @@ -39,8 +59,7 @@ dependencies { testImplementation 'org.ow2.asm:asm-commons:6.2' testImplementation ("org.terracotta:statistics:$parent.statisticVersion") - unsafeImplementation project(':api') - unsafeCompileOnly "com.github.spotbugs:spotbugs-annotations:${project.spotbugs.toolVersion}" + unsafeImplementation project(':ehcache-api') api files(sourceSets.unsafe.output.classesDirs) { builtBy compileUnsafeJava } @@ -56,7 +75,7 @@ jar { ) } -sourceJar { +sourcesJar { from sourceSets.unsafe.allSource } diff --git a/impl/config/checkstyle-suppressions.xml b/ehcache-impl/config/checkstyle-suppressions.xml similarity index 100% rename from impl/config/checkstyle-suppressions.xml rename to ehcache-impl/config/checkstyle-suppressions.xml diff --git a/impl/src/main/java/org/ehcache/config/builders/CacheConfigurationBuilder.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/CacheConfigurationBuilder.java similarity index 100% rename from impl/src/main/java/org/ehcache/config/builders/CacheConfigurationBuilder.java rename to ehcache-impl/src/main/java/org/ehcache/config/builders/CacheConfigurationBuilder.java diff --git a/impl/src/main/java/org/ehcache/config/builders/CacheEventListenerConfigurationBuilder.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/CacheEventListenerConfigurationBuilder.java similarity index 100% rename from impl/src/main/java/org/ehcache/config/builders/CacheEventListenerConfigurationBuilder.java rename to ehcache-impl/src/main/java/org/ehcache/config/builders/CacheEventListenerConfigurationBuilder.java diff --git a/impl/src/main/java/org/ehcache/config/builders/CacheManagerBuilder.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/CacheManagerBuilder.java similarity index 100% rename from impl/src/main/java/org/ehcache/config/builders/CacheManagerBuilder.java rename to ehcache-impl/src/main/java/org/ehcache/config/builders/CacheManagerBuilder.java diff --git a/impl/src/main/java/org/ehcache/config/builders/CacheManagerConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/CacheManagerConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/config/builders/CacheManagerConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/config/builders/CacheManagerConfiguration.java diff --git a/impl/src/main/java/org/ehcache/config/builders/ConfigurationBuilder.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/ConfigurationBuilder.java similarity index 100% rename from impl/src/main/java/org/ehcache/config/builders/ConfigurationBuilder.java rename to ehcache-impl/src/main/java/org/ehcache/config/builders/ConfigurationBuilder.java diff --git a/impl/src/main/java/org/ehcache/config/builders/ExpiryPolicyBuilder.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/ExpiryPolicyBuilder.java similarity index 100% rename from impl/src/main/java/org/ehcache/config/builders/ExpiryPolicyBuilder.java rename to ehcache-impl/src/main/java/org/ehcache/config/builders/ExpiryPolicyBuilder.java diff --git a/impl/src/main/java/org/ehcache/config/builders/PooledExecutionServiceConfigurationBuilder.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/PooledExecutionServiceConfigurationBuilder.java similarity index 100% rename from impl/src/main/java/org/ehcache/config/builders/PooledExecutionServiceConfigurationBuilder.java rename to ehcache-impl/src/main/java/org/ehcache/config/builders/PooledExecutionServiceConfigurationBuilder.java diff --git a/impl/src/main/java/org/ehcache/config/builders/ResourcePoolsBuilder.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/ResourcePoolsBuilder.java similarity index 100% rename from impl/src/main/java/org/ehcache/config/builders/ResourcePoolsBuilder.java rename to ehcache-impl/src/main/java/org/ehcache/config/builders/ResourcePoolsBuilder.java diff --git a/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java similarity index 100% rename from impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java rename to ehcache-impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java diff --git a/impl/src/main/java/org/ehcache/config/builders/UserManagedCacheConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/UserManagedCacheConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/config/builders/UserManagedCacheConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/config/builders/UserManagedCacheConfiguration.java diff --git a/impl/src/main/java/org/ehcache/config/builders/WriteBehindConfigurationBuilder.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/WriteBehindConfigurationBuilder.java similarity index 100% rename from impl/src/main/java/org/ehcache/config/builders/WriteBehindConfigurationBuilder.java rename to ehcache-impl/src/main/java/org/ehcache/config/builders/WriteBehindConfigurationBuilder.java diff --git a/impl/src/main/java/org/ehcache/config/builders/package-info.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/config/builders/package-info.java rename to ehcache-impl/src/main/java/org/ehcache/config/builders/package-info.java diff --git a/impl/src/main/java/org/ehcache/impl/config/AbstractResourcePool.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/AbstractResourcePool.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/AbstractResourcePool.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/AbstractResourcePool.java diff --git a/impl/src/main/java/org/ehcache/impl/config/BaseCacheConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/BaseCacheConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/BaseCacheConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/BaseCacheConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/ResourcePoolsImpl.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/ResourcePoolsImpl.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/ResourcePoolsImpl.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/ResourcePoolsImpl.java diff --git a/impl/src/main/java/org/ehcache/impl/config/SizedResourcePoolImpl.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/SizedResourcePoolImpl.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/SizedResourcePoolImpl.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/SizedResourcePoolImpl.java diff --git a/impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopierConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopierConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopierConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopierConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/copy/package-info.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/copy/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/copy/package-info.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/copy/package-info.java diff --git a/impl/src/main/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventListenerConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventListenerConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventListenerConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/event/DefaultCacheEventListenerConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/event/DefaultEventSourceConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/event/DefaultEventSourceConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/event/DefaultEventSourceConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/event/DefaultEventSourceConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/event/package-info.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/event/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/event/package-info.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/event/package-info.java diff --git a/impl/src/main/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/executor/package-info.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/executor/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/executor/package-info.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/executor/package-info.java diff --git a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/package-info.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/loaderwriter/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/loaderwriter/package-info.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/loaderwriter/package-info.java diff --git a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/DefaultBatchingConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/DefaultBatchingConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/DefaultBatchingConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/DefaultBatchingConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/DefaultWriteBehindConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/DefaultWriteBehindConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/DefaultWriteBehindConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/DefaultWriteBehindConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/package-info.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/package-info.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/loaderwriter/writebehind/package-info.java diff --git a/impl/src/main/java/org/ehcache/impl/config/persistence/CacheManagerPersistenceConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/persistence/CacheManagerPersistenceConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/persistence/CacheManagerPersistenceConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/persistence/CacheManagerPersistenceConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/persistence/UserManagedPersistenceContext.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/persistence/UserManagedPersistenceContext.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/persistence/UserManagedPersistenceContext.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/persistence/UserManagedPersistenceContext.java diff --git a/impl/src/main/java/org/ehcache/impl/config/persistence/package-info.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/persistence/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/persistence/package-info.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/persistence/package-info.java diff --git a/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializerConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializerConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializerConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/serializer/DefaultSerializerConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/serializer/package-info.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/serializer/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/serializer/package-info.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/serializer/package-info.java diff --git a/impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/store/disk/package-info.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/store/disk/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/store/disk/package-info.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/store/disk/package-info.java diff --git a/impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineProviderConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineProviderConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineProviderConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/store/heap/DefaultSizeOfEngineProviderConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/config/store/heap/package-info.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/store/heap/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/config/store/heap/package-info.java rename to ehcache-impl/src/main/java/org/ehcache/impl/config/store/heap/package-info.java diff --git a/impl/src/main/java/org/ehcache/impl/copy/IdentityCopier.java b/ehcache-impl/src/main/java/org/ehcache/impl/copy/IdentityCopier.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/copy/IdentityCopier.java rename to ehcache-impl/src/main/java/org/ehcache/impl/copy/IdentityCopier.java diff --git a/impl/src/main/java/org/ehcache/impl/copy/ReadWriteCopier.java b/ehcache-impl/src/main/java/org/ehcache/impl/copy/ReadWriteCopier.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/copy/ReadWriteCopier.java rename to ehcache-impl/src/main/java/org/ehcache/impl/copy/ReadWriteCopier.java diff --git a/impl/src/main/java/org/ehcache/impl/copy/SerializingCopier.java b/ehcache-impl/src/main/java/org/ehcache/impl/copy/SerializingCopier.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/copy/SerializingCopier.java rename to ehcache-impl/src/main/java/org/ehcache/impl/copy/SerializingCopier.java diff --git a/impl/src/main/java/org/ehcache/impl/copy/package-info.java b/ehcache-impl/src/main/java/org/ehcache/impl/copy/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/copy/package-info.java rename to ehcache-impl/src/main/java/org/ehcache/impl/copy/package-info.java diff --git a/impl/src/main/java/org/ehcache/impl/events/CacheEventAdapter.java b/ehcache-impl/src/main/java/org/ehcache/impl/events/CacheEventAdapter.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/events/CacheEventAdapter.java rename to ehcache-impl/src/main/java/org/ehcache/impl/events/CacheEventAdapter.java diff --git a/impl/src/main/java/org/ehcache/impl/events/CacheEventDispatcherImpl.java b/ehcache-impl/src/main/java/org/ehcache/impl/events/CacheEventDispatcherImpl.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/events/CacheEventDispatcherImpl.java rename to ehcache-impl/src/main/java/org/ehcache/impl/events/CacheEventDispatcherImpl.java diff --git a/impl/src/main/java/org/ehcache/impl/events/EventDispatchTask.java b/ehcache-impl/src/main/java/org/ehcache/impl/events/EventDispatchTask.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/events/EventDispatchTask.java rename to ehcache-impl/src/main/java/org/ehcache/impl/events/EventDispatchTask.java diff --git a/impl/src/main/java/org/ehcache/impl/events/package-info.java b/ehcache-impl/src/main/java/org/ehcache/impl/events/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/events/package-info.java rename to ehcache-impl/src/main/java/org/ehcache/impl/events/package-info.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/DefaultTimeSourceService.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/DefaultTimeSourceService.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/DefaultTimeSourceService.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/DefaultTimeSourceService.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/TimeSourceConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/TimeSourceConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/TimeSourceConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/TimeSourceConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/TimeSourceServiceFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProvider.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/ArrayUtils.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/ArrayUtils.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/ArrayUtils.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/ArrayUtils.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/ClassUtils.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/ClassUtils.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/ClassUtils.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/ClassUtils.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/ConstructorUtils.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/ConstructorUtils.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/ConstructorUtils.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/ConstructorUtils.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MemberUtils.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MemberUtils.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MemberUtils.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MemberUtils.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MethodUtils.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MethodUtils.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MethodUtils.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MethodUtils.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/AbstractStoreEventDispatcher.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/events/AbstractStoreEventDispatcher.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/events/AbstractStoreEventDispatcher.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/events/AbstractStoreEventDispatcher.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImpl.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImpl.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImpl.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImpl.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/CacheEventNotificationListenerServiceProviderFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/events/CacheEventNotificationListenerServiceProviderFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/events/CacheEventNotificationListenerServiceProviderFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/events/CacheEventNotificationListenerServiceProviderFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/CloseableStoreEventSink.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/events/CloseableStoreEventSink.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/events/CloseableStoreEventSink.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/events/CloseableStoreEventSink.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/DisabledCacheEventNotificationService.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/events/DisabledCacheEventNotificationService.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/events/DisabledCacheEventNotificationService.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/events/DisabledCacheEventNotificationService.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/FireableStoreEventHolder.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/events/FireableStoreEventHolder.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/events/FireableStoreEventHolder.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/events/FireableStoreEventHolder.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/FudgingInvocationScopedEventSink.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/events/FudgingInvocationScopedEventSink.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/events/FudgingInvocationScopedEventSink.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/events/FudgingInvocationScopedEventSink.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/InvocationScopedEventSink.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/events/InvocationScopedEventSink.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/events/InvocationScopedEventSink.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/events/InvocationScopedEventSink.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/StoreEventImpl.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/events/StoreEventImpl.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/events/StoreEventImpl.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/events/StoreEventImpl.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/StoreEvents.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/events/StoreEvents.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/events/StoreEvents.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/events/StoreEvents.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/events/ThreadLocalStoreEventDispatcher.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/events/ThreadLocalStoreEventDispatcher.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/events/ThreadLocalStoreEventDispatcher.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/events/ThreadLocalStoreEventDispatcher.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/DefaultExecutionServiceFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/executor/ExecutorUtil.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/ExecutorUtil.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/executor/ExecutorUtil.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/ExecutorUtil.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/executor/OnDemandExecutionService.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/OnDemandExecutionService.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/executor/OnDemandExecutionService.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/OnDemandExecutionService.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/executor/OutOfBandScheduledExecutor.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/OutOfBandScheduledExecutor.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/executor/OutOfBandScheduledExecutor.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/OutOfBandScheduledExecutor.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/executor/PartitionedOrderedExecutor.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/PartitionedOrderedExecutor.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/executor/PartitionedOrderedExecutor.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/PartitionedOrderedExecutor.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/executor/PartitionedScheduledExecutor.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/PartitionedScheduledExecutor.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/executor/PartitionedScheduledExecutor.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/PartitionedScheduledExecutor.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/executor/PartitionedUnorderedExecutor.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/PartitionedUnorderedExecutor.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/executor/PartitionedUnorderedExecutor.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/PartitionedUnorderedExecutor.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/executor/PooledExecutionService.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/PooledExecutionService.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/executor/PooledExecutionService.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/executor/PooledExecutionService.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehind.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehind.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehind.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehind.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/BatchingLocalHeapWriteBehindQueue.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/BatchingLocalHeapWriteBehindQueue.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/BatchingLocalHeapWriteBehindQueue.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/BatchingLocalHeapWriteBehindQueue.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/NonBatchingLocalHeapWriteBehindQueue.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/NonBatchingLocalHeapWriteBehindQueue.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/NonBatchingLocalHeapWriteBehindQueue.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/NonBatchingLocalHeapWriteBehindQueue.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/StripedWriteBehind.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/StripedWriteBehind.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/StripedWriteBehind.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/StripedWriteBehind.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehind.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehind.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehind.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehind.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/BatchOperation.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/BatchOperation.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/BatchOperation.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/BatchOperation.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/DeleteAllOperation.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/DeleteAllOperation.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/DeleteAllOperation.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/DeleteAllOperation.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/DeleteOperation.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/DeleteOperation.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/DeleteOperation.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/DeleteOperation.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/KeyBasedOperation.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/KeyBasedOperation.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/KeyBasedOperation.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/KeyBasedOperation.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/SingleOperation.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/SingleOperation.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/SingleOperation.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/SingleOperation.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/WriteAllOperation.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/WriteAllOperation.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/WriteAllOperation.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/WriteAllOperation.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/WriteOperation.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/WriteOperation.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/WriteOperation.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/loaderwriter/writebehind/operations/WriteOperation.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultDiskResourceServiceFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/persistence/DefaultLocalPersistenceServiceFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/resilience/AbstractResilienceStrategy.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/resilience/AbstractResilienceStrategy.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/resilience/AbstractResilienceStrategy.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/resilience/AbstractResilienceStrategy.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategy.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategy.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategy.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategy.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategy.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategy.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategy.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategy.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngine.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngine.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngine.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngine.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProvider.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProvider.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProvider.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProvider.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/sizeof/NoopSizeOfEngine.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/sizeof/NoopSizeOfEngine.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/sizeof/NoopSizeOfEngine.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/sizeof/NoopSizeOfEngine.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/sizeof/listeners/EhcacheVisitorListener.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/sizeof/listeners/EhcacheVisitorListener.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/sizeof/listeners/EhcacheVisitorListener.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/sizeof/listeners/EhcacheVisitorListener.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/sizeof/listeners/exceptions/VisitorListenerException.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/sizeof/listeners/exceptions/VisitorListenerException.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/sizeof/listeners/exceptions/VisitorListenerException.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/sizeof/listeners/exceptions/VisitorListenerException.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProvider.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProvider.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProvider.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProvider.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProvider.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProvider.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProvider.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProvider.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProvider.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProvider.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProvider.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProvider.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProvider.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProvider.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProvider.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProvider.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProvider.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProvider.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProvider.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProvider.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/BinaryValueHolder.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/BinaryValueHolder.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/BinaryValueHolder.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/BinaryValueHolder.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/DiskWriteThreadPool.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/disk/DiskWriteThreadPool.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/disk/DiskWriteThreadPool.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/disk/DiskWriteThreadPool.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCache.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCache.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCache.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCache.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStore.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/Backend.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/Backend.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/heap/Backend.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/Backend.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/KeyCopyBackend.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/KeyCopyBackend.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/heap/KeyCopyBackend.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/KeyCopyBackend.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStrategy.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/SimpleBackend.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/SimpleBackend.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/heap/SimpleBackend.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/SimpleBackend.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/BaseOnHeapKey.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/BaseOnHeapKey.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/BaseOnHeapKey.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/BaseOnHeapKey.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapKey.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapKey.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapKey.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapKey.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolder.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolder.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolder.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolder.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/LookupOnlyOnHeapKey.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/LookupOnlyOnHeapKey.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/LookupOnlyOnHeapKey.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/LookupOnlyOnHeapKey.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/OnHeapKey.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/OnHeapKey.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/OnHeapKey.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/OnHeapKey.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/OnHeapValueHolder.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/OnHeapValueHolder.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/OnHeapValueHolder.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/OnHeapValueHolder.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolder.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolder.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolder.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolder.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProvider.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProviderFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProviderFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProviderFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterStoreProviderFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterValueHolder.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterValueHolder.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterValueHolder.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LoaderWriterValueHolder.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalWriteBehindLoaderWriterStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalWriteBehindLoaderWriterStore.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalWriteBehindLoaderWriterStore.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalWriteBehindLoaderWriterStore.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolder.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolder.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolder.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolder.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolder.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolder.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolder.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolder.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/EhcacheConcurrentOffHeapClockCache.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/EhcacheConcurrentOffHeapClockCache.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/EhcacheConcurrentOffHeapClockCache.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/EhcacheConcurrentOffHeapClockCache.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/EhcacheOffHeapBackingMap.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/EhcacheOffHeapBackingMap.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/EhcacheOffHeapBackingMap.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/EhcacheOffHeapBackingMap.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/HeuristicConfiguration.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/HeuristicConfiguration.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/HeuristicConfiguration.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/HeuristicConfiguration.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolder.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/MemorySizeParser.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/MemorySizeParser.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/MemorySizeParser.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/MemorySizeParser.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapMapStatistics.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapMapStatistics.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapMapStatistics.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapMapStatistics.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStore.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreProviderFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreUtils.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreUtils.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreUtils.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreUtils.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolder.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolder.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolder.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolder.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/SwitchableEvictionAdvisor.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/SwitchableEvictionAdvisor.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/SwitchableEvictionAdvisor.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/SwitchableEvictionAdvisor.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/OffHeapValueHolderPortability.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/SerializerPortability.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/SerializerPortability.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/SerializerPortability.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/portability/SerializerPortability.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTier.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierProviderFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStoreProviderFactory.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/util/Pacer.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/util/Pacer.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/util/Pacer.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/util/Pacer.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/util/ServiceUtil.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/util/ServiceUtil.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/util/ServiceUtil.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/util/ServiceUtil.java diff --git a/impl/src/main/java/org/ehcache/impl/internal/util/ThreadFactoryUtil.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/util/ThreadFactoryUtil.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/internal/util/ThreadFactoryUtil.java rename to ehcache-impl/src/main/java/org/ehcache/impl/internal/util/ThreadFactoryUtil.java diff --git a/impl/src/main/java/org/ehcache/impl/persistence/DefaultDiskResourceService.java b/ehcache-impl/src/main/java/org/ehcache/impl/persistence/DefaultDiskResourceService.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/persistence/DefaultDiskResourceService.java rename to ehcache-impl/src/main/java/org/ehcache/impl/persistence/DefaultDiskResourceService.java diff --git a/impl/src/main/java/org/ehcache/impl/persistence/DefaultLocalPersistenceService.java b/ehcache-impl/src/main/java/org/ehcache/impl/persistence/DefaultLocalPersistenceService.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/persistence/DefaultLocalPersistenceService.java rename to ehcache-impl/src/main/java/org/ehcache/impl/persistence/DefaultLocalPersistenceService.java diff --git a/impl/src/main/java/org/ehcache/impl/persistence/FileBasedStateRepository.java b/ehcache-impl/src/main/java/org/ehcache/impl/persistence/FileBasedStateRepository.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/persistence/FileBasedStateRepository.java rename to ehcache-impl/src/main/java/org/ehcache/impl/persistence/FileBasedStateRepository.java diff --git a/impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java b/ehcache-impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java rename to ehcache-impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java diff --git a/impl/src/main/java/org/ehcache/impl/persistence/package-info.java b/ehcache-impl/src/main/java/org/ehcache/impl/persistence/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/persistence/package-info.java rename to ehcache-impl/src/main/java/org/ehcache/impl/persistence/package-info.java diff --git a/impl/src/main/java/org/ehcache/impl/serialization/ByteArraySerializer.java b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/ByteArraySerializer.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/serialization/ByteArraySerializer.java rename to ehcache-impl/src/main/java/org/ehcache/impl/serialization/ByteArraySerializer.java diff --git a/impl/src/main/java/org/ehcache/impl/serialization/CharSerializer.java b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/CharSerializer.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/serialization/CharSerializer.java rename to ehcache-impl/src/main/java/org/ehcache/impl/serialization/CharSerializer.java diff --git a/impl/src/main/java/org/ehcache/impl/serialization/CompactJavaSerializer.java b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/CompactJavaSerializer.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/serialization/CompactJavaSerializer.java rename to ehcache-impl/src/main/java/org/ehcache/impl/serialization/CompactJavaSerializer.java diff --git a/impl/src/main/java/org/ehcache/impl/serialization/DoubleSerializer.java b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/DoubleSerializer.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/serialization/DoubleSerializer.java rename to ehcache-impl/src/main/java/org/ehcache/impl/serialization/DoubleSerializer.java diff --git a/impl/src/main/java/org/ehcache/impl/serialization/FloatSerializer.java b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/FloatSerializer.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/serialization/FloatSerializer.java rename to ehcache-impl/src/main/java/org/ehcache/impl/serialization/FloatSerializer.java diff --git a/impl/src/main/java/org/ehcache/impl/serialization/IntegerSerializer.java b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/IntegerSerializer.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/serialization/IntegerSerializer.java rename to ehcache-impl/src/main/java/org/ehcache/impl/serialization/IntegerSerializer.java diff --git a/impl/src/main/java/org/ehcache/impl/serialization/LongSerializer.java b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/LongSerializer.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/serialization/LongSerializer.java rename to ehcache-impl/src/main/java/org/ehcache/impl/serialization/LongSerializer.java diff --git a/impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java rename to ehcache-impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java diff --git a/impl/src/main/java/org/ehcache/impl/serialization/StringSerializer.java b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/StringSerializer.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/serialization/StringSerializer.java rename to ehcache-impl/src/main/java/org/ehcache/impl/serialization/StringSerializer.java diff --git a/impl/src/main/java/org/ehcache/impl/serialization/TransientStateHolder.java b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/TransientStateHolder.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/serialization/TransientStateHolder.java rename to ehcache-impl/src/main/java/org/ehcache/impl/serialization/TransientStateHolder.java diff --git a/impl/src/main/java/org/ehcache/impl/serialization/TransientStateRepository.java b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/TransientStateRepository.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/serialization/TransientStateRepository.java rename to ehcache-impl/src/main/java/org/ehcache/impl/serialization/TransientStateRepository.java diff --git a/impl/src/main/java/org/ehcache/impl/serialization/package-info.java b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/package-info.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/serialization/package-info.java rename to ehcache-impl/src/main/java/org/ehcache/impl/serialization/package-info.java diff --git a/impl/src/main/java/org/ehcache/impl/store/BaseStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/store/BaseStore.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/store/BaseStore.java rename to ehcache-impl/src/main/java/org/ehcache/impl/store/BaseStore.java diff --git a/impl/src/main/java/org/ehcache/impl/store/DefaultStoreEventDispatcher.java b/ehcache-impl/src/main/java/org/ehcache/impl/store/DefaultStoreEventDispatcher.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/store/DefaultStoreEventDispatcher.java rename to ehcache-impl/src/main/java/org/ehcache/impl/store/DefaultStoreEventDispatcher.java diff --git a/impl/src/main/java/org/ehcache/impl/store/HashUtils.java b/ehcache-impl/src/main/java/org/ehcache/impl/store/HashUtils.java similarity index 100% rename from impl/src/main/java/org/ehcache/impl/store/HashUtils.java rename to ehcache-impl/src/main/java/org/ehcache/impl/store/HashUtils.java diff --git a/impl/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory b/ehcache-impl/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory similarity index 100% rename from impl/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory rename to ehcache-impl/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory diff --git a/impl/src/slow-test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapITest.java b/ehcache-impl/src/slow-test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapITest.java similarity index 100% rename from impl/src/slow-test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapITest.java rename to ehcache-impl/src/slow-test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapITest.java diff --git a/impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/EhcacheRuntimeConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java b/ehcache-impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java rename to ehcache-impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java diff --git a/impl/src/test/java/org/ehcache/config/builders/CacheManagerBuilderTest.java b/ehcache-impl/src/test/java/org/ehcache/config/builders/CacheManagerBuilderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/config/builders/CacheManagerBuilderTest.java rename to ehcache-impl/src/test/java/org/ehcache/config/builders/CacheManagerBuilderTest.java diff --git a/impl/src/test/java/org/ehcache/config/builders/ExpiryPolicyBuilderTest.java b/ehcache-impl/src/test/java/org/ehcache/config/builders/ExpiryPolicyBuilderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/config/builders/ExpiryPolicyBuilderTest.java rename to ehcache-impl/src/test/java/org/ehcache/config/builders/ExpiryPolicyBuilderTest.java diff --git a/impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java b/ehcache-impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java rename to ehcache-impl/src/test/java/org/ehcache/config/builders/PersistentCacheManagerTest.java diff --git a/impl/src/test/java/org/ehcache/config/builders/ResourcePoolsBuilderTest.java b/ehcache-impl/src/test/java/org/ehcache/config/builders/ResourcePoolsBuilderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/config/builders/ResourcePoolsBuilderTest.java rename to ehcache-impl/src/test/java/org/ehcache/config/builders/ResourcePoolsBuilderTest.java diff --git a/impl/src/test/java/org/ehcache/config/builders/TieringTest.java b/ehcache-impl/src/test/java/org/ehcache/config/builders/TieringTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/config/builders/TieringTest.java rename to ehcache-impl/src/test/java/org/ehcache/config/builders/TieringTest.java diff --git a/impl/src/test/java/org/ehcache/config/builders/UserManagedCacheBuilderTest.java b/ehcache-impl/src/test/java/org/ehcache/config/builders/UserManagedCacheBuilderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/config/builders/UserManagedCacheBuilderTest.java rename to ehcache-impl/src/test/java/org/ehcache/config/builders/UserManagedCacheBuilderTest.java diff --git a/impl/src/test/java/org/ehcache/config/builders/WriteBehindConfigurationBuilderTest.java b/ehcache-impl/src/test/java/org/ehcache/config/builders/WriteBehindConfigurationBuilderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/config/builders/WriteBehindConfigurationBuilderTest.java rename to ehcache-impl/src/test/java/org/ehcache/config/builders/WriteBehindConfigurationBuilderTest.java diff --git a/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerInteractionsTest.java b/ehcache-impl/src/test/java/org/ehcache/core/events/CacheManagerListenerInteractionsTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/core/events/CacheManagerListenerInteractionsTest.java rename to ehcache-impl/src/test/java/org/ehcache/core/events/CacheManagerListenerInteractionsTest.java diff --git a/impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java b/ehcache-impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java rename to ehcache-impl/src/test/java/org/ehcache/core/events/CacheManagerListenerTest.java diff --git a/impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java b/ehcache-impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java rename to ehcache-impl/src/test/java/org/ehcache/core/spi/ServiceProviderTest.java diff --git a/impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java b/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java similarity index 100% rename from impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java rename to ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java diff --git a/impl/src/test/java/org/ehcache/docs/Ehcache3.java b/ehcache-impl/src/test/java/org/ehcache/docs/Ehcache3.java similarity index 100% rename from impl/src/test/java/org/ehcache/docs/Ehcache3.java rename to ehcache-impl/src/test/java/org/ehcache/docs/Ehcache3.java diff --git a/impl/src/test/java/org/ehcache/docs/GettingStarted.java b/ehcache-impl/src/test/java/org/ehcache/docs/GettingStarted.java similarity index 100% rename from impl/src/test/java/org/ehcache/docs/GettingStarted.java rename to ehcache-impl/src/test/java/org/ehcache/docs/GettingStarted.java diff --git a/impl/src/test/java/org/ehcache/docs/ThreadPools.java b/ehcache-impl/src/test/java/org/ehcache/docs/ThreadPools.java similarity index 100% rename from impl/src/test/java/org/ehcache/docs/ThreadPools.java rename to ehcache-impl/src/test/java/org/ehcache/docs/ThreadPools.java diff --git a/impl/src/test/java/org/ehcache/docs/Tiering.java b/ehcache-impl/src/test/java/org/ehcache/docs/Tiering.java similarity index 100% rename from impl/src/test/java/org/ehcache/docs/Tiering.java rename to ehcache-impl/src/test/java/org/ehcache/docs/Tiering.java diff --git a/impl/src/test/java/org/ehcache/docs/UserManagedCaches.java b/ehcache-impl/src/test/java/org/ehcache/docs/UserManagedCaches.java similarity index 100% rename from impl/src/test/java/org/ehcache/docs/UserManagedCaches.java rename to ehcache-impl/src/test/java/org/ehcache/docs/UserManagedCaches.java diff --git a/impl/src/test/java/org/ehcache/docs/plugs/ListenerObject.java b/ehcache-impl/src/test/java/org/ehcache/docs/plugs/ListenerObject.java similarity index 100% rename from impl/src/test/java/org/ehcache/docs/plugs/ListenerObject.java rename to ehcache-impl/src/test/java/org/ehcache/docs/plugs/ListenerObject.java diff --git a/impl/src/test/java/org/ehcache/docs/plugs/LongCopier.java b/ehcache-impl/src/test/java/org/ehcache/docs/plugs/LongCopier.java similarity index 100% rename from impl/src/test/java/org/ehcache/docs/plugs/LongCopier.java rename to ehcache-impl/src/test/java/org/ehcache/docs/plugs/LongCopier.java diff --git a/impl/src/test/java/org/ehcache/docs/plugs/OddKeysEvictionAdvisor.java b/ehcache-impl/src/test/java/org/ehcache/docs/plugs/OddKeysEvictionAdvisor.java similarity index 100% rename from impl/src/test/java/org/ehcache/docs/plugs/OddKeysEvictionAdvisor.java rename to ehcache-impl/src/test/java/org/ehcache/docs/plugs/OddKeysEvictionAdvisor.java diff --git a/impl/src/test/java/org/ehcache/docs/plugs/SampleLoaderWriter.java b/ehcache-impl/src/test/java/org/ehcache/docs/plugs/SampleLoaderWriter.java similarity index 100% rename from impl/src/test/java/org/ehcache/docs/plugs/SampleLoaderWriter.java rename to ehcache-impl/src/test/java/org/ehcache/docs/plugs/SampleLoaderWriter.java diff --git a/impl/src/test/java/org/ehcache/docs/plugs/StringCopier.java b/ehcache-impl/src/test/java/org/ehcache/docs/plugs/StringCopier.java similarity index 100% rename from impl/src/test/java/org/ehcache/docs/plugs/StringCopier.java rename to ehcache-impl/src/test/java/org/ehcache/docs/plugs/StringCopier.java diff --git a/impl/src/test/java/org/ehcache/impl/config/BaseCacheConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/BaseCacheConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/BaseCacheConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/BaseCacheConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/ResourcePoolsImplTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/ResourcePoolsImplTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/ResourcePoolsImplTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/ResourcePoolsImplTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/SizedResourcePoolImplTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/SizedResourcePoolImplTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/SizedResourcePoolImplTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/SizedResourcePoolImplTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/copy/DefaultCopyProviderConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/event/CacheEventDispatcherFactoryConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventDispatcherConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventListenerConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventListenerConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventListenerConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/event/DefaultCacheEventListenerConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/event/DefaultEventSourceConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/event/DefaultEventSourceConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/event/DefaultEventSourceConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/event/DefaultEventSourceConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/executor/PooledExecutionServiceConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/loaderwriter/DefaultCacheLoaderWriterProviderConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/loaderwriter/writebehind/WriteBehindProviderConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/persistence/DefaultPersistenceConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/resilience/DefaultResilienceStrategyProviderConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/serializer/DefaultSerializationProviderConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/serializer/SerializerCountingTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/config/store/disk/OffHeapDiskStoreProviderConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/events/CacheEventDispatcherImplTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/events/CacheEventDispatcherImplTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/events/CacheEventDispatcherImplTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/events/CacheEventDispatcherImplTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/DefaultTimeSourceServiceTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/DefaultTimeSourceServiceTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/DefaultTimeSourceServiceTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/DefaultTimeSourceServiceTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/TimeSourceConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/TimeSourceConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/TimeSourceConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/TimeSourceConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/classes/ClassInstanceProviderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMapTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/concurrent/otherPackage/V8FeaturesTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/concurrent/otherPackage/V8FeaturesTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/concurrent/otherPackage/V8FeaturesTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/concurrent/otherPackage/V8FeaturesTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/copy/IdentityCopierTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/copy/IdentityCopierTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/copy/IdentityCopierTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/copy/IdentityCopierTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/copy/SerializingCopierTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/copy/SerializingCopierTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/copy/SerializingCopierTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/copy/SerializingCopierTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImplTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImplTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImplTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/events/CacheEventDispatcherFactoryImplTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/events/FudgingInvocationScopedEventSinkTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/events/FudgingInvocationScopedEventSinkTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/events/FudgingInvocationScopedEventSinkTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/events/FudgingInvocationScopedEventSinkTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/events/InvocationScopedEventSinkTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/events/InvocationScopedEventSinkTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/events/InvocationScopedEventSinkTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/events/InvocationScopedEventSinkTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/events/TestStoreEventDispatcher.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/events/TestStoreEventDispatcher.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/events/TestStoreEventDispatcher.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/events/TestStoreEventDispatcher.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedOrderedExecutorTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedOrderedExecutorTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedOrderedExecutorTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedOrderedExecutorTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedScheduledExecutorTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedScheduledExecutorTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedScheduledExecutorTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedScheduledExecutorTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedUnorderedExecutorTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedUnorderedExecutorTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedUnorderedExecutorTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/executor/PartitionedUnorderedExecutorTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/executor/PooledExecutionServiceTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/executor/PooledExecutionServiceTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/executor/PooledExecutionServiceTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/executor/PooledExecutionServiceTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehindTestBase.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehindTestBase.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehindTestBase.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/AbstractWriteBehindTestBase.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/PooledExecutorWriteBehindTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/PooledExecutorWriteBehindTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/PooledExecutorWriteBehindTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/PooledExecutorWriteBehindTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindEvictionTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindEvictionTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindEvictionTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindEvictionTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactoryTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactoryTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactoryTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindProviderFactoryTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindTestLoaderWriter.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindTestLoaderWriter.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindTestLoaderWriter.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/loaderwriter/writebehind/WriteBehindTestLoaderWriter.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/persistence/CacheManagerDestroyRemovesPersistenceTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/persistence/CacheManagerDestroyRemovesPersistenceTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/persistence/CacheManagerDestroyRemovesPersistenceTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/persistence/CacheManagerDestroyRemovesPersistenceTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/persistence/TestDiskResourceService.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/persistence/TestDiskResourceService.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/persistence/TestDiskResourceService.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/persistence/TestDiskResourceService.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategyTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategyTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategyTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/resilience/RobustLoaderWriterResilienceStrategyTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategyTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategyTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategyTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/resilience/RobustResilienceStrategyTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderConfigurationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderConfigurationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderConfigurationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderConfigurationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactoryTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactoryTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactoryTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineProviderFactoryTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/sizeof/DefaultSizeOfEngineTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/TestServiceProvider.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/spi/TestServiceProvider.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/spi/TestServiceProvider.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/spi/TestServiceProvider.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/spi/copy/DefaultCopyProviderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/spi/event/DefaultCacheEventListenerProviderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/spi/loaderwriter/DefaultCacheLoaderWriterProviderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactoryTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactoryTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactoryTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderFactoryTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/spi/resilience/DefaultResilienceStrategyProviderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/spi/serialization/DefaultSerializationProviderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultCacheStatisticsTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultStatisticsServiceTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsDisabledTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsDisabledTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsDisabledTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsDisabledTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/statistics/DefaultTierStatisticsTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/statistics/StatsUtilsTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/basic/DelegatingValueHolder.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/basic/DelegatingValueHolder.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/basic/DelegatingValueHolder.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/basic/DelegatingValueHolder.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/basic/SimpleValueHolder.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/basic/SimpleValueHolder.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/basic/SimpleValueHolder.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/basic/SimpleValueHolder.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/disk/EhcachePersistentConcurrentOffHeapClockCacheTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreProviderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreSPITest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/disk/OffHeapDiskStoreTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/disk/factories/EhcachePersistentSegmentTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByRefSPITest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/ByteSizedOnHeapStoreByValueSPITest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByRefTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByRefTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByRefTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByRefTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByValueTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByValueTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByValueTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/CountSizedOnHeapStoreByValueTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefSPITest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByRefTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueSPITest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreByValueTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByRefSPITest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreCachingTierByValueSPITest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreEvictionTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreProviderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStrategyTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByRefTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByRefTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByRefTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByRefTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByValueTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByValueTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByValueTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteSizedOnHeapStoreByValueTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByRefSPITest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreCachingTierByValueSPITest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreEvictionTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreEvictionTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreEvictionTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreEvictionTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OversizeMappingTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OversizeMappingTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OversizeMappingTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OversizeMappingTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapKeyTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapKeyTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapKeyTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapKeyTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/CopiedOnHeapValueHolderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/holders/SerializedOnHeapValueHolderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractEhcacheOffHeapBackingMapTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractEhcacheOffHeapBackingMapTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractEhcacheOffHeapBackingMapTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractEhcacheOffHeapBackingMapTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolder.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolder.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolder.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolder.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/AssertingOffHeapValueHolderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/BasicOffHeapValueHolderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/BinaryOffHeapValueHolderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/EhcacheConcurrentOffHeapClockCacheTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/EhcacheConcurrentOffHeapClockCacheTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/EhcacheConcurrentOffHeapClockCacheTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/EhcacheConcurrentOffHeapClockCacheTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/LazyOffHeapValueHolderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/MemorySizeParserTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/MemorySizeParserTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/MemorySizeParserTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/MemorySizeParserTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreSPITest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreUtilsTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreUtilsTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreUtilsTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreUtilsTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolderPortabilityTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolderPortabilityTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolderPortabilityTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapValueHolderPortabilityTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/factories/EhcacheSegmentTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/offheap/portability/AssertingOffHeapValueHolderPortability.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/portability/AssertingOffHeapValueHolderPortability.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/offheap/portability/AssertingOffHeapValueHolderPortability.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/portability/AssertingOffHeapValueHolderPortability.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierSPITest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/CompoundCachingTierTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreFlushWhileShutdownTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreMutatorTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreSPITest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreWith3TiersSPITest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/ByteBufferInputStreamTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/util/ByteBufferInputStreamTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/util/ByteBufferInputStreamTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/util/ByteBufferInputStreamTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchers.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchers.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchers.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchers.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/util/FileExistenceMatchersTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/Matchers.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/util/Matchers.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/util/Matchers.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/util/Matchers.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/PacerTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/util/PacerTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/util/PacerTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/util/PacerTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/StatisticsTestUtils.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/util/StatisticsTestUtils.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/util/StatisticsTestUtils.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/util/StatisticsTestUtils.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/ThreadFactoryUtilTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/util/ThreadFactoryUtilTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/util/ThreadFactoryUtilTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/util/ThreadFactoryUtilTest.java diff --git a/impl/src/test/java/org/ehcache/impl/internal/util/UnmatchedResourceType.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/util/UnmatchedResourceType.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/internal/util/UnmatchedResourceType.java rename to ehcache-impl/src/test/java/org/ehcache/impl/internal/util/UnmatchedResourceType.java diff --git a/impl/src/test/java/org/ehcache/impl/persistence/DefaultDiskResourceServiceTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/persistence/DefaultDiskResourceServiceTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/persistence/DefaultDiskResourceServiceTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/persistence/DefaultDiskResourceServiceTest.java diff --git a/impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/persistence/DefaultLocalPersistenceServiceTest.java diff --git a/impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/persistence/FileBasedStateRepositoryTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/AddedSuperClassTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedSuperClassTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/AddedSuperClassTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedSuperClassTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/ArrayPackageScopeTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/ArrayPackageScopeTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/ArrayPackageScopeTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/ArrayPackageScopeTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/BasicSerializationTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/BasicSerializationTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/BasicSerializationTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/BasicSerializationTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/ByteArraySerializerTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/ByteArraySerializerTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/ByteArraySerializerTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/ByteArraySerializerTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/CharSerializerTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CharSerializerTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/CharSerializerTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/CharSerializerTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassLoaderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassLoaderTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassLoaderTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassLoaderTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassUnloadingTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassUnloadingTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassUnloadingTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassUnloadingTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/DoubleSerializerTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/DoubleSerializerTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/DoubleSerializerTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/DoubleSerializerTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/DuplicateClassLoader.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/DuplicateClassLoader.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/DuplicateClassLoader.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/DuplicateClassLoader.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/EnumTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/EnumTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/EnumTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/EnumTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/FieldTypeChangeTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/FieldTypeChangeTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/FieldTypeChangeTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/FieldTypeChangeTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/FloatSerializerTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/FloatSerializerTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/FloatSerializerTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/FloatSerializerTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/GetFieldTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/GetFieldTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/GetFieldTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/GetFieldTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/IntegerSerializerTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/IntegerSerializerTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/IntegerSerializerTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/IntegerSerializerTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/LongSerializerTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/LongSerializerTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/LongSerializerTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/LongSerializerTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/PutFieldTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/PutFieldTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/PutFieldTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/PutFieldTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/ReadObjectNoDataTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/ReadObjectNoDataTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/ReadObjectNoDataTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/ReadObjectNoDataTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/SerializerTestUtilities.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/SerializerTestUtilities.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/SerializerTestUtilities.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/SerializerTestUtilities.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/StringSerializerTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/StringSerializerTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/StringSerializerTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/StringSerializerTest.java diff --git a/impl/src/test/java/org/ehcache/impl/serialization/TransientStateRepositoryTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/TransientStateRepositoryTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/serialization/TransientStateRepositoryTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/serialization/TransientStateRepositoryTest.java diff --git a/impl/src/test/java/org/ehcache/impl/store/DefaultStoreEventDispatcherTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/store/DefaultStoreEventDispatcherTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/store/DefaultStoreEventDispatcherTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/store/DefaultStoreEventDispatcherTest.java diff --git a/impl/src/test/java/org/ehcache/impl/store/HashUtilsTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/store/HashUtilsTest.java similarity index 100% rename from impl/src/test/java/org/ehcache/impl/store/HashUtilsTest.java rename to ehcache-impl/src/test/java/org/ehcache/impl/store/HashUtilsTest.java diff --git a/impl/src/test/java/org/ehcache/test/MockitoUtil.java b/ehcache-impl/src/test/java/org/ehcache/test/MockitoUtil.java similarity index 100% rename from impl/src/test/java/org/ehcache/test/MockitoUtil.java rename to ehcache-impl/src/test/java/org/ehcache/test/MockitoUtil.java diff --git a/impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java b/ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java similarity index 100% rename from impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java rename to ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java diff --git a/impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/EvictingConcurrentMap.java b/ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/EvictingConcurrentMap.java similarity index 100% rename from impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/EvictingConcurrentMap.java rename to ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/EvictingConcurrentMap.java diff --git a/impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ThreadLocalRandomUtil.java b/ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ThreadLocalRandomUtil.java similarity index 100% rename from impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ThreadLocalRandomUtil.java rename to ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ThreadLocalRandomUtil.java diff --git a/impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/package-info.java b/ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/package-info.java similarity index 100% rename from impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/package-info.java rename to ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/package-info.java diff --git a/management/build.gradle b/ehcache-management/build.gradle similarity index 68% rename from management/build.gradle rename to ehcache-management/build.gradle index b3417cad71..4110cbd634 100644 --- a/management/build.gradle +++ b/ehcache-management/build.gradle @@ -15,28 +15,35 @@ */ plugins { - id 'org.ehcache.build.deploy' + id 'org.ehcache.build.internal-module' +} + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache 3 Management and Monitoring module' + description = 'The Management and Monitoring module of Ehcache 3' + } } dependencies { implementation "org.terracotta:statistics:$statisticVersion" // optional: if we want xml config - compileOnly project(':xml') + compileOnly project(':ehcache-xml') // optional: if we want to use the clustered management layer - compileOnly project(':clustered:client') + compileOnly project(':clustered:ehcache-client') compileOnly "org.terracotta:entity-client-api:$terracottaApisVersion" compileOnly ("org.terracotta.management:nms-agent-entity-client:$terracottaPlatformVersion") { // This is to avoid stats lib being directly used. exclude group:'org.terracotta', module:'statistics' } - compileOnly project(':api') - compileOnly project(':core') - compileOnly project(':impl') + compileOnly project(':ehcache-api') + compileOnly project(':ehcache-core') + compileOnly project(':ehcache-impl') testImplementation "org.terracotta.management:management-registry:$terracottaPlatformVersion" - testImplementation project(':xml') - testImplementation project(':impl') + testImplementation project(':ehcache-xml') + testImplementation project(':ehcache-impl') testImplementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" - testImplementation testFixtures(project(':xml')) + testImplementation testFixtures(project(':ehcache-xml')) } diff --git a/management/config/checkstyle-suppressions.xml b/ehcache-management/config/checkstyle-suppressions.xml similarity index 100% rename from management/config/checkstyle-suppressions.xml rename to ehcache-management/config/checkstyle-suppressions.xml diff --git a/management/src/main/java/org/ehcache/management/CollectorService.java b/ehcache-management/src/main/java/org/ehcache/management/CollectorService.java similarity index 100% rename from management/src/main/java/org/ehcache/management/CollectorService.java rename to ehcache-management/src/main/java/org/ehcache/management/CollectorService.java diff --git a/management/src/main/java/org/ehcache/management/ExtendedStatisticsService.java b/ehcache-management/src/main/java/org/ehcache/management/ExtendedStatisticsService.java similarity index 100% rename from management/src/main/java/org/ehcache/management/ExtendedStatisticsService.java rename to ehcache-management/src/main/java/org/ehcache/management/ExtendedStatisticsService.java diff --git a/management/src/main/java/org/ehcache/management/ManagementRegistryService.java b/ehcache-management/src/main/java/org/ehcache/management/ManagementRegistryService.java similarity index 100% rename from management/src/main/java/org/ehcache/management/ManagementRegistryService.java rename to ehcache-management/src/main/java/org/ehcache/management/ManagementRegistryService.java diff --git a/management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java b/ehcache-management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java similarity index 100% rename from management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java rename to ehcache-management/src/main/java/org/ehcache/management/ManagementRegistryServiceConfiguration.java diff --git a/management/src/main/java/org/ehcache/management/SharedManagementService.java b/ehcache-management/src/main/java/org/ehcache/management/SharedManagementService.java similarity index 100% rename from management/src/main/java/org/ehcache/management/SharedManagementService.java rename to ehcache-management/src/main/java/org/ehcache/management/SharedManagementService.java diff --git a/management/src/main/java/org/ehcache/management/cluster/Clustering.java b/ehcache-management/src/main/java/org/ehcache/management/cluster/Clustering.java similarity index 100% rename from management/src/main/java/org/ehcache/management/cluster/Clustering.java rename to ehcache-management/src/main/java/org/ehcache/management/cluster/Clustering.java diff --git a/management/src/main/java/org/ehcache/management/cluster/ClusteringManagementService.java b/ehcache-management/src/main/java/org/ehcache/management/cluster/ClusteringManagementService.java similarity index 100% rename from management/src/main/java/org/ehcache/management/cluster/ClusteringManagementService.java rename to ehcache-management/src/main/java/org/ehcache/management/cluster/ClusteringManagementService.java diff --git a/management/src/main/java/org/ehcache/management/cluster/ClusteringManagementServiceConfiguration.java b/ehcache-management/src/main/java/org/ehcache/management/cluster/ClusteringManagementServiceConfiguration.java similarity index 100% rename from management/src/main/java/org/ehcache/management/cluster/ClusteringManagementServiceConfiguration.java rename to ehcache-management/src/main/java/org/ehcache/management/cluster/ClusteringManagementServiceConfiguration.java diff --git a/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java b/ehcache-management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java similarity index 100% rename from management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java rename to ehcache-management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementService.java diff --git a/management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementServiceConfiguration.java b/ehcache-management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementServiceConfiguration.java similarity index 100% rename from management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementServiceConfiguration.java rename to ehcache-management/src/main/java/org/ehcache/management/cluster/DefaultClusteringManagementServiceConfiguration.java diff --git a/management/src/main/java/org/ehcache/management/cluster/LoggingExecutor.java b/ehcache-management/src/main/java/org/ehcache/management/cluster/LoggingExecutor.java similarity index 100% rename from management/src/main/java/org/ehcache/management/cluster/LoggingExecutor.java rename to ehcache-management/src/main/java/org/ehcache/management/cluster/LoggingExecutor.java diff --git a/management/src/main/java/org/ehcache/management/providers/CacheBinding.java b/ehcache-management/src/main/java/org/ehcache/management/providers/CacheBinding.java similarity index 100% rename from management/src/main/java/org/ehcache/management/providers/CacheBinding.java rename to ehcache-management/src/main/java/org/ehcache/management/providers/CacheBinding.java diff --git a/management/src/main/java/org/ehcache/management/providers/CacheBindingManagementProvider.java b/ehcache-management/src/main/java/org/ehcache/management/providers/CacheBindingManagementProvider.java similarity index 100% rename from management/src/main/java/org/ehcache/management/providers/CacheBindingManagementProvider.java rename to ehcache-management/src/main/java/org/ehcache/management/providers/CacheBindingManagementProvider.java diff --git a/management/src/main/java/org/ehcache/management/providers/EhcacheStatisticCollectorProvider.java b/ehcache-management/src/main/java/org/ehcache/management/providers/EhcacheStatisticCollectorProvider.java similarity index 100% rename from management/src/main/java/org/ehcache/management/providers/EhcacheStatisticCollectorProvider.java rename to ehcache-management/src/main/java/org/ehcache/management/providers/EhcacheStatisticCollectorProvider.java diff --git a/management/src/main/java/org/ehcache/management/providers/ExposedCacheBinding.java b/ehcache-management/src/main/java/org/ehcache/management/providers/ExposedCacheBinding.java similarity index 100% rename from management/src/main/java/org/ehcache/management/providers/ExposedCacheBinding.java rename to ehcache-management/src/main/java/org/ehcache/management/providers/ExposedCacheBinding.java diff --git a/management/src/main/java/org/ehcache/management/providers/actions/EhcacheActionProvider.java b/ehcache-management/src/main/java/org/ehcache/management/providers/actions/EhcacheActionProvider.java similarity index 100% rename from management/src/main/java/org/ehcache/management/providers/actions/EhcacheActionProvider.java rename to ehcache-management/src/main/java/org/ehcache/management/providers/actions/EhcacheActionProvider.java diff --git a/management/src/main/java/org/ehcache/management/providers/actions/EhcacheActionWrapper.java b/ehcache-management/src/main/java/org/ehcache/management/providers/actions/EhcacheActionWrapper.java similarity index 100% rename from management/src/main/java/org/ehcache/management/providers/actions/EhcacheActionWrapper.java rename to ehcache-management/src/main/java/org/ehcache/management/providers/actions/EhcacheActionWrapper.java diff --git a/management/src/main/java/org/ehcache/management/providers/settings/EhcacheSettingsProvider.java b/ehcache-management/src/main/java/org/ehcache/management/providers/settings/EhcacheSettingsProvider.java similarity index 100% rename from management/src/main/java/org/ehcache/management/providers/settings/EhcacheSettingsProvider.java rename to ehcache-management/src/main/java/org/ehcache/management/providers/settings/EhcacheSettingsProvider.java diff --git a/management/src/main/java/org/ehcache/management/providers/settings/ExposedCacheSettings.java b/ehcache-management/src/main/java/org/ehcache/management/providers/settings/ExposedCacheSettings.java similarity index 100% rename from management/src/main/java/org/ehcache/management/providers/settings/ExposedCacheSettings.java rename to ehcache-management/src/main/java/org/ehcache/management/providers/settings/ExposedCacheSettings.java diff --git a/management/src/main/java/org/ehcache/management/providers/settings/Reflect.java b/ehcache-management/src/main/java/org/ehcache/management/providers/settings/Reflect.java similarity index 100% rename from management/src/main/java/org/ehcache/management/providers/settings/Reflect.java rename to ehcache-management/src/main/java/org/ehcache/management/providers/settings/Reflect.java diff --git a/management/src/main/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProvider.java b/ehcache-management/src/main/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProvider.java similarity index 100% rename from management/src/main/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProvider.java rename to ehcache-management/src/main/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProvider.java diff --git a/management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java b/ehcache-management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java similarity index 100% rename from management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java rename to ehcache-management/src/main/java/org/ehcache/management/providers/statistics/StandardEhcacheStatistics.java diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultCollectorService.java b/ehcache-management/src/main/java/org/ehcache/management/registry/DefaultCollectorService.java similarity index 100% rename from management/src/main/java/org/ehcache/management/registry/DefaultCollectorService.java rename to ehcache-management/src/main/java/org/ehcache/management/registry/DefaultCollectorService.java diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java b/ehcache-management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java similarity index 100% rename from management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java rename to ehcache-management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryConfiguration.java diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryFactory.java b/ehcache-management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryFactory.java similarity index 100% rename from management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryFactory.java rename to ehcache-management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryFactory.java diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java b/ehcache-management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java similarity index 100% rename from management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java rename to ehcache-management/src/main/java/org/ehcache/management/registry/DefaultManagementRegistryService.java diff --git a/management/src/main/java/org/ehcache/management/registry/DefaultSharedManagementService.java b/ehcache-management/src/main/java/org/ehcache/management/registry/DefaultSharedManagementService.java similarity index 100% rename from management/src/main/java/org/ehcache/management/registry/DefaultSharedManagementService.java rename to ehcache-management/src/main/java/org/ehcache/management/registry/DefaultSharedManagementService.java diff --git a/management/src/main/java/org/ehcache/management/registry/LatencyHistogramConfiguration.java b/ehcache-management/src/main/java/org/ehcache/management/registry/LatencyHistogramConfiguration.java similarity index 100% rename from management/src/main/java/org/ehcache/management/registry/LatencyHistogramConfiguration.java rename to ehcache-management/src/main/java/org/ehcache/management/registry/LatencyHistogramConfiguration.java diff --git a/management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java b/ehcache-management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java similarity index 100% rename from management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java rename to ehcache-management/src/main/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParser.java diff --git a/management/src/main/java/org/ehcache/management/registry/NodeListIterable.java b/ehcache-management/src/main/java/org/ehcache/management/registry/NodeListIterable.java similarity index 100% rename from management/src/main/java/org/ehcache/management/registry/NodeListIterable.java rename to ehcache-management/src/main/java/org/ehcache/management/registry/NodeListIterable.java diff --git a/management/src/main/java/org/ehcache/management/statistics/DefaultCacheStatistics.java b/ehcache-management/src/main/java/org/ehcache/management/statistics/DefaultCacheStatistics.java similarity index 100% rename from management/src/main/java/org/ehcache/management/statistics/DefaultCacheStatistics.java rename to ehcache-management/src/main/java/org/ehcache/management/statistics/DefaultCacheStatistics.java diff --git a/management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsService.java b/ehcache-management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsService.java similarity index 100% rename from management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsService.java rename to ehcache-management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsService.java diff --git a/management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsServiceFactory.java b/ehcache-management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsServiceFactory.java similarity index 100% rename from management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsServiceFactory.java rename to ehcache-management/src/main/java/org/ehcache/management/statistics/DefaultExtendedStatisticsServiceFactory.java diff --git a/management/src/main/java/org/ehcache/management/statistics/DefaultTierStatistics.java b/ehcache-management/src/main/java/org/ehcache/management/statistics/DefaultTierStatistics.java similarity index 100% rename from management/src/main/java/org/ehcache/management/statistics/DefaultTierStatistics.java rename to ehcache-management/src/main/java/org/ehcache/management/statistics/DefaultTierStatistics.java diff --git a/management/src/main/java/org/ehcache/management/statistics/DelegatedMappedOperationStatistics.java b/ehcache-management/src/main/java/org/ehcache/management/statistics/DelegatedMappedOperationStatistics.java similarity index 100% rename from management/src/main/java/org/ehcache/management/statistics/DelegatedMappedOperationStatistics.java rename to ehcache-management/src/main/java/org/ehcache/management/statistics/DelegatedMappedOperationStatistics.java diff --git a/management/src/main/java/org/ehcache/management/statistics/DelegatingOperationObserver.java b/ehcache-management/src/main/java/org/ehcache/management/statistics/DelegatingOperationObserver.java similarity index 100% rename from management/src/main/java/org/ehcache/management/statistics/DelegatingOperationObserver.java rename to ehcache-management/src/main/java/org/ehcache/management/statistics/DelegatingOperationObserver.java diff --git a/management/src/main/java/org/ehcache/management/statistics/StatsUtils.java b/ehcache-management/src/main/java/org/ehcache/management/statistics/StatsUtils.java similarity index 100% rename from management/src/main/java/org/ehcache/management/statistics/StatsUtils.java rename to ehcache-management/src/main/java/org/ehcache/management/statistics/StatsUtils.java diff --git a/management/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory b/ehcache-management/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory similarity index 100% rename from management/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory rename to ehcache-management/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory diff --git a/management/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser b/ehcache-management/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser similarity index 100% rename from management/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser rename to ehcache-management/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser diff --git a/management/src/main/resources/ehcache-management-ext.xsd b/ehcache-management/src/main/resources/ehcache-management-ext.xsd similarity index 100% rename from management/src/main/resources/ehcache-management-ext.xsd rename to ehcache-management/src/main/resources/ehcache-management-ext.xsd diff --git a/management/src/test/java/org/ehcache/docs/ManagementTest.java b/ehcache-management/src/test/java/org/ehcache/docs/ManagementTest.java similarity index 100% rename from management/src/test/java/org/ehcache/docs/ManagementTest.java rename to ehcache-management/src/test/java/org/ehcache/docs/ManagementTest.java diff --git a/management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java b/ehcache-management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java similarity index 100% rename from management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java rename to ehcache-management/src/test/java/org/ehcache/management/ManagementRegistryServiceConfigurationParserIT.java diff --git a/management/src/test/java/org/ehcache/management/providers/actions/EhcacheActionProviderTest.java b/ehcache-management/src/test/java/org/ehcache/management/providers/actions/EhcacheActionProviderTest.java similarity index 100% rename from management/src/test/java/org/ehcache/management/providers/actions/EhcacheActionProviderTest.java rename to ehcache-management/src/test/java/org/ehcache/management/providers/actions/EhcacheActionProviderTest.java diff --git a/management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java b/ehcache-management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java similarity index 100% rename from management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java rename to ehcache-management/src/test/java/org/ehcache/management/providers/settings/EhcacheSettingsProviderTest.java diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java b/ehcache-management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java similarity index 100% rename from management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java rename to ehcache-management/src/test/java/org/ehcache/management/providers/statistics/EhcacheStatisticsProviderTest.java diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/LatencyHistogramConfigurationTest.java b/ehcache-management/src/test/java/org/ehcache/management/providers/statistics/LatencyHistogramConfigurationTest.java similarity index 100% rename from management/src/test/java/org/ehcache/management/providers/statistics/LatencyHistogramConfigurationTest.java rename to ehcache-management/src/test/java/org/ehcache/management/providers/statistics/LatencyHistogramConfigurationTest.java diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java b/ehcache-management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java similarity index 100% rename from management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java rename to ehcache-management/src/test/java/org/ehcache/management/providers/statistics/StandardEhCacheStatisticsQueryTest.java diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java b/ehcache-management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java similarity index 100% rename from management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java rename to ehcache-management/src/test/java/org/ehcache/management/providers/statistics/StandardEhcacheStatisticsTest.java diff --git a/management/src/test/java/org/ehcache/management/providers/statistics/StatsUtil.java b/ehcache-management/src/test/java/org/ehcache/management/providers/statistics/StatsUtil.java similarity index 100% rename from management/src/test/java/org/ehcache/management/providers/statistics/StatsUtil.java rename to ehcache-management/src/test/java/org/ehcache/management/providers/statistics/StatsUtil.java diff --git a/management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java b/ehcache-management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java similarity index 100% rename from management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java rename to ehcache-management/src/test/java/org/ehcache/management/registry/DefaultCollectorServiceTest.java diff --git a/management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java b/ehcache-management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java similarity index 100% rename from management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java rename to ehcache-management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java diff --git a/management/src/test/java/org/ehcache/management/registry/DefaultSharedManagementServiceTest.java b/ehcache-management/src/test/java/org/ehcache/management/registry/DefaultSharedManagementServiceTest.java similarity index 100% rename from management/src/test/java/org/ehcache/management/registry/DefaultSharedManagementServiceTest.java rename to ehcache-management/src/test/java/org/ehcache/management/registry/DefaultSharedManagementServiceTest.java diff --git a/management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java b/ehcache-management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java similarity index 100% rename from management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java rename to ehcache-management/src/test/java/org/ehcache/management/registry/ManagementRegistryServiceConfigurationParserTest.java diff --git a/management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java b/ehcache-management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java similarity index 100% rename from management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java rename to ehcache-management/src/test/java/org/ehcache/management/registry/XmlConfigTest.java diff --git a/ehcache-management/src/test/resources/ehcache-management-1.xml b/ehcache-management/src/test/resources/ehcache-management-1.xml new file mode 100644 index 0000000000..3b6276efd1 --- /dev/null +++ b/ehcache-management/src/test/resources/ehcache-management-1.xml @@ -0,0 +1,16 @@ + + + + + + + + + java.lang.String + java.lang.String + 20 + + + diff --git a/management/src/test/resources/ehcache-management-2.xml b/ehcache-management/src/test/resources/ehcache-management-2.xml similarity index 59% rename from management/src/test/resources/ehcache-management-2.xml rename to ehcache-management/src/test/resources/ehcache-management-2.xml index 112e77d9cc..fd7702f853 100644 --- a/management/src/test/resources/ehcache-management-2.xml +++ b/ehcache-management/src/test/resources/ehcache-management-2.xml @@ -1,9 +1,6 @@ + xmlns:mnm='http://www.ehcache.org/v3/management'> diff --git a/management/src/test/resources/ehcache-management-3.xml b/ehcache-management/src/test/resources/ehcache-management-3.xml similarity index 62% rename from management/src/test/resources/ehcache-management-3.xml rename to ehcache-management/src/test/resources/ehcache-management-3.xml index 15ea08acfb..4be6c11bf9 100644 --- a/management/src/test/resources/ehcache-management-3.xml +++ b/ehcache-management/src/test/resources/ehcache-management-3.xml @@ -1,9 +1,6 @@ + xmlns:mnm='http://www.ehcache.org/v3/management'> diff --git a/management/src/test/resources/ehcache-management-4.xml b/ehcache-management/src/test/resources/ehcache-management-4.xml similarity index 59% rename from management/src/test/resources/ehcache-management-4.xml rename to ehcache-management/src/test/resources/ehcache-management-4.xml index 112e77d9cc..fd7702f853 100644 --- a/management/src/test/resources/ehcache-management-4.xml +++ b/ehcache-management/src/test/resources/ehcache-management-4.xml @@ -1,9 +1,6 @@ + xmlns:mnm='http://www.ehcache.org/v3/management'> diff --git a/management/src/test/resources/ehcache-management-5.xml b/ehcache-management/src/test/resources/ehcache-management-5.xml similarity index 59% rename from management/src/test/resources/ehcache-management-5.xml rename to ehcache-management/src/test/resources/ehcache-management-5.xml index 112e77d9cc..fd7702f853 100644 --- a/management/src/test/resources/ehcache-management-5.xml +++ b/ehcache-management/src/test/resources/ehcache-management-5.xml @@ -1,9 +1,6 @@ + xmlns:mnm='http://www.ehcache.org/v3/management'> diff --git a/management/src/test/resources/ehcache-management.xml b/ehcache-management/src/test/resources/ehcache-management.xml similarity index 80% rename from management/src/test/resources/ehcache-management.xml rename to ehcache-management/src/test/resources/ehcache-management.xml index b9aa21feae..c64d8b5530 100644 --- a/management/src/test/resources/ehcache-management.xml +++ b/ehcache-management/src/test/resources/ehcache-management.xml @@ -15,11 +15,8 @@ ~ limitations under the License. --> + xmlns:mnm='http://www.ehcache.org/v3/management'> diff --git a/management/src/test/resources/settings-capability.json b/ehcache-management/src/test/resources/settings-capability.json similarity index 100% rename from management/src/test/resources/settings-capability.json rename to ehcache-management/src/test/resources/settings-capability.json diff --git a/ehcache-transactions/build.gradle b/ehcache-transactions/build.gradle new file mode 100644 index 0000000000..0584802e93 --- /dev/null +++ b/ehcache-transactions/build.gradle @@ -0,0 +1,75 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id 'org.ehcache.build.public-module' + id 'org.ehcache.build.plugins.variant' +} + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache 3 transactions module' + description = 'The transactions module of Ehcache 3' + } +} + +variants { + variant('module') { + capability "org.ehcache:ehcache-transactions-provider:$version" + capability "org.ehcache:ehcache-transactions-modules:$version" + } +} + +configurations { + [apiElements, runtimeElements]*.outgoing { + capability "org.ehcache:ehcache-transactions-provider:$version" + capability "org.ehcache:ehcache-transactions:$version" + } +} + +dependencies { + api group: 'javax.transaction', name: 'jta', version: '1.1' + api project(':ehcache') + implementation(group: 'org.codehaus.btm', name: 'btm', version: '2.1.4') { + exclude group:'org.slf4j', module:'slf4j-api' + } + compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' + + testImplementation(project(':core-spi-test')) { + exclude group:'org.ehcache.modules' + } + testImplementation testFixtures(project(':ehcache-xml')) { + exclude group:'org.ehcache.modules', module:'ehcache-xml' + } + testImplementation "org.terracotta:statistics:$statisticVersion" + + moduleApi group: 'javax.transaction', name: 'jta', version: '1.1' + moduleApi project(':ehcache-core') + moduleImplementation project(':ehcache-impl') + moduleImplementation project(':ehcache-xml') + + moduleImplementation(group: 'org.codehaus.btm', name: 'btm', version: '2.1.4') { + exclude group:'org.slf4j', module:'slf4j-api' + } +} + +jar { + bnd ( + 'Bundle-SymbolicName': 'org.ehcache.transactions', + 'Export-Package': 'org.ehcache.transactions.xa.*', + 'Import-Package': 'bitronix.tm.*;resolution:=optional, javax.transaction.*;resolution:=optional, org.ehcache.xml.*;resolution:=optional, *', + ) +} diff --git a/transactions/config/checkstyle-suppressions.xml b/ehcache-transactions/config/checkstyle-suppressions.xml similarity index 100% rename from transactions/config/checkstyle-suppressions.xml rename to ehcache-transactions/config/checkstyle-suppressions.xml diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/EhcacheXAException.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/EhcacheXAException.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/EhcacheXAException.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/EhcacheXAException.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/XACacheException.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/XACacheException.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/XACacheException.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/XACacheException.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/configuration/XAStoreConfiguration.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/configuration/XAStoreConfiguration.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/configuration/XAStoreConfiguration.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/configuration/XAStoreConfiguration.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/EhcacheXAResource.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/EhcacheXAResource.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/EhcacheXAResource.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/EhcacheXAResource.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/SerializableXid.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/SerializableXid.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/SerializableXid.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/SerializableXid.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLock.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLock.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLock.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLock.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockValueCombinedCopier.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockValueCombinedCopier.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockValueCombinedCopier.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockValueCombinedCopier.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockValueCombinedSerializer.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockValueCombinedSerializer.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockValueCombinedSerializer.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/SoftLockValueCombinedSerializer.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/StatefulSoftLockValueCombinedSerializer.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/StatefulSoftLockValueCombinedSerializer.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/StatefulSoftLockValueCombinedSerializer.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/StatefulSoftLockValueCombinedSerializer.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/StoreEventSourceWrapper.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/StoreEventSourceWrapper.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/StoreEventSourceWrapper.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/StoreEventSourceWrapper.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/TransactionId.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/TransactionId.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/TransactionId.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/TransactionId.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/TypeUtil.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/TypeUtil.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/TypeUtil.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/TypeUtil.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XATransactionContext.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/XATransactionContext.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/XATransactionContext.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/XATransactionContext.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XATransactionContextFactory.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/XATransactionContextFactory.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/XATransactionContextFactory.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/XATransactionContextFactory.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/XAValueHolder.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/Command.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/Command.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/Command.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/Command.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/StoreEvictCommand.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/StoreEvictCommand.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/StoreEvictCommand.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/StoreEvictCommand.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/StorePutCommand.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/StorePutCommand.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/StorePutCommand.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/StorePutCommand.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/StoreRemoveCommand.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/StoreRemoveCommand.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/StoreRemoveCommand.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/commands/StoreRemoveCommand.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/configuration/XAStoreProviderFactory.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProvider.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProvider.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProvider.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProvider.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/DefaultJournalProviderFactory.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/Journal.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/Journal.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/Journal.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/Journal.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/JournalProvider.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/JournalProvider.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/JournalProvider.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/JournalProvider.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/PersistentJournal.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/PersistentJournal.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/PersistentJournal.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/PersistentJournal.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/TransientJournal.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/TransientJournal.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/TransientJournal.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/journal/TransientJournal.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/NullXAResourceRegistry.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/NullXAResourceRegistry.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/NullXAResourceRegistry.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/NullXAResourceRegistry.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/txmgr/provider/DefaultTransactionManagerProviderFactory.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParser.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParser.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/TransactionManagerWrapper.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/TransactionManagerWrapper.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/txmgr/TransactionManagerWrapper.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/TransactionManagerWrapper.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/XAResourceRegistry.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/XAResourceRegistry.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/txmgr/XAResourceRegistry.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/XAResourceRegistry.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixTransactionManagerLookup.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixTransactionManagerLookup.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixTransactionManagerLookup.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixTransactionManagerLookup.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixXAResourceRegistry.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixXAResourceRegistry.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixXAResourceRegistry.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/BitronixXAResourceRegistry.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/Ehcache3XAResourceHolder.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/Ehcache3XAResourceHolder.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/Ehcache3XAResourceHolder.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/Ehcache3XAResourceHolder.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/Ehcache3XAResourceProducer.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/Ehcache3XAResourceProducer.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/Ehcache3XAResourceProducer.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/btm/Ehcache3XAResourceProducer.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfiguration.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfiguration.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfiguration.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfiguration.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/TransactionManagerLookup.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/TransactionManagerLookup.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/TransactionManagerLookup.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/TransactionManagerLookup.java diff --git a/transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/TransactionManagerProvider.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/TransactionManagerProvider.java similarity index 100% rename from transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/TransactionManagerProvider.java rename to ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/TransactionManagerProvider.java diff --git a/transactions/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory b/ehcache-transactions/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory similarity index 100% rename from transactions/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory rename to ehcache-transactions/src/main/resources/META-INF/services/org.ehcache.core.spi.service.ServiceFactory diff --git a/transactions/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser b/ehcache-transactions/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser similarity index 100% rename from transactions/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser rename to ehcache-transactions/src/main/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser diff --git a/transactions/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser b/ehcache-transactions/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser similarity index 100% rename from transactions/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser rename to ehcache-transactions/src/main/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser diff --git a/transactions/src/main/resources/ehcache-tx-ext.xsd b/ehcache-transactions/src/main/resources/ehcache-tx-ext.xsd similarity index 100% rename from transactions/src/main/resources/ehcache-tx-ext.xsd rename to ehcache-transactions/src/main/resources/ehcache-tx-ext.xsd diff --git a/transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java b/ehcache-transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java similarity index 100% rename from transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java rename to ehcache-transactions/src/test/java/org/ehcache/docs/transactions/xa/XAGettingStarted.java diff --git a/transactions/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java b/ehcache-transactions/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java similarity index 79% rename from transactions/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java rename to ehcache-transactions/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java index 54f5114622..7668106c27 100644 --- a/transactions/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java +++ b/ehcache-transactions/src/test/java/org/ehcache/impl/internal/store/offheap/OffHeapStoreLifecycleHelper.java @@ -16,7 +16,11 @@ package org.ehcache.impl.internal.store.offheap; -import org.terracotta.statistics.StatisticsManager; +/* + * This is an import of a shaded class because we depend on the shaded distribution jar. + * This means we have to use the shaded StatisticsManager when digging in to the internals like this. + */ +import org.ehcache.shadow.org.terracotta.statistics.StatisticsManager; /** * @author Ludovic Orban diff --git a/transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/NonXACacheTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/TransactionalCacheParserIT.java diff --git a/transactions/src/test/java/org/ehcache/transactions/XmlConfigTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/XmlConfigTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/XmlConfigTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/XmlConfigTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/configuration/XAStoreConfigurationTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/configuration/XAStoreConfigurationTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/configuration/XAStoreConfigurationTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/configuration/XAStoreConfigurationTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/integration/StatefulSerializerTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/integration/StatefulSerializerTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/integration/StatefulSerializerTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/integration/StatefulSerializerTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/EhcacheXAResourceTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/EhcacheXAResourceTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/internal/EhcacheXAResourceTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/EhcacheXAResourceTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/UnSupportedResourceTypeTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/UnSupportedResourceTypeTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/internal/UnSupportedResourceTypeTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/UnSupportedResourceTypeTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreProviderTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreProviderTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreProviderTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreProviderTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/XAValueHolderTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XAValueHolderTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/internal/XAValueHolderTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XAValueHolderTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/AbstractJournalTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/AbstractJournalTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/AbstractJournalTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/AbstractJournalTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/PersistentJournalTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/TransientJournalTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/TransientJournalTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/TransientJournalTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/journal/TransientJournalTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheManagerServiceConfigurationParserTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/xml/TxCacheServiceConfigurationParserTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfigurationTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfigurationTest.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfigurationTest.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProviderConfigurationTest.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java diff --git a/transactions/src/test/java/org/ehcache/transactions/xa/utils/TestXid.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/utils/TestXid.java similarity index 100% rename from transactions/src/test/java/org/ehcache/transactions/xa/utils/TestXid.java rename to ehcache-transactions/src/test/java/org/ehcache/transactions/xa/utils/TestXid.java diff --git a/transactions/src/test/resources/configs/simple-xa.xml b/ehcache-transactions/src/test/resources/configs/simple-xa.xml similarity index 77% rename from transactions/src/test/resources/configs/simple-xa.xml rename to ehcache-transactions/src/test/resources/configs/simple-xa.xml index 772cdd5475..fcb384f582 100644 --- a/transactions/src/test/resources/configs/simple-xa.xml +++ b/ehcache-transactions/src/test/resources/configs/simple-xa.xml @@ -14,11 +14,8 @@ ~ limitations under the License. --> + xmlns:tx='http://www.ehcache.org/v3/tx'> diff --git a/transactions/src/test/resources/configs/template-xa.xml b/ehcache-transactions/src/test/resources/configs/template-xa.xml similarity index 79% rename from transactions/src/test/resources/configs/template-xa.xml rename to ehcache-transactions/src/test/resources/configs/template-xa.xml index 98dd5912f7..9958139655 100644 --- a/transactions/src/test/resources/configs/template-xa.xml +++ b/ehcache-transactions/src/test/resources/configs/template-xa.xml @@ -15,11 +15,8 @@ --> + xmlns:tx='http://www.ehcache.org/v3/tx'> diff --git a/transactions/src/test/resources/configs/transactional-cache.xml b/ehcache-transactions/src/test/resources/configs/transactional-cache.xml similarity index 78% rename from transactions/src/test/resources/configs/transactional-cache.xml rename to ehcache-transactions/src/test/resources/configs/transactional-cache.xml index ce0bd34d23..65fef5a049 100644 --- a/transactions/src/test/resources/configs/transactional-cache.xml +++ b/ehcache-transactions/src/test/resources/configs/transactional-cache.xml @@ -15,11 +15,8 @@ --> + xmlns:tx='http://www.ehcache.org/v3/tx'> + xmlns:tx='http://www.ehcache.org/v3/tx'> diff --git a/xml/README.adoc b/ehcache-xml/README.adoc similarity index 100% rename from xml/README.adoc rename to ehcache-xml/README.adoc diff --git a/ehcache-xml/build.gradle b/ehcache-xml/build.gradle new file mode 100644 index 0000000000..f60cf4abbc --- /dev/null +++ b/ehcache-xml/build.gradle @@ -0,0 +1,97 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id 'org.ehcache.build.internal-module' + id 'org.unbroken-dome.xjc' + id 'java-test-fixtures' +} + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache 3 XML Parsing module' + description = 'The module containing all XML parsing logic Ehcache 3' + } +} + +components.java { + withVariantsFromConfiguration(configurations.testFixturesApiElements) { skip() } + withVariantsFromConfiguration(configurations.testFixturesRuntimeElements) { skip() } +} + +sourceSets { + main { + resources.source(xjcSchema) + } +} +tasks.named('sourcesJar') { + filesMatching('*.xsd') { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + } +} + +configurations { + lowerBoundTestRuntimeClasspath { + extendsFrom testRuntimeClasspath + resolutionStrategy.dependencySubstitution { + substitute module('org.glassfish.jaxb:jaxb-runtime') using module('com.sun.xml.bind:jaxb-impl:2.2.8-b01') + } + } +} + +dependencies { + api project(':ehcache-api') + implementation project(':ehcache-core') + implementation project(':ehcache-impl') + + api 'javax.xml.bind:jaxb-api:[2.2,3)' + runtimeOnly 'org.glassfish.jaxb:jaxb-runtime:[2.2,3)' + + testFixturesApi 'org.xmlunit:xmlunit-core:2.6.0', 'org.xmlunit:xmlunit-matchers:2.6.0' + + xjcClasspath 'org.jvnet.jaxb2_commons:jaxb2-fluent-api:3.0' + xjcClasspath 'org.jvnet.jaxb2_commons:jaxb2-basics-annotate:1.1.0' + + lowerBoundTestRuntimeClasspath 'com.sun.activation:javax.activation:1.2.0' +} + +jar { + bnd ( + 'Export-Package': 'org.ehcache.xml, org.ehcache.xml.exceptions, org.ehcache.xml.model', + 'Import-Package': "javax.xml.bind*;version=\"[2.2,3)\", *" + ) +} + +xjc { + extraArgs.add '-Xfluent-api' + extraArgs.add '-Xannotate' + + // ehcache-multi.xsd references ehcache-core.xsd but we cannot control the order they get presented to XJC in. + // Turning off strict checks prevents failing on when seeing the resultant schema parsing issues. + strictCheck = false +} + +tasks.register('lowerBoundTest', Test) { + group = JavaBasePlugin.VERIFICATION_GROUP + //remove the original runtime classpath + classpath -= configurations.testRuntimeClasspath + //add the classpath we want + classpath += configurations.lowerBoundTestRuntimeClasspath +} + +tasks.named('check') { + dependsOn tasks.lowerBoundTest +} diff --git a/xml/config/checkstyle-suppressions.xml b/ehcache-xml/config/checkstyle-suppressions.xml similarity index 80% rename from xml/config/checkstyle-suppressions.xml rename to ehcache-xml/config/checkstyle-suppressions.xml index a287bf4e21..c385350074 100644 --- a/xml/config/checkstyle-suppressions.xml +++ b/ehcache-xml/config/checkstyle-suppressions.xml @@ -5,6 +5,6 @@ "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd"> - + diff --git a/xml/src/main/java/org/ehcache/xml/BaseConfigParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/BaseConfigParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/BaseConfigParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/BaseConfigParser.java diff --git a/xml/src/main/java/org/ehcache/xml/CacheManagerServiceConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/CacheManagerServiceConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/CacheManagerServiceConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/CacheManagerServiceConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/CacheResourceConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/CacheResourceConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/CacheResourceConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/CacheResourceConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/CacheServiceConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/CacheServiceConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/CacheServiceConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/CacheServiceConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/ConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/ConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/ConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/ConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/CoreServiceConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/CoreServiceConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/CoreServiceConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/CoreServiceConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/CoreServiceCreationConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/CoreServiceCreationConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/CoreServiceCreationConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/CoreServiceCreationConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/DomUtil.java b/ehcache-xml/src/main/java/org/ehcache/xml/DomUtil.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/DomUtil.java rename to ehcache-xml/src/main/java/org/ehcache/xml/DomUtil.java diff --git a/xml/src/main/java/org/ehcache/xml/JaxbHelper.java b/ehcache-xml/src/main/java/org/ehcache/xml/JaxbHelper.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/JaxbHelper.java rename to ehcache-xml/src/main/java/org/ehcache/xml/JaxbHelper.java diff --git a/xml/src/main/java/org/ehcache/xml/JaxbParsers.java b/ehcache-xml/src/main/java/org/ehcache/xml/JaxbParsers.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/JaxbParsers.java rename to ehcache-xml/src/main/java/org/ehcache/xml/JaxbParsers.java diff --git a/xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/ServiceConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/ServiceConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/ServiceConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/ServiceConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/ServiceCreationConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/ServiceCreationConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/ServiceCreationConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/ServiceCreationConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/XmlConfiguration.java b/ehcache-xml/src/main/java/org/ehcache/xml/XmlConfiguration.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/XmlConfiguration.java rename to ehcache-xml/src/main/java/org/ehcache/xml/XmlConfiguration.java diff --git a/xml/src/main/java/org/ehcache/xml/XmlModel.java b/ehcache-xml/src/main/java/org/ehcache/xml/XmlModel.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/XmlModel.java rename to ehcache-xml/src/main/java/org/ehcache/xml/XmlModel.java diff --git a/xml/src/main/java/org/ehcache/xml/exceptions/XmlConfigurationException.java b/ehcache-xml/src/main/java/org/ehcache/xml/exceptions/XmlConfigurationException.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/exceptions/XmlConfigurationException.java rename to ehcache-xml/src/main/java/org/ehcache/xml/exceptions/XmlConfigurationException.java diff --git a/xml/src/main/java/org/ehcache/xml/model/CacheDefinition.java b/ehcache-xml/src/main/java/org/ehcache/xml/model/CacheDefinition.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/model/CacheDefinition.java rename to ehcache-xml/src/main/java/org/ehcache/xml/model/CacheDefinition.java diff --git a/xml/src/main/java/org/ehcache/xml/model/CacheSpec.java b/ehcache-xml/src/main/java/org/ehcache/xml/model/CacheSpec.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/model/CacheSpec.java rename to ehcache-xml/src/main/java/org/ehcache/xml/model/CacheSpec.java diff --git a/xml/src/main/java/org/ehcache/xml/model/CacheTemplate.java b/ehcache-xml/src/main/java/org/ehcache/xml/model/CacheTemplate.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/model/CacheTemplate.java rename to ehcache-xml/src/main/java/org/ehcache/xml/model/CacheTemplate.java diff --git a/xml/src/main/java/org/ehcache/xml/model/Expiry.java b/ehcache-xml/src/main/java/org/ehcache/xml/model/Expiry.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/model/Expiry.java rename to ehcache-xml/src/main/java/org/ehcache/xml/model/Expiry.java diff --git a/xml/src/main/java/org/ehcache/xml/model/ListenersConfig.java b/ehcache-xml/src/main/java/org/ehcache/xml/model/ListenersConfig.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/model/ListenersConfig.java rename to ehcache-xml/src/main/java/org/ehcache/xml/model/ListenersConfig.java diff --git a/xml/src/main/java/org/ehcache/xml/model/SizeOfEngineLimits.java b/ehcache-xml/src/main/java/org/ehcache/xml/model/SizeOfEngineLimits.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/model/SizeOfEngineLimits.java rename to ehcache-xml/src/main/java/org/ehcache/xml/model/SizeOfEngineLimits.java diff --git a/xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java b/ehcache-xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java rename to ehcache-xml/src/main/java/org/ehcache/xml/multi/XmlMultiConfiguration.java diff --git a/xml/src/main/java/org/ehcache/xml/provider/CacheEventDispatcherFactoryConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/provider/CacheEventDispatcherFactoryConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/provider/CacheEventDispatcherFactoryConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/provider/CacheEventDispatcherFactoryConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/provider/CacheManagerPersistenceConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/provider/CacheManagerPersistenceConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/provider/CacheManagerPersistenceConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/provider/CacheManagerPersistenceConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/provider/DefaultSerializationProviderConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/provider/DefaultSerializationProviderConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/provider/DefaultSerializationProviderConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/provider/DefaultSerializationProviderConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/provider/DefaultSizeOfEngineProviderConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/provider/DefaultSizeOfEngineProviderConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/provider/DefaultSizeOfEngineProviderConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/provider/DefaultSizeOfEngineProviderConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/provider/OffHeapDiskStoreProviderConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/provider/OffHeapDiskStoreProviderConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/provider/OffHeapDiskStoreProviderConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/provider/OffHeapDiskStoreProviderConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/provider/PooledExecutionServiceConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/provider/PooledExecutionServiceConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/provider/PooledExecutionServiceConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/provider/PooledExecutionServiceConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/provider/SimpleCoreServiceCreationConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/provider/SimpleCoreServiceCreationConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/provider/SimpleCoreServiceCreationConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/provider/SimpleCoreServiceCreationConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/provider/ThreadPoolServiceCreationConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/provider/ThreadPoolServiceCreationConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/provider/ThreadPoolServiceCreationConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/provider/ThreadPoolServiceCreationConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/provider/WriteBehindProviderConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/provider/WriteBehindProviderConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/provider/WriteBehindProviderConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/provider/WriteBehindProviderConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventDispatcherConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventDispatcherConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventDispatcherConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventDispatcherConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultCopierConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultCopierConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/service/DefaultCopierConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultCopierConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultSerializerConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultSerializerConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/service/DefaultSerializerConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultSerializerConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultSizeOfEngineConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultSizeOfEngineConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/service/DefaultSizeOfEngineConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultSizeOfEngineConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/service/OffHeapDiskStoreConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/service/OffHeapDiskStoreConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/service/OffHeapDiskStoreConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/service/OffHeapDiskStoreConfigurationParser.java diff --git a/xml/src/main/java/org/ehcache/xml/service/SimpleCoreServiceConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/service/SimpleCoreServiceConfigurationParser.java similarity index 100% rename from xml/src/main/java/org/ehcache/xml/service/SimpleCoreServiceConfigurationParser.java rename to ehcache-xml/src/main/java/org/ehcache/xml/service/SimpleCoreServiceConfigurationParser.java diff --git a/xml/src/main/resources/ehcache-core.xsd b/ehcache-xml/src/main/schema/ehcache-core.xsd similarity index 100% rename from xml/src/main/resources/ehcache-core.xsd rename to ehcache-xml/src/main/schema/ehcache-core.xsd diff --git a/xml/src/main/resources/ehcache-multi.xsd b/ehcache-xml/src/main/schema/ehcache-multi.xsd similarity index 100% rename from xml/src/main/resources/ehcache-multi.xsd rename to ehcache-xml/src/main/schema/ehcache-multi.xsd diff --git a/xml/src/test/java/com/pany/ehcache/DeprecatedExpiry.java b/ehcache-xml/src/test/java/com/pany/ehcache/DeprecatedExpiry.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/DeprecatedExpiry.java rename to ehcache-xml/src/test/java/com/pany/ehcache/DeprecatedExpiry.java diff --git a/xml/src/test/java/com/pany/ehcache/MyExpiry.java b/ehcache-xml/src/test/java/com/pany/ehcache/MyExpiry.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/MyExpiry.java rename to ehcache-xml/src/test/java/com/pany/ehcache/MyExpiry.java diff --git a/xml/src/test/java/com/pany/ehcache/copier/AnotherDescriptionCopier.java b/ehcache-xml/src/test/java/com/pany/ehcache/copier/AnotherDescriptionCopier.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/copier/AnotherDescriptionCopier.java rename to ehcache-xml/src/test/java/com/pany/ehcache/copier/AnotherDescriptionCopier.java diff --git a/xml/src/test/java/com/pany/ehcache/copier/AnotherPersonCopier.java b/ehcache-xml/src/test/java/com/pany/ehcache/copier/AnotherPersonCopier.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/copier/AnotherPersonCopier.java rename to ehcache-xml/src/test/java/com/pany/ehcache/copier/AnotherPersonCopier.java diff --git a/xml/src/test/java/com/pany/ehcache/copier/Description.java b/ehcache-xml/src/test/java/com/pany/ehcache/copier/Description.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/copier/Description.java rename to ehcache-xml/src/test/java/com/pany/ehcache/copier/Description.java diff --git a/xml/src/test/java/com/pany/ehcache/copier/DescriptionCopier.java b/ehcache-xml/src/test/java/com/pany/ehcache/copier/DescriptionCopier.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/copier/DescriptionCopier.java rename to ehcache-xml/src/test/java/com/pany/ehcache/copier/DescriptionCopier.java diff --git a/xml/src/test/java/com/pany/ehcache/copier/Employee.java b/ehcache-xml/src/test/java/com/pany/ehcache/copier/Employee.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/copier/Employee.java rename to ehcache-xml/src/test/java/com/pany/ehcache/copier/Employee.java diff --git a/xml/src/test/java/com/pany/ehcache/copier/Person.java b/ehcache-xml/src/test/java/com/pany/ehcache/copier/Person.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/copier/Person.java rename to ehcache-xml/src/test/java/com/pany/ehcache/copier/Person.java diff --git a/xml/src/test/java/com/pany/ehcache/copier/PersonCopier.java b/ehcache-xml/src/test/java/com/pany/ehcache/copier/PersonCopier.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/copier/PersonCopier.java rename to ehcache-xml/src/test/java/com/pany/ehcache/copier/PersonCopier.java diff --git a/xml/src/test/java/com/pany/ehcache/integration/TestCacheEventListener.java b/ehcache-xml/src/test/java/com/pany/ehcache/integration/TestCacheEventListener.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/integration/TestCacheEventListener.java rename to ehcache-xml/src/test/java/com/pany/ehcache/integration/TestCacheEventListener.java diff --git a/xml/src/test/java/com/pany/ehcache/integration/TestCacheLoaderWriter.java b/ehcache-xml/src/test/java/com/pany/ehcache/integration/TestCacheLoaderWriter.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/integration/TestCacheLoaderWriter.java rename to ehcache-xml/src/test/java/com/pany/ehcache/integration/TestCacheLoaderWriter.java diff --git a/xml/src/test/java/com/pany/ehcache/integration/TestEvictionAdvisor.java b/ehcache-xml/src/test/java/com/pany/ehcache/integration/TestEvictionAdvisor.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/integration/TestEvictionAdvisor.java rename to ehcache-xml/src/test/java/com/pany/ehcache/integration/TestEvictionAdvisor.java diff --git a/xml/src/test/java/com/pany/ehcache/integration/TestResilienceStrategy.java b/ehcache-xml/src/test/java/com/pany/ehcache/integration/TestResilienceStrategy.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/integration/TestResilienceStrategy.java rename to ehcache-xml/src/test/java/com/pany/ehcache/integration/TestResilienceStrategy.java diff --git a/xml/src/test/java/com/pany/ehcache/integration/TestSecondCacheEventListener.java b/ehcache-xml/src/test/java/com/pany/ehcache/integration/TestSecondCacheEventListener.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/integration/TestSecondCacheEventListener.java rename to ehcache-xml/src/test/java/com/pany/ehcache/integration/TestSecondCacheEventListener.java diff --git a/xml/src/test/java/com/pany/ehcache/integration/ThreadRememberingLoaderWriter.java b/ehcache-xml/src/test/java/com/pany/ehcache/integration/ThreadRememberingLoaderWriter.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/integration/ThreadRememberingLoaderWriter.java rename to ehcache-xml/src/test/java/com/pany/ehcache/integration/ThreadRememberingLoaderWriter.java diff --git a/xml/src/test/java/com/pany/ehcache/serializer/TestSerializer.java b/ehcache-xml/src/test/java/com/pany/ehcache/serializer/TestSerializer.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/serializer/TestSerializer.java rename to ehcache-xml/src/test/java/com/pany/ehcache/serializer/TestSerializer.java diff --git a/xml/src/test/java/com/pany/ehcache/serializer/TestSerializer2.java b/ehcache-xml/src/test/java/com/pany/ehcache/serializer/TestSerializer2.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/serializer/TestSerializer2.java rename to ehcache-xml/src/test/java/com/pany/ehcache/serializer/TestSerializer2.java diff --git a/xml/src/test/java/com/pany/ehcache/serializer/TestSerializer3.java b/ehcache-xml/src/test/java/com/pany/ehcache/serializer/TestSerializer3.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/serializer/TestSerializer3.java rename to ehcache-xml/src/test/java/com/pany/ehcache/serializer/TestSerializer3.java diff --git a/xml/src/test/java/com/pany/ehcache/serializer/TestSerializer4.java b/ehcache-xml/src/test/java/com/pany/ehcache/serializer/TestSerializer4.java similarity index 100% rename from xml/src/test/java/com/pany/ehcache/serializer/TestSerializer4.java rename to ehcache-xml/src/test/java/com/pany/ehcache/serializer/TestSerializer4.java diff --git a/xml/src/test/java/org/ehcache/docs/GettingStarted.java b/ehcache-xml/src/test/java/org/ehcache/docs/GettingStarted.java similarity index 100% rename from xml/src/test/java/org/ehcache/docs/GettingStarted.java rename to ehcache-xml/src/test/java/org/ehcache/docs/GettingStarted.java diff --git a/xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java b/ehcache-xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java similarity index 100% rename from xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java rename to ehcache-xml/src/test/java/org/ehcache/docs/MultiGettingStarted.java diff --git a/xml/src/test/java/org/ehcache/xml/BarConfiguration.java b/ehcache-xml/src/test/java/org/ehcache/xml/BarConfiguration.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/BarConfiguration.java rename to ehcache-xml/src/test/java/org/ehcache/xml/BarConfiguration.java diff --git a/xml/src/test/java/org/ehcache/xml/BarParser.java b/ehcache-xml/src/test/java/org/ehcache/xml/BarParser.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/BarParser.java rename to ehcache-xml/src/test/java/org/ehcache/xml/BarParser.java diff --git a/xml/src/test/java/org/ehcache/xml/BazParser.java b/ehcache-xml/src/test/java/org/ehcache/xml/BazParser.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/BazParser.java rename to ehcache-xml/src/test/java/org/ehcache/xml/BazParser.java diff --git a/xml/src/test/java/org/ehcache/xml/BazResource.java b/ehcache-xml/src/test/java/org/ehcache/xml/BazResource.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/BazResource.java rename to ehcache-xml/src/test/java/org/ehcache/xml/BazResource.java diff --git a/xml/src/test/java/org/ehcache/xml/CoreCacheConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/CoreCacheConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/CoreCacheConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/CoreCacheConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/FancyParser.java b/ehcache-xml/src/test/java/org/ehcache/xml/FancyParser.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/FancyParser.java rename to ehcache-xml/src/test/java/org/ehcache/xml/FancyParser.java diff --git a/xml/src/test/java/org/ehcache/xml/FooConfiguration.java b/ehcache-xml/src/test/java/org/ehcache/xml/FooConfiguration.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/FooConfiguration.java rename to ehcache-xml/src/test/java/org/ehcache/xml/FooConfiguration.java diff --git a/xml/src/test/java/org/ehcache/xml/FooParser.java b/ehcache-xml/src/test/java/org/ehcache/xml/FooParser.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/FooParser.java rename to ehcache-xml/src/test/java/org/ehcache/xml/FooParser.java diff --git a/xml/src/test/java/org/ehcache/xml/FromTemplateCacheConfigurationBuilderDefaultTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/FromTemplateCacheConfigurationBuilderDefaultTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/FromTemplateCacheConfigurationBuilderDefaultTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/FromTemplateCacheConfigurationBuilderDefaultTest.java diff --git a/xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java diff --git a/xml/src/test/java/org/ehcache/xml/JaxbParsersTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/JaxbParsersTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/JaxbParsersTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/JaxbParsersTest.java diff --git a/xml/src/test/java/org/ehcache/xml/NiResilience.java b/ehcache-xml/src/test/java/org/ehcache/xml/NiResilience.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/NiResilience.java rename to ehcache-xml/src/test/java/org/ehcache/xml/NiResilience.java diff --git a/xml/src/test/java/org/ehcache/xml/PropertySubstitutionTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/PropertySubstitutionTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/PropertySubstitutionTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/PropertySubstitutionTest.java diff --git a/xml/src/test/java/org/ehcache/xml/ShrubberyResilience.java b/ehcache-xml/src/test/java/org/ehcache/xml/ShrubberyResilience.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/ShrubberyResilience.java rename to ehcache-xml/src/test/java/org/ehcache/xml/ShrubberyResilience.java diff --git a/xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/XmlConfigurationTest.java diff --git a/xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/multi/XmlMultiConfigurationTest.java diff --git a/xml/src/test/java/org/ehcache/xml/provider/CacheEventDispatcherFactoryConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/provider/CacheEventDispatcherFactoryConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/provider/CacheEventDispatcherFactoryConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/provider/CacheEventDispatcherFactoryConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/provider/CacheManagerPersistenceConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/provider/CacheManagerPersistenceConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/provider/CacheManagerPersistenceConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/provider/CacheManagerPersistenceConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/provider/DefaultCopyProviderConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/provider/DefaultSerializationProviderConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/provider/DefaultSerializationProviderConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/provider/DefaultSerializationProviderConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/provider/DefaultSerializationProviderConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/provider/DefaultSizeOfEngineProviderConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/provider/DefaultSizeOfEngineProviderConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/provider/DefaultSizeOfEngineProviderConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/provider/DefaultSizeOfEngineProviderConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/provider/OffHeapDiskStoreProviderConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/provider/OffHeapDiskStoreProviderConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/provider/OffHeapDiskStoreProviderConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/provider/OffHeapDiskStoreProviderConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/provider/PooledExecutionServiceConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/provider/PooledExecutionServiceConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/provider/PooledExecutionServiceConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/provider/PooledExecutionServiceConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/provider/WriteBehindProviderConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/provider/WriteBehindProviderConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/provider/WriteBehindProviderConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/provider/WriteBehindProviderConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventDispatcherConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventDispatcherConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventDispatcherConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventDispatcherConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultCacheEventListenerConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultCacheLoaderWriterConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultCopierConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultCopierConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/service/DefaultCopierConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultCopierConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultResilienceStrategyConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultSerializerConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultSerializerConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/service/DefaultSerializerConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultSerializerConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultSizeOfEngineConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultSizeOfEngineConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/service/DefaultSizeOfEngineConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultSizeOfEngineConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/service/DefaultWriteBehindConfigurationParserTest.java diff --git a/xml/src/test/java/org/ehcache/xml/service/OffHeapDiskStoreConfigurationParserTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/service/OffHeapDiskStoreConfigurationParserTest.java similarity index 100% rename from xml/src/test/java/org/ehcache/xml/service/OffHeapDiskStoreConfigurationParserTest.java rename to ehcache-xml/src/test/java/org/ehcache/xml/service/OffHeapDiskStoreConfigurationParserTest.java diff --git a/xml/src/test/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser b/ehcache-xml/src/test/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser similarity index 100% rename from xml/src/test/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser rename to ehcache-xml/src/test/resources/META-INF/services/org.ehcache.xml.CacheManagerServiceConfigurationParser diff --git a/xml/src/test/resources/META-INF/services/org.ehcache.xml.CacheResourceConfigurationParser b/ehcache-xml/src/test/resources/META-INF/services/org.ehcache.xml.CacheResourceConfigurationParser similarity index 100% rename from xml/src/test/resources/META-INF/services/org.ehcache.xml.CacheResourceConfigurationParser rename to ehcache-xml/src/test/resources/META-INF/services/org.ehcache.xml.CacheResourceConfigurationParser diff --git a/xml/src/test/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser b/ehcache-xml/src/test/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser similarity index 100% rename from xml/src/test/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser rename to ehcache-xml/src/test/resources/META-INF/services/org.ehcache.xml.CacheServiceConfigurationParser diff --git a/xml/src/test/resources/configs/all-extensions.xml b/ehcache-xml/src/test/resources/configs/all-extensions.xml similarity index 80% rename from xml/src/test/resources/configs/all-extensions.xml rename to ehcache-xml/src/test/resources/configs/all-extensions.xml index 9ede9b445f..e0c40e6ec4 100644 --- a/xml/src/test/resources/configs/all-extensions.xml +++ b/ehcache-xml/src/test/resources/configs/all-extensions.xml @@ -15,13 +15,10 @@ --> + xmlns='http://www.ehcache.org/v3'> diff --git a/xml/src/test/resources/configs/bar.xsd b/ehcache-xml/src/test/resources/configs/bar.xsd similarity index 100% rename from xml/src/test/resources/configs/bar.xsd rename to ehcache-xml/src/test/resources/configs/bar.xsd diff --git a/xml/src/test/resources/configs/baz.xsd b/ehcache-xml/src/test/resources/configs/baz.xsd similarity index 100% rename from xml/src/test/resources/configs/baz.xsd rename to ehcache-xml/src/test/resources/configs/baz.xsd diff --git a/xml/src/test/resources/configs/cache-copiers.xml b/ehcache-xml/src/test/resources/configs/cache-copiers.xml similarity index 93% rename from xml/src/test/resources/configs/cache-copiers.xml rename to ehcache-xml/src/test/resources/configs/cache-copiers.xml index a8c15d6e5a..d95315edb2 100644 --- a/xml/src/test/resources/configs/cache-copiers.xml +++ b/ehcache-xml/src/test/resources/configs/cache-copiers.xml @@ -14,9 +14,7 @@ ~ limitations under the License. --> - + com.pany.ehcache.copier.DescriptionCopier diff --git a/xml/src/test/resources/configs/cache-integration.xml b/ehcache-xml/src/test/resources/configs/cache-integration.xml similarity index 87% rename from xml/src/test/resources/configs/cache-integration.xml rename to ehcache-xml/src/test/resources/configs/cache-integration.xml index 73fdb780c8..80e8578c20 100644 --- a/xml/src/test/resources/configs/cache-integration.xml +++ b/ehcache-xml/src/test/resources/configs/cache-integration.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + java.lang.Number java.lang.String diff --git a/xml/src/test/resources/configs/custom-resource.xml b/ehcache-xml/src/test/resources/configs/custom-resource.xml similarity index 78% rename from xml/src/test/resources/configs/custom-resource.xml rename to ehcache-xml/src/test/resources/configs/custom-resource.xml index 08ff612e75..e35d015bb1 100644 --- a/xml/src/test/resources/configs/custom-resource.xml +++ b/ehcache-xml/src/test/resources/configs/custom-resource.xml @@ -15,11 +15,8 @@ --> + xmlns:ehcache='http://www.ehcache.org/v3'> java.lang.String java.lang.String diff --git a/xml/src/test/resources/configs/default-serializer.xml b/ehcache-xml/src/test/resources/configs/default-serializer.xml similarity index 95% rename from xml/src/test/resources/configs/default-serializer.xml rename to ehcache-xml/src/test/resources/configs/default-serializer.xml index d4110ef1c9..1b68d8c363 100644 --- a/xml/src/test/resources/configs/default-serializer.xml +++ b/ehcache-xml/src/test/resources/configs/default-serializer.xml @@ -14,9 +14,7 @@ ~ limitations under the License. --> - + com.pany.ehcache.serializer.TestSerializer diff --git a/xml/src/test/resources/configs/defaultTypes-cache.xml b/ehcache-xml/src/test/resources/configs/defaultTypes-cache.xml similarity index 81% rename from xml/src/test/resources/configs/defaultTypes-cache.xml rename to ehcache-xml/src/test/resources/configs/defaultTypes-cache.xml index ebd36b4c93..02c668a2fb 100644 --- a/xml/src/test/resources/configs/defaultTypes-cache.xml +++ b/ehcache-xml/src/test/resources/configs/defaultTypes-cache.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + diff --git a/xml/src/test/resources/configs/disk-persistent-cache.xml b/ehcache-xml/src/test/resources/configs/disk-persistent-cache.xml similarity index 84% rename from xml/src/test/resources/configs/disk-persistent-cache.xml rename to ehcache-xml/src/test/resources/configs/disk-persistent-cache.xml index 9aa45133e1..7a4f4a4003 100644 --- a/xml/src/test/resources/configs/disk-persistent-cache.xml +++ b/ehcache-xml/src/test/resources/configs/disk-persistent-cache.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + diff --git a/xml/src/test/resources/configs/docs/expiry.xml b/ehcache-xml/src/test/resources/configs/docs/expiry.xml similarity index 83% rename from xml/src/test/resources/configs/docs/expiry.xml rename to ehcache-xml/src/test/resources/configs/docs/expiry.xml index 335745c9e7..93b5b98c9d 100644 --- a/xml/src/test/resources/configs/docs/expiry.xml +++ b/ehcache-xml/src/test/resources/configs/docs/expiry.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + diff --git a/xml/src/test/resources/configs/docs/getting-started.xml b/ehcache-xml/src/test/resources/configs/docs/getting-started.xml similarity index 86% rename from xml/src/test/resources/configs/docs/getting-started.xml rename to ehcache-xml/src/test/resources/configs/docs/getting-started.xml index 6850b517cc..9000aefcd5 100644 --- a/xml/src/test/resources/configs/docs/getting-started.xml +++ b/ehcache-xml/src/test/resources/configs/docs/getting-started.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + java.lang.String diff --git a/xml/src/test/resources/configs/docs/multi/multiple-managers.xml b/ehcache-xml/src/test/resources/configs/docs/multi/multiple-managers.xml similarity index 73% rename from xml/src/test/resources/configs/docs/multi/multiple-managers.xml rename to ehcache-xml/src/test/resources/configs/docs/multi/multiple-managers.xml index bf16bbd5d9..e7bd481a6f 100644 --- a/xml/src/test/resources/configs/docs/multi/multiple-managers.xml +++ b/ehcache-xml/src/test/resources/configs/docs/multi/multiple-managers.xml @@ -1,9 +1,6 @@ + xmlns:multi='http://www.ehcache.org/v3/multi'> diff --git a/xml/src/test/resources/configs/docs/multi/multiple-variants.xml b/ehcache-xml/src/test/resources/configs/docs/multi/multiple-variants.xml similarity index 81% rename from xml/src/test/resources/configs/docs/multi/multiple-variants.xml rename to ehcache-xml/src/test/resources/configs/docs/multi/multiple-variants.xml index 8191a908e4..e04b3c858e 100644 --- a/xml/src/test/resources/configs/docs/multi/multiple-variants.xml +++ b/ehcache-xml/src/test/resources/configs/docs/multi/multiple-variants.xml @@ -1,9 +1,6 @@ + xmlns:multi='http://www.ehcache.org/v3/multi'> diff --git a/xml/src/test/resources/configs/docs/template-sample.xml b/ehcache-xml/src/test/resources/configs/docs/template-sample.xml similarity index 81% rename from xml/src/test/resources/configs/docs/template-sample.xml rename to ehcache-xml/src/test/resources/configs/docs/template-sample.xml index 75bfcae4dd..5248231cee 100644 --- a/xml/src/test/resources/configs/docs/template-sample.xml +++ b/ehcache-xml/src/test/resources/configs/docs/template-sample.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + diff --git a/xml/src/test/resources/configs/docs/thread-pools.xml b/ehcache-xml/src/test/resources/configs/docs/thread-pools.xml similarity index 90% rename from xml/src/test/resources/configs/docs/thread-pools.xml rename to ehcache-xml/src/test/resources/configs/docs/thread-pools.xml index 5d0ad14009..7e6a5dd133 100644 --- a/xml/src/test/resources/configs/docs/thread-pools.xml +++ b/ehcache-xml/src/test/resources/configs/docs/thread-pools.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + diff --git a/xml/src/test/resources/configs/ehcache-cacheEventListener.xml b/ehcache-xml/src/test/resources/configs/ehcache-cacheEventListener.xml similarity index 92% rename from xml/src/test/resources/configs/ehcache-cacheEventListener.xml rename to ehcache-xml/src/test/resources/configs/ehcache-cacheEventListener.xml index 3d7e354971..ec46c1c18f 100644 --- a/xml/src/test/resources/configs/ehcache-cacheEventListener.xml +++ b/ehcache-xml/src/test/resources/configs/ehcache-cacheEventListener.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + diff --git a/xml/src/test/resources/configs/ehcache-complete.xml b/ehcache-xml/src/test/resources/configs/ehcache-complete.xml similarity index 95% rename from xml/src/test/resources/configs/ehcache-complete.xml rename to ehcache-xml/src/test/resources/configs/ehcache-complete.xml index cdab276c61..3744479b4d 100644 --- a/xml/src/test/resources/configs/ehcache-complete.xml +++ b/ehcache-xml/src/test/resources/configs/ehcache-complete.xml @@ -15,10 +15,7 @@ ~ limitations under the License. --> - + diff --git a/xml/src/test/resources/configs/ehcache-multipleCacheEventListener.xml b/ehcache-xml/src/test/resources/configs/ehcache-multipleCacheEventListener.xml similarity index 90% rename from xml/src/test/resources/configs/ehcache-multipleCacheEventListener.xml rename to ehcache-xml/src/test/resources/configs/ehcache-multipleCacheEventListener.xml index 5a8b4fdd10..c18819a6fc 100644 --- a/xml/src/test/resources/configs/ehcache-multipleCacheEventListener.xml +++ b/ehcache-xml/src/test/resources/configs/ehcache-multipleCacheEventListener.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + java.lang.Number diff --git a/xml/src/test/resources/configs/ehcache-system-props.xml b/ehcache-xml/src/test/resources/configs/ehcache-system-props.xml similarity index 92% rename from xml/src/test/resources/configs/ehcache-system-props.xml rename to ehcache-xml/src/test/resources/configs/ehcache-system-props.xml index f9a9474fad..152607a540 100644 --- a/xml/src/test/resources/configs/ehcache-system-props.xml +++ b/ehcache-xml/src/test/resources/configs/ehcache-system-props.xml @@ -15,10 +15,7 @@ ~ limitations under the License. --> - + diff --git a/xml/src/test/resources/configs/expiry-caches.xml b/ehcache-xml/src/test/resources/configs/expiry-caches.xml similarity index 91% rename from xml/src/test/resources/configs/expiry-caches.xml rename to ehcache-xml/src/test/resources/configs/expiry-caches.xml index 84b3771ed7..629d0fbc57 100644 --- a/xml/src/test/resources/configs/expiry-caches.xml +++ b/ehcache-xml/src/test/resources/configs/expiry-caches.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + java.lang.String diff --git a/xml/src/test/resources/configs/fancy.xsd b/ehcache-xml/src/test/resources/configs/fancy.xsd similarity index 100% rename from xml/src/test/resources/configs/fancy.xsd rename to ehcache-xml/src/test/resources/configs/fancy.xsd diff --git a/xml/src/test/resources/configs/foo.xsd b/ehcache-xml/src/test/resources/configs/foo.xsd similarity index 100% rename from xml/src/test/resources/configs/foo.xsd rename to ehcache-xml/src/test/resources/configs/foo.xsd diff --git a/xml/src/test/resources/configs/invalid-core.xml b/ehcache-xml/src/test/resources/configs/invalid-core.xml similarity index 84% rename from xml/src/test/resources/configs/invalid-core.xml rename to ehcache-xml/src/test/resources/configs/invalid-core.xml index becc7e392f..35b913aa1d 100644 --- a/xml/src/test/resources/configs/invalid-core.xml +++ b/ehcache-xml/src/test/resources/configs/invalid-core.xml @@ -1,5 +1,4 @@ diff --git a/xml/src/test/resources/configs/invalid-service.xml b/ehcache-xml/src/test/resources/configs/invalid-service.xml similarity index 75% rename from xml/src/test/resources/configs/invalid-service.xml rename to ehcache-xml/src/test/resources/configs/invalid-service.xml index 7fad4a9256..1372dc9511 100644 --- a/xml/src/test/resources/configs/invalid-service.xml +++ b/ehcache-xml/src/test/resources/configs/invalid-service.xml @@ -1,5 +1,4 @@ diff --git a/ehcache-xml/src/test/resources/configs/invalid-two-caches.xml b/ehcache-xml/src/test/resources/configs/invalid-two-caches.xml new file mode 100644 index 0000000000..b9dc49818c --- /dev/null +++ b/ehcache-xml/src/test/resources/configs/invalid-two-caches.xml @@ -0,0 +1,11 @@ + + + + 2000 + + + + 2000 + + + diff --git a/ehcache-xml/src/test/resources/configs/multi/empty.xml b/ehcache-xml/src/test/resources/configs/multi/empty.xml new file mode 100644 index 0000000000..0f2027efef --- /dev/null +++ b/ehcache-xml/src/test/resources/configs/multi/empty.xml @@ -0,0 +1,2 @@ + + diff --git a/xml/src/test/resources/configs/multi/extended.xml b/ehcache-xml/src/test/resources/configs/multi/extended.xml similarity index 92% rename from xml/src/test/resources/configs/multi/extended.xml rename to ehcache-xml/src/test/resources/configs/multi/extended.xml index 4968bb5621..81a028949c 100644 --- a/xml/src/test/resources/configs/multi/extended.xml +++ b/ehcache-xml/src/test/resources/configs/multi/extended.xml @@ -1,5 +1,4 @@ diff --git a/xml/src/test/resources/configs/multi/multiple-variants.xml b/ehcache-xml/src/test/resources/configs/multi/multiple-variants.xml similarity index 95% rename from xml/src/test/resources/configs/multi/multiple-variants.xml rename to ehcache-xml/src/test/resources/configs/multi/multiple-variants.xml index f13baa93b2..c2ba086e56 100644 --- a/xml/src/test/resources/configs/multi/multiple-variants.xml +++ b/ehcache-xml/src/test/resources/configs/multi/multiple-variants.xml @@ -1,6 +1,5 @@ diff --git a/xml/src/test/resources/configs/nonExistentAdvisor-cache.xml b/ehcache-xml/src/test/resources/configs/nonExistentAdvisor-cache.xml similarity index 79% rename from xml/src/test/resources/configs/nonExistentAdvisor-cache.xml rename to ehcache-xml/src/test/resources/configs/nonExistentAdvisor-cache.xml index 52ad6e1c24..30a767611a 100644 --- a/xml/src/test/resources/configs/nonExistentAdvisor-cache.xml +++ b/ehcache-xml/src/test/resources/configs/nonExistentAdvisor-cache.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + com.foo.NonExistentAdvisorInCache diff --git a/xml/src/test/resources/configs/nonExistentAdvisor-template.xml b/ehcache-xml/src/test/resources/configs/nonExistentAdvisor-template.xml similarity index 80% rename from xml/src/test/resources/configs/nonExistentAdvisor-template.xml rename to ehcache-xml/src/test/resources/configs/nonExistentAdvisor-template.xml index 84be19ae24..74abaeed8b 100644 --- a/xml/src/test/resources/configs/nonExistentAdvisor-template.xml +++ b/ehcache-xml/src/test/resources/configs/nonExistentAdvisor-template.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + com.foo.NonExistentAdvisorInTemplate diff --git a/xml/src/test/resources/configs/one-cache.xml b/ehcache-xml/src/test/resources/configs/one-cache.xml similarity index 78% rename from xml/src/test/resources/configs/one-cache.xml rename to ehcache-xml/src/test/resources/configs/one-cache.xml index 2d4d64eb61..98091e81f8 100644 --- a/xml/src/test/resources/configs/one-cache.xml +++ b/ehcache-xml/src/test/resources/configs/one-cache.xml @@ -15,11 +15,8 @@ --> + xmlns:ehcache='http://www.ehcache.org/v3'> java.lang.String java.lang.String diff --git a/xml/src/test/resources/configs/one-service.xml b/ehcache-xml/src/test/resources/configs/one-service.xml similarity index 75% rename from xml/src/test/resources/configs/one-service.xml rename to ehcache-xml/src/test/resources/configs/one-service.xml index ab9e7028bd..fda8541468 100644 --- a/xml/src/test/resources/configs/one-service.xml +++ b/ehcache-xml/src/test/resources/configs/one-service.xml @@ -15,11 +15,8 @@ --> + xmlns:ehcache='http://www.ehcache.org/v3'> diff --git a/ehcache-xml/src/test/resources/configs/persistence-config.xml b/ehcache-xml/src/test/resources/configs/persistence-config.xml new file mode 100644 index 0000000000..bbba65a64b --- /dev/null +++ b/ehcache-xml/src/test/resources/configs/persistence-config.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/xml/src/test/resources/configs/pretty-typed-caches.xml b/ehcache-xml/src/test/resources/configs/pretty-typed-caches.xml similarity index 87% rename from xml/src/test/resources/configs/pretty-typed-caches.xml rename to ehcache-xml/src/test/resources/configs/pretty-typed-caches.xml index 39f4f41045..583b53dce2 100644 --- a/xml/src/test/resources/configs/pretty-typed-caches.xml +++ b/ehcache-xml/src/test/resources/configs/pretty-typed-caches.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + java.lang.Integer diff --git a/xml/src/test/resources/configs/resilience-config.xml b/ehcache-xml/src/test/resources/configs/resilience-config.xml similarity index 86% rename from xml/src/test/resources/configs/resilience-config.xml rename to ehcache-xml/src/test/resources/configs/resilience-config.xml index 092eb30243..3902b2ab62 100644 --- a/xml/src/test/resources/configs/resilience-config.xml +++ b/ehcache-xml/src/test/resources/configs/resilience-config.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + java.lang.Number diff --git a/xml/src/test/resources/configs/resources-caches.xml b/ehcache-xml/src/test/resources/configs/resources-caches.xml similarity index 91% rename from xml/src/test/resources/configs/resources-caches.xml rename to ehcache-xml/src/test/resources/configs/resources-caches.xml index 1fd65d4ed3..5a81099b44 100644 --- a/xml/src/test/resources/configs/resources-caches.xml +++ b/ehcache-xml/src/test/resources/configs/resources-caches.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + diff --git a/xml/src/test/resources/configs/resources-templates.xml b/ehcache-xml/src/test/resources/configs/resources-templates.xml similarity index 92% rename from xml/src/test/resources/configs/resources-templates.xml rename to ehcache-xml/src/test/resources/configs/resources-templates.xml index 22d67c644b..2369fbf895 100644 --- a/xml/src/test/resources/configs/resources-templates.xml +++ b/ehcache-xml/src/test/resources/configs/resources-templates.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + java.lang.String diff --git a/xml/src/test/resources/configs/sizeof-engine-cm-defaults-one.xml b/ehcache-xml/src/test/resources/configs/sizeof-engine-cm-defaults-one.xml similarity index 84% rename from xml/src/test/resources/configs/sizeof-engine-cm-defaults-one.xml rename to ehcache-xml/src/test/resources/configs/sizeof-engine-cm-defaults-one.xml index c8aa2fc11d..d78453284a 100644 --- a/xml/src/test/resources/configs/sizeof-engine-cm-defaults-one.xml +++ b/ehcache-xml/src/test/resources/configs/sizeof-engine-cm-defaults-one.xml @@ -13,10 +13,7 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - + 100000 diff --git a/xml/src/test/resources/configs/sizeof-engine-cm-defaults-two.xml b/ehcache-xml/src/test/resources/configs/sizeof-engine-cm-defaults-two.xml similarity index 84% rename from xml/src/test/resources/configs/sizeof-engine-cm-defaults-two.xml rename to ehcache-xml/src/test/resources/configs/sizeof-engine-cm-defaults-two.xml index 1cf04f67ea..a4fbb7517a 100644 --- a/xml/src/test/resources/configs/sizeof-engine-cm-defaults-two.xml +++ b/ehcache-xml/src/test/resources/configs/sizeof-engine-cm-defaults-two.xml @@ -13,10 +13,7 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - + 200 diff --git a/xml/src/test/resources/configs/sizeof-engine.xml b/ehcache-xml/src/test/resources/configs/sizeof-engine.xml similarity index 92% rename from xml/src/test/resources/configs/sizeof-engine.xml rename to ehcache-xml/src/test/resources/configs/sizeof-engine.xml index a8341f0818..95aaa398e9 100644 --- a/xml/src/test/resources/configs/sizeof-engine.xml +++ b/ehcache-xml/src/test/resources/configs/sizeof-engine.xml @@ -13,10 +13,7 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - + 200 diff --git a/xml/src/test/resources/configs/template-cache.xml b/ehcache-xml/src/test/resources/configs/template-cache.xml similarity index 81% rename from xml/src/test/resources/configs/template-cache.xml rename to ehcache-xml/src/test/resources/configs/template-cache.xml index 086470eaf6..38bab168b4 100644 --- a/xml/src/test/resources/configs/template-cache.xml +++ b/ehcache-xml/src/test/resources/configs/template-cache.xml @@ -15,11 +15,8 @@ --> + xmlns:ehcache='http://www.ehcache.org/v3'> java.lang.String diff --git a/xml/src/test/resources/configs/template-defaults.xml b/ehcache-xml/src/test/resources/configs/template-defaults.xml similarity index 69% rename from xml/src/test/resources/configs/template-defaults.xml rename to ehcache-xml/src/test/resources/configs/template-defaults.xml index 6cd5e5a209..62cb319745 100644 --- a/xml/src/test/resources/configs/template-defaults.xml +++ b/ehcache-xml/src/test/resources/configs/template-defaults.xml @@ -14,12 +14,7 @@ ~ limitations under the License. --> - + diff --git a/xml/src/test/resources/configs/thread-pools.xml b/ehcache-xml/src/test/resources/configs/thread-pools.xml similarity index 87% rename from xml/src/test/resources/configs/thread-pools.xml rename to ehcache-xml/src/test/resources/configs/thread-pools.xml index 60bba2ac6e..00376dbb6f 100644 --- a/xml/src/test/resources/configs/thread-pools.xml +++ b/ehcache-xml/src/test/resources/configs/thread-pools.xml @@ -14,9 +14,7 @@ ~ limitations under the License. --> - + diff --git a/xml/src/test/resources/configs/unknown-resource.xml b/ehcache-xml/src/test/resources/configs/unknown-resource.xml similarity index 84% rename from xml/src/test/resources/configs/unknown-resource.xml rename to ehcache-xml/src/test/resources/configs/unknown-resource.xml index 0ee99b09ef..bf94d680ba 100644 --- a/xml/src/test/resources/configs/unknown-resource.xml +++ b/ehcache-xml/src/test/resources/configs/unknown-resource.xml @@ -1,6 +1,5 @@ diff --git a/xml/src/test/resources/configs/unknown-service-creation.xml b/ehcache-xml/src/test/resources/configs/unknown-service-creation.xml similarity index 81% rename from xml/src/test/resources/configs/unknown-service-creation.xml rename to ehcache-xml/src/test/resources/configs/unknown-service-creation.xml index 2f983b475c..254a6dec2b 100644 --- a/xml/src/test/resources/configs/unknown-service-creation.xml +++ b/ehcache-xml/src/test/resources/configs/unknown-service-creation.xml @@ -1,6 +1,5 @@ diff --git a/xml/src/test/resources/configs/unknown-service.xml b/ehcache-xml/src/test/resources/configs/unknown-service.xml similarity index 81% rename from xml/src/test/resources/configs/unknown-service.xml rename to ehcache-xml/src/test/resources/configs/unknown-service.xml index e54fb4085d..2873544bcf 100644 --- a/xml/src/test/resources/configs/unknown-service.xml +++ b/ehcache-xml/src/test/resources/configs/unknown-service.xml @@ -1,6 +1,5 @@ diff --git a/xml/src/test/resources/configs/writebehind-cache.xml b/ehcache-xml/src/test/resources/configs/writebehind-cache.xml similarity index 90% rename from xml/src/test/resources/configs/writebehind-cache.xml rename to ehcache-xml/src/test/resources/configs/writebehind-cache.xml index 85b7459e85..68925f1e53 100644 --- a/xml/src/test/resources/configs/writebehind-cache.xml +++ b/ehcache-xml/src/test/resources/configs/writebehind-cache.xml @@ -14,10 +14,7 @@ ~ limitations under the License. --> - + diff --git a/xml/src/testFixtures/java/org/ehcache/xml/XmlConfigurationMatchers.java b/ehcache-xml/src/testFixtures/java/org/ehcache/xml/XmlConfigurationMatchers.java similarity index 100% rename from xml/src/testFixtures/java/org/ehcache/xml/XmlConfigurationMatchers.java rename to ehcache-xml/src/testFixtures/java/org/ehcache/xml/XmlConfigurationMatchers.java diff --git a/ehcache/build.gradle b/ehcache/build.gradle new file mode 100644 index 0000000000..ef5a4436b9 --- /dev/null +++ b/ehcache/build.gradle @@ -0,0 +1,96 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import aQute.bnd.osgi.Constants + +import static org.gradle.api.attributes.Bundling.EXTERNAL +import static org.gradle.api.attributes.Category.DOCUMENTATION +import static org.gradle.api.attributes.Usage.JAVA_RUNTIME + +plugins { + id 'org.ehcache.build.package' +} + +publishing.publications.withType(MavenPublication) { + pom { + name = 'Ehcache' + description = 'End-user ehcache3 jar artifact' + } +} + +configurations { + contents { + exclude group:'org.glassfish.jaxb' + exclude group:'org.slf4j' + exclude group:'javax.cache' + exclude group:'javax.xml.bind' + } +} + +dependencies { + contents project(':ehcache-api') + contents project(':ehcache-core') + contents project(':ehcache-impl') + contents project(':ehcache-107') + contents project(':ehcache-xml') + + api "javax.cache:cache-api:$parent.jcacheVersion" + implementation "org.slf4j:slf4j-api:$parent.slf4jVersion" + runtimeOnly 'org.glassfish.jaxb:jaxb-runtime:[2.2,3)' +} + +tasks.named('jar') { + osgi { + instruction Constants.BUNDLE_NAME, 'Ehcache 3' + instruction Constants.BUNDLE_SYMBOLICNAME, 'org.ehcache' + instruction Constants.BUNDLE_DESCRIPTION, 'Ehcache is an open-source caching library, compliant with the JSR-107 standard.' + instruction Constants.BUNDLE_ACTIVATOR, 'org.ehcache.core.osgi.EhcacheActivator' + instruction Constants.EXPORT_PACKAGE, '!org.ehcache.jsr107.tck, !org.ehcache.*.internal.*, org.ehcache.*' + instruction Constants.IMPORT_PACKAGE, 'javax.cache.*;resolution:=optional, !javax.annotation, !sun.misc, javax.xml.bind*;version="[2.2,3)", *' + } +} + +tasks.withType(Javadoc).matching({ name.equals('spiJavadoc') }).configureEach { + exclude '**/core/**', '**/impl/**', '**/xml/**', '**/jsr107/**', '**/transactions/**', '**/management/**', '**/tck/**' +} + +TaskProvider spiJavadoc = tasks.register('spiJavadoc', Javadoc) { + title = "$project.archivesBaseName $project.version API & SPI"; + source = tasks.javadoc.source + setClasspath(tasks.javadoc.classpath) + exclude "**/internal/**" + setDestinationDir project.file("$project.buildDir/docs/spi-javadoc") +} + +TaskProvider spiJavadocJar = project.getTasks().register('spiJavadocJar', Jar) { + from(spiJavadoc); + getArchiveClassifier().set("spi-javadoc"); +} +Configuration spiJavadocElements = project.getConfigurations().create("spiJavadocElements", config -> { + config.setDescription("javadoc elements for SPI documentation."); + config.attributes(attributes -> { + attributes.attribute(Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, JAVA_RUNTIME)); + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.getObjects().named(Category.class, DOCUMENTATION)); + attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, project.getObjects().named(Bundling.class, EXTERNAL)); + attributes.attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.getObjects().named(DocsType.class, "spi-javadoc")); + }); + config.getOutgoing().artifact(spiJavadocJar); +}); + +components.named('java', AdhocComponentWithVariants) { + addVariantsFromConfiguration(spiJavadocElements) {} +} diff --git a/dist/templates/github-release-issue.md b/ehcache/templates/github-release-issue.md similarity index 100% rename from dist/templates/github-release-issue.md rename to ehcache/templates/github-release-issue.md diff --git a/dist/templates/github-release.md b/ehcache/templates/github-release.md similarity index 100% rename from dist/templates/github-release.md rename to ehcache/templates/github-release.md diff --git a/gradle.properties b/gradle.properties index d00d675194..4fa2259dcb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # Ehcache version -ehcacheVersion = 3.9-SNAPSHOT +ehcacheVersion = 3.10-SNAPSHOT # Terracotta third parties offheapVersion = 2.5.2 @@ -7,7 +7,6 @@ statisticVersion = 2.1 jcacheVersion = 1.1.0 slf4jVersion = 1.7.25 sizeofVersion = 0.4.0 -jaxbVersion = [2.2,3) # Terracotta clustered terracottaPlatformVersion = 5.8.9-pre5 @@ -24,9 +23,6 @@ mockitoVersion = 2.23.4 jacksonVersion = 2.12.4 jcacheTckVersion = 1.1.0 -# Tools -jacocoVersion = 0.8.5 - sonatypeUser = OVERRIDE_ME sonatypePwd = OVERRIDE_ME diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1ba7206f88..a0f7639f7d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/impl/.gitignore b/impl/.gitignore deleted file mode 100755 index ae3c172604..0000000000 --- a/impl/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/impl/gradle.properties b/impl/gradle.properties deleted file mode 100644 index 1c43b6bdd0..0000000000 --- a/impl/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -subPomName = Ehcache 3 Implementation module -subPomDesc = The implementation module of Ehcache 3 diff --git a/integration-test/.gitignore b/integration-test/.gitignore deleted file mode 100644 index ae3c172604..0000000000 --- a/integration-test/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/integration-test/build.gradle b/integration-test/build.gradle index 13d536b828..876994e798 100644 --- a/integration-test/build.gradle +++ b/integration-test/build.gradle @@ -14,11 +14,19 @@ * limitations under the License. */ +plugins { + id 'org.ehcache.build.conventions.java' +} + dependencies { testImplementation "javax.cache:cache-api:$parent.jcacheVersion" - testImplementation project(':107') - testImplementation project(':impl') - testImplementation project(':transactions') + testImplementation project(':ehcache-107') + testImplementation project(':ehcache-impl') + testImplementation(project(':ehcache-transactions')) { + capabilities { + requireCapability('org.ehcache:ehcache-transactions-modules') + } + } testImplementation (group: 'org.codehaus.btm', name: 'btm', version: '2.1.4') { exclude group:'org.slf4j', module:'slf4j-api' } diff --git a/integration-test/gradle.properties b/integration-test/gradle.properties deleted file mode 100644 index 8a8b81c0c3..0000000000 --- a/integration-test/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -subPomName = Ehcache 3 Integration Tests module -subPomDesc = The integration tests module of Ehcache 3 diff --git a/integration-test/src/test/resources/configs/simple-xa.xml b/integration-test/src/test/resources/configs/simple-xa.xml index 4efbc3e835..ba09416aba 100644 --- a/integration-test/src/test/resources/configs/simple-xa.xml +++ b/integration-test/src/test/resources/configs/simple-xa.xml @@ -14,11 +14,8 @@ ~ limitations under the License. --> + xmlns:tx='http://www.ehcache.org/v3/tx'> diff --git a/management/.gitignore b/management/.gitignore deleted file mode 100755 index ae3c172604..0000000000 --- a/management/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/management/gradle.properties b/management/gradle.properties deleted file mode 100644 index 226794f83c..0000000000 --- a/management/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -subPomName = Ehcache 3 Management and Monitoring module -subPomDesc = The Management and Monitoring module of Ehcache 3 -osgi = {"Import-Package" : ["!sun.misc.*", "!sun.security.action.*"]} diff --git a/management/src/test/resources/ehcache-management-1.xml b/management/src/test/resources/ehcache-management-1.xml deleted file mode 100644 index 6dc090cfd3..0000000000 --- a/management/src/test/resources/ehcache-management-1.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - java.lang.String - java.lang.String - 20 - - - diff --git a/osgi-test/build.gradle b/osgi-test/build.gradle index a2d9750f54..666463b594 100644 --- a/osgi-test/build.gradle +++ b/osgi-test/build.gradle @@ -14,7 +14,12 @@ * limitations under the License. */ +plugins { + id 'org.ehcache.build.conventions.java-library' +} + configurations { + modularOsgiModule osgiModule lowerBoundOsgiModule.extendsFrom osgiModule testCompileOnly.extendsFrom osgiModule @@ -35,19 +40,19 @@ dependencies { exclude group:'org.slf4j', module:'slf4j-api' } - osgiModule project(':api') - osgiModule project(':core') - osgiModule project(':impl') - osgiModule project(':xml') - osgiModule project(':107') - osgiModule project(':transactions') + modularOsgiModule project(':ehcache-api') + modularOsgiModule project(':ehcache-core') + modularOsgiModule project(':ehcache-impl') + modularOsgiModule project(':ehcache-xml') + modularOsgiModule project(':ehcache-107') + osgiModule project(':ehcache-transactions') osgiModule "javax.cache:cache-api:$parent.jcacheVersion" osgiModule ('org.codehaus.btm:btm:2.1.4') { exclude group:'org.slf4j', module:'slf4j-api' } - osgiModule project(':dist') + osgiModule project(':ehcache') osgiModule "org.slf4j:slf4j-simple:$parent.slf4jVersion" osgiModule 'org.apache.felix:org.apache.felix.scr:2.1.6' @@ -95,9 +100,9 @@ if (testJava.javaVersion.isJava9Compatible()) { } test { - dependsOn configurations.osgiModule + dependsOn configurations.osgiModule, configurations.modularOsgiModule doFirst { - configurations.osgiModule.resolvedConfiguration.resolvedArtifacts.forEach({ + [configurations.modularOsgiModule, configurations.osgiModule]*.resolvedConfiguration*.resolvedArtifacts*.forEach({ systemProperty "$it.moduleVersion.id.module:osgi-path", it.file }) } @@ -114,11 +119,11 @@ dependencies { lowerBoundOsgiModule 'javax.xml.bind:jaxb-api:2.2.9' } -tasks.register('lowerBoundTest', Test) { +tasks.register('lowerBoundTest', Test) { test -> group = JavaBasePlugin.VERIFICATION_GROUP - dependsOn configurations.lowerBoundOsgiModule + dependsOn configurations.lowerBoundOsgiModule, configurations.modularOsgiModule doFirst { - configurations.lowerBoundOsgiModule.resolvedConfiguration.resolvedArtifacts.forEach { + [configurations.modularOsgiModule, configurations.lowerBoundOsgiModule]*.resolvedConfiguration*.resolvedArtifacts*.forEach { systemProperty "$it.moduleVersion.id.module:osgi-path", it.file } } diff --git a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java index 251078b307..67591f89d3 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/ByteSizedOnHeapOsgiTest.java @@ -42,9 +42,9 @@ public class ByteSizedOnHeapOsgiTest { @Configuration public Option[] individualModules() { return options( - gradleBundle("org.ehcache.modules:impl"), - gradleBundle("org.ehcache.modules:core"), - gradleBundle("org.ehcache.modules:api"), + gradleBundle("org.ehcache.modules:ehcache-impl"), + gradleBundle("org.ehcache.modules:ehcache-core"), + gradleBundle("org.ehcache.modules:ehcache-api"), gradleBundle("org.terracotta:statistics"), gradleBundle("org.ehcache:sizeof"), @@ -58,7 +58,7 @@ public Option[] individualModules() { @Configuration public Option[] uberJar() { return options( - gradleBundle("org.ehcache:dist"), jaxbConfiguration(), + gradleBundle("org.ehcache:ehcache"), jaxbConfiguration(), baseConfiguration("ByteSizedOnHeapOsgiTest", "uberJar") ); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java index 47495dd6c6..f96c601241 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/Jsr107OsgiTest.java @@ -57,11 +57,11 @@ public class Jsr107OsgiTest { @Configuration public Option[] individualModules() { return options( - gradleBundle("org.ehcache.modules:impl"), - gradleBundle("org.ehcache.modules:xml"), jaxbConfiguration(), - gradleBundle("org.ehcache.modules:107"), - gradleBundle("org.ehcache.modules:core"), - gradleBundle("org.ehcache.modules:api"), + gradleBundle("org.ehcache.modules:ehcache-impl"), + gradleBundle("org.ehcache.modules:ehcache-xml"), jaxbConfiguration(), + gradleBundle("org.ehcache.modules:ehcache-107"), + gradleBundle("org.ehcache.modules:ehcache-core"), + gradleBundle("org.ehcache.modules:ehcache-api"), gradleBundle("javax.cache:cache-api"), gradleBundle("org.terracotta:statistics"), @@ -76,7 +76,7 @@ public Option[] individualModules() { @Configuration public Option[] uberJar() { return options( - gradleBundle("org.ehcache:dist"), jaxbConfiguration(), + gradleBundle("org.ehcache:ehcache"), jaxbConfiguration(), gradleBundle("javax.cache:cache-api"), baseConfiguration("Jsr107OsgiTest", "uberJar") diff --git a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java index 157297ab03..4143fbc681 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/OffHeapOsgiTest.java @@ -49,9 +49,9 @@ public class OffHeapOsgiTest { @Configuration public Option[] individualModules() { return options( - gradleBundle("org.ehcache.modules:api"), - gradleBundle("org.ehcache.modules:core"), - gradleBundle("org.ehcache.modules:impl"), + gradleBundle("org.ehcache.modules:ehcache-api"), + gradleBundle("org.ehcache.modules:ehcache-core"), + gradleBundle("org.ehcache.modules:ehcache-impl"), gradleBundle("org.terracotta:statistics"), gradleBundle("org.ehcache:sizeof"), @@ -65,7 +65,7 @@ public Option[] individualModules() { @Configuration public Option[] uberJarWithOsgiServiceLoading() { return options( - gradleBundle("org.ehcache:dist"), jaxbConfiguration(), + gradleBundle("org.ehcache:ehcache"), jaxbConfiguration(), baseConfiguration("OffHeapOsgiTest", "uberJarWithOsgiServiceLoading") ); @@ -76,7 +76,7 @@ public Option[] uberJarWithJdkServiceLoading() { return options( frameworkProperty(OSGI_LOADING).value("false"), - gradleBundle("org.ehcache:dist"), jaxbConfiguration(), + gradleBundle("org.ehcache:ehcache"), jaxbConfiguration(), baseConfiguration("OffHeapOsgiTest", "uberJarWithJdkServiceLoading") ); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java index b3f64d9cfe..7498a7e22d 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/SimpleOsgiTest.java @@ -62,10 +62,10 @@ public class SimpleOsgiTest { @Configuration public Option[] individualModules() { return options( - gradleBundle("org.ehcache.modules:api"), - gradleBundle("org.ehcache.modules:core"), - gradleBundle("org.ehcache.modules:impl"), - gradleBundle("org.ehcache.modules:xml"), jaxbConfiguration(), + gradleBundle("org.ehcache.modules:ehcache-api"), + gradleBundle("org.ehcache.modules:ehcache-core"), + gradleBundle("org.ehcache.modules:ehcache-impl"), + gradleBundle("org.ehcache.modules:ehcache-xml"), jaxbConfiguration(), gradleBundle("org.terracotta:statistics"), gradleBundle("org.ehcache:sizeof"), @@ -79,7 +79,7 @@ public Option[] individualModules() { @Configuration public Option[] uberJarWithOsgiServiceLoading() { return options( - gradleBundle("org.ehcache:dist"), jaxbConfiguration(), + gradleBundle("org.ehcache:ehcache"), jaxbConfiguration(), baseConfiguration("SimpleOsgiTest", "uberJarWithOsgiServiceLoading") ); @@ -90,7 +90,7 @@ public Option[] uberJarWithJdkServiceLoading() { return options( frameworkProperty(OSGI_LOADING).value("false"), - gradleBundle("org.ehcache:dist"), jaxbConfiguration(), + gradleBundle("org.ehcache:ehcache"), jaxbConfiguration(), baseConfiguration("SimpleOsgiTest", "uberJarWithJdkServiceLoading") ); diff --git a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java index 856cf49646..e5966016f8 100644 --- a/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java +++ b/osgi-test/src/test/java/org/ehcache/osgi/TransactionalOsgiTest.java @@ -52,11 +52,11 @@ public class TransactionalOsgiTest { @Configuration public Option[] individualModules() { return options( - gradleBundle("org.ehcache.modules:api"), - gradleBundle("org.ehcache.modules:core"), - gradleBundle("org.ehcache.modules:impl"), - gradleBundle("org.ehcache.modules:xml"), jaxbConfiguration(), - gradleBundle("org.ehcache:transactions"), jtaConfiguration(), + gradleBundle("org.ehcache.modules:ehcache-api"), + gradleBundle("org.ehcache.modules:ehcache-core"), + gradleBundle("org.ehcache.modules:ehcache-impl"), + gradleBundle("org.ehcache.modules:ehcache-xml"), jaxbConfiguration(), + gradleBundle("org.ehcache:ehcache-transactions"), jtaConfiguration(), gradleBundle("org.terracotta:statistics"), gradleBundle("org.ehcache:sizeof"), @@ -70,8 +70,8 @@ public Option[] individualModules() { @Configuration public Option[] uberJar() { return options( - gradleBundle("org.ehcache:dist"), jaxbConfiguration(), - gradleBundle("org.ehcache:transactions"), jtaConfiguration(), + gradleBundle("org.ehcache:ehcache"), jaxbConfiguration(), + gradleBundle("org.ehcache:ehcache-transactions"), jtaConfiguration(), baseConfiguration("TransactionalOsgiTest", "uberJar") ); diff --git a/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-107-osgi.xml b/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-107-osgi.xml index 43633160f3..5c757fccc5 100644 --- a/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-107-osgi.xml +++ b/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-107-osgi.xml @@ -15,11 +15,8 @@ --> + xmlns:jsr107='http://www.ehcache.org/v3/jsr107'> diff --git a/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-osgi.xml b/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-osgi.xml index 704738aa26..8155f7476e 100644 --- a/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-osgi.xml +++ b/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-osgi.xml @@ -30,9 +30,7 @@ ~ limitations under the License. --> - + java.lang.String org.ehcache.osgi.Person diff --git a/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-xa-osgi.xml b/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-xa-osgi.xml index 497e95814d..97624b7556 100644 --- a/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-xa-osgi.xml +++ b/osgi-test/src/test/resources/org/ehcache/osgi/ehcache-xa-osgi.xml @@ -14,7 +14,6 @@ ~ limitations under the License. --> diff --git a/settings.gradle b/settings.gradle index 5af54e753a..1117a15add 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,20 +16,21 @@ pluginManagement { plugins { - id 'io.codearte.nexus-staging' version '0.21.1' - id 'com.github.spotbugs' version '2.0.1' - id 'org.jayware.osgi-ds' version '0.5.6' - id 'org.owasp.dependencycheck' version '5.2.4' - id 'biz.aQute.bnd.builder' version '4.1.0' - id 'org.gretty' version '2.3.1' - id 'org.asciidoctor.jvm.base' version '2.3.0' - id 'org.unbroken-dome.xjc' version '1.4.3' + id 'io.codearte.nexus-staging' version '0.30.0' + id 'org.owasp.dependencycheck' version '6.2.2' + id 'org.gretty' version '3.0.6' + id 'org.asciidoctor.jvm.base' version '3.3.2' + id 'org.unbroken-dome.xjc' version '2.0.0' } + + includeBuild 'build-logic' } -include "api", "spi-tester", "core", "core-spi-test", "impl", "management", "transactions", "107", "xml", - "clustered", "clustered:common-api", "clustered:common", - "clustered:server:service-api", "clustered:server:service", "clustered:server:entity", - "clustered:client", "clustered:clustered-dist", "clustered:ops-tool", - "clustered:test-utils", "clustered:integration-test", - "integration-test", "dist", "osgi-test", "clustered:osgi-test", "demos", "demos:00-NoCache", "demos:01-CacheAside", "docs" +include "ehcache-api", "ehcache-core", "ehcache-impl", "ehcache-107", "ehcache-xml", + "ehcache-management", "ehcache-transactions", "ehcache", + "spi-tester", "core-spi-test", + "clustered:ehcache-common-api", "clustered:ehcache-common", + "clustered:server:ehcache-service-api", "clustered:server:ehcache-service", "clustered:server:ehcache-entity", + "clustered:ehcache-client", "clustered:ehcache-clustered", "clustered:ops-tool", + "clustered:test-utils", "clustered:integration-test", + "integration-test", "osgi-test", "clustered:osgi-test", "demos", "demos:00-NoCache", "demos:01-CacheAside", "docs" diff --git a/spi-tester/.gitignore b/spi-tester/.gitignore deleted file mode 100755 index ae3c172604..0000000000 --- a/spi-tester/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/spi-tester/build.gradle b/spi-tester/build.gradle new file mode 100644 index 0000000000..f119623938 --- /dev/null +++ b/spi-tester/build.gradle @@ -0,0 +1,3 @@ +plugins { + id 'org.ehcache.build.conventions.java-library' +} diff --git a/spi-tester/gradle.properties b/spi-tester/gradle.properties deleted file mode 100644 index 607a9322c8..0000000000 --- a/spi-tester/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -subPomName = Ehcache 3 SPI Tester module -subPomDesc = SPI Tester diff --git a/transactions/build.gradle b/transactions/build.gradle deleted file mode 100644 index 0f8fb20ac7..0000000000 --- a/transactions/build.gradle +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -plugins { - id 'biz.aQute.bnd.builder' - id 'org.jayware.osgi-ds' - id 'org.ehcache.build.pom-mangle' -} - -group = 'org.ehcache' - -dependencies { - api group: 'javax.transaction', name: 'jta', version: '1.1' - api project(':core') - implementation project(':impl') - implementation project(':xml') - implementation (group: 'org.codehaus.btm', name: 'btm', version: '2.1.4') { - exclude group:'org.slf4j', module:'slf4j-api' - } - compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' - testImplementation project(':core-spi-test') - testImplementation testFixtures(project(':xml')) - testImplementation "org.terracotta:statistics:$statisticVersion" -} - -// For EhPomMangle -dependencies { - pomOnlyCompile "org.ehcache:ehcache:$parent.baseVersion" - pomOnlyProvided 'javax.transaction:jta:1.1', 'org.codehaus.btm:btm:2.1.4' -} - -jar { - bnd ( - 'Bundle-SymbolicName': 'org.ehcache.transactions', - 'Export-Package': 'org.ehcache.transactions.xa.*', - 'Import-Package': 'bitronix.tm.*;resolution:=optional, javax.transaction.*;resolution:=optional, org.ehcache.xml.*;resolution:=optional, *', - ) -} - -project.signing { - required { project.isReleaseVersion && project.gradle.taskGraph.hasTask("uploadArchives") } - sign project.configurations.getByName('archives') -} diff --git a/transactions/gradle.properties b/transactions/gradle.properties deleted file mode 100644 index 6a1f373c75..0000000000 --- a/transactions/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -subPomName = Ehcache 3 transactions module -subPomDesc = The transactions module of Ehcache 3 diff --git a/xml/.gitignore b/xml/.gitignore deleted file mode 100755 index ae3c172604..0000000000 --- a/xml/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/xml/build.gradle b/xml/build.gradle deleted file mode 100644 index 39c0afbdd5..0000000000 --- a/xml/build.gradle +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -plugins { - id 'org.unbroken-dome.xjc' - id 'org.ehcache.build.deploy' - id 'biz.aQute.bnd.builder' - id 'java-test-fixtures' -} - -dependencies { - api project(':api') - implementation project(':core') - implementation project(':impl') - providedImplementation "org.glassfish.jaxb:jaxb-runtime:$parent.jaxbVersion" - - testFixturesApi 'org.xmlunit:xmlunit-core:2.6.0', 'org.xmlunit:xmlunit-matchers:2.6.0' - xjcClasspath 'org.jvnet.jaxb2_commons:jaxb2-fluent-api:3.0' - xjcClasspath 'org.jvnet.jaxb2_commons:jaxb2-basics-annotate:1.1.0' -} - -configurations.xjcClasspath.resolutionStrategy.dependencySubstitution { - substitute module('commons-beanutils:commons-beanutils:1.9.3') with module('commons-beanutils:commons-beanutils:1.9.4') -} - -jar { - bnd ( - 'Export-Package': 'org.ehcache.xml, org.ehcache.xml.exceptions, org.ehcache.xml.model', - 'Import-Package': "javax.xml.bind*;version=\"${parent.jaxbVersion}\", *" - ) -} - -xjcGenerate { - source = ['src/main/resources/ehcache-core.xsd', 'src/main/resources/ehcache-multi.xsd'] - extension = true - extraArgs = ['-Xfluent-api', '-Xannotate'] -} - -configurations { - lowerBoundTestRuntime.extendsFrom testRuntimeClasspath -} -configurations { - lowerBoundTestRuntime { - resolutionStrategy.dependencySubstitution { - substitute module('org.glassfish.jaxb:jaxb-runtime') with module('com.sun.xml.bind:jaxb-impl:2.2.8-b01') - } - } -} -dependencies { - lowerBoundTestRuntime 'com.sun.activation:javax.activation:1.2.0' -} - -tasks.register('lowerBoundTest', Test) { - group = JavaBasePlugin.VERIFICATION_GROUP - //remove the original runtime classpath - classpath -= configurations.testRuntimeClasspath - //add the classpath we want - classpath += configurations.lowerBoundTestRuntime -} - -tasks.named('check') { - dependsOn tasks.lowerBoundTest -} diff --git a/xml/gradle.properties b/xml/gradle.properties deleted file mode 100644 index c5f4931900..0000000000 --- a/xml/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright Terracotta, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -subPomName = Ehcache 3 XML Parsing module -subPomDesc = The module containing all XML parsing logic Ehcache 3 diff --git a/xml/src/test/java/org/ehcache/xml/ConfigurationParserTestHelper.java b/xml/src/test/java/org/ehcache/xml/ConfigurationParserTestHelper.java deleted file mode 100644 index f92295e6b9..0000000000 --- a/xml/src/test/java/org/ehcache/xml/ConfigurationParserTestHelper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Terracotta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.ehcache.xml; - -import org.w3c.dom.Node; -import org.xmlunit.builder.Input; -import org.xmlunit.diff.DefaultNodeMatcher; -import org.xmlunit.diff.ElementSelectors; - -import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; - -/** - * ConfigurationParserTestHelper - */ -public class ConfigurationParserTestHelper { - public static void assertElement(String inputString, Node rootElement) { - } -} diff --git a/xml/src/test/resources/configs/invalid-two-caches.xml b/xml/src/test/resources/configs/invalid-two-caches.xml deleted file mode 100644 index cbefbca7b9..0000000000 --- a/xml/src/test/resources/configs/invalid-two-caches.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - 2000 - - - - 2000 - - - diff --git a/xml/src/test/resources/configs/multi/empty.xml b/xml/src/test/resources/configs/multi/empty.xml deleted file mode 100644 index f5f0961bf1..0000000000 --- a/xml/src/test/resources/configs/multi/empty.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/xml/src/test/resources/configs/persistence-config.xml b/xml/src/test/resources/configs/persistence-config.xml deleted file mode 100644 index 7a4692ad43..0000000000 --- a/xml/src/test/resources/configs/persistence-config.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - \ No newline at end of file