Use Caffeine (W-TinyLFU) for on-heap caches patch by Ben Manes; reviewed by Robert Stupp for CASSANDRA-10855
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/c607d764 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/c607d764 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/c607d764 Branch: refs/heads/trunk Commit: c607d76413be81a0e125c5780e068d7ab7594612 Parents: 95c4320 Author: Ben Manes <[email protected]> Authored: Sun Jan 1 11:00:42 2017 +0100 Committer: Robert Stupp <[email protected]> Committed: Sun Jan 1 11:00:42 2017 +0100 ---------------------------------------------------------------------- CHANGES.txt | 1 + build.xml | 82 ++++---- lib/caffeine-2.2.6.jar | Bin 947685 -> 0 bytes lib/caffeine-2.3.5.jar | Bin 0 -> 972705 bytes lib/concurrentlinkedhashmap-lru-1.4.jar | Bin 116575 -> 0 bytes lib/licenses/caffeine-2.2.6.txt | 202 ------------------- lib/licenses/caffeine-2.3.5.txt | 202 +++++++++++++++++++ .../concurrentlinkedhashmap-lru-1.4.txt | 202 ------------------- .../org/apache/cassandra/auth/AuthCache.java | 62 ++---- .../cassandra/auth/PasswordAuthenticator.java | 29 +-- .../apache/cassandra/cache/CaffeineCache.java | 142 +++++++++++++ .../cache/ConcurrentLinkedHashCache.java | 133 ------------ .../cassandra/cache/SerializingCache.java | 91 ++++----- .../apache/cassandra/cql3/QueryProcessor.java | 32 +-- .../sasi/analyzer/filter/StemmerFactory.java | 11 +- .../sasi/analyzer/filter/StopWordFactory.java | 22 +- .../cassandra/metrics/HintedHandoffMetrics.java | 33 ++- .../cassandra/net/RateBasedBackPressure.java | 66 +++--- .../cassandra/security/CipherFactory.java | 41 ++-- .../apache/cassandra/service/CacheService.java | 4 +- .../cassandra/cache/CacheProviderTest.java | 38 ++-- 21 files changed, 571 insertions(+), 822 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index ba0e3f1..977e189 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 4.0 + * Use Caffeine (W-TinyLFU) for on-heap caches (CASSANDRA-10855) * Thrift removal (CASSANDRA-11115) * Remove pre-3.0 compatibility code for 4.0 (CASSANDRA-12716) * Add column definition kind to dropped columns in schema (CASSANDRA-12705) http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/build.xml ---------------------------------------------------------------------- diff --git a/build.xml b/build.xml index 06a7938..0bbb457 100644 --- a/build.xml +++ b/build.xml @@ -66,10 +66,10 @@ <property name="tmp.dir" value="${java.io.tmpdir}"/> <property name="doc.dir" value="${basedir}/doc"/> - + <property name="source.version" value="1.8"/> <property name="target.version" value="1.8"/> - + <condition property="version" value="${base.version}"> <isset property="release"/> </condition> @@ -77,7 +77,7 @@ <property name="version.properties.dir" value="${build.src.resources}/org/apache/cassandra/config/" /> <property name="final.name" value="${ant.project.name}-${version}"/> - + <!-- details of what version of Maven ANT Tasks to fetch --> <property name="maven-ant-tasks.version" value="2.1.3" /> <property name="maven-ant-tasks.local" value="${user.home}/.m2/repository/org/apache/maven/maven-ant-tasks"/> @@ -103,7 +103,7 @@ <!-- skip flushing schema tables during tests --> <property name="cassandra.test.flush_local_schema_changes" value="false" /> - + <!-- http://www.eclemma.org/jacoco/ --> <property name="jacoco.export.dir" value="${build.dir}/jacoco/" /> <property name="jacoco.partials.dir" value="${jacoco.export.dir}/partials" /> @@ -216,7 +216,7 @@ </srcfiles> </uptodate> </target> - + <target name="gen-cql3-grammar" depends="check-gen-cql3-grammar" unless="cql3current"> <echo>Building Grammar ${build.src.antlr}/Cql.g ...</echo> <java classname="org.antlr.Tool" @@ -364,7 +364,6 @@ <dependency groupId="commons-codec" artifactId="commons-codec" version="1.9"/> <dependency groupId="org.apache.commons" artifactId="commons-lang3" version="3.1"/> <dependency groupId="org.apache.commons" artifactId="commons-math3" version="3.2"/> - <dependency groupId="com.googlecode.concurrentlinkedhashmap" artifactId="concurrentlinkedhashmap-lru" version="1.4"/> <dependency groupId="org.antlr" artifactId="antlr" version="3.5.2"> <exclusion groupId="org.antlr" artifactId="stringtemplate"/> </dependency> @@ -381,7 +380,7 @@ <dependency groupId="com.googlecode.json-simple" artifactId="json-simple" version="1.1"/> <dependency groupId="com.boundary" artifactId="high-scale-lib" version="1.0.6"/> <dependency groupId="com.github.jbellis" artifactId="jamm" version="0.3.0"/> - + <dependency groupId="org.yaml" artifactId="snakeyaml" version="1.11"/> <dependency groupId="junit" artifactId="junit" version="4.6" /> <dependency groupId="org.apache.rat" artifactId="apache-rat" version="0.10"> @@ -437,7 +436,7 @@ <dependency groupId="de.jflex" artifactId="jflex" version="1.6.0" /> <dependency groupId="com.github.rholder" artifactId="snowball-stemmer" version="1.3.0.581.1" /> <dependency groupId="com.googlecode.concurrent-trees" artifactId="concurrent-trees" version="2.4.0" /> - <dependency groupId="com.github.ben-manes.caffeine" artifactId="caffeine" version="2.2.6" /> + <dependency groupId="com.github.ben-manes.caffeine" artifactId="caffeine" version="2.3.5" /> <dependency groupId="org.jctools" artifactId="jctools-core" version="1.2.1"/> </dependencyManagement> <developer id="alakshman" name="Avinash Lakshman"/> @@ -557,7 +556,6 @@ <dependency groupId="commons-codec" artifactId="commons-codec"/> <dependency groupId="org.apache.commons" artifactId="commons-lang3"/> <dependency groupId="org.apache.commons" artifactId="commons-math3"/> - <dependency groupId="com.googlecode.concurrentlinkedhashmap" artifactId="concurrentlinkedhashmap-lru"/> <dependency groupId="org.antlr" artifactId="antlr"/> <dependency groupId="org.antlr" artifactId="antlr-runtime"/> <dependency groupId="org.slf4j" artifactId="slf4j-api"/> @@ -663,8 +661,8 @@ <target name="maven-ant-tasks-retrieve-test" depends="maven-ant-tasks-init"> <artifact:dependencies pomRefId="test-deps-pom" filesetId="test-dependency-jars" - sourcesFilesetId="test-dependency-sources" - cacheDependencyRefs="true" + sourcesFilesetId="test-dependency-sources" + cacheDependencyRefs="true" dependencyRefsBuildFile="${build.dir}/test-dependencies.xml"> <remoteRepository refid="apache"/> <remoteRepository refid="central"/> @@ -790,7 +788,7 @@ <target name="write-poms" unless="without.maven"> <antcall target="_write-poms" /> </target> - + <!-- The jar target makes cassandra.jar output. --> @@ -848,7 +846,7 @@ <jar jarfile="${build.dir}/${final.name}-javadoc.jar" basedir="${javadoc.jars.dir}/main"/> - <!-- javadoc task always rebuilds so might as well remove the generated docs to prevent + <!-- javadoc task always rebuilds so might as well remove the generated docs to prevent being pulled into the distribution by accident --> <delete quiet="true" dir="${javadoc.jars.dir}"/> </target> @@ -925,7 +923,7 @@ <include name="*.jar" /> </fileset> </copy> - <artifact:writepom pomRefId="dist-pom" + <artifact:writepom pomRefId="dist-pom" file="${build.dir}/${final.name}-dist.pom"/> <tar compression="gzip" longfile="gnu" destfile="${build.dir}/${final.name}-bin.tar.gz"> @@ -1040,7 +1038,7 @@ debuglevel="${debuglevel}" destdir="${test.classes}" includeantruntime="false" - source="${source.version}" + source="${source.version}" target="${target.version}" encoding="utf-8"> <classpath> @@ -1149,7 +1147,7 @@ </testmacro> <fileset dir="${test.unit.src}" /> </target> - + <!-- Will not generate a junit report or fail on error since it is called in parallel for test-compression That is taken care of by testparallel --> <macrodef name="testlist"> @@ -1235,7 +1233,7 @@ <jvmarg value="-Dcassandra.skip_sync=true" /> </testmacro> </target> - + <target name="test-compression" depends="build-test" description="Execute unit tests with sstable compression enabled"> <property name="compressed_yaml" value="${build.test.dir}/cassandra.compressed.yaml"/> <concat destfile="${compressed_yaml}"> @@ -1273,7 +1271,7 @@ <testmacro inputdir="${test.unit.src}" timeout="${test.timeout}" filter="**/SerializationsTest.java"/> </target> - + <target name="msg-ser-test-7" depends="build-test" description="Generates message serializations"> <testmacro inputdir="${test.unit.src}" timeout="${test.timeout}" filter="**/SerializationsTest.java"> @@ -1372,10 +1370,10 @@ </sequential> </target> - <target name="test-all" + <target name="test-all" depends="eclipse-warnings,test,long-test,test-compression,stress-test" description="Run all tests except for those under test-burn" /> - + <!-- Use JaCoCo ant extension without needing externally saved lib --> <target name="jacoco-init" depends="maven-ant-tasks-init"> <artifact:dependencies pathId="jacocoant.classpath"> @@ -1431,7 +1429,7 @@ </target> <target name="rat-check" depends="rat-init"> - <rat:report xmlns:rat="antlib:org.apache.rat.anttasks" + <rat:report xmlns:rat="antlib:org.apache.rat.anttasks" reportFile="${build.dir}/rat-report.log"> <fileset dir="." excludesfile=".rat-excludes" /> </rat:report> @@ -1648,7 +1646,7 @@ <classpathentry kind="lib" path="test/conf"/> <classpathentry kind="lib" path="${java.home}/../lib/tools.jar"/> ]]> - </echo> + </echo> <path id="eclipse-project-libs-path"> <fileset dir="lib"> <include name="**/*.jar" /> @@ -1662,27 +1660,27 @@ var File = java.io.File; var FilenameUtils = Packages.org.apache.commons.io.FilenameUtils; jars = project.getProperty("eclipse-project-libs").split(project.getProperty("path.separator")); - + cp = ""; for (i=0; i< jars.length; i++) { srcjar = FilenameUtils.getBaseName(jars[i]) + '-sources.jar'; srcdir = FilenameUtils.concat(project.getProperty("build.dir.lib"), 'sources'); srcfile = new File(FilenameUtils.concat(srcdir, srcjar)); - + cp += ' <classpathentry kind="lib" path="' + jars[i] + '"'; if (srcfile.exists()) { cp += ' sourcepath="' + srcfile.getAbsolutePath() + '"'; } cp += '/>\n'; } - + cp += '</classpath>'; - + echo = project.createTask("echo"); echo.setMessage(cp); echo.setFile(new File(".classpath")); echo.setAppend(true); - echo.perform(); + echo.perform(); ]]> </script> <mkdir dir=".settings" /> </target> @@ -1702,29 +1700,29 @@ </target> - <target name="eclipse-warnings" depends="build" description="Run eclipse compiler code analysis"> + <target name="eclipse-warnings" depends="build" description="Run eclipse compiler code analysis"> <property name="ecj.log.dir" value="${build.dir}/ecj" /> <property name="ecj.warnings.file" value="${ecj.log.dir}/eclipse_compiler_checks.txt"/> <mkdir dir="${ecj.log.dir}" /> - <property name="ecj.properties" value="${basedir}/eclipse_compiler.properties" /> + <property name="ecj.properties" value="${basedir}/eclipse_compiler.properties" /> + + <echo message="Running Eclipse Code Analysis. Output logged to ${ecj.warnings.file}" /> - <echo message="Running Eclipse Code Analysis. Output logged to ${ecj.warnings.file}" /> - - <java + <java jar="${build.dir.lib}/jars/ecj-${ecj.version}.jar" fork="true" failonerror="true" - maxmemory="512m"> + maxmemory="512m"> <arg value="-source"/> - <arg value="${source.version}" /> + <arg value="${source.version}" /> <arg value="-target"/> - <arg value="${target.version}" /> + <arg value="${target.version}" /> <arg value="-d" /> <arg value="none" /> - <arg value="-proc:none" /> + <arg value="-proc:none" /> <arg value="-log" /> - <arg value="${ecj.warnings.file}" /> + <arg value="${ecj.warnings.file}" /> <arg value="-properties" /> <arg value="${ecj.properties}" /> <arg value="-cp" /> @@ -1732,13 +1730,13 @@ <arg value="${build.src.java}" /> </java> </target> - + <!-- Publish artifacts to Maven repositories --> <target name="mvn-install" depends="maven-declare-dependencies,artifacts,jar,sources-jar,javadoc-jar" description="Installs the artifacts in the Maven Local Repository"> - + <!-- the parent --> <install pomFile="${build.dir}/${final.name}-parent.pom" file="${build.dir}/${final.name}-parent.pom" @@ -1756,7 +1754,7 @@ file="${build.dir}/${final.name}-src.tar.gz" packaging="tar.gz" classifier="src"/> - + <!-- the cassandra-all jar --> <install pomFile="${build.dir}/${final.name}.pom" file="${build.dir}/${final.name}.jar"/> @@ -1772,7 +1770,7 @@ depends="mvn-install" if="release" description="Publishes the artifacts to the Maven repository"> - + <!-- the parent --> <deploy pomFile="${build.dir}/${final.name}-parent.pom" file="${build.dir}/${final.name}-parent.pom" @@ -1790,7 +1788,7 @@ file="${build.dir}/${final.name}-src.tar.gz" packaging="tar.gz" classifier="src"/> - + <!-- the cassandra-all jar --> <deploy pomFile="${build.dir}/${final.name}.pom" file="${build.dir}/${final.name}.jar"/> http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/lib/caffeine-2.2.6.jar ---------------------------------------------------------------------- diff --git a/lib/caffeine-2.2.6.jar b/lib/caffeine-2.2.6.jar deleted file mode 100644 index 74b91bc..0000000 Binary files a/lib/caffeine-2.2.6.jar and /dev/null differ http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/lib/caffeine-2.3.5.jar ---------------------------------------------------------------------- diff --git a/lib/caffeine-2.3.5.jar b/lib/caffeine-2.3.5.jar new file mode 100644 index 0000000..70cf178 Binary files /dev/null and b/lib/caffeine-2.3.5.jar differ http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/lib/concurrentlinkedhashmap-lru-1.4.jar ---------------------------------------------------------------------- diff --git a/lib/concurrentlinkedhashmap-lru-1.4.jar b/lib/concurrentlinkedhashmap-lru-1.4.jar deleted file mode 100644 index 572b258..0000000 Binary files a/lib/concurrentlinkedhashmap-lru-1.4.jar and /dev/null differ http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/lib/licenses/caffeine-2.2.6.txt ---------------------------------------------------------------------- diff --git a/lib/licenses/caffeine-2.2.6.txt b/lib/licenses/caffeine-2.2.6.txt deleted file mode 100644 index d645695..0000000 --- a/lib/licenses/caffeine-2.2.6.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/lib/licenses/caffeine-2.3.5.txt ---------------------------------------------------------------------- diff --git a/lib/licenses/caffeine-2.3.5.txt b/lib/licenses/caffeine-2.3.5.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/lib/licenses/caffeine-2.3.5.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/lib/licenses/concurrentlinkedhashmap-lru-1.4.txt ---------------------------------------------------------------------- diff --git a/lib/licenses/concurrentlinkedhashmap-lru-1.4.txt b/lib/licenses/concurrentlinkedhashmap-lru-1.4.txt deleted file mode 100644 index d645695..0000000 --- a/lib/licenses/concurrentlinkedhashmap-lru-1.4.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/src/java/org/apache/cassandra/auth/AuthCache.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/auth/AuthCache.java b/src/java/org/apache/cassandra/auth/AuthCache.java index 0d2a01e..87fe564 100644 --- a/src/java/org/apache/cassandra/auth/AuthCache.java +++ b/src/java/org/apache/cassandra/auth/AuthCache.java @@ -20,7 +20,6 @@ package org.apache.cassandra.auth; import java.lang.management.ManagementFactory; import java.util.concurrent.ExecutionException; -import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; @@ -29,16 +28,13 @@ import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListenableFutureTask; +import com.google.common.util.concurrent.MoreExecutors; + +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.cassandra.concurrent.DebuggableThreadPoolExecutor; - public class AuthCache<K, V> implements AuthCacheMBean { private static final Logger logger = LoggerFactory.getLogger(AuthCache.class); @@ -46,7 +42,6 @@ public class AuthCache<K, V> implements AuthCacheMBean private static final String MBEAN_NAME_BASE = "org.apache.cassandra.auth:type="; private volatile LoadingCache<K, V> cache; - private ThreadPoolExecutor cacheRefreshExecutor; private final String name; private final Consumer<Integer> setValidityDelegate; @@ -82,7 +77,6 @@ public class AuthCache<K, V> implements AuthCacheMBean protected void init() { - this.cacheRefreshExecutor = new DebuggableThreadPoolExecutor(name + "Refresh", Thread.NORM_PRIORITY); this.cache = initCache(null); try { @@ -172,36 +166,22 @@ public class AuthCache<K, V> implements AuthCacheMBean logger.info("(Re)initializing {} (validity period/update interval/max entries) ({}/{}/{})", name, getValidity(), getUpdateInterval(), getMaxEntries()); - LoadingCache<K, V> newcache = CacheBuilder.newBuilder() - .refreshAfterWrite(getUpdateInterval(), TimeUnit.MILLISECONDS) - .expireAfterWrite(getValidity(), TimeUnit.MILLISECONDS) - .maximumSize(getMaxEntries()) - .build(new CacheLoader<K, V>() - { - public V load(K k) - { - return loadFunction.apply(k); - } - - public ListenableFuture<V> reload(final K k, final V oldV) - { - ListenableFutureTask<V> task = ListenableFutureTask.create(() -> { - try - { - return loadFunction.apply(k); - } - catch (Exception e) - { - logger.trace("Error performing async refresh of auth data in {}", name, e); - throw e; - } - }); - cacheRefreshExecutor.execute(task); - return task; - } - }); - if (existing != null) - newcache.putAll(existing.asMap()); - return newcache; + if (existing == null) { + return Caffeine.newBuilder() + .refreshAfterWrite(getUpdateInterval(), TimeUnit.MILLISECONDS) + .expireAfterWrite(getValidity(), TimeUnit.MILLISECONDS) + .maximumSize(getMaxEntries()) + .executor(MoreExecutors.directExecutor()) + .build(loadFunction::apply); + } + + // Always set as manditory + cache.policy().refreshAfterWrite().ifPresent(policy -> + policy.setExpiresAfter(getUpdateInterval(), TimeUnit.MILLISECONDS)); + cache.policy().expireAfterWrite().ifPresent(policy -> + policy.setExpiresAfter(getValidity(), TimeUnit.MILLISECONDS)); + cache.policy().eviction().ifPresent(policy -> + policy.setMaximum(getMaxEntries())); + return cache; } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/src/java/org/apache/cassandra/auth/PasswordAuthenticator.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/auth/PasswordAuthenticator.java b/src/java/org/apache/cassandra/auth/PasswordAuthenticator.java index 4b667ae..b1b0536 100644 --- a/src/java/org/apache/cassandra/auth/PasswordAuthenticator.java +++ b/src/java/org/apache/cassandra/auth/PasswordAuthenticator.java @@ -26,7 +26,6 @@ import java.util.concurrent.ExecutionException; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; -import com.google.common.util.concurrent.UncheckedExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -92,24 +91,13 @@ public class PasswordAuthenticator implements IAuthenticator return new AuthenticatedUser(username); } - catch (ExecutionException | UncheckedExecutionException e) + catch (ExecutionException e) { - // the credentials were somehow invalid - either a non-existent role, or one without a defined password - if (e.getCause() instanceof NoSuchCredentialsException) - throw new AuthenticationException(String.format("Provided username %s and/or password are incorrect", username)); - - // an unanticipated exception occured whilst querying the credentials table - if (e.getCause() instanceof RequestExecutionException) - { - logger.trace("Error performing internal authentication", e); - throw new AuthenticationException(String.format("Error during authentication of user %s : %s", username, e.getMessage())); - } - throw new RuntimeException(e); } } - private String queryHashedPassword(String username) throws NoSuchCredentialsException + private String queryHashedPassword(String username) { try { @@ -125,18 +113,17 @@ public class PasswordAuthenticator implements IAuthenticator // were found for that role we don't want to cache the result so we throw // a specific, but unchecked, exception to keep LoadingCache happy. if (rows.result.isEmpty()) - throw new NoSuchCredentialsException(); + throw new AuthenticationException(String.format("Provided username %s and/or password are incorrect", username)); UntypedResultSet result = UntypedResultSet.create(rows.result); if (!result.one().has(SALTED_HASH)) - throw new NoSuchCredentialsException(); + throw new AuthenticationException(String.format("Provided username %s and/or password are incorrect", username)); return result.one().getString(SALTED_HASH); } catch (RequestExecutionException e) { - logger.trace("Error performing internal authentication", e); - throw e; + throw new AuthenticationException(String.format("Error performing internal authentication of user %s : %s", username, e.getMessage())); } } @@ -305,10 +292,4 @@ public class PasswordAuthenticator implements IAuthenticator { public void invalidateCredentials(String roleName); } - - // Just a marker so we can identify that invalid credentials were the - // cause of a loading exception from the cache - private static final class NoSuchCredentialsException extends RuntimeException - { - } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/src/java/org/apache/cassandra/cache/CaffeineCache.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cache/CaffeineCache.java b/src/java/org/apache/cassandra/cache/CaffeineCache.java new file mode 100644 index 0000000..d51ea84 --- /dev/null +++ b/src/java/org/apache/cassandra/cache/CaffeineCache.java @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cassandra.cache; + +import static com.google.common.base.Preconditions.checkState; + +import java.util.Iterator; + +import com.google.common.util.concurrent.MoreExecutors; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.Policy.Eviction; +import com.github.benmanes.caffeine.cache.Weigher; + +/** + * An adapter from a Caffeine cache to the ICache interface. This provides an on-heap cache using + * the W-TinyLFU eviction policy (http://arxiv.org/pdf/1512.00727.pdf), which has a higher hit rate + * than an LRU. + */ +public class CaffeineCache<K extends IMeasurableMemory, V extends IMeasurableMemory> implements ICache<K, V> +{ + private final Cache<K, V> cache; + private final Eviction<K, V> policy; + + private CaffeineCache(Cache<K, V> cache) + { + this.cache = cache; + this.policy = cache.policy().eviction().orElseThrow(() -> + new IllegalArgumentException("Expected a size bounded cache")); + checkState(policy.isWeighted(), "Expected a weighted cache"); + } + + /** + * Initialize a cache with initial capacity with weightedCapacity + */ + public static <K extends IMeasurableMemory, V extends IMeasurableMemory> CaffeineCache<K, V> create(long weightedCapacity, Weigher<K, V> weigher) + { + Cache<K, V> cache = Caffeine.newBuilder() + .maximumWeight(weightedCapacity) + .weigher(weigher) + .executor(MoreExecutors.directExecutor()) + .build(); + return new CaffeineCache<>(cache); + } + + public static <K extends IMeasurableMemory, V extends IMeasurableMemory> CaffeineCache<K, V> create(long weightedCapacity) + { + return create(weightedCapacity, (key, value) -> { + long size = key.unsharedHeapSize() + value.unsharedHeapSize(); + if (size > Integer.MAX_VALUE) { + throw new IllegalArgumentException("Serialized size cannot be more than 2GB/Integer.MAX_VALUE"); + } + return (int) size; + }); + } + + public long capacity() + { + return policy.getMaximum(); + } + + public void setCapacity(long capacity) + { + policy.setMaximum(capacity); + } + + public boolean isEmpty() + { + return cache.asMap().isEmpty(); + } + + public int size() + { + return cache.asMap().size(); + } + + public long weightedSize() + { + return policy.weightedSize().getAsLong(); + } + + public void clear() + { + cache.invalidateAll(); + } + + public V get(K key) + { + return cache.getIfPresent(key); + } + + public void put(K key, V value) + { + cache.put(key, value); + } + + public boolean putIfAbsent(K key, V value) + { + return cache.asMap().putIfAbsent(key, value) == null; + } + + public boolean replace(K key, V old, V value) + { + return cache.asMap().replace(key, old, value); + } + + public void remove(K key) + { + cache.invalidate(key); + } + + public Iterator<K> keyIterator() + { + return cache.asMap().keySet().iterator(); + } + + public Iterator<K> hotKeyIterator(int n) + { + return policy.hottest(n).keySet().iterator(); + } + + public boolean containsKey(K key) + { + return cache.asMap().containsKey(key); + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/src/java/org/apache/cassandra/cache/ConcurrentLinkedHashCache.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cache/ConcurrentLinkedHashCache.java b/src/java/org/apache/cassandra/cache/ConcurrentLinkedHashCache.java deleted file mode 100644 index bb14055..0000000 --- a/src/java/org/apache/cassandra/cache/ConcurrentLinkedHashCache.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.cassandra.cache; - -import java.util.Iterator; - -import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; -import com.googlecode.concurrentlinkedhashmap.EntryWeigher; - -/** Wrapper so CLHM can implement ICache interface. - * (this is what you get for making library classes final.) */ -public class ConcurrentLinkedHashCache<K extends IMeasurableMemory, V extends IMeasurableMemory> implements ICache<K, V> -{ - public static final int DEFAULT_CONCURENCY_LEVEL = 64; - private final ConcurrentLinkedHashMap<K, V> map; - - private ConcurrentLinkedHashCache(ConcurrentLinkedHashMap<K, V> map) - { - this.map = map; - } - - /** - * Initialize a cache with initial capacity with weightedCapacity - */ - public static <K extends IMeasurableMemory, V extends IMeasurableMemory> ConcurrentLinkedHashCache<K, V> create(long weightedCapacity, EntryWeigher<K, V> entryWeiger) - { - ConcurrentLinkedHashMap<K, V> map = new ConcurrentLinkedHashMap.Builder<K, V>() - .weigher(entryWeiger) - .maximumWeightedCapacity(weightedCapacity) - .concurrencyLevel(DEFAULT_CONCURENCY_LEVEL) - .build(); - - return new ConcurrentLinkedHashCache<>(map); - } - - public static <K extends IMeasurableMemory, V extends IMeasurableMemory> ConcurrentLinkedHashCache<K, V> create(long weightedCapacity) - { - return create(weightedCapacity, new EntryWeigher<K, V>() - { - public int weightOf(K key, V value) - { - long size = key.unsharedHeapSize() + value.unsharedHeapSize(); - assert size <= Integer.MAX_VALUE : "Serialized size cannot be more than 2GB/Integer.MAX_VALUE"; - return (int) size; - } - }); - } - - public long capacity() - { - return map.capacity(); - } - - public void setCapacity(long capacity) - { - map.setCapacity(capacity); - } - - public boolean isEmpty() - { - return map.isEmpty(); - } - - public int size() - { - return map.size(); - } - - public long weightedSize() - { - return map.weightedSize(); - } - - public void clear() - { - map.clear(); - } - - public V get(K key) - { - return map.get(key); - } - - public void put(K key, V value) - { - map.put(key, value); - } - - public boolean putIfAbsent(K key, V value) - { - return map.putIfAbsent(key, value) == null; - } - - public boolean replace(K key, V old, V value) - { - return map.replace(key, old, value); - } - - public void remove(K key) - { - map.remove(key); - } - - public Iterator<K> keyIterator() - { - return map.keySet().iterator(); - } - - public Iterator<K> hotKeyIterator(int n) - { - return map.descendingKeySetWithLimit(n).iterator(); - } - - public boolean containsKey(K key) - { - return map.containsKey(key); - } -} http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/src/java/org/apache/cassandra/cache/SerializingCache.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cache/SerializingCache.java b/src/java/org/apache/cassandra/cache/SerializingCache.java index 0ece686..320bb15 100644 --- a/src/java/org/apache/cassandra/cache/SerializingCache.java +++ b/src/java/org/apache/cassandra/cache/SerializingCache.java @@ -17,21 +17,22 @@ */ package org.apache.cassandra.cache; -import java.io.IOException; -import java.util.Iterator; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; -import com.googlecode.concurrentlinkedhashmap.EvictionListener; -import com.googlecode.concurrentlinkedhashmap.Weigher; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.Weigher; import org.apache.cassandra.io.ISerializer; import org.apache.cassandra.io.util.MemoryInputStream; import org.apache.cassandra.io.util.MemoryOutputStream; import org.apache.cassandra.io.util.WrappedDataOutputStreamPlus; import org.apache.cassandra.utils.FBUtilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.Iterator; + +import com.google.common.util.concurrent.MoreExecutors; /** * Serializes cache values off-heap. @@ -40,46 +41,38 @@ public class SerializingCache<K, V> implements ICache<K, V> { private static final Logger logger = LoggerFactory.getLogger(SerializingCache.class); - private static final int DEFAULT_CONCURENCY_LEVEL = 64; - - private final ConcurrentLinkedHashMap<K, RefCountedMemory> map; + private final Cache<K, RefCountedMemory> cache; private final ISerializer<V> serializer; - private SerializingCache(long capacity, Weigher<RefCountedMemory> weigher, ISerializer<V> serializer) + private SerializingCache(long capacity, Weigher<K, RefCountedMemory> weigher, ISerializer<V> serializer) { this.serializer = serializer; - EvictionListener<K,RefCountedMemory> listener = new EvictionListener<K, RefCountedMemory>() - { - public void onEviction(K k, RefCountedMemory mem) - { - mem.unreference(); - } - }; - - this.map = new ConcurrentLinkedHashMap.Builder<K, RefCountedMemory>() + this.cache = Caffeine.newBuilder() .weigher(weigher) - .maximumWeightedCapacity(capacity) - .concurrencyLevel(DEFAULT_CONCURENCY_LEVEL) - .listener(listener) + .maximumWeight(capacity) + .executor(MoreExecutors.directExecutor()) + .removalListener((key, mem, cause) -> { + if (cause.wasEvicted()) { + mem.unreference(); + } + }) .build(); } - public static <K, V> SerializingCache<K, V> create(long weightedCapacity, Weigher<RefCountedMemory> weigher, ISerializer<V> serializer) + public static <K, V> SerializingCache<K, V> create(long weightedCapacity, Weigher<K, RefCountedMemory> weigher, ISerializer<V> serializer) { return new SerializingCache<>(weightedCapacity, weigher, serializer); } public static <K, V> SerializingCache<K, V> create(long weightedCapacity, ISerializer<V> serializer) { - return create(weightedCapacity, new Weigher<RefCountedMemory>() - { - public int weightOf(RefCountedMemory value) - { - long size = value.size(); - assert size < Integer.MAX_VALUE : "Serialized size cannot be more than 2GB"; - return (int) size; + return create(weightedCapacity, (key, value) -> { + long size = value.size(); + if (size > Integer.MAX_VALUE) { + throw new IllegalArgumentException("Serialized size must not be more than 2GB"); } + return (int) size; }, serializer); } @@ -126,38 +119,38 @@ public class SerializingCache<K, V> implements ICache<K, V> public long capacity() { - return map.capacity(); + return cache.policy().eviction().get().getMaximum(); } public void setCapacity(long capacity) { - map.setCapacity(capacity); + cache.policy().eviction().get().setMaximum(capacity); } public boolean isEmpty() { - return map.isEmpty(); + return cache.asMap().isEmpty(); } public int size() { - return map.size(); + return cache.asMap().size(); } public long weightedSize() { - return map.weightedSize(); + return cache.policy().eviction().get().weightedSize().getAsLong(); } public void clear() { - map.clear(); + cache.invalidateAll(); } @SuppressWarnings("resource") public V get(K key) { - RefCountedMemory mem = map.get(key); + RefCountedMemory mem = cache.getIfPresent(key); if (mem == null) return null; if (!mem.reference()) @@ -182,7 +175,7 @@ public class SerializingCache<K, V> implements ICache<K, V> RefCountedMemory old; try { - old = map.put(key, mem); + old = cache.asMap().put(key, mem); } catch (Throwable t) { @@ -204,7 +197,7 @@ public class SerializingCache<K, V> implements ICache<K, V> RefCountedMemory old; try { - old = map.putIfAbsent(key, mem); + old = cache.asMap().putIfAbsent(key, mem); } catch (Throwable t) { @@ -221,8 +214,8 @@ public class SerializingCache<K, V> implements ICache<K, V> @SuppressWarnings("resource") public boolean replace(K key, V oldToReplace, V value) { - // if there is no old value in our map, we fail - RefCountedMemory old = map.get(key); + // if there is no old value in our cache, we fail + RefCountedMemory old = cache.getIfPresent(key); if (old == null) return false; @@ -245,7 +238,7 @@ public class SerializingCache<K, V> implements ICache<K, V> boolean success; try { - success = map.replace(key, old, mem); + success = cache.asMap().replace(key, old, mem); } catch (Throwable t) { @@ -263,23 +256,23 @@ public class SerializingCache<K, V> implements ICache<K, V> public void remove(K key) { @SuppressWarnings("resource") - RefCountedMemory mem = map.remove(key); + RefCountedMemory mem = cache.asMap().remove(key); if (mem != null) mem.unreference(); } public Iterator<K> keyIterator() { - return map.keySet().iterator(); + return cache.asMap().keySet().iterator(); } public Iterator<K> hotKeyIterator(int n) { - return map.descendingKeySetWithLimit(n).iterator(); + return cache.policy().eviction().get().hottest(n).keySet().iterator(); } public boolean containsKey(K key) { - return map.containsKey(key); + return cache.asMap().containsKey(key); } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/src/java/org/apache/cassandra/cql3/QueryProcessor.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/QueryProcessor.java b/src/java/org/apache/cassandra/cql3/QueryProcessor.java index 354ee72..6fa97a6 100644 --- a/src/java/org/apache/cassandra/cql3/QueryProcessor.java +++ b/src/java/org/apache/cassandra/cql3/QueryProcessor.java @@ -24,15 +24,18 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.RemovalCause; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Iterators; import com.google.common.primitives.Ints; +import com.google.common.util.concurrent.MoreExecutors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; import org.antlr.runtime.*; import org.apache.cassandra.concurrent.ScheduledExecutors; import org.apache.cassandra.config.DatabaseDescriptor; @@ -65,7 +68,7 @@ public class QueryProcessor implements QueryHandler private static final Logger logger = LoggerFactory.getLogger(QueryProcessor.class); - private static final ConcurrentLinkedHashMap<MD5Digest, ParsedStatement.Prepared> preparedStatements; + private static final Cache<MD5Digest, ParsedStatement.Prepared> preparedStatements; // A map for prepared statements used internally (which we don't want to mix with user statement, in particular we don't // bother with expiration on those. @@ -79,12 +82,15 @@ public class QueryProcessor implements QueryHandler static { - preparedStatements = new ConcurrentLinkedHashMap.Builder<MD5Digest, ParsedStatement.Prepared>() - .maximumWeightedCapacity(capacityToBytes(DatabaseDescriptor.getPreparedStatementsCacheSizeMB())) + preparedStatements = Caffeine.newBuilder() + .executor(MoreExecutors.directExecutor()) + .maximumWeight(capacityToBytes(DatabaseDescriptor.getPreparedStatementsCacheSizeMB())) .weigher(QueryProcessor::measure) - .listener((md5Digest, prepared) -> { - metrics.preparedStatementsEvicted.inc(); - lastMinuteEvictionsCount.incrementAndGet(); + .removalListener((md5Digest, prepared, cause) -> { + if (cause == RemovalCause.SIZE) { + metrics.preparedStatementsEvicted.inc(); + lastMinuteEvictionsCount.incrementAndGet(); + } }).build(); ScheduledExecutors.scheduledTasks.scheduleAtFixedRate(() -> { @@ -106,7 +112,7 @@ public class QueryProcessor implements QueryHandler public static int preparedStatementsCount() { - return preparedStatements.size(); + return preparedStatements.asMap().size(); } // Work around initialization dependency @@ -147,7 +153,7 @@ public class QueryProcessor implements QueryHandler @VisibleForTesting public static void clearPrepraredStatements() { - preparedStatements.clear(); + preparedStatements.invalidateAll();; } private static QueryState internalQueryState() @@ -162,7 +168,7 @@ public class QueryProcessor implements QueryHandler public ParsedStatement.Prepared getPrepared(MD5Digest id) { - return preparedStatements.get(id); + return preparedStatements.getIfPresent(id); } public static void validateKey(ByteBuffer key) throws InvalidRequestException @@ -405,7 +411,7 @@ public class QueryProcessor implements QueryHandler throws InvalidRequestException { MD5Digest statementId = computeId(queryString, keyspace); - ParsedStatement.Prepared existing = preparedStatements.get(statementId); + ParsedStatement.Prepared existing = preparedStatements.getIfPresent(statementId); if (existing == null) return null; @@ -558,14 +564,14 @@ public class QueryProcessor implements QueryHandler private static void removeInvalidPreparedStatements(String ksName, String cfName) { removeInvalidPreparedStatements(internalStatements.values().iterator(), ksName, cfName); - removeInvalidPersistentPreparedStatements(preparedStatements.entrySet().iterator(), ksName, cfName); + removeInvalidPersistentPreparedStatements(preparedStatements.asMap().entrySet().iterator(), ksName, cfName); } private static void removeInvalidPreparedStatementsForFunction(String ksName, String functionName) { Predicate<Function> matchesFunction = f -> ksName.equals(f.name().keyspace) && functionName.equals(f.name().name); - for (Iterator<Map.Entry<MD5Digest, ParsedStatement.Prepared>> iter = preparedStatements.entrySet().iterator(); + for (Iterator<Map.Entry<MD5Digest, ParsedStatement.Prepared>> iter = preparedStatements.asMap().entrySet().iterator(); iter.hasNext();) { Map.Entry<MD5Digest, ParsedStatement.Prepared> pstmt = iter.next(); http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/src/java/org/apache/cassandra/index/sasi/analyzer/filter/StemmerFactory.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/index/sasi/analyzer/filter/StemmerFactory.java b/src/java/org/apache/cassandra/index/sasi/analyzer/filter/StemmerFactory.java index ae232db..d278c28 100644 --- a/src/java/org/apache/cassandra/index/sasi/analyzer/filter/StemmerFactory.java +++ b/src/java/org/apache/cassandra/index/sasi/analyzer/filter/StemmerFactory.java @@ -22,12 +22,14 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; +import com.google.common.util.concurrent.MoreExecutors; + import org.tartarus.snowball.SnowballStemmer; import org.tartarus.snowball.ext.*; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; +import com.github.benmanes.caffeine.cache.CacheLoader; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,7 +41,8 @@ import org.slf4j.LoggerFactory; public class StemmerFactory { private static final Logger logger = LoggerFactory.getLogger(StemmerFactory.class); - private static final LoadingCache<Class, Constructor<?>> STEMMER_CONSTRUCTOR_CACHE = CacheBuilder.newBuilder() + private static final LoadingCache<Class, Constructor<?>> STEMMER_CONSTRUCTOR_CACHE = Caffeine.newBuilder() + .executor(MoreExecutors.directExecutor()) .build(new CacheLoader<Class, Constructor<?>>() { public Constructor<?> load(Class aClass) throws Exception http://git-wip-us.apache.org/repos/asf/cassandra/blob/c607d764/src/java/org/apache/cassandra/index/sasi/analyzer/filter/StopWordFactory.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/index/sasi/analyzer/filter/StopWordFactory.java b/src/java/org/apache/cassandra/index/sasi/analyzer/filter/StopWordFactory.java index 8ec02e0..1548a6a 100644 --- a/src/java/org/apache/cassandra/index/sasi/analyzer/filter/StopWordFactory.java +++ b/src/java/org/apache/cassandra/index/sasi/analyzer/filter/StopWordFactory.java @@ -26,11 +26,12 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Locale; import java.util.Set; -import java.util.concurrent.ExecutionException; +import java.util.concurrent.CompletionException; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; +import com.google.common.util.concurrent.MoreExecutors; + +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,14 +50,9 @@ public class StopWordFactory Arrays.asList("ar","bg","cs","de","en","es","fi","fr","hi","hu","it", "pl","pt","ro","ru","sv")); - private static final LoadingCache<String, Set<String>> STOP_WORDS_CACHE = CacheBuilder.newBuilder() - .build(new CacheLoader<String, Set<String>>() - { - public Set<String> load(String s) - { - return getStopWordsFromResource(s); - } - }); + private static final LoadingCache<String, Set<String>> STOP_WORDS_CACHE = Caffeine.newBuilder() + .executor(MoreExecutors.directExecutor()) + .build(StopWordFactory::getStopWordsFromResource); public static Set<String> getStopWordsForLanguage(Locale locale) { @@ -68,7 +64,7 @@ public class StopWordFactory { return (!SUPPORTED_LANGUAGES.contains(rootLang)) ? null : STOP_WORDS_CACHE.get(rootLang); } - catch (ExecutionException e) + catch (CompletionException e) { logger.error("Failed to populate Stop Words Cache for language [{}]", locale.getLanguage(), e); return null;
