mirror of https://github.com/apache/cassandra
Add JDK21 support
Patch by Josh McKenzie; reviewed by Mick Semb Wever and Ekaterina Dimitrova for CASSANDRA-18831 Co-authored-by: Aleksey Yeschenko Co-authored-by: Achilles Benetopoulos Co-authored-by: Mick Semb Wever
This commit is contained in:
parent
4184e759de
commit
940739a488
|
|
@ -56,7 +56,8 @@ fi
|
|||
################################
|
||||
|
||||
if grep "^ID=" /etc/os-release | grep -q 'debian\|ubuntu' ; then
|
||||
sudo update-java-alternatives --set java-1.${java_version}.0-openjdk-$(dpkg --print-architecture)
|
||||
sudo update-alternatives --set java /usr/lib/jvm/java-${java_version}-openjdk-$(dpkg --print-architecture)/bin/java
|
||||
sudo update-alternatives --set javac /usr/lib/jvm/java-${java_version}-openjdk-$(dpkg --print-architecture)/bin/javac
|
||||
else
|
||||
sudo alternatives --set java $(alternatives --display java | grep "family java-${java_version}-openjdk" | cut -d' ' -f1)
|
||||
sudo alternatives --set javac $(alternatives --display javac | grep "family java-${java_version}-openjdk" | cut -d' ' -f1)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ RUN yum -y install \
|
|||
git \
|
||||
java-11-openjdk-devel \
|
||||
java-17-openjdk-devel \
|
||||
java-21-openjdk-devel \
|
||||
make \
|
||||
rpm-build \
|
||||
sudo \
|
||||
|
|
|
|||
|
|
@ -18,5 +18,5 @@
|
|||
#
|
||||
# Creates the tarball artifact
|
||||
|
||||
$(dirname -- "$0")/_docker_run.sh bullseye-build.docker build-artifacts.sh $1
|
||||
$(dirname -- "$0")/_docker_run.sh debian-build.docker build-artifacts.sh $1
|
||||
exit $?
|
||||
|
|
|
|||
|
|
@ -32,5 +32,5 @@ echo
|
|||
#
|
||||
# Creates the debian package
|
||||
|
||||
$(dirname -- "$0")/_docker_run.sh bullseye-build.docker docker/_build-debian.sh $1
|
||||
$(dirname -- "$0")/_docker_run.sh debian-build.docker docker/_build-debian.sh $1
|
||||
exit $?
|
||||
|
|
|
|||
|
|
@ -18,5 +18,5 @@
|
|||
#
|
||||
# Build the jars
|
||||
|
||||
$(dirname -- "$0")/_docker_run.sh bullseye-build.docker build-jars.sh $1
|
||||
$(dirname -- "$0")/_docker_run.sh debian-build.docker build-jars.sh $1
|
||||
exit $?
|
||||
|
|
|
|||
|
|
@ -20,4 +20,4 @@
|
|||
|
||||
export CASSANDRA_DOCKER_ANT_OPTS="-Ddependency-check.home.base=/tmp"
|
||||
|
||||
$(dirname -- "$0")/_docker_run.sh bullseye-build.docker check-code.sh $1
|
||||
$(dirname -- "$0")/_docker_run.sh debian-build.docker check-code.sh $1
|
||||
|
|
|
|||
|
|
@ -36,16 +36,31 @@ RUN echo 'Acquire::http::Timeout "60";' > /etc/apt/apt.conf.d/80proxy.conf
|
|||
RUN echo 'Acquire::ftp::Timeout "60";' >> /etc/apt/apt.conf.d/80proxy.conf
|
||||
|
||||
# install deps
|
||||
RUN until apt-get update \
|
||||
&& apt-get -y install ant build-essential curl devscripts ed git sudo \
|
||||
RUN until apt-get update && apt-get -y install ant build-essential curl devscripts ed git sudo \
|
||||
python3-pip rsync procps dh-python quilt bash-completion ; \
|
||||
do echo "apt failed… trying again in 10s… " ; sleep 10 ; done
|
||||
|
||||
RUN until apt-get update \
|
||||
&& apt-get install -y --no-install-recommends openjdk-11-jdk openjdk-17-jdk ; \
|
||||
RUN until apt-get install -y --no-install-recommends openjdk-11-jdk openjdk-17-jdk; \
|
||||
do echo "apt failed… trying again in 10s… " ; sleep 10 ; done
|
||||
|
||||
RUN update-java-alternatives --set java-1.11.0-openjdk-$(dpkg --print-architecture)
|
||||
# Download and install OpenJDK 21.0.2 for the current architecture
|
||||
RUN sh -c '\
|
||||
JDK_OS=linux ;\
|
||||
JDK_TAR="openjdk-21.0.2_${JDK_OS}-$(uname -m | sed "s/x86_64/x64/")_bin.tar.gz" ;\
|
||||
JDK_VERSION_SHAS="08db1392a48d4eb5ea5315cf8f18b89dbaf36cda663ba882cf03c704c9257ec2 a2def047a73941e01a73739f92755f86b895811afb1f91243db214cff5bdac3f 8fd09e15dc406387a0aba70bf5d99692874e999bf9cd9208b452b5d76ac922d3 b3d588e16ec1e0ef9805d8a696591bd518a5cea62567da8f53b5ce32d11d22e4" ;\
|
||||
curl -L --fail --silent --retry 2 --retry-delay 5 --max-time 3600 "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/${JDK_TAR}" -o $JDK_TAR ;\
|
||||
JDK_SHA="$(sha256sum $JDK_TAR | cut -d" " -f2)" ;\
|
||||
echo "$JDK_VERSION_SHAS" | sed "s/ /\n/g" | grep -q "$JDK_SHA" || { echo "SHA256 mismatch for $JDK_TAR $JDK_SHA"; exit 1; } ;\
|
||||
mkdir -p /usr/lib/jvm/java-21-openjdk-$(dpkg --print-architecture) ;\
|
||||
tar -C /usr/lib/jvm/java-21-openjdk-$(dpkg --print-architecture) --strip-components=1 -xzf $JDK_TAR ;\
|
||||
rm $JDK_TAR'
|
||||
|
||||
# Add OpenJDK 21 to update-alternatives
|
||||
RUN update-alternatives --install /usr/bin/java java /usr/lib/jvm/java-21-openjdk-$(dpkg --print-architecture)/bin/java 1
|
||||
RUN update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/java-21-openjdk-$(dpkg --print-architecture)/bin/javac 1
|
||||
|
||||
RUN update-alternatives --set java /usr/lib/jvm/java-11-openjdk-$(dpkg --print-architecture)/bin/java
|
||||
RUN update-alternatives --set javac /usr/lib/jvm/java-11-openjdk-$(dpkg --print-architecture)/bin/javac
|
||||
|
||||
# python3 is needed for the gen-doc target
|
||||
RUN pip install --upgrade pip
|
||||
|
|
@ -58,11 +73,8 @@ RUN sh -c '\
|
|||
GO_VERSION="1.24.3" ;\
|
||||
GO_VERSION_SHAS="3333f6ea53afa971e9078895eaa4ac7204a8c6b5c68c10e6bc9a33e8e391bdd8 a463cb59382bd7ae7d8f4c68846e73c4d589f223c589ac76871b66811ded7836 13e6fe3fcf65689d77d40e633de1e31c6febbdbcb846eb05fc2434ed2213e92b 64a3fa22142f627e78fac3018ce3d4aeace68b743eff0afda8aae0411df5e4fb" ;\
|
||||
GO_OS=linux ;\
|
||||
[ $(uname) = "Darwin" ] && GO_OS=darwin ;\
|
||||
GO_PLATFORM=amd64 ;\
|
||||
[ $(uname -m) = "aarch64" ] && GO_PLATFORM=arm64 ;\
|
||||
GO_TAR="go${GO_VERSION}.${GO_OS}-${GO_PLATFORM}.tar.gz" ;\
|
||||
curl -L --fail --silent --retry 2 --retry-delay 5 --max-time 30 https://go.dev/dl/$GO_TAR -o $GO_TAR ;\
|
||||
GO_TAR="go${GO_VERSION}.${GO_OS}-$(dpkg --print-architecture).tar.gz" ;\
|
||||
curl -L --fail --silent --retry 2 --retry-delay 5 --max-time 3600 https://go.dev/dl/$GO_TAR -o $GO_TAR ;\
|
||||
GO_SHA="$(sha256sum $GO_TAR | cut -d" " -f2)" ;\
|
||||
echo "$GO_VERSION_SHAS" | sed "s/ /\n/g" | grep -q "$GO_SHA" || { echo "SHA256 mismatch for $GO_TAR $GO_SHA"; exit 1; } ;\
|
||||
tar -C /usr/local -xzf $GO_TAR ;\
|
||||
|
|
@ -71,3 +83,10 @@ RUN sh -c '\
|
|||
ENV GOROOT="/usr/local/go"
|
||||
ENV GOPATH="$BUILD_HOME/go"
|
||||
ENV PATH="$PATH:/usr/local/go/bin"
|
||||
|
||||
# allow lower UIDs and GIDs
|
||||
RUN sed -i 's/UID_MIN 1000/UID_MIN 100/' /etc/login.defs
|
||||
RUN sed -i 's/UID_MIN 1000/UID_MIN 10/' /etc/login.defs
|
||||
|
||||
# suppress warnings about mismatching ownership
|
||||
RUN git config --global --add safe.directory ${CASSANDRA_DIR}
|
||||
|
|
@ -134,7 +134,7 @@ docker --version
|
|||
pushd ${cassandra_dir}/.build >/dev/null
|
||||
|
||||
# build test image
|
||||
dockerfile="ubuntu2004_test.docker"
|
||||
dockerfile="ubuntu-test.docker"
|
||||
image_tag="$(md5sum docker/${dockerfile} | cut -d' ' -f1)"
|
||||
image_name="apache/cassandra-${dockerfile/.docker/}:${image_tag}"
|
||||
docker_mounts="-v ${cassandra_dir}:/home/cassandra/cassandra -v "${build_dir}":/home/cassandra/cassandra/build -v ${m2_dir}:/home/cassandra/.m2/repository"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
# limitations under the License.
|
||||
|
||||
FROM ubuntu:20.04
|
||||
MAINTAINER Apache Cassandra <dev@cassandra.apache.org>
|
||||
LABEL org.opencontainers.image.authors="Apache Cassandra <dev@cassandra.apache.org>"
|
||||
|
||||
# CONTEXT is expected to be cassandra/.build
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
|
|||
python3.11 python3.11-venv python3.11-dev \
|
||||
virtualenv net-tools libev4 libev-dev wget gcc libxml2 libxslt1-dev \
|
||||
vim lsof sudo libjemalloc2 dumb-init locales rsync \
|
||||
openjdk-8-jdk openjdk-11-jdk openjdk-17-jdk ant ant-optional
|
||||
openjdk-8-jdk openjdk-11-jdk openjdk-17-jdk openjdk-21-jdk ant ant-optional
|
||||
|
||||
|
||||
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.8 2
|
||||
|
|
@ -71,8 +71,9 @@ RUN chmod 0644 /opt/requirements.txt
|
|||
RUN pip3 install virtualenv virtualenv-clone
|
||||
RUN pip3 install --upgrade wheel
|
||||
|
||||
# make Java 8 the default executable (we use to run all tests against Java 8)
|
||||
RUN update-java-alternatives --set java-1.8.0-openjdk-$(dpkg --print-architecture)
|
||||
# make Java 11 the default executable
|
||||
RUN update-alternatives --set java /usr/lib/jvm/java-11-openjdk-$(dpkg --print-architecture)/bin/java
|
||||
RUN update-alternatives --set javac /usr/lib/jvm/java-11-openjdk-$(dpkg --print-architecture)/bin/javac
|
||||
|
||||
# enable legacy TLSv1 and TLSv1.1 (CASSANDRA-16848)
|
||||
RUN find /etc -type f -name java.security -exec sed -i 's/TLSv1, TLSv1.1//' {} \;
|
||||
|
|
@ -36,8 +36,8 @@
|
|||
</license>
|
||||
</licenses>
|
||||
<properties>
|
||||
<bytebuddy.version>1.12.13</bytebuddy.version>
|
||||
<byteman.version>4.0.20</byteman.version>
|
||||
<bytebuddy.version>1.17.8</bytebuddy.version>
|
||||
<byteman.version>4.0.26</byteman.version>
|
||||
<netty.version>4.1.130.Final</netty.version>
|
||||
<ohc.version>0.5.1</ohc.version>
|
||||
<async-profiler.version>4.2</async-profiler.version>
|
||||
|
|
@ -494,13 +494,13 @@
|
|||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>5.12.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-inline</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>5.2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
@ -891,7 +891,8 @@
|
|||
<dependency>
|
||||
<groupId>net.openhft</groupId>
|
||||
<artifactId>chronicle-queue</artifactId>
|
||||
<version>5.23.37</version>
|
||||
<!-- chronicle ea builds before the corresponding Final are code identical; Final builds are not made available on Maven -->
|
||||
<version>5.25ea16</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>tools</artifactId>
|
||||
|
|
@ -907,7 +908,12 @@
|
|||
<dependency>
|
||||
<groupId>net.openhft</groupId>
|
||||
<artifactId>chronicle-core</artifactId>
|
||||
<version>2.23.36</version>
|
||||
<!-- While we broadly don't want to use ea libraries in the project, the Chronicle ecosystem has moved
|
||||
to an approach of only allowing paid usage for non-ea builds. The ea builds are identical to the .0 release
|
||||
of the next major version, so "ea" in this context signifies "stable GA build" for this major release line.
|
||||
We plan to move away from chronicle for this and other reasons; the details of the conversation on the mailing
|
||||
list can be found here: https://issues.apache.org/jira/browse/CASSANDRA-18831?focusedCommentId=17902034&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-17902034 -->
|
||||
<version>2.25ea14</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>chronicle-analytics</artifactId>
|
||||
|
|
@ -922,7 +928,8 @@
|
|||
<dependency>
|
||||
<groupId>net.openhft</groupId>
|
||||
<artifactId>chronicle-bytes</artifactId>
|
||||
<version>2.23.33</version>
|
||||
<!-- See above for details about exception re: inclusion of ea lib -->
|
||||
<version>2.25ea10</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>annotations</artifactId>
|
||||
|
|
@ -933,7 +940,8 @@
|
|||
<dependency>
|
||||
<groupId>net.openhft</groupId>
|
||||
<artifactId>chronicle-wire</artifactId>
|
||||
<version>2.23.39</version>
|
||||
<!-- See above for details about exception re: inclusion of ea lib -->
|
||||
<version>2.25ea15</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>compiler</artifactId>
|
||||
|
|
@ -949,7 +957,8 @@
|
|||
<dependency>
|
||||
<groupId>net.openhft</groupId>
|
||||
<artifactId>chronicle-threads</artifactId>
|
||||
<version>2.23.25</version>
|
||||
<!-- See above for details about exception re: inclusion of ea lib -->
|
||||
<version>2.25ea7</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<!-- pulls in affinity-3.23ea1 which pulls in third-party-bom-3.22.4-SNAPSHOT -->
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ set -e # enable immediate exit if venv setup fails
|
|||
# fresh virtualenv and test logs results everytime
|
||||
[[ "/" == "${DIST_DIR}" ]] || rm -rf "${DIST_DIR}/venv" "${DIST_DIR}/test/{html,output,logs}"
|
||||
|
||||
# re-use when possible the pre-installed virtualenv found in the cassandra-ubuntu2004_test docker image
|
||||
# re-use when possible the pre-installed virtualenv found in the cassandra2004_test docker image
|
||||
virtualenv-clone ${BUILD_HOME}/env${python_version} ${DIST_DIR}/venv || virtualenv --python=python${python_version} ${DIST_DIR}/venv
|
||||
source ${DIST_DIR}/venv/bin/activate
|
||||
pip3 install --exists-action w -r ${CASSANDRA_DTEST_DIR}/requirements.txt
|
||||
|
|
|
|||
|
|
@ -254,7 +254,11 @@ _run_testlist() {
|
|||
for ((i=0; i < _test_iterations; i++)); do
|
||||
[ "${_test_iterations}" -eq 1 ] || printf "–––– run ${i}\n"
|
||||
set +o errexit
|
||||
ant "$_testlist_target" -Dtest.classlistprefix="${_target_prefix}" -Dtest.classlistfile=<(echo "${testlist}") -Dtest.timeout="${_test_timeout}" ${ANT_TEST_OPTS}
|
||||
ant "$_testlist_target" \
|
||||
-Dtest.classlistprefix="${_target_prefix}" \
|
||||
-Dtest.classlistfile=<(echo "${testlist}") \
|
||||
-Dtest.timeout="${_test_timeout}" \
|
||||
${ANT_TEST_OPTS}
|
||||
ant_status=$?
|
||||
set -o errexit
|
||||
if [[ $ant_status -ne 0 ]]; then
|
||||
|
|
|
|||
|
|
@ -352,7 +352,7 @@ def build(command, cell) {
|
|||
test -f .jenkins/Jenkinsfile || { echo "Invalid git fork/branch"; exit 1; }
|
||||
grep -q "Jenkins CI declaration" .jenkins/Jenkinsfile || { echo "Only Cassandra 5.0+ supported"; exit 1; }
|
||||
"""
|
||||
fetchDockerImages("redhat" == cell.step ? ['almalinux-build'] : ['bullseye-build'])
|
||||
fetchDockerImages("redhat" == cell.step ? ['almalinux-build'] : ['debian-build'])
|
||||
def cell_suffix = "_jdk${cell.jdk}_${cell.arch}"
|
||||
def logfile = "stage-logs/${JOB_NAME}_${BUILD_NUMBER}_${cell.step}${cell_suffix}_attempt${attempt}.log.xz"
|
||||
def script_vars = "#!/bin/bash \n set -o pipefail ; " // pipe to tee needs pipefail
|
||||
|
|
@ -391,7 +391,7 @@ def test(command, cell) {
|
|||
withEnv(cell.collect { k, v -> "${k}=${v}" }) {
|
||||
ws("workspace/${JOB_NAME}/${BUILD_NUMBER}/${cell.step}/${cell.arch}/jdk-${cell.jdk}/python-${cell.python}") {
|
||||
fetchSource(cell.step, cell.arch, cell.jdk)
|
||||
fetchDockerImages(['ubuntu2004_test'])
|
||||
fetchDockerImages(['ubuntu-test'])
|
||||
def cell_suffix = "_jdk${cell.jdk}_python_${cell.python}_${cell.cython}_${cell.arch}_${cell.split}_${splits}"
|
||||
def logfile = "stage-logs/${JOB_NAME}_${BUILD_NUMBER}_${cell.step}${cell_suffix}_attempt${attempt}.log.xz"
|
||||
def script_vars = "#!/bin/bash \n set -o pipefail ; " // pipe to tee needs pipefail
|
||||
|
|
@ -594,11 +594,11 @@ def generateTestReports() {
|
|||
echo "Report for \${target} (\$(find build/test/output/\${target} -name '*.xml' | wc -l) test files)"
|
||||
CASSANDRA_DOCKER_ANT_OPTS="-Dbuild.test.output.dir=build/test/output/\${target} -Dbuild.test.report.dir=build/test/reports/\${target}"
|
||||
export CASSANDRA_DOCKER_ANT_OPTS
|
||||
.build/docker/_docker_run.sh bullseye-build.docker ci/generate-test-report.sh
|
||||
.build/docker/_docker_run.sh debian-build.docker ci/generate-test-report.sh
|
||||
fi
|
||||
done
|
||||
|
||||
.build/docker/_docker_run.sh bullseye-build.docker ci/generate-ci-summary.sh || echo "failed generate-ci-summary.sh"
|
||||
.build/docker/_docker_run.sh debian-build.docker ci/generate-ci-summary.sh || echo "failed generate-ci-summary.sh"
|
||||
|
||||
tar -cf build/results_details.tar -C build/test/ reports
|
||||
xz -8f build/results_details.tar ) ${teeSuffix}
|
||||
|
|
|
|||
8
NEWS.txt
8
NEWS.txt
|
|
@ -80,6 +80,9 @@ using the provided 'sstableupgrade' tool.
|
|||
|
||||
New features
|
||||
------------
|
||||
- JDK21 and Generational ZGC are now officially supported and generational ZGC is now the default Garbage Collector
|
||||
when using JDK21. See jvm21-server.options for more details and configuration parameters. We do not recommend using
|
||||
non-generational ZGC with Apache Cassandra.
|
||||
[The following is a placeholder, to be revised asap]
|
||||
- CEP-37 Auto Repair is a fully automated scheduler that provides repair orchestration within Apache Cassandra. This
|
||||
significantly reduces operational overhead by eliminating the need for operators to deploy external tools to submit
|
||||
|
|
@ -205,6 +208,11 @@ Upgrading
|
|||
Deprecation
|
||||
-----------
|
||||
- `use_deterministic_table_id` is no longer supported and should be removed from cassandra.yaml. Table IDs may still be supplied explicitly on CREATE.
|
||||
- Updating dependencies for JDK21 necessitated updating Chronicle Queue, which has changed the enums used for log
|
||||
rolling (cassandra.yaml -> full_query_logging_options:roll_cycle). Older legacy options will still work for the
|
||||
foreseeable future but you will see warnings in logs and future dependency upgrades may break your log rolling param.
|
||||
The default log rolling param has been changed from HOURLY to FAST_HOURLY, primarily different on how frequently
|
||||
indexes are built (256 in FAST_HOURLY vs. 16 in HOURLY).
|
||||
- IEndpointSnitch has been deprecated as ClusterMetadata is now the source of truth regarding topology information.
|
||||
The responsibilities of the snitch have been broken out to a handful of new classes:
|
||||
* o.a.c.locator.Locator provides datacenter and rack info for endpoints. This is not configurable as topology is
|
||||
|
|
|
|||
|
|
@ -114,56 +114,36 @@ if [ -z $JAVA ] ; then
|
|||
fi
|
||||
|
||||
# Matches variable 'java.supported' in build.xml
|
||||
java_versions_supported=11,17
|
||||
java_versions_supported="11 17 21"
|
||||
java_version_string=$(IFS=" "; echo "${java_versions_supported}")
|
||||
|
||||
# Determine the sort of JVM we'll be running on.
|
||||
java_ver_output=`"${JAVA:-java}" -version 2>&1`
|
||||
jvmver=`echo "$java_ver_output" | grep '[openjdk|java] version' | awk -F'"' 'NR==1 {print $2}' | cut -d\- -f1`
|
||||
JVM_VERSION=${jvmver%_*}
|
||||
short=$(echo "${jvmver}" | cut -c1-2)
|
||||
JAVA_VERSION=$(java -version 2>&1 | grep '[openjdk|java] version' | cut -d '"' -f2 | cut -d '.' -f1)
|
||||
|
||||
# Unsupported JDKs below the upper supported version are not allowed
|
||||
if [ "$short" != "$(echo "$java_versions_supported" | cut -d, -f1)" ] && [ "$JVM_VERSION" \< "$(echo "$java_versions_supported" | cut -d, -f2)" ] ; then
|
||||
echo "Unsupported Java $JVM_VERSION. Supported are $java_versions_supported"
|
||||
exit 1;
|
||||
fi
|
||||
# Allow execution of supported Java versions, and newer if CASSANDRA_JDK_UNSUPPORTED is set
|
||||
is_supported_version=$(echo "$java_versions_supported" | tr "," '\n' | grep -F -x "$short")
|
||||
if [ -z "$is_supported_version" ] ; then
|
||||
if [ -z "$CASSANDRA_JDK_UNSUPPORTED" ] ; then
|
||||
echo "Unsupported Java $JVM_VERSION. Supported are $java_versions_supported"
|
||||
echo "If you would like to test with newer Java versions set CASSANDRA_JDK_UNSUPPORTED to any value (for example, CASSANDRA_JDK_UNSUPPORTED=true). Unset the parameter for default behavior"
|
||||
exit 1;
|
||||
else
|
||||
echo "######################################################################"
|
||||
echo "Warning! You are using JDK$short. This Cassandra version only supports $java_versions_supported."
|
||||
echo "######################################################################"
|
||||
fi
|
||||
fi
|
||||
JAVA_VERSION=$short
|
||||
supported=0
|
||||
for version in ${java_versions_supported}; do
|
||||
if [ "$version" -eq "$JAVA_VERSION" ]; then
|
||||
supported=1
|
||||
fi
|
||||
done
|
||||
|
||||
jvm=`echo "$java_ver_output" | grep -A 1 '[openjdk|java] version' | awk 'NR==2 {print $1}'`
|
||||
case "$jvm" in
|
||||
OpenJDK)
|
||||
JVM_VENDOR=OpenJDK
|
||||
# this will be "64-Bit" or "32-Bit"
|
||||
JVM_ARCH=`echo "$java_ver_output" | awk 'NR==3 {print $2}'`
|
||||
;;
|
||||
"Java(TM)")
|
||||
JVM_VENDOR=Oracle
|
||||
# this will be "64-Bit" or "32-Bit"
|
||||
JVM_ARCH=`echo "$java_ver_output" | awk 'NR==3 {print $3}'`
|
||||
;;
|
||||
*)
|
||||
# Help fill in other JVM values
|
||||
JVM_VENDOR=other
|
||||
JVM_ARCH=unknown
|
||||
;;
|
||||
esac
|
||||
if [ "$supported" -eq 0 ]; then
|
||||
if [ -z "$CASSANDRA_JDK_UNSUPPORTED" ]; then
|
||||
echo "Unsupported Java $JAVA_VERSION. Supported are $java_version_string"
|
||||
echo "If you would like to test with newer Java versions set CASSANDRA_JDK_UNSUPPORTED to any value (for example, CASSANDRA_JDK_UNSUPPORTED=true). Unset the parameter for default behavior"
|
||||
exit 1
|
||||
else
|
||||
echo "######################################################################"
|
||||
echo "Warning! You are using JDK$JAVA_VERSION. This Cassandra version only supports $java_version_string"
|
||||
echo "######################################################################"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Read user-defined JVM options from jvm-server.options file
|
||||
JVM_OPTS_FILE=$CASSANDRA_CONF/jvm${jvmoptions_variant:--clients}.options
|
||||
if [ $JAVA_VERSION -ge 17 ] ; then
|
||||
if [ $JAVA_VERSION -ge 21 ] ; then
|
||||
JVM_DEP_OPTS_FILE=$CASSANDRA_CONF/jvm21${jvmoptions_variant:--clients}.options
|
||||
elif [ $JAVA_VERSION -ge 17 ] ; then
|
||||
JVM_DEP_OPTS_FILE=$CASSANDRA_CONF/jvm17${jvmoptions_variant:--clients}.options
|
||||
elif [ $JAVA_VERSION -ge 11 ] ; then
|
||||
JVM_DEP_OPTS_FILE=$CASSANDRA_CONF/jvm11${jvmoptions_variant:--clients}.options
|
||||
|
|
|
|||
112
build.xml
112
build.xml
|
|
@ -45,7 +45,7 @@
|
|||
The use of both CASSANDRA_USE_JDK11 and use-jdk11 is deprecated.
|
||||
-->
|
||||
<property name="java.default" value="11" />
|
||||
<property name="java.supported" value="11,17" />
|
||||
<property name="java.supported" value="11,17,21" />
|
||||
|
||||
<!-- directory details -->
|
||||
<property name="basedir" value="."/>
|
||||
|
|
@ -173,7 +173,7 @@
|
|||
<!-- When updating ASM, please, do consider whether you might need to update also FBUtilities#ASM_BYTECODE_VERSION
|
||||
and the simulator InterceptClasses#BYTECODE_VERSION, in particular if we are looking to provide Cassandra support
|
||||
for newer JDKs (CASSANDRA-17873). -->
|
||||
<property name="asm.version" value="9.4"/>
|
||||
<property name="asm.version" value="9.5"/>
|
||||
<property name="allocation-instrumenter.version" value="3.1.0"/>
|
||||
|
||||
<condition property="is.source.artifact">
|
||||
|
|
@ -323,14 +323,82 @@
|
|||
<string>--add-opens java.base/java.lang=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/java.util=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/java.nio=ALL-UNNAMED</string>
|
||||
|
||||
<string>--add-opens java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED</string>
|
||||
|
||||
<!-- Needed for in-jvm dtests straddling 6.0+ -->
|
||||
<string>--add-opens java.base/java.util.concurrent=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/java.util.concurrent.atomic=ALL-UNNAMED</string>
|
||||
</resources>
|
||||
<pathconvert property="_jvm17_args_concat" refid="_jvm17_arg_items" pathsep=" "/>
|
||||
<condition property="java-jvmargs" value="${_jvm17_args_concat}">
|
||||
<equals arg1="${ant.java.version}" arg2="17"/>
|
||||
</condition>
|
||||
|
||||
<resources id="_jvm21_arg_items">
|
||||
<string>-Djdk.attach.allowAttachSelf=true</string>
|
||||
|
||||
<string>-XX:+UseZGC</string>
|
||||
<string>-XX:+ZGenerational</string>
|
||||
|
||||
<!-- Temporary workaround for jamm having incorrect default CompressedOops for JDK21 -->
|
||||
<!-- Without this, memory layout and sizing calculations will be incorrect as jamm assumes compressedOops -->
|
||||
<string>-XX:-UseCompressedOops</string>
|
||||
|
||||
<!-- <string>-XX:+UseLargePages</string> -->
|
||||
|
||||
<!-- Max size ZGC will _attempt_ to stay below -->
|
||||
<!-- <string>-XX:+SoftMaxHeapSize=12G</string> -->
|
||||
|
||||
<!-- Disable returning memory to the OS -->
|
||||
<!-- <string>-XX:-ZUncommit</string> -->
|
||||
|
||||
<!-- Time memory should have been unused before eligible for uncommit in seconds -->
|
||||
<!-- <string>-XX:ZUncommitDelay=300</string> -->
|
||||
|
||||
<!-- Pay the tax up front to pretouch memory to smooth out latency later -->
|
||||
<!-- <string>-XX:+AlwaysPreTouch</string> -->
|
||||
|
||||
<!-- Need to explicitly allow security manager on JDK21; deprecated for removal -->
|
||||
<string>-Djava.security.manager=allow</string>
|
||||
|
||||
<string>--add-exports java.base/java.lang.ref=ALL-UNNAMED</string>
|
||||
<string>--add-exports java.base/java.lang.reflect=ALL-UNNAMED</string>
|
||||
<string>--add-exports java.base/jdk.internal.misc=ALL-UNNAMED</string>
|
||||
<string>--add-exports java.base/jdk.internal.ref=ALL-UNNAMED</string>
|
||||
<string>--add-exports java.base/sun.nio.ch=ALL-UNNAMED</string>
|
||||
<string>--add-exports java.management.rmi/com.sun.jmx.remote.internal.rmi=ALL-UNNAMED</string>
|
||||
<string>--add-exports java.rmi/sun.rmi.registry=ALL-UNNAMED</string>
|
||||
<string>--add-exports java.rmi/sun.rmi.server=ALL-UNNAMED</string>
|
||||
<string>--add-exports java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED</string>
|
||||
<string>--add-exports java.sql/java.sql=ALL-UNNAMED</string>
|
||||
<string>--add-exports jdk.unsupported/sun.misc=ALL-UNNAMED</string>
|
||||
<string>--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</string>
|
||||
<string>--add-exports jdk.attach/sun.tools.attach=ALL-UNNAMED</string>
|
||||
|
||||
<string>--add-opens java.base/java.io=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/java.lang=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/java.lang.module=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/java.lang.reflect=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/java.math=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/java.net=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/java.nio=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/java.util=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/java.util.concurrent=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/java.util.concurrent.atomic=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/jdk.internal.loader=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/jdk.internal.math=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/jdk.internal.module=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/jdk.internal.ref=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/jdk.internal.reflect=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.base/sun.nio.ch=ALL-UNNAMED</string>
|
||||
<string>--add-opens java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED</string>
|
||||
<string>--add-opens jdk.management/com.sun.management=ALL-UNNAMED</string>
|
||||
</resources>
|
||||
<pathconvert property="_jvm21_args_concat" refid="_jvm21_arg_items" pathsep=" "/>
|
||||
<condition property="java-jvmargs" value="${_jvm21_args_concat}" else="">
|
||||
<equals arg1="${ant.java.version}" arg2="21"/>
|
||||
</condition>
|
||||
|
||||
<!--
|
||||
JVM arguments for tests.
|
||||
|
||||
|
|
@ -344,21 +412,48 @@
|
|||
buffer construction (see CASSANDRA-16493)
|
||||
-->
|
||||
<resources id="_jvm11_test_arg_items">
|
||||
<string>-XX:+HeapDumpOnOutOfMemoryError</string>
|
||||
<string>-XX:-CMSClassUnloadingEnabled</string>
|
||||
<string>-Dio.netty.tryReflectionSetAccessible=true</string>
|
||||
<string>-XX:MaxMetaspaceSize=2G</string>
|
||||
</resources>
|
||||
<pathconvert property="_jvm11_test_arg_items_concat" refid="_jvm11_test_arg_items" pathsep=" "/>
|
||||
|
||||
<resources id="_jvm17_test_arg_items">
|
||||
<string>-XX:+HeapDumpOnOutOfMemoryError</string>
|
||||
<string>-Dio.netty.tryReflectionSetAccessible=true</string>
|
||||
<!-- Open things up so we don't run into any jamm rejections that'd then go unsafe and crash out on in-jvm dtests -->
|
||||
<string>--add-opens=java.base/java.lang=ALL-UNNAMED</string>
|
||||
<string>--add-exports=java.base/jdk.internal.vm.annotation=ALL-UNNAMED</string>
|
||||
</resources>
|
||||
<pathconvert property="_jvm17_test_arg_items_concat" refid="_jvm17_test_arg_items" pathsep=" "/>
|
||||
|
||||
<resources id="_jvm21_test_arg_items">
|
||||
<string>-XX:+HeapDumpOnOutOfMemoryError</string>
|
||||
<string>-Dnet.bytebuddy.experimental=true</string>
|
||||
<string>-Djava.security.manager=allow</string>
|
||||
<string>-Dio.netty.tryReflectionSetAccessible=true</string>
|
||||
|
||||
<!-- Open things up so we don't run into any jamm rejections that'd then go unsafe and crash out on in-jvm dtests-->
|
||||
<string>--add-opens=java.base/java.lang=ALL-UNNAMED</string>
|
||||
<string>--add-exports=java.base/jdk.internal.vm.annotation=ALL-UNNAMED</string>
|
||||
|
||||
<!-- Revert to pre-JEP-416 Core Reflection implementation (without method handles) -->
|
||||
<!-- without this, FieldUtils cannot overwrite static final fields, breaking some tests -->
|
||||
<!-- removed in 22 (JDK-8309635) so will need a proper fix for 25 -->
|
||||
<string>-Djdk.reflect.useDirectMethodHandle=false</string>
|
||||
</resources>
|
||||
<pathconvert property="_jvm21_test_arg_items_concat" refid="_jvm21_test_arg_items" pathsep=" "/>
|
||||
|
||||
<condition property="_std-test-jvmargs" value="${_jvm11_test_arg_items_concat}">
|
||||
<equals arg1="${ant.java.version}" arg2="11"/>
|
||||
<equals arg1="${ant.java.version}" arg2="11"/>
|
||||
</condition>
|
||||
<condition property="_std-test-jvmargs" value="${_jvm17_test_arg_items_concat}">
|
||||
<equals arg1="${ant.java.version}" arg2="17"/>
|
||||
</condition>
|
||||
<condition property="_std-test-jvmargs" value="${_jvm21_test_arg_items_concat}">
|
||||
<equals arg1="${ant.java.version}" arg2="21"/>
|
||||
</condition>
|
||||
|
||||
<!-- needed to compile org.apache.cassandra.utils.JMXServerUtils -->
|
||||
<!-- needed to compile org.apache.cassandra.distributed.impl.Instance-->
|
||||
|
|
@ -484,9 +579,13 @@
|
|||
|
||||
<target name="gen-cql3-grammar" depends="check-gen-cql3-grammar" unless="cql3current">
|
||||
<echo>Building Grammar ${build.src.antlr}/Cql.g ...</echo>
|
||||
<!-- antlr will crash on the first run on JDK21 and subsequently succeed if we don't fork it and execute in a separate JVM... -->
|
||||
<java classname="org.antlr.Tool"
|
||||
classpathref="cql3-grammar.classpath"
|
||||
failonerror="true">
|
||||
failonerror="true"
|
||||
fork="true"
|
||||
outputproperty="antlr.output"
|
||||
errorproperty="antlr.error">
|
||||
<arg value="-Xconversiontimeout" />
|
||||
<arg value="10000" />
|
||||
<arg value="${build.src.antlr}/Cql.g" />
|
||||
|
|
@ -1237,6 +1336,8 @@
|
|||
<jvmarg value="-ea"/>
|
||||
<jvmarg value="-Djava.io.tmpdir=${tmp.dir}"/>
|
||||
<jvmarg value="-Dcassandra.debugrefcount=true"/>
|
||||
<!-- Pull this up for genZGC / JDK21 -->
|
||||
<jvmarg value="-Xms512M"/>
|
||||
<jvmarg value="${jvm_xss}"/>
|
||||
<!-- When we do classloader manipulation SoftReferences can cause memory leaks
|
||||
that can OOM our test runs. The next two settings informs our GC
|
||||
|
|
@ -1491,6 +1592,7 @@
|
|||
<test if="withMethods" name="${test.name}" methods="${test.methods}" todir="${build.test.output.dir}/" outfile="TEST-${test.name}-${test.methods}"/>
|
||||
<test if="withoutMethods" name="${test.name}" todir="${build.test.output.dir}/" outfile="TEST-${test.name}"/>
|
||||
<jvmarg value="-Dlogback.configurationFile=test/conf/logback-burntest.xml"/>
|
||||
<jvmarg value="-Dnet.bytebuddy.experimental=true"/>
|
||||
</testmacro>
|
||||
</target>
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@ echo $JVM_OPTS | grep -q UseConcMarkSweepGC
|
|||
USING_CMS=$?
|
||||
echo $JVM_OPTS | grep -q +UseG1GC
|
||||
USING_G1=$?
|
||||
echo $JVM_OPTS | grep -q +UseZGC
|
||||
USING_ZGC=$?
|
||||
|
||||
calculate_heap_sizes
|
||||
|
||||
|
|
@ -177,6 +179,11 @@ if [ $DEFINED_XMN -eq 0 ] && [ $USING_G1 -eq 0 ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# If a user tries to use -Xmn with ZGC we should let them know it's not going to work. Not worth killing the node over though.
|
||||
if [ $DEFINED_XMN -eq 0 ] && [ $USING_ZGC -eq 0]; then
|
||||
echo "-Xmn does nothing when used in conjunction with ZGC; this setting will be ignored."
|
||||
fi
|
||||
|
||||
if [ $USING_G1 -eq 0 ] && [ $DEFINED_PARALLEL_GC_THREADS -ne 0 ] && [ $DEFINED_CONC_GC_THREADS -ne 0 ] ; then
|
||||
# Set ParallelGCThreads and ConcGCThreads equal to number of cpu cores.
|
||||
# Setting both to the same value is important to reduce STW durations.
|
||||
|
|
|
|||
|
|
@ -2129,7 +2129,7 @@ audit_logging_options:
|
|||
# excluded_categories:
|
||||
# included_users:
|
||||
# excluded_users:
|
||||
# roll_cycle: HOURLY
|
||||
# roll_cycle: FAST_HOURLY
|
||||
# block: true
|
||||
# max_queue_weight: 268435456 # 256 MiB
|
||||
# max_log_size: 17179869184 # 16 GiB
|
||||
|
|
@ -2144,7 +2144,7 @@ audit_logging_options:
|
|||
# nodetool enablefullquerylog
|
||||
# full_query_logging_options:
|
||||
# log_dir:
|
||||
# roll_cycle: HOURLY
|
||||
# roll_cycle: FAST_HOURLY
|
||||
# block: true
|
||||
# max_queue_weight: 268435456 # 256 MiB
|
||||
# max_log_size: 17179869184 # 16 GiB
|
||||
|
|
|
|||
|
|
@ -185,6 +185,9 @@
|
|||
# For production use you may wish to adjust this for your environment.
|
||||
# If that's the case, see MAX_HEAP_SIZE (and HEAP_NEWSIZE for CMS) in cassandra-env.sh
|
||||
|
||||
# Need experimental bytebuddy for JDK21
|
||||
-Dnet.bytebuddy.experimental
|
||||
|
||||
#####################
|
||||
# OFF-HEAP SETTINGS #
|
||||
#####################
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
###########################################################################
|
||||
# jvm21-clients.options #
|
||||
# #
|
||||
# See jvm-clients.options. This file is specific for Java 21 #
|
||||
###########################################################################
|
||||
|
||||
###################
|
||||
# JPMS SETTINGS #
|
||||
###################
|
||||
|
||||
-Djdk.attach.allowAttachSelf=true
|
||||
|
||||
--add-exports java.base/java.lang.ref=ALL-UNNAMED
|
||||
--add-exports java.base/jdk.internal.misc=ALL-UNNAMED
|
||||
--add-exports java.management.rmi/com.sun.jmx.remote.internal.rmi=ALL-UNNAMED
|
||||
--add-exports java.rmi/sun.rmi.registry=ALL-UNNAMED
|
||||
--add-exports java.rmi/sun.rmi.server=ALL-UNNAMED
|
||||
--add-exports java.sql/java.sql=ALL-UNNAMED
|
||||
--add-exports jdk.unsupported/sun.misc=ALL-UNNAMED
|
||||
|
||||
--add-opens java.base/java.io=ALL-UNNAMED
|
||||
--add-opens java.base/java.lang=ALL-UNNAMED
|
||||
--add-opens java.base/java.lang.module=ALL-UNNAMED
|
||||
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
|
||||
--add-opens java.base/java.nio=ALL-UNNAMED
|
||||
--add-opens java.base/java.util=ALL-UNNAMED
|
||||
--add-opens java.base/jdk.internal.loader=ALL-UNNAMED
|
||||
--add-opens java.base/jdk.internal.math=ALL-UNNAMED
|
||||
--add-opens java.base/jdk.internal.module=ALL-UNNAMED
|
||||
--add-opens java.base/jdk.internal.ref=ALL-UNNAMED
|
||||
--add-opens java.base/jdk.internal.reflect=ALL-UNNAMED
|
||||
--add-opens java.base/sun.nio.ch=ALL-UNNAMED
|
||||
--add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED
|
||||
|
||||
# The newline in the end of file is intentional
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
###########################################################################
|
||||
# jvm21-server.options #
|
||||
# #
|
||||
# See jvm-server.options. This file is specific for Java 21 and newer. #
|
||||
###########################################################################
|
||||
|
||||
#################
|
||||
# GC SETTINGS #
|
||||
#################
|
||||
|
||||
|
||||
### Generational ZGC settings
|
||||
-XX:+UseZGC
|
||||
-XX:+ZGenerational
|
||||
|
||||
# Temporary workaround for jamm's incorrect default CompressedOops; if you're using ZGC this needs to be set
|
||||
-XX:-UseCompressedOops
|
||||
|
||||
# Blanket enabling of all the THP / large pages available in the env
|
||||
# -XX:+UseLargePages
|
||||
|
||||
# Max size ZGC will _attempt_ to stay below
|
||||
# -XX:+SoftMaxHeapSize=12G
|
||||
|
||||
# Don't let ZGC return unclaimed memory to the OS by setting the following
|
||||
# -XX:-ZUncommit
|
||||
|
||||
# Time memory should have been unused before eligible for uncommit in seconds
|
||||
# -XX:ZUncommitDelay=300
|
||||
|
||||
# Tell GC to touch heap and allocate and fault in memory pages backing heap at startup. Can prevent later allocation pauses
|
||||
# -XX:+AlwaysPreTouch
|
||||
|
||||
### G1 Settings
|
||||
## Use the Hotspot garbage-first collector.
|
||||
#-XX:+UseG1GC
|
||||
#-XX:+ParallelRefProcEnabled
|
||||
#-XX:MaxTenuringThreshold=2
|
||||
#-XX:G1HeapRegionSize=16m
|
||||
|
||||
# Floor the young generation size to 50% of the heap size
|
||||
#-XX:+UnlockExperimentalVMOptions
|
||||
#-XX:G1NewSizePercent=50
|
||||
|
||||
# Have the JVM do less remembered set work during STW, instead
|
||||
# preferring concurrent GC. Reduces p99.9 latency.
|
||||
#-XX:G1RSetUpdatingPauseTimePercent=5
|
||||
|
||||
# Main G1GC tunable: lowering the pause target will lower throughput and vise versa.
|
||||
# 200ms is the JVM default and lowest viable setting
|
||||
# 1000ms increases throughput. Keep it smaller than the timeouts in cassandra.yaml.
|
||||
#-XX:MaxGCPauseMillis=300
|
||||
|
||||
## Optional G1 Settings
|
||||
# Save CPU time on large (>= 16GB) heaps by delaying region scanning
|
||||
# until the heap is 70% full. The default in Hotspot 8u40 is 40%.
|
||||
#-XX:InitiatingHeapOccupancyPercent=70
|
||||
|
||||
# For systems with > 8 cores, the default ParallelGCThreads is 5/8 the number of logical cores.
|
||||
# Otherwise equal to the number of cores when 8 or less.
|
||||
# Machines with > 10 cores should try setting these to <= full cores.
|
||||
# By default, ConcGCThreads is 1/4 of ParallelGCThreads.
|
||||
# Setting both to the same value can reduce STW durations.
|
||||
# When leaving both unset then cassandra-env.sh will set them both to the number of your cores.
|
||||
#-XX:ParallelGCThreads=16
|
||||
#-XX:ConcGCThreads=16
|
||||
|
||||
### JPMS
|
||||
|
||||
-Djdk.attach.allowAttachSelf=true
|
||||
|
||||
--add-exports java.base/java.lang.ref=ALL-UNNAMED
|
||||
--add-exports java.base/jdk.internal.misc=ALL-UNNAMED
|
||||
--add-exports java.management.rmi/com.sun.jmx.remote.internal.rmi=ALL-UNNAMED
|
||||
--add-exports java.rmi/sun.rmi.registry=ALL-UNNAMED
|
||||
--add-exports java.rmi/sun.rmi.server=ALL-UNNAMED
|
||||
--add-exports java.sql/java.sql=ALL-UNNAMED
|
||||
--add-exports jdk.unsupported/sun.misc=ALL-UNNAMED
|
||||
|
||||
--add-opens java.base/java.io=ALL-UNNAMED
|
||||
--add-opens java.base/java.lang=ALL-UNNAMED
|
||||
--add-opens java.base/java.lang.module=ALL-UNNAMED
|
||||
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
|
||||
--add-opens java.base/java.nio=ALL-UNNAMED
|
||||
--add-opens java.base/java.util=ALL-UNNAMED
|
||||
--add-opens java.base/jdk.internal.loader=ALL-UNNAMED
|
||||
--add-opens java.base/jdk.internal.math=ALL-UNNAMED
|
||||
--add-opens java.base/jdk.internal.module=ALL-UNNAMED
|
||||
--add-opens java.base/jdk.internal.ref=ALL-UNNAMED
|
||||
--add-opens java.base/jdk.internal.reflect=ALL-UNNAMED
|
||||
--add-opens java.base/sun.nio.ch=ALL-UNNAMED
|
||||
--add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED
|
||||
|
||||
|
||||
### GC logging options -- uncomment to enable
|
||||
|
||||
# Java 11 (and newer) GC logging options:
|
||||
# See description of https://bugs.openjdk.java.net/browse/JDK-8046148 for details about the syntax
|
||||
# The following is the equivalent to -XX:+PrintGCDetails -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=10M
|
||||
#-Xlog:gc=info,heap*=trace,age*=debug,safepoint=info,promotion*=trace:file=/var/log/cassandra/gc.log:time,uptime,pid,tid,level:filecount=10,filesize=10485760
|
||||
|
||||
# Notes for Java 8 migration:
|
||||
#
|
||||
# -XX:+PrintGCDetails maps to -Xlog:gc*:... - i.e. add a '*' after "gc"
|
||||
# -XX:+PrintGCDateStamps maps to decorator 'time'
|
||||
#
|
||||
# -XX:+PrintHeapAtGC maps to 'heap' with level 'trace'
|
||||
# -XX:+PrintTenuringDistribution maps to 'age' with level 'debug'
|
||||
# -XX:+PrintGCApplicationStoppedTime maps to 'safepoint' with level 'info'
|
||||
# -XX:+PrintPromotionFailure maps to 'promotion' with level 'trace'
|
||||
# -XX:PrintFLSStatistics=1 maps to 'freelist' with level 'trace'
|
||||
|
||||
### Netty Options
|
||||
|
||||
# On Java >= 9 Netty requires the io.netty.tryReflectionSetAccessible system property to be set to true to enable
|
||||
# creation of direct buffers using Unsafe. Without it, this falls back to ByteBuffer.allocateDirect which has
|
||||
# inferior performance and risks exceeding MaxDirectMemory
|
||||
-Dio.netty.tryReflectionSetAccessible=true
|
||||
|
||||
# Revert changes in defaults introduced in https://netty.io/news/2022/03/10/4-1-75-Final.html
|
||||
-Dio.netty.allocator.useCacheForAllThreads=true
|
||||
-Dio.netty.allocator.maxOrder=11
|
||||
|
||||
|
||||
# Need to explicitly allow security manager on JDK21; deprecated for removal
|
||||
-Djava.security.manager=allow
|
||||
|
||||
# The newline in the end of file is intentional
|
||||
|
|
@ -3,7 +3,7 @@ Section: misc
|
|||
Priority: extra
|
||||
Maintainer: Eric Evans <eevans@apache.org>
|
||||
Uploaders: Sylvain Lebresne <slebresne@apache.org>
|
||||
Build-Depends: debhelper (>= 11), openjdk-17-jdk-headless | openjdk-11-jdk-headless | java17-sdk | java11-sdk, ant (>= 1.10), ant-optional (>= 1.10), dh-python, python3-dev (>= 3.6), quilt, bash-completion
|
||||
Build-Depends: debhelper (>= 11), openjdk-21-jdk-headless | openjdk-17-jdk-headless | openjdk-11-jdk-headless | java21-sdk | java17-sdk | java11-sdk, ant (>= 1.10), ant-optional (>= 1.10), dh-python, python3-dev (>= 3.6), quilt, bash-completion
|
||||
Homepage: https://cassandra.apache.org
|
||||
Vcs-Git: https://gitbox.apache.org/repos/asf/cassandra.git
|
||||
Vcs-Browser: https://gitbox.apache.org/repos/asf?p=cassandra.git
|
||||
|
|
@ -11,7 +11,7 @@ Standards-Version: 3.8.3
|
|||
|
||||
Package: cassandra
|
||||
Architecture: all
|
||||
Depends: openjdk-17-jre-headless | openjdk-11-jre-headless | java17-runtime | java11-runtime, adduser, python3 (>= 3.6), procps, ${misc:Depends}
|
||||
Depends: openjdk-21-jre-headless | openjdk-17-jre-headless | openjdk-11-jre-headless | java21-runtime | java17-runtime | java11-runtime, adduser, python3 (>= 3.6), procps, ${misc:Depends}
|
||||
Recommends: ntp | time-daemon
|
||||
Suggests: cassandra-tools
|
||||
Conflicts: apache-cassandra1
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
= jvm-* files
|
||||
|
||||
Several files for JVM configuration are included in Cassandra. The
|
||||
`jvm-server.options` file, and corresponding files `jvm8-server.options`
|
||||
and `jvm11-server.options` are the main file for settings that affect
|
||||
`jvm-server.options` file, and corresponding JDK specific files
|
||||
`jvmN-server.options` are the main file for settings that affect
|
||||
the operation of the Cassandra JVM on cluster nodes. The file includes
|
||||
startup parameters, general JVM settings such as garbage collection, and
|
||||
heap settings. The `jvm-clients.options` and corresponding
|
||||
`jvm8-clients.options` and `jvm11-clients.options` files can be used to
|
||||
configure JVM settings for clients like `nodetool` and the `sstable`
|
||||
tools.
|
||||
heap settings. Likewise, the `jvm-clients.options` and corresponding
|
||||
`jvmN-clients.options` files can be used to configure JVM settings for
|
||||
clients like `nodetool` and the `sstable` tools.
|
||||
|
||||
See each file for examples of settings.
|
||||
|
||||
|
|
|
|||
|
|
@ -190,9 +190,11 @@ To use `BinAuditLogger` as a logger in AuditLogging, set the logger to `BinAudit
|
|||
oldest file. Default is set to `16L * 1024L * 1024L * 1024L`
|
||||
`roll_cycle`::
|
||||
How often to roll Audit log segments so they can potentially be
|
||||
reclaimed. Available options are: MINUTELY, HOURLY, DAILY,
|
||||
LARGE_DAILY, XLARGE_DAILY, HUGE_DAILY.For more options, refer:
|
||||
net.openhft.chronicle.queue.RollCycles. Default is set to `"HOURLY"`
|
||||
reclaimed. Some available options are:
|
||||
`FIVE_MINUTELY, FAST_HOURLY, FAST_DAILY,
|
||||
LargeRollCycles.LARGE_DAILY, LargeRollCycles.XLARGE_DAILY, LargeRollCycles.HUGE_DAILY.`
|
||||
For more options, refer: net.openhft.chronicle.queue.RollCycles.
|
||||
Default is set to `"FAST_HOURLY"`
|
||||
|
||||
== Configuring FileAuditLogger
|
||||
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@
|
|||
-Dcassandra.storagedir=$PROJECT_DIR$/data
|
||||
-Dlogback.configurationFile=file://$PROJECT_DIR$/conf/logback.xml
|
||||
-XX:HeapDumpPath=build/test
|
||||
-Dnet.bytebuddy.experimental=true
|
||||
-ea" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="" />
|
||||
|
|
@ -217,6 +218,8 @@
|
|||
-XX:MaxMetaspaceSize=2G
|
||||
-XX:ReservedCodeCacheSize=256M
|
||||
-XX:Tier4CompileThreshold=1000
|
||||
-XX:SoftRefLRUPolicyMSPerMB=0
|
||||
-Dnet.bytebuddy.experimental=true
|
||||
-ea" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<fork_mode value="class" />
|
||||
|
|
@ -248,6 +251,7 @@
|
|||
-Dlogback.configurationFile=file://$PROJECT_DIR$/conf/logback.xml
|
||||
-XX:HeapDumpPath=build/test
|
||||
-Xmx1G
|
||||
-Dnet.bytebuddy.experimental=true
|
||||
-ea" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ set -e # enable immediate exit if venv setup fails
|
|||
# fresh virtualenv and test logs results everytime
|
||||
rm -fr ${DIST_DIR}/venv ${DIST_DIR}/test/{html,output,logs}
|
||||
|
||||
# re-use when possible the pre-installed virtualenv found in the cassandra-ubuntu2004_test docker image
|
||||
# re-use when possible the pre-installed virtualenv found in the cassandra12004_test docker image
|
||||
virtualenv-clone ${BUILD_HOME}/env${python_version} ${BUILD_DIR}/venv || virtualenv --python=python3 ${BUILD_DIR}/venv
|
||||
source ${BUILD_DIR}/venv/bin/activate
|
||||
|
||||
|
|
|
|||
|
|
@ -121,57 +121,39 @@ if [ -z $JAVA ] ; then
|
|||
exit 1;
|
||||
fi
|
||||
|
||||
# TODO: Factor this out to something we source so we don't have the duplication all over our scripts
|
||||
# Matches variable 'java.supported' in build.xml
|
||||
java_versions_supported=11,17
|
||||
java_versions_supported=(11 17 21)
|
||||
java_version_string=$(IFS=" "; echo "${java_versions_supported[*]}")
|
||||
|
||||
# Determine the sort of JVM we'll be running on.
|
||||
java_ver_output=`"${JAVA:-java}" -version 2>&1`
|
||||
jvmver=`echo "$java_ver_output" | grep '[openjdk|java] version' | awk -F'"' 'NR==1 {print $2}' | cut -d\- -f1`
|
||||
JVM_VERSION=${jvmver%_*}
|
||||
short=$(echo "${jvmver}" | cut -c1-2)
|
||||
JAVA_VERSION=$(java -version 2>&1 | grep '[openjdk|java] version' | cut -d '"' -f2 | cut -d '.' -f1)
|
||||
|
||||
# Unsupported JDKs below the upper supported version are not allowed
|
||||
if [ "$short" != "$(echo "$java_versions_supported" | cut -d, -f1)" ] && [ "$JVM_VERSION" \< "$(echo "$java_versions_supported" | cut -d, -f2)" ] ; then
|
||||
echo "Unsupported Java $JVM_VERSION. Supported are $java_versions_supported"
|
||||
exit 1;
|
||||
fi
|
||||
# Allow execution of supported Java versions, and newer if CASSANDRA_JDK_UNSUPPORTED is set
|
||||
is_supported_version=$(echo "$java_versions_supported" | tr "," '\n' | grep -F -x "$short")
|
||||
if [ -z "$is_supported_version" ] ; then
|
||||
if [ -z "$CASSANDRA_JDK_UNSUPPORTED" ] ; then
|
||||
echo "Unsupported Java $JVM_VERSION. Supported are $java_versions_supported"
|
||||
echo "If you would like to test with newer Java versions set CASSANDRA_JDK_UNSUPPORTED to any value (for example, CASSANDRA_JDK_UNSUPPORTED=true). Unset the parameter for default behavior"
|
||||
exit 1;
|
||||
else
|
||||
echo "######################################################################"
|
||||
echo "Warning! You are using JDK$short. This Cassandra version only supports $java_versions_supported."
|
||||
echo "######################################################################"
|
||||
fi
|
||||
fi
|
||||
JAVA_VERSION=$short
|
||||
supported=0
|
||||
for version in "${java_versions_supported[@]}"; do
|
||||
if [ "$version" -eq "$JAVA_VERSION" ]; then
|
||||
supported=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$supported" -eq 0 ]]; then
|
||||
if [ -z "$CASSANDRA_JDK_UNSUPPORTED" ]; then
|
||||
echo "Unsupported Java $JAVA_VERSION. Supported are $java_version_string"
|
||||
echo "If you would like to test with newer Java versions set CASSANDRA_JDK_UNSUPPORTED to any value (for example, CASSANDRA_JDK_UNSUPPORTED=true). Unset the parameter for default behavior"
|
||||
exit 1
|
||||
else
|
||||
echo "######################################################################"
|
||||
echo "Warning! You are using JDK$JAVA_VERSION. This Cassandra version only supports $java_version_string"
|
||||
echo "######################################################################"
|
||||
fi
|
||||
fi
|
||||
|
||||
jvm=`echo "$java_ver_output" | grep -A 1 '[openjdk|java] version' | awk 'NR==2 {print $1}'`
|
||||
case "$jvm" in
|
||||
OpenJDK)
|
||||
JVM_VENDOR=OpenJDK
|
||||
# this will be "64-Bit" or "32-Bit"
|
||||
JVM_ARCH=`echo "$java_ver_output" | awk 'NR==3 {print $2}'`
|
||||
;;
|
||||
"Java(TM)")
|
||||
JVM_VENDOR=Oracle
|
||||
# this will be "64-Bit" or "32-Bit"
|
||||
JVM_ARCH=`echo "$java_ver_output" | awk 'NR==3 {print $3}'`
|
||||
;;
|
||||
*)
|
||||
# Help fill in other JVM values
|
||||
JVM_VENDOR=other
|
||||
JVM_ARCH=unknown
|
||||
;;
|
||||
esac
|
||||
|
||||
# Read user-defined JVM options from jvm-server.options file
|
||||
JVM_OPTS_FILE=$CASSANDRA_CONF/jvm${jvmoptions_variant:--clients}.options
|
||||
if [ $JAVA_VERSION -ge 17 ] ; then
|
||||
if [ $JAVA_VERSION -ge 21 ] ; then
|
||||
JVM_DEP_OPTS_FILE=$CASSANDRA_CONF/jvm21${jvmoptions_variant:--clients}.options
|
||||
elif [ $JAVA_VERSION -ge 17 ] ; then
|
||||
JVM_DEP_OPTS_FILE=$CASSANDRA_CONF/jvm17${jvmoptions_variant:--clients}.options
|
||||
elif [ $JAVA_VERSION -ge 11 ] ; then
|
||||
JVM_DEP_OPTS_FILE=$CASSANDRA_CONF/jvm11${jvmoptions_variant:--clients}.options
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ BuildRoot: %{_tmppath}/%{relname}root-%(%{__id_u} -n)
|
|||
BuildRequires: ant >= 1.9
|
||||
BuildRequires: ant-junit >= 1.9
|
||||
|
||||
Requires: (java-11-headless or java-17-headless)
|
||||
Requires: (java-11-headless or java-17-headless or java-21-headless)
|
||||
Requires: python(abi) >= 3.6
|
||||
Requires: procps-ng >= 3.3
|
||||
Requires(pre): user(cassandra)
|
||||
|
|
|
|||
|
|
@ -4779,27 +4779,46 @@ public class DatabaseDescriptor
|
|||
|
||||
public static void setGCLogThreshold(int threshold)
|
||||
{
|
||||
if (threshold <= 0)
|
||||
throw new IllegalArgumentException("Threshold value for gc_log_threshold must be greater than 0");
|
||||
|
||||
long gcWarnThresholdInMs = getGCWarnThreshold();
|
||||
if (gcWarnThresholdInMs != 0 && threshold > gcWarnThresholdInMs)
|
||||
throw new IllegalArgumentException("Threshold value for gc_log_threshold (" + threshold + ") must be less than gc_warn_threshold which is currently "
|
||||
+ gcWarnThresholdInMs);
|
||||
|
||||
validateGCParams(threshold, getGCWarnThreshold());
|
||||
conf.gc_log_threshold = new DurationSpec.IntMillisecondsBound(threshold);
|
||||
}
|
||||
|
||||
public static void validateGCParams(long logThreshold, long warnThreshold)
|
||||
{
|
||||
if (logThreshold <= 0)
|
||||
throw new IllegalArgumentException("Threshold value for gc_log*_threshold must be greater than 0");
|
||||
if (logThreshold > Integer.MAX_VALUE)
|
||||
throw new IllegalArgumentException("Threshold value for gc_log*_threshold must be less than Integer.MAX_VALUE");
|
||||
|
||||
if (warnThreshold <= 0)
|
||||
throw new IllegalArgumentException("Threshold value for gc_warn*_threshold must be greater than 0");
|
||||
if (warnThreshold > Integer.MAX_VALUE)
|
||||
throw new IllegalArgumentException("Threshold value for gc_warn*_threshold must be less than Integer.MAX_VALUE");
|
||||
|
||||
if (warnThreshold != 0 && logThreshold > warnThreshold)
|
||||
throw new IllegalArgumentException("Threshold value for gc_log*_threshold (" + logThreshold + ") must be less than gc_warn*_threshold which is currently "
|
||||
+ warnThreshold);
|
||||
}
|
||||
|
||||
public static EncryptionContext getEncryptionContext()
|
||||
{
|
||||
return encryptionContext;
|
||||
|
||||
}
|
||||
|
||||
public static long getGCWarnThreshold()
|
||||
{
|
||||
return conf.gc_warn_threshold.toMilliseconds();
|
||||
}
|
||||
|
||||
public static void setGCWarnThreshold(int threshold)
|
||||
public static void setGCWarnThreshold(long threshold)
|
||||
{
|
||||
if (threshold < 0)
|
||||
throw new IllegalArgumentException("Threshold value for gc_warn_threshold must be greater than or equal to 0");
|
||||
|
||||
if (threshold > Integer.MAX_VALUE)
|
||||
throw new IllegalArgumentException("Threshold must be less than Integer.MAX_VALUE");
|
||||
|
||||
long gcLogThresholdInMs = getGCLogThreshold();
|
||||
if (threshold != 0 && threshold <= gcLogThresholdInMs)
|
||||
throw new IllegalArgumentException("Threshold value for gc_warn_threshold (" + threshold + ") must be greater than gc_log_threshold which is currently "
|
||||
|
|
@ -4844,11 +4863,6 @@ public class DatabaseDescriptor
|
|||
conf.gc_concurrent_phase_warn_threshold = new DurationSpec.IntMillisecondsBound(threshold);
|
||||
}
|
||||
|
||||
public static EncryptionContext getEncryptionContext()
|
||||
{
|
||||
return encryptionContext;
|
||||
}
|
||||
|
||||
public static boolean isCDCEnabled()
|
||||
{
|
||||
return conf.cdc_enabled;
|
||||
|
|
|
|||
|
|
@ -640,6 +640,7 @@ public abstract class CommitLogSegment
|
|||
{
|
||||
TableMetadata m = Schema.instance.getTableMetadata(tableId);
|
||||
sb.append(m == null ? "<deleted>" : m.name).append(" (").append(tableId)
|
||||
.append(", keyspace: ").append(m.keyspace)
|
||||
.append(", dirty: ").append(tableDirty.get(tableId))
|
||||
.append(", clean: ").append(tableClean.get(tableId))
|
||||
.append("), ");
|
||||
|
|
|
|||
|
|
@ -790,7 +790,7 @@ abstract class AbstractPatriciaTrie<K, V> extends AbstractTrie<K, V>
|
|||
* This is implemented by going always to the left until
|
||||
* we encounter a valid uplink. That uplink is the first key.
|
||||
*/
|
||||
TrieEntry<K, V> firstEntry()
|
||||
public TrieEntry<K, V> firstEntry()
|
||||
{
|
||||
// if Trie is empty, no first node.
|
||||
return isEmpty() ? null : followLeft(root);
|
||||
|
|
|
|||
|
|
@ -422,7 +422,7 @@ public class PatriciaTrie<K, V> extends AbstractPatriciaTrie<K, V> implements Se
|
|||
* <p>This is implemented by going always to the right until
|
||||
* we encounter a valid uplink. That uplink is the last key.
|
||||
*/
|
||||
private TrieEntry<K, V> lastEntry()
|
||||
public TrieEntry<K, V> lastEntry()
|
||||
{
|
||||
return followRight(root.left);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -517,4 +517,10 @@ public class RepairSession extends AsyncFuture<RepairSessionResult> implements I
|
|||
delegate.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public int syncingCount()
|
||||
{
|
||||
return syncingTasks.size();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,15 +123,17 @@ public class GCInspector implements NotificationListener, GCInspectorMXBean
|
|||
final GarbageCollectorMXBean gcBean;
|
||||
final boolean assumeGCIsPartiallyConcurrent;
|
||||
final boolean assumeGCIsOldGen;
|
||||
final boolean isZGC;
|
||||
private String[] keys;
|
||||
long lastGcTotalDuration = 0;
|
||||
|
||||
|
||||
GCState(GarbageCollectorMXBean gcBean, boolean assumeGCIsPartiallyConcurrent, boolean assumeGCIsOldGen)
|
||||
GCState(GarbageCollectorMXBean gcBean, boolean assumeGCIsPartiallyConcurrent, boolean assumeGCIsOldGen, boolean isZGC)
|
||||
{
|
||||
this.gcBean = gcBean;
|
||||
this.assumeGCIsPartiallyConcurrent = assumeGCIsPartiallyConcurrent;
|
||||
this.assumeGCIsOldGen = assumeGCIsOldGen;
|
||||
this.isZGC = isZGC;
|
||||
}
|
||||
|
||||
String[] keys(GarbageCollectionNotificationInfo info)
|
||||
|
|
@ -144,6 +146,11 @@ public class GCInspector implements NotificationListener, GCInspectorMXBean
|
|||
|
||||
return keys;
|
||||
}
|
||||
|
||||
public boolean isZGC()
|
||||
{
|
||||
return isZGC;
|
||||
}
|
||||
}
|
||||
|
||||
final AtomicReference<State> state = new AtomicReference<>(new State());
|
||||
|
|
@ -158,7 +165,7 @@ public class GCInspector implements NotificationListener, GCInspectorMXBean
|
|||
for (ObjectName name : MBeanWrapper.instance.queryNames(gcName, null))
|
||||
{
|
||||
GarbageCollectorMXBean gc = ManagementFactory.newPlatformMXBeanProxy(MBeanWrapper.instance.getMBeanServer(), name.getCanonicalName(), GarbageCollectorMXBean.class);
|
||||
gcStates.put(gc.getName(), new GCState(gc, assumeGCIsPartiallyConcurrent(gc), assumeGCIsOldGen(gc)));
|
||||
gcStates.put(gc.getName(), new GCState(gc, assumeGCIsPartiallyConcurrent(gc), assumeGCIsOldGen(gc), isZGC(gc)));
|
||||
}
|
||||
ObjectName me = new ObjectName(MBEAN_NAME);
|
||||
if (!MBeanWrapper.instance.isRegistered(me))
|
||||
|
|
@ -182,32 +189,45 @@ public class GCInspector implements NotificationListener, GCInspectorMXBean
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean isZGC(GarbageCollectorMXBean gc)
|
||||
{
|
||||
return gc.getName().contains("ZGC");
|
||||
}
|
||||
|
||||
/*
|
||||
* Assume that a GC type is at least partially concurrent and so a side channel method
|
||||
* should be used to calculate application stopped time due to the GC.
|
||||
*
|
||||
* If the GC isn't recognized then assume that is concurrent and we need to do our own calculation
|
||||
* via the the side channel.
|
||||
* via the side channel.
|
||||
*/
|
||||
private static boolean assumeGCIsPartiallyConcurrent(GarbageCollectorMXBean gc)
|
||||
{
|
||||
switch (gc.getName())
|
||||
{
|
||||
//First two are from the serial collector
|
||||
// First two are from the serial collector
|
||||
case "Copy":
|
||||
case "MarkSweepCompact":
|
||||
//Parallel collector
|
||||
// Parallel collector
|
||||
case "PS MarkSweep":
|
||||
case "PS Scavenge":
|
||||
case "G1 Young Generation":
|
||||
//CMS young generation collector
|
||||
// CMS young generation collector
|
||||
case "ParNew":
|
||||
// gen zgc
|
||||
case "ZGC Minor Pauses":
|
||||
case "ZGC Major Pauses":
|
||||
// zgc
|
||||
case "ZGC Pauses":
|
||||
return false;
|
||||
case "ConcurrentMarkSweep":
|
||||
case "G1 Old Generation":
|
||||
case "ZGC Minor Cycles":
|
||||
case "ZGC Major Cycles":
|
||||
case "ZGC Cycles":
|
||||
return true;
|
||||
default:
|
||||
//Assume possibly concurrent if unsure
|
||||
// Assume possibly concurrent if unsure
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -226,15 +246,22 @@ public class GCInspector implements NotificationListener, GCInspectorMXBean
|
|||
case "PS Scavenge":
|
||||
case "G1 Young Generation":
|
||||
case "ParNew":
|
||||
case "ZGC Minor Cycles":
|
||||
case "ZGC Minor Pauses":
|
||||
return false;
|
||||
case "MarkSweepCompact":
|
||||
case "PS MarkSweep":
|
||||
case "ConcurrentMarkSweep":
|
||||
case "G1 Old Generation":
|
||||
case "ZGC Major Cycles":
|
||||
case "ZGC Major Pauses":
|
||||
// assume non-generational zgc is old gen
|
||||
case "ZGC Cycles":
|
||||
case "ZGC Pauses":
|
||||
return true;
|
||||
default:
|
||||
//Assume not old gen otherwise, don't call
|
||||
//TransactionLogs.rescheduleFailedTasks()
|
||||
// Assume not old gen otherwise, don't call
|
||||
// TransactionLogs.rescheduleFailedTasks()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -425,9 +452,15 @@ public class GCInspector implements NotificationListener, GCInspectorMXBean
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* While we _technically_ could only set the threshold based on which GC we're running, there's really no
|
||||
* perceptable value-add from doing that. Responsibility for enforcing the validity of the params is entrusted
|
||||
* to the {@link DatabaseDescriptor}
|
||||
*/
|
||||
@Override
|
||||
public void setGcWarnThresholdInMs(long threshold)
|
||||
{
|
||||
DatabaseDescriptor.setGCWarnThreshold((int)threshold);
|
||||
DatabaseDescriptor.setGCWarnThreshold(threshold);
|
||||
}
|
||||
|
||||
public long getGcWarnThresholdInMs()
|
||||
|
|
|
|||
|
|
@ -1216,7 +1216,7 @@ public interface StorageServiceMBean extends NotificationEmitter
|
|||
* Start the fully query logger.
|
||||
*
|
||||
* @param path Path where the full query log will be stored. If null cassandra.yaml value is used.
|
||||
* @param rollCycle How often to create a new file for query data (MINUTELY, DAILY, HOURLY)
|
||||
* @param rollCycle How often to create a new file for query data (FIVE_MINUTELY, FAST_DAILY, FAST_HOURLY)
|
||||
* @param blocking Whether threads submitting queries to the query log should block if they can't be drained to the filesystem or alternatively drops samples and log
|
||||
* @param maxQueueWeight How many bytes of query data to queue before blocking or dropping samples
|
||||
* @param maxLogSize How many bytes of log data to store before dropping segments. Might not be respected if a log file hasn't rolled so it can be deleted.
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ public class AuditLogViewer
|
|||
private static class AuditLogViewerOptions
|
||||
{
|
||||
private final List<String> pathList;
|
||||
private String rollCycle = "HOURLY";
|
||||
private String rollCycle = "FAST_HOURLY";
|
||||
private boolean follow;
|
||||
private boolean ignoreUnsupported;
|
||||
|
||||
|
|
@ -238,7 +238,7 @@ public class AuditLogViewer
|
|||
{
|
||||
Options options = new Options();
|
||||
|
||||
options.addOption(new Option("r", ROLL_CYCLE, true, "How often to roll the log file was rolled. May be necessary for Chronicle to correctly parse file names. (MINUTELY, HOURLY, DAILY). Default HOURLY."));
|
||||
options.addOption(new Option("r", ROLL_CYCLE, true, "How often to roll the log file was rolled. May be necessary for Chronicle to correctly parse file names. (FIVE_MINUTELY, FAST_HOURLY, FAST_DAILY). Default FAST_HOURLY."));
|
||||
options.addOption(new Option("f", FOLLOW, false, "Upon reacahing the end of the log continue indefinitely waiting for more records"));
|
||||
options.addOption(new Option("i", IGNORE, false, "Silently ignore unsupported records"));
|
||||
options.addOption(new Option("h", HELP_OPTION, false, "display this help message"));
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ public class EnableAuditLog extends AbstractCommand
|
|||
@Option(paramLabel = "excluded_users", names = { "--excluded-users" }, description = "Comma separated list of users to be excluded for audit log. If not set the value from cassandra.yaml will be used")
|
||||
private String excluded_users = null;
|
||||
|
||||
@Option(paramLabel = "roll_cycle", names = { "--roll-cycle" }, description = "How often to roll the log file (MINUTELY, HOURLY, DAILY).")
|
||||
@Option(paramLabel = "roll_cycle", names = { "--roll-cycle" }, description = "How often to roll the log file (FAST_MINUTELY, FAST_HOURLY, FAST_DAILY).")
|
||||
private String rollCycle = null;
|
||||
|
||||
@Option(paramLabel = "blocking", names = { "--blocking" }, description = "If the queue is full whether to block producers or drop samples [true|false].")
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import picocli.CommandLine.Option;
|
|||
@Command(name = "enablefullquerylog", description = "Enable full query logging, defaults for the options are configured in cassandra.yaml")
|
||||
public class EnableFullQueryLog extends AbstractCommand
|
||||
{
|
||||
@Option(paramLabel = "roll_cycle", names = { "--roll-cycle" }, description = "How often to roll the log file (MINUTELY, HOURLY, DAILY).")
|
||||
@Option(paramLabel = "roll_cycle", names = { "--roll-cycle" }, description = "How often to roll the log file (FAST_MINUTELY, FAST_HOURLY, FAST_DAILY).")
|
||||
private String rollCycle = null;
|
||||
|
||||
@Option(paramLabel = "blocking", names = { "--blocking" }, description = "If the queue is full whether to block producers or drop samples [true|false].")
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public final class JavaUtils
|
|||
* @return the java version number
|
||||
* @throws NumberFormatException if the version cannot be retrieved
|
||||
*/
|
||||
private static int parseJavaVersion(String jreVersion)
|
||||
public static int parseJavaVersion(String jreVersion)
|
||||
{
|
||||
String version;
|
||||
if (jreVersion.startsWith("1."))
|
||||
|
|
|
|||
|
|
@ -1630,6 +1630,12 @@ public class MerkleTree
|
|||
return getHelper(root, fullRange.left, fullRange.right, t);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public boolean isReleased()
|
||||
{
|
||||
return root == null;
|
||||
}
|
||||
|
||||
private TreeRange getHelper(Node node, Token pleft, Token pright, Token t)
|
||||
{
|
||||
int depth = 0;
|
||||
|
|
|
|||
|
|
@ -458,4 +458,19 @@ public class MerkleTrees implements Iterable<Map.Entry<Range<Token>, MerkleTree>
|
|||
return rt1.compareTo(rt2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For purposes of our checking in test, either "nothing is or was ever here" or "what was here is now gone" suffice.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public boolean isReleased()
|
||||
{
|
||||
if (merkleTrees.isEmpty())
|
||||
return true;
|
||||
|
||||
boolean result = true;
|
||||
for (MerkleTree mt : merkleTrees.values())
|
||||
result &= mt.isReleased();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@ import static org.github.jamm.utils.ArrayMeasurementUtils.computeArraySize;
|
|||
*/
|
||||
public class ObjectSizes
|
||||
{
|
||||
/**
|
||||
* For debugging purposes, you can construct this with .printVisitedTree() to get a printout of all the objects
|
||||
* and their calculated size on heap to debug jamm related issues. See:
|
||||
* <a href="https://github.com/jbellis/jamm/blob/master/README.md#visited-object-tree">README.md on github</a>
|
||||
*/
|
||||
private static final MemoryMeter meter = MemoryMeter.builder().withGuessing(Guess.INSTRUMENTATION_AND_SPECIFICATION,
|
||||
Guess.UNSAFE)
|
||||
.build();
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import net.openhft.chronicle.queue.ExcerptAppender;
|
|||
import net.openhft.chronicle.queue.RollCycles;
|
||||
import net.openhft.chronicle.queue.impl.single.SingleChronicleQueue;
|
||||
import net.openhft.chronicle.queue.impl.single.SingleChronicleQueueBuilder;
|
||||
import net.openhft.chronicle.queue.rollcycles.TestRollCycles;
|
||||
import net.openhft.chronicle.wire.WireOut;
|
||||
import net.openhft.chronicle.wire.WriteMarshallable;
|
||||
import net.openhft.posix.PosixAPI;
|
||||
|
|
@ -55,6 +56,7 @@ import org.apache.cassandra.utils.concurrent.UncheckedInterruptedException;
|
|||
import org.apache.cassandra.utils.concurrent.WeightedQueue;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static net.openhft.chronicle.queue.rollcycles.TestRollCycles.TEST_SECONDLY;
|
||||
import static org.apache.cassandra.config.CassandraRelevantProperties.CHRONICLE_ANNOUNCER_DISABLE;
|
||||
import static org.apache.cassandra.utils.LocalizeString.toUpperCaseLocalized;
|
||||
|
||||
|
|
@ -140,7 +142,11 @@ public class BinLog implements Runnable
|
|||
Preconditions.checkNotNull(options.roll_cycle, "roll_cycle was null");
|
||||
Preconditions.checkArgument(options.max_queue_weight > 0, "max_queue_weight must be > 0");
|
||||
SingleChronicleQueueBuilder builder = SingleChronicleQueueBuilder.single(path.toFile()); // checkstyle: permit this invocation
|
||||
builder.rollCycle(RollCycles.valueOf(options.roll_cycle));
|
||||
|
||||
// RollCycles.TEST_SECONDLY is deprecated; avoid logging a warning here in cases where test code may be referencing the old value.
|
||||
builder.rollCycle(options.roll_cycle.equals("TEST_SECONDLY")
|
||||
? TEST_SECONDLY
|
||||
: RollCycles.valueOf(options.roll_cycle));
|
||||
|
||||
sampleQueue = new WeightedQueue<>(options.max_queue_weight);
|
||||
this.archiver = archiver;
|
||||
|
|
@ -394,7 +400,10 @@ public class BinLog implements Runnable
|
|||
Preconditions.checkNotNull(rollCycle, "rollCycle was null");
|
||||
rollCycle = toUpperCaseLocalized(rollCycle);
|
||||
Preconditions.checkNotNull(RollCycles.valueOf(rollCycle), "unrecognized roll cycle");
|
||||
this.rollCycle = rollCycle;
|
||||
// Avoid using deprecated RollCycles.TEST_SECONDLY in test cases where we pass the text blindly; logs a warning
|
||||
this.rollCycle = rollCycle.equals("TEST_SECONDLY")
|
||||
? TestRollCycles.TEST_SECONDLY.toString()
|
||||
: rollCycle;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,11 +31,12 @@ public class BinLogOptions
|
|||
*/
|
||||
public boolean allow_nodetool_archive_command = false;
|
||||
/**
|
||||
* How often to roll BinLog segments so they can potentially be reclaimed. Available options are:
|
||||
* MINUTELY, HOURLY, DAILY, LARGE_DAILY, XLARGE_DAILY, HUGE_DAILY.
|
||||
* For more options, refer: net.openhft.chronicle.queue.RollCycles
|
||||
* How often to roll BinLog segments so they can potentially be reclaimed. Some available options are:
|
||||
* FIVE_MINUTELY, FAST_HOURLY, FAST_DAILY, LargeRollCycles.LARGE_DAILY, LargeRollCycles.XLARGE_DAILY, LargeRollCycles.HUGE_DAILY.
|
||||
* See FAQ: <a href="https://github.com/OpenHFT/Chronicle-Queue/blob/50af322d0022fb8d265779ed6f4c1073d32b6b54/docs/FAQ.adoc" />
|
||||
* For more options, refer: {@link net.openhft.chronicle.queue.RollCycles}
|
||||
*/
|
||||
public String roll_cycle = "HOURLY";
|
||||
public String roll_cycle = "FAST_HOURLY";
|
||||
/**
|
||||
* Indicates if the BinLog should block if the it falls behind or should drop bin log records.
|
||||
* Default is set to true so that BinLog records wont be lost
|
||||
|
|
|
|||
|
|
@ -328,6 +328,40 @@ public class BTreeSet<V> extends AbstractSet<V> implements NavigableSet<V>, List
|
|||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
public BTreeSet<V> reversed()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public V removeLast()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public V removeFirst()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public V getLast()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public V getFirst()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void addLast(V v)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void addFirst(V v)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public static class BTreeRange<V> extends BTreeSet<V>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -125,6 +125,10 @@ public final class Ref<T> implements RefCounted<T>
|
|||
public static final boolean DEBUG_EVENTS_ENABLED = TEST_DEBUG_REF_EVENTS.getBoolean();
|
||||
static OnLeak ON_LEAK;
|
||||
|
||||
/** NOT INTENDED FOR USE OUTSIDE TESTS AND DEBUGGING */
|
||||
@VisibleForTesting
|
||||
private static boolean TEST_TRACE_ENABLED = false;
|
||||
|
||||
@Shared(scope = SIMULATION)
|
||||
public interface OnLeak
|
||||
{
|
||||
|
|
@ -146,6 +150,14 @@ public final class Ref<T> implements RefCounted<T>
|
|||
this.referent = referent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generally don't go around mutating this willy-nilly in non-test code please.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static void enableTestTracing() { TEST_TRACE_ENABLED = true; }
|
||||
@VisibleForTesting
|
||||
public static void disableTestTracing() { TEST_TRACE_ENABLED = false; }
|
||||
|
||||
/**
|
||||
* Must be called exactly once, when the logical operation for which this Ref was created has terminated.
|
||||
* Failure to abide by this contract will result in an error (eventually) being reported, assuming a
|
||||
|
|
@ -629,7 +641,7 @@ public final class Ref<T> implements RefCounted<T>
|
|||
{
|
||||
if (Thread.currentThread().isInterrupted())
|
||||
throw new UncheckedInterruptedException(new InterruptedException());
|
||||
//If necessary fetch the next object to start tracing
|
||||
// If necessary fetch the next object to start tracing
|
||||
if (inProgress == null)
|
||||
inProgress = path.pollLast();
|
||||
|
||||
|
|
@ -646,6 +658,25 @@ public final class Ref<T> implements RefCounted<T>
|
|||
field = p.right;
|
||||
}
|
||||
|
||||
if (TEST_TRACE_ENABLED)
|
||||
{
|
||||
logger.debug("[Ref tracing for {}, Object: {}]", rootObject, child);
|
||||
if (field != null && child != null)
|
||||
{
|
||||
logger.debug(" - Visiting field '{}' of object {} -> value class {}",
|
||||
field.getName(),
|
||||
inProgress.o.getClass().getName(),
|
||||
child.getClass().getName());
|
||||
}
|
||||
else if (field != null)
|
||||
{
|
||||
// Field exists but the next child is null – still useful to know the path.
|
||||
logger.debug(" - Visiting field '{}' of object {} -> value is null",
|
||||
field.getName(),
|
||||
inProgress.o.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (child != null && visited.add(child))
|
||||
{
|
||||
path.offer(inProgress);
|
||||
|
|
|
|||
|
|
@ -83,7 +83,8 @@ OPTIONS
|
|||
Path to the JMX password file
|
||||
|
||||
--roll-cycle <roll_cycle>
|
||||
How often to roll the log file (MINUTELY, HOURLY, DAILY).
|
||||
How often to roll the log file (FAST_MINUTELY, FAST_HOURLY,
|
||||
FAST_DAILY).
|
||||
|
||||
-u <username>, --username <username>
|
||||
Remote jmx agent username
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ OPTIONS
|
|||
Path to the JMX password file
|
||||
|
||||
--roll-cycle <roll_cycle>
|
||||
How often to roll the log file (MINUTELY, HOURLY, DAILY).
|
||||
How often to roll the log file (FAST_MINUTELY, FAST_HOURLY,
|
||||
FAST_DAILY).
|
||||
|
||||
-u <username>, --username <username>
|
||||
Remote jmx agent username
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ import static org.apache.cassandra.simulator.asm.InterceptClasses.Cached.Kind.UN
|
|||
// WARNING: does not implement IClassTransformer directly as must be accessible to bootstrap class loader
|
||||
public class InterceptClasses implements BiFunction<String, byte[], byte[]>
|
||||
{
|
||||
public static final int BYTECODE_VERSION = Opcodes.ASM7;
|
||||
public static final int BYTECODE_VERSION = Opcodes.ASM9;
|
||||
|
||||
// TODO (cleanup): use annotations
|
||||
private static final Pattern MONITORS = Pattern.compile( "org[/.]apache[/.]cassandra[/.]utils[/.]concurrent[/.].*" +
|
||||
|
|
|
|||
|
|
@ -243,6 +243,12 @@ public class ShadowingTransformer extends ClassTransformer
|
|||
super.visitInnerClass(name, toShadowType(outerName), innerName, access);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPermittedSubclass(String permittedSubclass)
|
||||
{
|
||||
super.visitPermittedSubclass(toShadowType(permittedSubclass));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ package org.apache.cassandra.simulator.systems;
|
|||
import java.util.ArrayDeque;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.LongConsumer;
|
||||
import java.util.function.ToIntFunction;
|
||||
|
|
@ -487,21 +488,35 @@ public interface InterceptorOfGlobalMethods extends InterceptorOfSystemMethods,
|
|||
|
||||
private final IntSupplier nextId;
|
||||
private final WeakIdentityHashMap<Object, Integer> saved = new WeakIdentityHashMap<>();
|
||||
private final ReentrantLock mapLock = new ReentrantLock();
|
||||
|
||||
public IdentityHashCode(IntSupplier nextId)
|
||||
{
|
||||
this.nextId = nextId;
|
||||
}
|
||||
|
||||
public synchronized int applyAsInt(Object value)
|
||||
/**
|
||||
* As {@link #saved} is not thread safe, we want to preserve weak reference semantics, and we want to gracefully
|
||||
* support virtual threads, we need to use another locking mechanism other than synchronized since that is a risk
|
||||
* of deadlock in JDK21 as virtual threads block on held monitors and won't release.
|
||||
*/
|
||||
public int applyAsInt(Object value)
|
||||
{
|
||||
Integer id = saved.get(value);
|
||||
if (id == null)
|
||||
mapLock.lock();
|
||||
try
|
||||
{
|
||||
id = nextId.getAsInt();
|
||||
saved.put(value, id);
|
||||
Integer id = saved.get(value);
|
||||
if (id == null)
|
||||
{
|
||||
id = nextId.getAsInt();
|
||||
saved.put(value, id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
finally
|
||||
{
|
||||
mapLock.unlock();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@ import static org.apache.cassandra.simulator.RandomSource.Choices.uniform;
|
|||
// TODO (cleanup): when we encounter an exception and unwind the simulation, we should restore normal time to go with normal waits etc.
|
||||
public class SimulatedTime
|
||||
{
|
||||
private static final Pattern PERMITTED_TIME_THREADS = Pattern.compile("(logback|SimulationLiveness|Reconcile)[-:][0-9]+|RMI Scheduler\\(\\d+\\)");
|
||||
private static final Pattern PERMITTED_TIME_THREADS = Pattern.compile("(logback|SimulationLiveness|Reconcile|Reference-Reaper)[-:][0-9]+|RMI Scheduler\\(\\d+\\)");
|
||||
private static final Pattern PERMITTED_TIME_CLEANER_THREADS = Pattern.compile("(LocalPool-Cleaner[-a-z]+[-:][0-9]+|Common-Cleaner)");
|
||||
|
||||
@Shared(scope = Shared.Scope.SIMULATION)
|
||||
public interface Listener
|
||||
|
|
@ -148,7 +149,7 @@ public class SimulatedTime
|
|||
if (interceptibleThread.isIntercepting())
|
||||
return interceptibleThread.time();
|
||||
}
|
||||
if (PERMITTED_TIME_THREADS.matcher(Thread.currentThread().getName()).matches())
|
||||
if (PERMITTED_TIME_THREADS.matcher(Thread.currentThread().getName()).matches() || PERMITTED_TIME_CLEANER_THREADS.matcher(Thread.currentThread().getName()).matches())
|
||||
return disabled;
|
||||
throw new IllegalStateException("Using time is not allowed during simulation");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -755,7 +755,7 @@ public class AuditLoggerTest extends CQLTester
|
|||
assertEquals(1, AuthEvents.instance.listenerCount());
|
||||
|
||||
Path p = Files.createTempDirectory("fql");
|
||||
StorageService.instance.enableFullQueryLogger(p.toString(), RollCycles.HOURLY.toString(), false, 1000, 1000, null, 0);
|
||||
StorageService.instance.enableFullQueryLogger(p.toString(), RollCycles.FAST_HOURLY.toString(), false, 1000, 1000, null, 0);
|
||||
assertEquals(2, QueryEvents.instance.listenerCount());
|
||||
assertEquals(1, AuthEvents.instance.listenerCount()); // fql not listening to auth events
|
||||
StorageService.instance.resetFullQueryLogger();
|
||||
|
|
@ -778,7 +778,7 @@ public class AuditLoggerTest extends CQLTester
|
|||
{
|
||||
assertEquals(1, QueryEvents.instance.listenerCount());
|
||||
assertEquals(1, AuthEvents.instance.listenerCount());
|
||||
StorageService.instance.enableFullQueryLogger(options.audit_logs_dir, RollCycles.HOURLY.toString(), false, 1000, 1000, null, 0);
|
||||
StorageService.instance.enableFullQueryLogger(options.audit_logs_dir, RollCycles.FAST_HOURLY.toString(), false, 1000, 1000, null, 0);
|
||||
fail("Conflicting directories - should throw exception");
|
||||
}
|
||||
catch (IllegalStateException e)
|
||||
|
|
@ -796,7 +796,7 @@ public class AuditLoggerTest extends CQLTester
|
|||
disableAuditLogOptions();
|
||||
AuditLogOptions options = getBaseAuditLogOptions();
|
||||
DatabaseDescriptor.setAuditLoggingOptions(options);
|
||||
StorageService.instance.enableFullQueryLogger(options.audit_logs_dir, RollCycles.HOURLY.toString(), false, 1000, 1000, null, 0);
|
||||
StorageService.instance.enableFullQueryLogger(options.audit_logs_dir, RollCycles.FAST_HOURLY.toString(), false, 1000, 1000, null, 0);
|
||||
try
|
||||
{
|
||||
assertEquals(1, QueryEvents.instance.listenerCount());
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ import com.datastax.driver.core.Session;
|
|||
|
||||
import net.openhft.chronicle.queue.ChronicleQueue;
|
||||
import net.openhft.chronicle.queue.ExcerptTailer;
|
||||
import net.openhft.chronicle.queue.RollCycles;
|
||||
import net.openhft.chronicle.queue.impl.single.SingleChronicleQueueBuilder;
|
||||
import net.openhft.chronicle.queue.rollcycles.TestRollCycles;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
|
@ -76,7 +76,7 @@ public class BinAuditLoggerTest extends CQLTester
|
|||
ResultSet rs = session.execute(pstmt.bind(1));
|
||||
|
||||
assertEquals(1, rs.all().size());
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(tempDir.toFile()).rollCycle(RollCycles.TEST_SECONDLY).build())
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(tempDir.toFile()).rollCycle(TestRollCycles.TEST_SECONDLY).build())
|
||||
{
|
||||
ExcerptTailer tailer = queue.createTailer();
|
||||
assertTrue(tailer.readDocument(wire -> {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ public class CommitlogShutdownTest
|
|||
@BMRule(name = "Make removing commitlog segments slow",
|
||||
targetClass = "CommitLogSegment",
|
||||
targetMethod = "discard",
|
||||
action = "Thread.sleep(50)")
|
||||
action = "Thread.sleep(250L)") // We need to add the unit to Thread.sleep calls in ByteBuddy now
|
||||
public void testShutdownWithPendingTasks() throws Exception
|
||||
{
|
||||
new Random().nextBytes(entropy);
|
||||
|
|
@ -77,8 +77,7 @@ public class CommitlogShutdownTest
|
|||
KeyspaceParams.simple(1),
|
||||
SchemaLoader.standardCFMD(KEYSPACE1, STANDARD1, 0, AsciiType.instance, BytesType.instance));
|
||||
|
||||
CompactionManager.instance.disableAutoCompaction();
|
||||
|
||||
CompactionManager.instance.disableAutoCompaction();
|
||||
ColumnFamilyStore cfs1 = Keyspace.open(KEYSPACE1).getColumnFamilyStore(STANDARD1);
|
||||
|
||||
final Mutation m = new RowUpdateBuilder(cfs1.metadata.get(), 0, "k")
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public class AntiCompactionBytemanTest extends CQLTester
|
|||
targetMethod = "antiCompactGroup",
|
||||
condition = "not flagged(\"done\")",
|
||||
targetLocation = "AFTER INVOKE prepareToCommit",
|
||||
action = "Thread.sleep(2000);") } )
|
||||
action = "Thread.sleep(2000L);") } ) // We need to add the unit to Thread.sleep calls in ByteBuddy now
|
||||
public void testRedundantTransitions() throws Throwable
|
||||
{
|
||||
createTable("create table %s (id int primary key, i int)");
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ public class CompactionsBytemanTest extends CQLTester
|
|||
targetMethod = "submitBackground",
|
||||
targetLocation = "AT INVOKE java.util.concurrent.Future.isCancelled",
|
||||
condition = "!$cfs.getKeyspaceName().contains(\"system\")",
|
||||
action = "Thread.sleep(5000)")
|
||||
action = "Thread.sleep(5000L)") // We need to add the unit to Thread.sleep calls in ByteBuddy now
|
||||
public void testCompactingCFCounting() throws Throwable
|
||||
{
|
||||
createTable("CREATE TABLE %s (k INT, c INT, v INT, PRIMARY KEY (k, c))");
|
||||
|
|
|
|||
|
|
@ -45,13 +45,13 @@ public class MemtableQuickTest extends CQLTester
|
|||
{
|
||||
static final Logger logger = LoggerFactory.getLogger(MemtableQuickTest.class);
|
||||
|
||||
static final int partitions = 50_000;
|
||||
static final int partitions = 45_000;
|
||||
static final int rowsPerPartition = 4;
|
||||
|
||||
static final int deletedPartitionsStart = 20_000;
|
||||
static final int deletedPartitionsStart = 15_000;
|
||||
static final int deletedPartitionsEnd = deletedPartitionsStart + 10_000;
|
||||
|
||||
static final int deletedRowsStart = 40_000;
|
||||
static final int deletedRowsStart = 35_000;
|
||||
static final int deletedRowsEnd = deletedRowsStart + 5_000;
|
||||
|
||||
@Parameterized.Parameter()
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ import javax.annotation.Nullable;
|
|||
|
||||
import net.openhft.chronicle.queue.ChronicleQueue;
|
||||
import net.openhft.chronicle.queue.ExcerptTailer;
|
||||
import net.openhft.chronicle.queue.RollCycles;
|
||||
import net.openhft.chronicle.queue.impl.single.SingleChronicleQueueBuilder;
|
||||
import net.openhft.chronicle.queue.rollcycles.TestRollCycles;
|
||||
import net.openhft.chronicle.wire.ValueIn;
|
||||
import net.openhft.chronicle.wire.WireOut;
|
||||
|
||||
|
|
@ -323,7 +323,7 @@ public class FullQueryLoggerTest extends CQLTester
|
|||
|
||||
private boolean checkForQueries(List<String> queries)
|
||||
{
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(tempDir.toFile()).rollCycle(RollCycles.TEST_SECONDLY).build())
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(tempDir.toFile()).rollCycle(TestRollCycles.TEST_SECONDLY).build())
|
||||
{
|
||||
ExcerptTailer tailer = queue.createTailer();
|
||||
List<String> expectedQueries = new LinkedList<>(queries);
|
||||
|
|
@ -434,7 +434,7 @@ public class FullQueryLoggerTest extends CQLTester
|
|||
|
||||
private void assertRoundTripQuery(@Nullable String keyspace)
|
||||
{
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(tempDir.toFile()).rollCycle(RollCycles.TEST_SECONDLY).build())
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(tempDir.toFile()).rollCycle(TestRollCycles.TEST_SECONDLY).build())
|
||||
{
|
||||
ExcerptTailer tailer = queue.createTailer();
|
||||
assertTrue(tailer.readDocument(wire ->
|
||||
|
|
@ -473,7 +473,7 @@ public class FullQueryLoggerTest extends CQLTester
|
|||
|
||||
Util.spinAssertEquals(true, () ->
|
||||
{
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(tempDir.toFile()).rollCycle(RollCycles.TEST_SECONDLY).build())
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(tempDir.toFile()).rollCycle(TestRollCycles.TEST_SECONDLY).build())
|
||||
{
|
||||
return queue.createTailer().readingDocument().isPresent();
|
||||
}
|
||||
|
|
@ -497,7 +497,7 @@ public class FullQueryLoggerTest extends CQLTester
|
|||
|
||||
Util.spinAssertEquals(true, () ->
|
||||
{
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(tempDir.toFile()).rollCycle(RollCycles.TEST_SECONDLY).build())
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(tempDir.toFile()).rollCycle(TestRollCycles.TEST_SECONDLY).build())
|
||||
{
|
||||
return queue.createTailer().readingDocument().isPresent();
|
||||
}
|
||||
|
|
@ -509,7 +509,7 @@ public class FullQueryLoggerTest extends CQLTester
|
|||
|
||||
private void assertRoundTripBatch(@Nullable String keyspace)
|
||||
{
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(tempDir.toFile()).rollCycle(RollCycles.TEST_SECONDLY).build())
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(tempDir.toFile()).rollCycle(TestRollCycles.TEST_SECONDLY).build())
|
||||
{
|
||||
ExcerptTailer tailer = queue.createTailer();
|
||||
assertTrue(tailer.readDocument(wire -> {
|
||||
|
|
|
|||
|
|
@ -22,9 +22,12 @@ import java.time.Duration;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.awaitility.Awaitility;
|
||||
import org.jboss.byteman.contrib.bmunit.BMRule;
|
||||
import org.jboss.byteman.contrib.bmunit.BMUnitConfig;
|
||||
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
|
@ -91,12 +94,14 @@ public class HintServiceBytemanTest
|
|||
HintsService.instance.startDispatch();
|
||||
}
|
||||
|
||||
@Test
|
||||
// When this test hangs it does it _hard_. Working now but don't want to make the worker in CI hang out for full timeout.
|
||||
@Test (timeout = 300000)
|
||||
@BMUnitConfig(bmunitVerbose=true, verbose=true)
|
||||
@BMRule(name = "Delay delivering hints",
|
||||
targetClass = "DispatchHintsTask",
|
||||
targetMethod = "run",
|
||||
action = "Thread.sleep(DatabaseDescriptor.getHintsFlushPeriodInMS() * 3L)")
|
||||
public void testListPendingHints() throws InterruptedException, ExecutionException
|
||||
public void testListPendingHints() throws InterruptedException, ExecutionException, TimeoutException
|
||||
{
|
||||
HintsService.instance.resumeDispatch();
|
||||
MockMessagingSpy spy = sendHintsAndResponses(metadata, 20000, -1);
|
||||
|
|
@ -111,7 +116,9 @@ public class HintServiceBytemanTest
|
|||
assertEquals(1, info.totalFiles);
|
||||
assertEquals(info.oldestTimestamp, info.newestTimestamp); // there is 1 descriptor with only 1 timestamp
|
||||
|
||||
spy.interceptMessageOut(20000).get();
|
||||
// JDK21 genZGC uncovered some flakiness / hanging here waiting on Condition
|
||||
spy.interceptMessageOut(20000).get(60, TimeUnit.SECONDS);
|
||||
spy.printMessageCounts();
|
||||
assertEquals(Collections.emptyList(), HintsService.instance.getPendingHints());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@ import com.google.common.util.concurrent.MoreExecutors;
|
|||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.Timeout;
|
||||
|
||||
import accord.primitives.Keys;
|
||||
import accord.primitives.TxnId;
|
||||
|
|
@ -64,6 +66,7 @@ import org.apache.cassandra.tcm.ClusterMetadata;
|
|||
import org.apache.cassandra.transport.Dispatcher;
|
||||
import org.apache.cassandra.utils.MockFailureDetector;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static org.apache.cassandra.Util.spinAssertEquals;
|
||||
import static org.apache.cassandra.config.CassandraRelevantProperties.HINT_DISPATCH_INTERVAL_MS;
|
||||
import static org.apache.cassandra.hints.HintsTestUtil.sendHintsAndResponses;
|
||||
|
|
@ -83,6 +86,14 @@ public class HintsServiceTest
|
|||
private final MockFailureDetector failureDetector = new MockFailureDetector();
|
||||
private static TableMetadata metadata;
|
||||
|
||||
// Had some trouble with this test OOM'ing and misbehaving; trying to tighten things up a bit. It's good now but leaving
|
||||
// this here to defend against future long CI hangs making workers burn cycles.
|
||||
@Rule
|
||||
public final Timeout perTestTimeout = Timeout.builder()
|
||||
.withTimeout(8, MINUTES) // match test.timeout in build.xml
|
||||
.withLookingForStuckThread(true) // dumps stack of a likely stuck thread
|
||||
.build();
|
||||
|
||||
@BeforeClass
|
||||
public static void defineSchema()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ import org.apache.cassandra.locator.InetAddressAndPort;
|
|||
*/
|
||||
public class MockMessagingService
|
||||
{
|
||||
|
||||
private MockMessagingService()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,12 +36,37 @@ import org.slf4j.LoggerFactory;
|
|||
import static org.apache.cassandra.utils.concurrent.BlockingQueues.newBlockingQueue;
|
||||
|
||||
/**
|
||||
* Allows inspecting the behavior of mocked messaging by observing {@link MatcherResponse}.
|
||||
* Test utility that spies on mocked messaging interactions.
|
||||
*
|
||||
* <p>This class records inbound mocked messages and outbound messages that would have been
|
||||
* sent, allowing tests to capture, assert or wait for specific communication patterns.</p>
|
||||
*
|
||||
* <h2>Debug logging</h2>
|
||||
* <p>The internal {@code debugLog} method writes detailed information about the spy’s
|
||||
* activity. By default, the logger uses TRACE level; to make the output visible at INFO
|
||||
* level, set the environment variable {@code MOCK_MESSAGING_SPY_DEBUG=true} before starting
|
||||
* the JVM.
|
||||
*
|
||||
* @see MatcherResponse
|
||||
* @see MockMessagingService
|
||||
*/
|
||||
public class MockMessagingSpy
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(MockMessagingSpy.class);
|
||||
|
||||
// checkstyle: suppress below 'blockSystemPropertyUsage'
|
||||
private static boolean DEBUG_ENABLED = Boolean.parseBoolean(System.getenv("MOCK_MESSAGING_SPY_DEBUG"));
|
||||
private void debugLog(String format, Object... args)
|
||||
{
|
||||
if (DEBUG_ENABLED)
|
||||
logger.info(format, args);
|
||||
else
|
||||
logger.trace(format, args);
|
||||
}
|
||||
|
||||
public static void enableDebug() {DEBUG_ENABLED = true; }
|
||||
public static void disableDebug() {DEBUG_ENABLED = false; }
|
||||
|
||||
private final AtomicInteger messagesIntercepted = new AtomicInteger();
|
||||
private final AtomicInteger mockedMessageResponses = new AtomicInteger();
|
||||
|
||||
|
|
@ -142,17 +167,22 @@ public class MockMessagingSpy
|
|||
return mockedMessageResponses.get();
|
||||
}
|
||||
|
||||
public void printMessageCounts()
|
||||
{
|
||||
logger.info("Messages intercepted: {}. Mocked Message responses: {}", messagesIntercepted(), mockedMessageResponses());
|
||||
}
|
||||
|
||||
void matchingMessage(Message<?> message)
|
||||
{
|
||||
messagesIntercepted.incrementAndGet();
|
||||
logger.trace("Received matching message: {}", message);
|
||||
int count = messagesIntercepted.incrementAndGet();
|
||||
debugLog("messagesInterceptedCount: {}. Received matching message: {}", count, message);
|
||||
interceptedMessages.add(message);
|
||||
}
|
||||
|
||||
void matchingResponse(Message<?> response)
|
||||
{
|
||||
mockedMessageResponses.incrementAndGet();
|
||||
logger.trace("Responding to intercepted message: {}", response);
|
||||
int count = mockedMessageResponses.incrementAndGet();
|
||||
debugLog("mockedMessageResponseCount: {}. Responding to intercepted message: {}", count, response);
|
||||
deliveredResponses.add(response);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -266,6 +266,10 @@ public class RepairJobTest
|
|||
|
||||
long singleTreeSize = ObjectSizes.measureDeep(mockTrees.get(addr1));
|
||||
|
||||
assertEquals(0, session.syncingCount());
|
||||
for (var mt : mockTrees.values())
|
||||
assertThat(mt.isReleased()).isFalse();
|
||||
|
||||
// Use addr4 instead of one of the provided trees to force everything to be remote sync tasks as
|
||||
// LocalSyncTasks try to reach over the network.
|
||||
List<SyncTask> syncTasks = RepairJob.createStandardSyncTasks(SharedContext.Global.instance, sessionJobDesc, mockTreeResponses,
|
||||
|
|
@ -275,30 +279,41 @@ public class RepairJobTest
|
|||
session.pullRepair,
|
||||
session.previewKind);
|
||||
|
||||
// All trees in our mockTrees should be released after SyncTask creation
|
||||
for (var mt : mockTrees.values())
|
||||
assertThat(mt.isReleased()).isTrue();
|
||||
assertThat(session.syncingCount()).isEqualTo(0);
|
||||
|
||||
// SyncTasks themselves should not contain significant memory
|
||||
SyncTaskListAssert.assertThat(syncTasks).hasSizeLessThan(0.2 * singleTreeSize);
|
||||
|
||||
// Remember the size of the session before we've executed any tasks
|
||||
long sizeBeforeExecution = ObjectSizes.measureDeep(session);
|
||||
// We can't directly check the memory size in the session post JDK21; jamm has trouble walking the internal
|
||||
// object graph of a ConcurrentHashMap's implementation post JDK21 and has bugs with the @Contended case (which
|
||||
// indicates we should consider moving away from it... jamm, that is. Which we've discussed as a project).
|
||||
// Instead, we treat the presence or removal of SyncTasks as indicative of the memory usage since the reference
|
||||
// to the MerkleTrees lives on there after creation.
|
||||
|
||||
// block syncComplete execution until test has verified session still retains the trees
|
||||
CompletableFuture<?> future = new CompletableFuture<>();
|
||||
session.registerSyncCompleteCallback(future::get);
|
||||
ListenableFuture<List<SyncStat>> syncResults = job.executeTasks(syncTasks);
|
||||
|
||||
// Immediately following execution the internal execution queue should still retain the trees
|
||||
long sizeDuringExecution = ObjectSizes.measureDeep(session);
|
||||
assertThat(sizeDuringExecution).isGreaterThan(sizeBeforeExecution + (syncTasks.size() * singleTreeSize));
|
||||
ListenableFuture<List<SyncStat>> syncResults = job.executeTasks(syncTasks);
|
||||
// Immediately following execution the SyncTasks should still be live and thus taking memory
|
||||
assertThat(session.syncingCount()).isNotEqualTo(0);
|
||||
|
||||
// unblock syncComplete callback, session should remove trees
|
||||
future.complete(null);
|
||||
|
||||
// The session retains memory in the contained executor until the threads expire, so we wait for the threads
|
||||
// that ran the Tree -> SyncTask conversions to die and release the memory
|
||||
long millisUntilFreed;
|
||||
|
||||
// Confirm that it's the thread timeout mechanism that's causing the SyncTasks to retire
|
||||
assertThat(session.syncingCount()).isNotEqualTo(0);
|
||||
for (millisUntilFreed = 0; millisUntilFreed < TEST_TIMEOUT_S * 1000; millisUntilFreed += THREAD_TIMEOUT_MILLIS)
|
||||
{
|
||||
TimeUnit.MILLISECONDS.sleep(THREAD_TIMEOUT_MILLIS);
|
||||
if (ObjectSizes.measureDeep(session) < (sizeDuringExecution - (syncTasks.size() * singleTreeSize)))
|
||||
if (session.syncingCount() == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
package org.apache.cassandra.service;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
|
@ -30,7 +31,6 @@ import static org.junit.Assert.assertTrue;
|
|||
|
||||
public class GCInspectorTest
|
||||
{
|
||||
|
||||
GCInspector gcInspector;
|
||||
|
||||
@BeforeClass
|
||||
|
|
@ -48,8 +48,8 @@ public class GCInspectorTest
|
|||
@Test
|
||||
public void ensureStaticFieldsHydrateFromConfig()
|
||||
{
|
||||
assertEquals(DatabaseDescriptor.getGCLogThreshold(), gcInspector.getGcLogThresholdInMs());
|
||||
assertEquals(DatabaseDescriptor.getGCWarnThreshold(), gcInspector.getGcWarnThresholdInMs());
|
||||
Assert.assertEquals(DatabaseDescriptor.getGCLogThreshold(), gcInspector.getGcLogThresholdInMs());
|
||||
Assert.assertEquals(DatabaseDescriptor.getGCWarnThreshold(), gcInspector.getGcWarnThresholdInMs());
|
||||
assertEquals(DatabaseDescriptor.getGCConcurrentPhaseLogThreshold(), gcInspector.getGcConcurrentPhaseLogThresholdInMs());
|
||||
assertEquals(DatabaseDescriptor.getGCConcurrentPhaseWarnThreshold(), gcInspector.getGcConcurrentPhaseWarnThresholdInMs());
|
||||
}
|
||||
|
|
@ -64,12 +64,12 @@ public class GCInspectorTest
|
|||
public void ensureWarnGreaterThanLog()
|
||||
{
|
||||
assertThatThrownBy(() -> gcInspector.setGcWarnThresholdInMs(gcInspector.getGcLogThresholdInMs()))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Threshold value for gc_warn_threshold (200) must be greater than gc_log_threshold which is currently 200");
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("must be greater than");
|
||||
|
||||
assertThatThrownBy(() -> gcInspector.setGcConcurrentPhaseWarnThresholdInMs(gcInspector.getGcConcurrentPhaseLogThresholdInMs()))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Threshold value for gc_concurrent_phase_warn_threshold (1000) must be greater than gc_concurrent_phase_log_threshold which is currently 1000");
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("must be greater than");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -85,24 +85,33 @@ public class GCInspectorTest
|
|||
assertEquals(1000, DatabaseDescriptor.getGCConcurrentPhaseLogThreshold());
|
||||
}
|
||||
|
||||
/**
|
||||
* We keep the concurrent log values the same for JDK21 since we have to infer
|
||||
* See {@code GCInspector#assumeGCIsPartiallyConcurrent()}
|
||||
*/
|
||||
@Test
|
||||
public void ensureLogLessThanWarn()
|
||||
{
|
||||
assertEquals(200, gcInspector.getGcLogThresholdInMs());
|
||||
gcInspector.setGcWarnThresholdInMs(1000);
|
||||
assertEquals(1000, gcInspector.getGcWarnThresholdInMs());
|
||||
int gcLog = 200;
|
||||
int gcWarn = 1000;
|
||||
int gcConcurrentLog = 1000;
|
||||
int gcConcurrentWarn = 2000;
|
||||
|
||||
Assert.assertEquals(gcLog, gcInspector.getGcLogThresholdInMs());
|
||||
gcInspector.setGcWarnThresholdInMs(gcWarn);
|
||||
assertEquals(gcWarn, gcInspector.getGcWarnThresholdInMs());
|
||||
|
||||
assertThatThrownBy(() -> gcInspector.setGcLogThresholdInMs(gcInspector.getGcWarnThresholdInMs() + 1))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Threshold value for gc_log_threshold (1001) must be less than gc_warn_threshold which is currently 1000");
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("must be less than");
|
||||
|
||||
assertEquals(1000, gcInspector.getGcConcurrentPhaseLogThresholdInMs());
|
||||
gcInspector.setGcConcurrentPhaseWarnThresholdInMs(2000);
|
||||
assertEquals(2000, gcInspector.getGcConcurrentPhaseWarnThresholdInMs());
|
||||
assertEquals(gcConcurrentLog, gcInspector.getGcConcurrentPhaseLogThresholdInMs());
|
||||
gcInspector.setGcConcurrentPhaseWarnThresholdInMs(gcConcurrentWarn);
|
||||
assertEquals(gcConcurrentWarn, gcInspector.getGcConcurrentPhaseWarnThresholdInMs());
|
||||
|
||||
assertThatThrownBy(() -> gcInspector.setGcConcurrentPhaseLogThresholdInMs(gcInspector.getGcConcurrentPhaseWarnThresholdInMs() + 1))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Threshold value for gc_concurrent_phase_log_threshold (2001) must be less than gc_concurrent_phase_warn_threshold which is currently 2000");
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("must be less than");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ import com.google.common.collect.Lists;
|
|||
import net.openhft.chronicle.core.io.IORuntimeException;
|
||||
import net.openhft.chronicle.queue.ChronicleQueue;
|
||||
import net.openhft.chronicle.queue.ExcerptAppender;
|
||||
import net.openhft.chronicle.queue.RollCycles;
|
||||
import net.openhft.chronicle.queue.impl.single.SingleChronicleQueueBuilder;
|
||||
import net.openhft.chronicle.queue.rollcycles.TestRollCycles;
|
||||
import net.openhft.chronicle.wire.WireOut;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
|
@ -98,7 +98,8 @@ public class AuditLogViewerTest
|
|||
" -i,--ignore Silently ignore unsupported records\n" +
|
||||
" -r,--roll_cycle <arg> How often to roll the log file was rolled. May be\n" +
|
||||
" necessary for Chronicle to correctly parse file\n" +
|
||||
" names. (MINUTELY, HOURLY, DAILY). Default HOURLY.\n";
|
||||
" names. (FIVE_MINUTELY, FAST_HOURLY, FAST_DAILY).\n" +
|
||||
" Default FAST_HOURLY.\n";
|
||||
Assertions.assertThat(tool.getStdout()).isEqualTo(help);
|
||||
}
|
||||
|
||||
|
|
@ -162,7 +163,7 @@ public class AuditLogViewerTest
|
|||
records.add("Test foo bar 1");
|
||||
records.add("Test foo bar 2");
|
||||
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(path.toFile()).rollCycle(RollCycles.TEST_SECONDLY).build())
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(path.toFile()).rollCycle(TestRollCycles.TEST_SECONDLY).build())
|
||||
{
|
||||
ExcerptAppender appender = queue.acquireAppender();
|
||||
|
||||
|
|
@ -171,7 +172,7 @@ public class AuditLogViewerTest
|
|||
|
||||
//Read those written records
|
||||
List<String> actualRecords = new ArrayList<>();
|
||||
AuditLogViewer.dump(ImmutableList.of(path.toString()), RollCycles.TEST_SECONDLY.toString(), false, false, actualRecords::add);
|
||||
AuditLogViewer.dump(ImmutableList.of(path.toString()), TestRollCycles.TEST_SECONDLY.toString(), false, false, actualRecords::add);
|
||||
|
||||
assertRecordsMatch(records, actualRecords);
|
||||
}
|
||||
|
|
@ -180,12 +181,12 @@ public class AuditLogViewerTest
|
|||
@Test (expected = IORuntimeException.class)
|
||||
public void testRejectFutureVersionRecord()
|
||||
{
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(path.toFile()).rollCycle(RollCycles.TEST_SECONDLY).build())
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(path.toFile()).rollCycle(TestRollCycles.TEST_SECONDLY).build())
|
||||
{
|
||||
ExcerptAppender appender = queue.acquireAppender();
|
||||
appender.writeDocument(createFutureRecord());
|
||||
|
||||
AuditLogViewer.dump(ImmutableList.of(path.toString()), RollCycles.TEST_SECONDLY.toString(), false, false, dummy -> {});
|
||||
AuditLogViewer.dump(ImmutableList.of(path.toString()), TestRollCycles.TEST_SECONDLY.toString(), false, false, dummy -> {});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -201,7 +202,7 @@ public class AuditLogViewerTest
|
|||
records.add("Test foo bar 1");
|
||||
records.add("Test foo bar 2");
|
||||
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(path.toFile()).rollCycle(RollCycles.TEST_SECONDLY).build())
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(path.toFile()).rollCycle(TestRollCycles.TEST_SECONDLY).build())
|
||||
{
|
||||
ExcerptAppender appender = queue.acquireAppender();
|
||||
|
||||
|
|
@ -213,7 +214,7 @@ public class AuditLogViewerTest
|
|||
|
||||
//Read those written records
|
||||
List<String> actualRecords = new ArrayList<>();
|
||||
AuditLogViewer.dump(ImmutableList.of(path.toString()), RollCycles.TEST_SECONDLY.toString(), false, true, actualRecords::add);
|
||||
AuditLogViewer.dump(ImmutableList.of(path.toString()), TestRollCycles.TEST_SECONDLY.toString(), false, true, actualRecords::add);
|
||||
|
||||
// Assert all current records are present
|
||||
assertRecordsMatch(records, actualRecords);
|
||||
|
|
@ -223,12 +224,12 @@ public class AuditLogViewerTest
|
|||
@Test (expected = IORuntimeException.class)
|
||||
public void testRejectUnknownTypeRecord()
|
||||
{
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(path.toFile()).rollCycle(RollCycles.TEST_SECONDLY).build())
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(path.toFile()).rollCycle(TestRollCycles.TEST_SECONDLY).build())
|
||||
{
|
||||
ExcerptAppender appender = queue.acquireAppender();
|
||||
appender.writeDocument(createUnknownTypeRecord());
|
||||
|
||||
AuditLogViewer.dump(ImmutableList.of(path.toString()), RollCycles.TEST_SECONDLY.toString(), false, false, dummy -> {});
|
||||
AuditLogViewer.dump(ImmutableList.of(path.toString()), TestRollCycles.TEST_SECONDLY.toString(), false, false, dummy -> {});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -244,7 +245,7 @@ public class AuditLogViewerTest
|
|||
records.add("Test foo bar 1");
|
||||
records.add("Test foo bar 2");
|
||||
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(path.toFile()).rollCycle(RollCycles.TEST_SECONDLY).build())
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(path.toFile()).rollCycle(TestRollCycles.TEST_SECONDLY).build())
|
||||
{
|
||||
ExcerptAppender appender = queue.acquireAppender();
|
||||
|
||||
|
|
@ -256,7 +257,7 @@ public class AuditLogViewerTest
|
|||
|
||||
//Read those written records
|
||||
List<String> actualRecords = new ArrayList<>();
|
||||
AuditLogViewer.dump(ImmutableList.of(path.toString()), RollCycles.TEST_SECONDLY.toString(), false, true, actualRecords::add);
|
||||
AuditLogViewer.dump(ImmutableList.of(path.toString()), TestRollCycles.TEST_SECONDLY.toString(), false, true, actualRecords::add);
|
||||
|
||||
// Assert all supported records are present
|
||||
assertRecordsMatch(records, actualRecords);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
package org.apache.cassandra.tools;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.datastax.driver.core.exceptions.NoHostAvailableException;
|
||||
|
||||
import org.hamcrest.CoreMatchers;
|
||||
|
|
@ -31,6 +35,20 @@ import static org.junit.Assert.assertThat;
|
|||
|
||||
public class BulkLoaderTest extends OfflineToolUtils
|
||||
{
|
||||
private static final String[] ALLOWED_BULK_LOADER_THREADS = new String[]{
|
||||
"ObjectCleanerThread",
|
||||
"globalEventExecutor-[1-9]-[1-9]",
|
||||
"globalEventExecutor-[1-9]-[1-9]",
|
||||
"Shutdown-checker",
|
||||
"cluster[0-9]-connection-reaper-[0-9]",
|
||||
"Attach Listener",
|
||||
"process reaper",
|
||||
"JNA Cleaner",
|
||||
};
|
||||
|
||||
// the driver isn't expected to terminate threads on close synchronously (CASSANDRA-19000)
|
||||
private static final String SYNC_DRIVER_THREAD = "cluster[0-9]-nio-worker-[0-9]";
|
||||
|
||||
@Test
|
||||
public void testBulkLoader_NoArgs()
|
||||
{
|
||||
|
|
@ -38,10 +56,10 @@ public class BulkLoaderTest extends OfflineToolUtils
|
|||
assertEquals(1, tool.getExitCode());
|
||||
assertThat(tool.getCleanedStderr(), CoreMatchers.containsString("Missing sstable directory argument"));
|
||||
|
||||
assertNoUnexpectedThreadsStarted(new String[] { "ObjectCleanerThread",
|
||||
"Shutdown-checker",
|
||||
"cluster[0-9]-connection-reaper-[0-9]" },
|
||||
false);
|
||||
assertNoUnexpectedThreadsStarted(false, "ObjectCleanerThread",
|
||||
"Shutdown-checker",
|
||||
"cluster[0-9]-connection-reaper-[0-9]");
|
||||
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
@ -63,15 +81,8 @@ public class BulkLoaderTest extends OfflineToolUtils
|
|||
if (!(tool.getException().getCause().getCause().getCause() instanceof NoHostAvailableException))
|
||||
throw tool.getException();
|
||||
|
||||
assertNoUnexpectedThreadsStarted(new String[] { "ObjectCleanerThread",
|
||||
"globalEventExecutor-[1-9]-[1-9]",
|
||||
"globalEventExecutor-[1-9]-[1-9]",
|
||||
"Shutdown-checker",
|
||||
"cluster[0-9]-connection-reaper-[0-9]",
|
||||
"Attach Listener",
|
||||
"process reaper",
|
||||
"JNA Cleaner"},
|
||||
false);
|
||||
|
||||
assertNoUnexpectedThreadsStarted(false, ALLOWED_BULK_LOADER_THREADS);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
@ -95,21 +106,11 @@ public class BulkLoaderTest extends OfflineToolUtils
|
|||
if (!(tool.getException().getCause().getCause().getCause() instanceof NoHostAvailableException))
|
||||
throw tool.getException();
|
||||
|
||||
assertNoUnexpectedThreadsStarted(new String[] { "ObjectCleanerThread",
|
||||
"globalEventExecutor-[1-9]-[1-9]",
|
||||
"globalEventExecutor-[1-9]-[1-9]",
|
||||
"Shutdown-checker",
|
||||
"cluster[0-9]-connection-reaper-[0-9]",
|
||||
"Attach Listener",
|
||||
"process reaper",
|
||||
"JNA Cleaner",
|
||||
// the driver isn't expected to terminate threads on close synchronously (CASSANDRA-19000)
|
||||
"cluster[0-9]-nio-worker-[0-9]" },
|
||||
false);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
assertKeyspaceNotLoaded();
|
||||
assertNoUnexpectedThreadsStarted(false, appendToAllowedThreads(SYNC_DRIVER_THREAD));
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
assertKeyspaceNotLoaded();
|
||||
assertServerNotLoaded();
|
||||
}
|
||||
|
||||
|
|
@ -129,17 +130,7 @@ public class BulkLoaderTest extends OfflineToolUtils
|
|||
if (!(tool.getException().getCause().getCause().getCause() instanceof NoHostAvailableException))
|
||||
throw tool.getException();
|
||||
|
||||
assertNoUnexpectedThreadsStarted(new String[] { "ObjectCleanerThread",
|
||||
"globalEventExecutor-[1-9]-[1-9]",
|
||||
"globalEventExecutor-[1-9]-[1-9]",
|
||||
"Shutdown-checker",
|
||||
"cluster[0-9]-connection-reaper-[0-9]",
|
||||
"Attach Listener",
|
||||
"process reaper",
|
||||
"JNA Cleaner",
|
||||
// the driver isn't expected to terminate threads on close synchronously (CASSANDRA-19000)
|
||||
"cluster[0-9]-nio-worker-[0-9]" },
|
||||
false);
|
||||
assertNoUnexpectedThreadsStarted(false, appendToAllowedThreads(SYNC_DRIVER_THREAD));
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
@ -216,4 +207,11 @@ public class BulkLoaderTest extends OfflineToolUtils
|
|||
assertEquals(6, DatabaseDescriptor.getEntireSSTableInterDCStreamThroughputOutboundMebibytesPerSec(), 0.0);
|
||||
throw tool.getException().getCause().getCause().getCause();
|
||||
}
|
||||
|
||||
private String[] appendToAllowedThreads(String... optionalThreads)
|
||||
{
|
||||
var result = new ArrayList<>(Arrays.asList(ALLOWED_BULK_LOADER_THREADS));
|
||||
Collections.addAll(result, optionalThreads);
|
||||
return result.toArray(String[]::new);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public class GetVersionTest extends OfflineToolUtils
|
|||
{
|
||||
ToolResult tool = ToolRunner.invokeClass(GetVersion.class);
|
||||
tool.assertOnCleanExit();
|
||||
assertNoUnexpectedThreadsStarted(null, false);
|
||||
assertNoUnexpectedThreadsStarted(false);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
|
|||
|
|
@ -27,15 +27,13 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.apache.cassandra.config.CassandraRelevantProperties;
|
||||
|
|
@ -44,7 +42,6 @@ import org.apache.cassandra.io.util.File;
|
|||
|
||||
import static org.apache.cassandra.utils.FBUtilities.preventIllegalAccessWarnings;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
|
|
@ -52,6 +49,8 @@ import static org.junit.Assert.fail;
|
|||
*/
|
||||
public abstract class OfflineToolUtils
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(OfflineToolUtils.class);
|
||||
|
||||
static
|
||||
{
|
||||
preventIllegalAccessWarnings();
|
||||
|
|
@ -60,68 +59,77 @@ public abstract class OfflineToolUtils
|
|||
private static List<ThreadInfo> initialThreads;
|
||||
|
||||
static final String[] OPTIONAL_THREADS_WITH_SCHEMA = {
|
||||
"ScheduledTasks:[1-9]",
|
||||
"ScheduledFastTasks:[1-9]",
|
||||
"OptionalTasks:[1-9]",
|
||||
"Reference-Reaper",
|
||||
"LocalPool-Cleaner(-networking|-chunk-cache)",
|
||||
"CacheCleanupExecutor:[1-9]",
|
||||
"CompactionExecutor:[1-9]",
|
||||
"ValidationExecutor:[1-9]",
|
||||
"NonPeriodicTasks:[1-9]",
|
||||
"Sampler:[1-9]",
|
||||
"SecondaryIndexManagement:[1-9]",
|
||||
"Strong-Reference-Leak-Detector:[1-9]",
|
||||
"Background_Reporter:[1-9]",
|
||||
"EXPIRING-MAP-REAPER:[1-9]",
|
||||
"ObjectCleanerThread",
|
||||
"process reaper", // spawned by the jvm when executing external processes
|
||||
// and may still be active when we check
|
||||
"Attach Listener", // spawned in intellij IDEA
|
||||
"JNA Cleaner", // spawned by JNA
|
||||
"ThreadLocalMetrics-Cleaner", // spawned by org.apache.cassandra.metrics.ThreadLocalMetrics
|
||||
"Native reference cleanup thread",
|
||||
"^ForkJoinPool\\.commonPool-worker-\\d+$"
|
||||
"ScheduledTasks:[1-9]",
|
||||
"ScheduledFastTasks:[1-9]",
|
||||
"OptionalTasks:[1-9]",
|
||||
"Reference-Reaper",
|
||||
"LocalPool-Cleaner(-networking|-chunk-cache)",
|
||||
"CacheCleanupExecutor:[1-9]",
|
||||
"CompactionExecutor:[1-9]",
|
||||
"ValidationExecutor:[1-9]",
|
||||
"NonPeriodicTasks:[1-9]",
|
||||
"Sampler:[1-9]",
|
||||
"SecondaryIndexManagement:[1-9]",
|
||||
"Strong-Reference-Leak-Detector:[1-9]",
|
||||
"Background_Reporter:[1-9]",
|
||||
"EXPIRING-MAP-REAPER:[1-9]",
|
||||
"ObjectCleanerThread",
|
||||
"process reaper", // spawned by the jvm when executing external processes and may still be active when we check
|
||||
// and may still be active when we check
|
||||
"Attach Listener", // spawned in intellij IDEA
|
||||
"JNA Cleaner", // spawned by JNA
|
||||
"ThreadLocalMetrics-Cleaner", // spawned by org.apache.cassandra.metrics.ThreadLocalMetrics
|
||||
"Native reference cleanup thread",
|
||||
"^ForkJoinPool\\.commonPool-worker-\\d+$"
|
||||
};
|
||||
|
||||
static final String[] NON_DEFAULT_MEMTABLE_THREADS =
|
||||
{
|
||||
"((Native|Slab|Heap)Pool|Logged)Cleaner"
|
||||
"((Native|Slab|Heap)Pool|Logged)Cleaner"
|
||||
};
|
||||
|
||||
public void assertNoUnexpectedThreadsStarted(String[] optionalThreadNames, boolean allowNonDefaultMemtableThreads)
|
||||
/** We have some threads that show up in the presence of other JDK's; account for those here */
|
||||
private static final String[] EXTRA_JDK_THREADS = new String[]{
|
||||
"Native reference cleanup thread", // Corretto janitor thread
|
||||
};
|
||||
|
||||
/**
|
||||
* When unexpected threads or core singleton objects are inadvertantly initialized during tool runs it can lead to
|
||||
* the tool hanging on shutdown. We have a whitelisted number of threads above along with whatever initial threads
|
||||
* were there on first tool creation we can diff against; if we find _anything_ new, it's an error condition - this
|
||||
* needs to either be added to the list above or debugged and fixed.
|
||||
*/
|
||||
public void assertNoUnexpectedThreadsStarted(boolean allowNonDefaultMemtableThreads, String... optionalThreadNames)
|
||||
{
|
||||
ThreadMXBean threads = ManagementFactory.getThreadMXBean();
|
||||
var allowedThreadNames = initialThreads.stream()
|
||||
.map(ThreadInfo::getThreadName)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Set<String> initial = initialThreads
|
||||
.stream()
|
||||
.map(ThreadInfo::getThreadName)
|
||||
.collect(Collectors.toSet());
|
||||
Collections.addAll(allowedThreadNames, EXTRA_JDK_THREADS);
|
||||
Collections.addAll(allowedThreadNames, optionalThreadNames);
|
||||
|
||||
Set<String> current = Arrays.stream(threads.getThreadInfo(threads.getAllThreadIds()))
|
||||
.filter(Objects::nonNull)
|
||||
.map(ThreadInfo::getThreadName)
|
||||
.collect(Collectors.toSet());
|
||||
Iterable<String> optionalNames = optionalThreadNames != null
|
||||
? Arrays.asList(optionalThreadNames)
|
||||
: Collections.emptyList();
|
||||
if (allowNonDefaultMemtableThreads && DatabaseDescriptor.getMemtableConfigurations().containsKey("default"))
|
||||
optionalNames = Iterables.concat(optionalNames, Arrays.asList(NON_DEFAULT_MEMTABLE_THREADS));
|
||||
Collections.addAll(allowedThreadNames, NON_DEFAULT_MEMTABLE_THREADS);
|
||||
|
||||
List<Pattern> optional = StreamSupport.stream(optionalNames.spliterator(), false)
|
||||
.map(Pattern::compile)
|
||||
.collect(Collectors.toList());
|
||||
var allowedRegexes = allowedThreadNames.stream()
|
||||
.map(Pattern::compile)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
current.removeAll(initial);
|
||||
var threads = ManagementFactory.getThreadMXBean();
|
||||
var badThreads = Arrays.stream(threads.getThreadInfo(threads.getAllThreadIds()))
|
||||
.filter(Objects::nonNull)
|
||||
.filter(threadInfo -> allowedRegexes.stream().noneMatch(pattern -> pattern.matcher(threadInfo.getThreadName()).matches()))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Set<String> remain = current.stream()
|
||||
.filter(threadName -> optional.stream().noneMatch(pattern -> pattern.matcher(threadName).matches()))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (!remain.isEmpty())
|
||||
System.err.println("Unexpected thread names: " + remain);
|
||||
|
||||
assertTrue("Wrong thread status, active threads unaccounted for: " + remain, remain.isEmpty());
|
||||
if (!badThreads.isEmpty())
|
||||
{
|
||||
logger.error("Found unexpected disallowed threads during check. Printing thread details.");
|
||||
badThreads.forEach(info -> logger.error(info.toString()));
|
||||
var errorMessage = new StringBuilder("Bad threads found:");
|
||||
badThreads.forEach(ti -> errorMessage.append("\n ").append(ti.getThreadName()));
|
||||
errorMessage.append("\n-Tools should not start threads that initialize singletons or other system resources");
|
||||
Assert.fail(errorMessage.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void assertSchemaNotLoaded()
|
||||
|
|
@ -239,7 +247,7 @@ public abstract class OfflineToolUtils
|
|||
|
||||
protected void assertCorrectEnvPostTest()
|
||||
{
|
||||
assertNoUnexpectedThreadsStarted(OPTIONAL_THREADS_WITH_SCHEMA, true);
|
||||
assertNoUnexpectedThreadsStarted(true, OPTIONAL_THREADS_WITH_SCHEMA);
|
||||
assertSchemaLoaded();
|
||||
assertServerNotLoaded();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ public class SSTableExpiredBlockersTest extends OfflineToolUtils
|
|||
assertThat(tool.getCleanedStderr(), CoreMatchers.containsStringIgnoringCase("Missing arguments"));
|
||||
assertEquals(1, tool.getExitCode());
|
||||
|
||||
assertNoUnexpectedThreadsStarted(null, false);
|
||||
assertNoUnexpectedThreadsStarted(false);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ public class SSTableExportSchemaLoadingTest extends OfflineToolUtils
|
|||
*/
|
||||
private void assertPostTestEnv()
|
||||
{
|
||||
assertNoUnexpectedThreadsStarted(OPTIONAL_THREADS_WITH_SCHEMA, true);
|
||||
assertNoUnexpectedThreadsStarted(true, OPTIONAL_THREADS_WITH_SCHEMA);
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
assertKeyspaceNotLoaded();
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ public class SSTableExportTest extends OfflineToolUtils
|
|||
*/
|
||||
private void assertPostTestEnv()
|
||||
{
|
||||
assertNoUnexpectedThreadsStarted(OPTIONAL_THREADS_WITH_SCHEMA, false);
|
||||
assertNoUnexpectedThreadsStarted(false, OPTIONAL_THREADS_WITH_SCHEMA);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ public class SSTableLevelResetterTest extends OfflineToolUtils
|
|||
assertThat(tool.getStdout(), CoreMatchers.containsStringIgnoringCase("usage:"));
|
||||
Assertions.assertThat(tool.getCleanedStderr()).isEmpty();
|
||||
assertEquals(1, tool.getExitCode());
|
||||
assertNoUnexpectedThreadsStarted(null, false);
|
||||
assertNoUnexpectedThreadsStarted(false);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public class SSTableMetadataViewerTest extends OfflineToolUtils
|
|||
assertThat(tool.getCleanedStderr(), CoreMatchers.containsStringIgnoringCase("Options:"));
|
||||
assertEquals(1, tool.getExitCode());
|
||||
}
|
||||
assertNoUnexpectedThreadsStarted(null, false);
|
||||
assertNoUnexpectedThreadsStarted(false);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
@ -218,7 +218,7 @@ public class SSTableMetadataViewerTest extends OfflineToolUtils
|
|||
|
||||
private void assertGoodEnvPostTest()
|
||||
{
|
||||
assertNoUnexpectedThreadsStarted(OPTIONAL_THREADS_WITH_SCHEMA, false);
|
||||
assertNoUnexpectedThreadsStarted(false, OPTIONAL_THREADS_WITH_SCHEMA);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ public class SSTableOfflineRelevelTest extends OfflineToolUtils
|
|||
assertThat(tool.getStdout(), CoreMatchers.containsStringIgnoringCase("usage:"));
|
||||
Assertions.assertThat(tool.getCleanedStderr()).isEmpty();
|
||||
assertEquals(1, tool.getExitCode());
|
||||
assertNoUnexpectedThreadsStarted(null, false);
|
||||
assertNoUnexpectedThreadsStarted(false);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ public class SSTablePartitionsTest extends OfflineToolUtils
|
|||
@After
|
||||
public void assertPostTestEnv()
|
||||
{
|
||||
assertNoUnexpectedThreadsStarted(OPTIONAL_THREADS_WITH_SCHEMA, false);
|
||||
assertNoUnexpectedThreadsStarted(false, OPTIONAL_THREADS_WITH_SCHEMA);
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
assertKeyspaceNotLoaded();
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ public class SSTableRepairedAtSetterTest extends OfflineToolUtils
|
|||
assertThat(tool.getStdout(), CoreMatchers.containsStringIgnoringCase("usage:"));
|
||||
Assertions.assertThat(tool.getCleanedStderr()).isEmpty();
|
||||
assertEquals(1, tool.getExitCode());
|
||||
assertNoUnexpectedThreadsStarted(null, false);
|
||||
assertNoUnexpectedThreadsStarted(false);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
@ -79,7 +79,7 @@ public class SSTableRepairedAtSetterTest extends OfflineToolUtils
|
|||
"--is-repaired",
|
||||
findOneSSTable("legacy_sstables", "legacy_ma_simple"));
|
||||
tool.assertOnCleanExit();
|
||||
assertNoUnexpectedThreadsStarted(OPTIONAL_THREADS_WITH_SCHEMA, false);
|
||||
assertNoUnexpectedThreadsStarted(false, OPTIONAL_THREADS_WITH_SCHEMA);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
@ -95,7 +95,7 @@ public class SSTableRepairedAtSetterTest extends OfflineToolUtils
|
|||
"--is-unrepaired",
|
||||
findOneSSTable("legacy_sstables", "legacy_ma_simple"));
|
||||
tool.assertOnCleanExit();
|
||||
assertNoUnexpectedThreadsStarted(OPTIONAL_THREADS_WITH_SCHEMA, false);
|
||||
assertNoUnexpectedThreadsStarted(false, OPTIONAL_THREADS_WITH_SCHEMA);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
@ -113,7 +113,7 @@ public class SSTableRepairedAtSetterTest extends OfflineToolUtils
|
|||
String file = tmpFile.absolutePath();
|
||||
ToolResult tool = ToolRunner.invokeClass(SSTableRepairedAtSetter.class, "--really-set", "--is-repaired", "-f", file);
|
||||
tool.assertOnCleanExit();
|
||||
assertNoUnexpectedThreadsStarted(OPTIONAL_THREADS_WITH_SCHEMA, false);
|
||||
assertNoUnexpectedThreadsStarted(false, OPTIONAL_THREADS_WITH_SCHEMA);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ public class ToolRunner
|
|||
protected static final Logger logger = LoggerFactory.getLogger(ToolRunner.class);
|
||||
|
||||
public static final ImmutableList<String> DEFAULT_CLEANERS = ImmutableList.of("(?im)^picked up.*\\R",
|
||||
"(?im)^.*package jdk.internal.util.jar not in java.base*\\R",
|
||||
"(?im)^.*Not generating a deterministic id for table.*\\R",
|
||||
"(?im)^.*`USE <keyspace>` with prepared statements is.*\\R");
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public class ToolsSchemaLoadingTest extends OfflineToolUtils
|
|||
assertThat(tool.getStdout(), CoreMatchers.containsStringIgnoringCase("usage:"));
|
||||
assertThat(tool.getCleanedStderr(), CoreMatchers.containsStringIgnoringCase("Missing arguments"));
|
||||
assertEquals(1, tool.getExitCode());
|
||||
assertNoUnexpectedThreadsStarted(null, false);
|
||||
assertNoUnexpectedThreadsStarted(false);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
@ -48,7 +48,7 @@ public class ToolsSchemaLoadingTest extends OfflineToolUtils
|
|||
assertThat(tool.getStdout(), CoreMatchers.containsStringIgnoringCase("usage:"));
|
||||
assertThat(tool.getCleanedStderr(), CoreMatchers.containsStringIgnoringCase("Missing arguments"));
|
||||
assertEquals(1, tool.getExitCode());
|
||||
assertNoUnexpectedThreadsStarted(null, false);
|
||||
assertNoUnexpectedThreadsStarted(false);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
@ -63,7 +63,7 @@ public class ToolsSchemaLoadingTest extends OfflineToolUtils
|
|||
assertThat(tool.getStdout(), CoreMatchers.containsStringIgnoringCase("usage:"));
|
||||
assertThat(tool.getCleanedStderr(), CoreMatchers.containsStringIgnoringCase("No sstables to split"));
|
||||
assertEquals(1, tool.getExitCode());
|
||||
assertNoUnexpectedThreadsStarted(null, false);
|
||||
assertNoUnexpectedThreadsStarted(false);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
@ -78,7 +78,7 @@ public class ToolsSchemaLoadingTest extends OfflineToolUtils
|
|||
assertThat(tool.getStdout(), CoreMatchers.containsStringIgnoringCase("usage:"));
|
||||
assertThat(tool.getCleanedStderr(), CoreMatchers.containsStringIgnoringCase("Missing arguments"));
|
||||
assertEquals(1, tool.getExitCode());
|
||||
assertNoUnexpectedThreadsStarted(null, false);
|
||||
assertNoUnexpectedThreadsStarted(false);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
@ -93,7 +93,7 @@ public class ToolsSchemaLoadingTest extends OfflineToolUtils
|
|||
assertThat(tool.getStdout(), CoreMatchers.containsStringIgnoringCase("usage:"));
|
||||
assertThat(tool.getCleanedStderr(), CoreMatchers.containsStringIgnoringCase("Missing arguments"));
|
||||
assertEquals(1, tool.getExitCode());
|
||||
assertNoUnexpectedThreadsStarted(null, false);
|
||||
assertNoUnexpectedThreadsStarted(false);
|
||||
assertSchemaNotLoaded();
|
||||
assertCLSMNotLoaded();
|
||||
assertSystemKSNotLoaded();
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ public class GetAuditLogTest extends CQLTester
|
|||
final String output = getAuditLogOutput.replaceAll("( )+", " ").trim();
|
||||
assertThat(output).startsWith("enabled true");
|
||||
assertThat(output).contains("logger BinAuditLogger");
|
||||
assertThat(output).contains("roll_cycle HOURLY");
|
||||
assertThat(output).contains("roll_cycle FAST_HOURLY");
|
||||
assertThat(output).contains("block true");
|
||||
assertThat(output).contains("max_log_size 17179869184");
|
||||
assertThat(output).contains("max_queue_weight 268435456");
|
||||
|
|
@ -131,7 +131,7 @@ public class GetAuditLogTest extends CQLTester
|
|||
final String output = getAuditLogOutput.replaceAll("( )+", " ").trim();
|
||||
assertThat(output).startsWith("enabled true");
|
||||
assertThat(output).contains("logger BinAuditLogger");
|
||||
assertThat(output).contains("roll_cycle HOURLY");
|
||||
assertThat(output).contains("roll_cycle FAST_HOURLY");
|
||||
assertThat(output).contains("block true");
|
||||
assertThat(output).contains("max_log_size 17179869184");
|
||||
assertThat(output).contains("max_queue_weight 268435456");
|
||||
|
|
@ -150,7 +150,7 @@ public class GetAuditLogTest extends CQLTester
|
|||
final String output = getAuditLogOutput.replaceAll("( )+", " ").trim();
|
||||
assertThat(output).startsWith("enabled false");
|
||||
assertThat(output).contains("logger BinAuditLogger");
|
||||
assertThat(output).contains("roll_cycle HOURLY");
|
||||
assertThat(output).contains("roll_cycle FAST_HOURLY");
|
||||
assertThat(output).contains("block true");
|
||||
assertThat(output).contains("max_log_size 17179869184");
|
||||
assertThat(output).contains("max_queue_weight 268435456");
|
||||
|
|
|
|||
|
|
@ -17,14 +17,11 @@
|
|||
*/
|
||||
package org.apache.cassandra.transport;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
|
@ -48,8 +45,8 @@ import org.apache.cassandra.transport.messages.QueryMessage;
|
|||
import org.apache.cassandra.transport.messages.ResultMessage;
|
||||
import org.apache.cassandra.utils.ByteArrayUtil;
|
||||
import org.apache.cassandra.utils.MD5Digest;
|
||||
import org.apache.cassandra.utils.ReflectionUtils;
|
||||
|
||||
import static org.apache.cassandra.config.CassandraRelevantProperties.CUSTOM_QUERY_HANDLER_CLASS;
|
||||
import static org.apache.cassandra.utils.ByteBufferUtil.bytes;
|
||||
|
||||
public class MessagePayloadTest extends CQLTester
|
||||
|
|
@ -57,47 +54,11 @@ public class MessagePayloadTest extends CQLTester
|
|||
public static Map<String, ByteBuffer> requestPayload;
|
||||
public static Map<String, ByteBuffer> responsePayload;
|
||||
|
||||
private static Field cqlQueryHandlerField;
|
||||
private static boolean modifiersAccessible;
|
||||
|
||||
@BeforeClass
|
||||
public static void makeCqlQueryHandlerAccessible()
|
||||
public static void setUpClass()
|
||||
{
|
||||
try
|
||||
{
|
||||
cqlQueryHandlerField = ClientState.class.getDeclaredField("cqlQueryHandler");
|
||||
cqlQueryHandlerField.setAccessible(true);
|
||||
|
||||
Field modifiersField = ReflectionUtils.getModifiersField();
|
||||
modifiersAccessible = modifiersField.isAccessible();
|
||||
modifiersField.setAccessible(true);
|
||||
modifiersField.setInt(cqlQueryHandlerField, cqlQueryHandlerField.getModifiers() & ~Modifier.FINAL);
|
||||
}
|
||||
catch (IllegalAccessException | NoSuchFieldException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void resetCqlQueryHandlerField()
|
||||
{
|
||||
if (cqlQueryHandlerField == null)
|
||||
return;
|
||||
try
|
||||
{
|
||||
Field modifiersField = ReflectionUtils.getModifiersField();
|
||||
modifiersField.setAccessible(true);
|
||||
modifiersField.setInt(cqlQueryHandlerField, cqlQueryHandlerField.getModifiers() | Modifier.FINAL);
|
||||
|
||||
cqlQueryHandlerField.setAccessible(false);
|
||||
|
||||
modifiersField.setAccessible(modifiersAccessible);
|
||||
}
|
||||
catch (IllegalAccessException | NoSuchFieldException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
CUSTOM_QUERY_HANDLER_CLASS.setString("org.apache.cassandra.transport.MessagePayloadTest$TestQueryHandler");
|
||||
CQLTester.setUpClass();
|
||||
}
|
||||
|
||||
@After
|
||||
|
|
@ -116,13 +77,9 @@ public class MessagePayloadTest extends CQLTester
|
|||
@Test
|
||||
public void testMessagePayloadBeta() throws Throwable
|
||||
{
|
||||
QueryHandler queryHandler = (QueryHandler) cqlQueryHandlerField.get(null);
|
||||
cqlQueryHandlerField.set(null, new TestQueryHandler());
|
||||
try
|
||||
{
|
||||
requireNetwork();
|
||||
requireNetwork();
|
||||
|
||||
Assert.assertSame(TestQueryHandler.class, ClientState.getCQLQueryHandler().getClass());
|
||||
Assert.assertSame(TestQueryHandler.class, ClientState.getCQLQueryHandler().getClass());
|
||||
|
||||
SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(),
|
||||
nativePort,
|
||||
|
|
@ -133,239 +90,216 @@ public class MessagePayloadTest extends CQLTester
|
|||
{
|
||||
client.connect(false);
|
||||
|
||||
Map<String, ByteBuffer> reqMap;
|
||||
Map<String, ByteBuffer> respMap;
|
||||
Map<String, ByteBuffer> reqMap;
|
||||
Map<String, ByteBuffer> respMap;
|
||||
|
||||
QueryOptions queryOptions = QueryOptions.create(
|
||||
QueryOptions.DEFAULT.getConsistency(),
|
||||
QueryOptions.DEFAULT.getValues(),
|
||||
QueryOptions.DEFAULT.skipMetadata(),
|
||||
QueryOptions.DEFAULT.getPageSize(),
|
||||
QueryOptions.DEFAULT.getPagingState(),
|
||||
QueryOptions.DEFAULT.getSerialConsistency(),
|
||||
ProtocolVersion.V5,
|
||||
KEYSPACE);
|
||||
QueryMessage queryMessage = new QueryMessage("CREATE TABLE atable (pk int PRIMARY KEY, v text)",
|
||||
queryOptions);
|
||||
PrepareMessage prepareMessage = new PrepareMessage("SELECT * FROM atable", KEYSPACE);
|
||||
QueryOptions queryOptions = QueryOptions.create(
|
||||
QueryOptions.DEFAULT.getConsistency(),
|
||||
QueryOptions.DEFAULT.getValues(),
|
||||
QueryOptions.DEFAULT.skipMetadata(),
|
||||
QueryOptions.DEFAULT.getPageSize(),
|
||||
QueryOptions.DEFAULT.getPagingState(),
|
||||
QueryOptions.DEFAULT.getSerialConsistency(),
|
||||
ProtocolVersion.V5,
|
||||
KEYSPACE);
|
||||
QueryMessage queryMessage = new QueryMessage("CREATE TABLE atable (pk int PRIMARY KEY, v text)",
|
||||
queryOptions);
|
||||
PrepareMessage prepareMessage = new PrepareMessage("SELECT * FROM atable", KEYSPACE);
|
||||
|
||||
reqMap = Collections.singletonMap("foo", bytes(42));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(42));
|
||||
queryMessage.setCustomPayload(reqMap);
|
||||
Message.Response queryResponse = client.execute(queryMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, queryResponse.getCustomPayload());
|
||||
reqMap = Collections.singletonMap("foo", bytes(42));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(42));
|
||||
queryMessage.setCustomPayload(reqMap);
|
||||
Message.Response queryResponse = client.execute(queryMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, queryResponse.getCustomPayload());
|
||||
|
||||
reqMap = Collections.singletonMap("foo", bytes(43));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(43));
|
||||
prepareMessage.setCustomPayload(reqMap);
|
||||
ResultMessage.Prepared prepareResponse = (ResultMessage.Prepared) client.execute(prepareMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, prepareResponse.getCustomPayload());
|
||||
reqMap = Collections.singletonMap("foo", bytes(43));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(43));
|
||||
prepareMessage.setCustomPayload(reqMap);
|
||||
ResultMessage.Prepared prepareResponse = (ResultMessage.Prepared) client.execute(prepareMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, prepareResponse.getCustomPayload());
|
||||
|
||||
ExecuteMessage executeMessage = new ExecuteMessage(prepareResponse.statementId, prepareResponse.resultMetadataId, QueryOptions.DEFAULT);
|
||||
reqMap = Collections.singletonMap("foo", bytes(44));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(44));
|
||||
executeMessage.setCustomPayload(reqMap);
|
||||
Message.Response executeResponse = client.execute(executeMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, executeResponse.getCustomPayload());
|
||||
ExecuteMessage executeMessage = new ExecuteMessage(prepareResponse.statementId, prepareResponse.resultMetadataId, QueryOptions.DEFAULT);
|
||||
reqMap = Collections.singletonMap("foo", bytes(44));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(44));
|
||||
executeMessage.setCustomPayload(reqMap);
|
||||
Message.Response executeResponse = client.execute(executeMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, executeResponse.getCustomPayload());
|
||||
|
||||
BatchMessage batchMessage = new BatchMessage(BatchStatement.Type.UNLOGGED,
|
||||
Collections.<Object>singletonList("INSERT INTO " + KEYSPACE + ".atable (pk,v) VALUES (1, 'foo')"),
|
||||
Collections.singletonList(ByteArrayUtil.EMPTY_ARRAY_OF_BYTE_ARRAYS),
|
||||
queryOptions);
|
||||
reqMap = Collections.singletonMap("foo", bytes(45));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(45));
|
||||
batchMessage.setCustomPayload(reqMap);
|
||||
Message.Response batchResponse = client.execute(batchMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, batchResponse.getCustomPayload());
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
BatchMessage batchMessage = new BatchMessage(BatchStatement.Type.UNLOGGED,
|
||||
Collections.<Object>singletonList("INSERT INTO " + KEYSPACE + ".atable (pk,v) VALUES (1, 'foo')"),
|
||||
Collections.singletonList(ByteArrayUtil.EMPTY_ARRAY_OF_BYTE_ARRAYS),
|
||||
queryOptions);
|
||||
reqMap = Collections.singletonMap("foo", bytes(45));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(45));
|
||||
batchMessage.setCustomPayload(reqMap);
|
||||
Message.Response batchResponse = client.execute(batchMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, batchResponse.getCustomPayload());
|
||||
}
|
||||
finally
|
||||
{
|
||||
cqlQueryHandlerField.set(null, queryHandler);
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessagePayload() throws Throwable
|
||||
{
|
||||
QueryHandler queryHandler = (QueryHandler) cqlQueryHandlerField.get(null);
|
||||
cqlQueryHandlerField.set(null, new TestQueryHandler());
|
||||
requireNetwork();
|
||||
|
||||
Assert.assertSame(TestQueryHandler.class, ClientState.getCQLQueryHandler().getClass());
|
||||
|
||||
SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort);
|
||||
try
|
||||
{
|
||||
requireNetwork();
|
||||
client.connect(false);
|
||||
|
||||
Assert.assertSame(TestQueryHandler.class, ClientState.getCQLQueryHandler().getClass());
|
||||
Map<String, ByteBuffer> reqMap;
|
||||
Map<String, ByteBuffer> respMap;
|
||||
|
||||
SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort);
|
||||
try
|
||||
{
|
||||
client.connect(false);
|
||||
QueryMessage queryMessage = new QueryMessage(
|
||||
"CREATE TABLE " + KEYSPACE + ".atable (pk int PRIMARY KEY, v text)",
|
||||
QueryOptions.DEFAULT
|
||||
);
|
||||
PrepareMessage prepareMessage = new PrepareMessage("SELECT * FROM " + KEYSPACE + ".atable", null);
|
||||
|
||||
Map<String, ByteBuffer> reqMap;
|
||||
Map<String, ByteBuffer> respMap;
|
||||
reqMap = Collections.singletonMap("foo", bytes(42));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(42));
|
||||
queryMessage.setCustomPayload(reqMap);
|
||||
Message.Response queryResponse = client.execute(queryMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, queryResponse.getCustomPayload());
|
||||
|
||||
QueryMessage queryMessage = new QueryMessage(
|
||||
"CREATE TABLE " + KEYSPACE + ".atable (pk int PRIMARY KEY, v text)",
|
||||
QueryOptions.DEFAULT
|
||||
);
|
||||
PrepareMessage prepareMessage = new PrepareMessage("SELECT * FROM " + KEYSPACE + ".atable", null);
|
||||
reqMap = Collections.singletonMap("foo", bytes(43));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(43));
|
||||
prepareMessage.setCustomPayload(reqMap);
|
||||
ResultMessage.Prepared prepareResponse = (ResultMessage.Prepared) client.execute(prepareMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, prepareResponse.getCustomPayload());
|
||||
|
||||
reqMap = Collections.singletonMap("foo", bytes(42));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(42));
|
||||
queryMessage.setCustomPayload(reqMap);
|
||||
Message.Response queryResponse = client.execute(queryMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, queryResponse.getCustomPayload());
|
||||
ExecuteMessage executeMessage = new ExecuteMessage(prepareResponse.statementId, prepareResponse.resultMetadataId, QueryOptions.DEFAULT);
|
||||
reqMap = Collections.singletonMap("foo", bytes(44));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(44));
|
||||
executeMessage.setCustomPayload(reqMap);
|
||||
Message.Response executeResponse = client.execute(executeMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, executeResponse.getCustomPayload());
|
||||
|
||||
reqMap = Collections.singletonMap("foo", bytes(43));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(43));
|
||||
prepareMessage.setCustomPayload(reqMap);
|
||||
ResultMessage.Prepared prepareResponse = (ResultMessage.Prepared) client.execute(prepareMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, prepareResponse.getCustomPayload());
|
||||
|
||||
ExecuteMessage executeMessage = new ExecuteMessage(prepareResponse.statementId, prepareResponse.resultMetadataId, QueryOptions.DEFAULT);
|
||||
reqMap = Collections.singletonMap("foo", bytes(44));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(44));
|
||||
executeMessage.setCustomPayload(reqMap);
|
||||
Message.Response executeResponse = client.execute(executeMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, executeResponse.getCustomPayload());
|
||||
|
||||
BatchMessage batchMessage = new BatchMessage(BatchStatement.Type.UNLOGGED,
|
||||
Collections.<Object>singletonList("INSERT INTO " + KEYSPACE + ".atable (pk,v) VALUES (1, 'foo')"),
|
||||
Collections.singletonList(ByteArrayUtil.EMPTY_ARRAY_OF_BYTE_ARRAYS),
|
||||
QueryOptions.DEFAULT);
|
||||
reqMap = Collections.singletonMap("foo", bytes(45));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(45));
|
||||
batchMessage.setCustomPayload(reqMap);
|
||||
Message.Response batchResponse = client.execute(batchMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, batchResponse.getCustomPayload());
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
BatchMessage batchMessage = new BatchMessage(BatchStatement.Type.UNLOGGED,
|
||||
Collections.<Object>singletonList("INSERT INTO " + KEYSPACE + ".atable (pk,v) VALUES (1, 'foo')"),
|
||||
Collections.singletonList(ByteArrayUtil.EMPTY_ARRAY_OF_BYTE_ARRAYS),
|
||||
QueryOptions.DEFAULT);
|
||||
reqMap = Collections.singletonMap("foo", bytes(45));
|
||||
responsePayload = respMap = Collections.singletonMap("bar", bytes(45));
|
||||
batchMessage.setCustomPayload(reqMap);
|
||||
Message.Response batchResponse = client.execute(batchMessage);
|
||||
payloadEquals(reqMap, requestPayload);
|
||||
payloadEquals(respMap, batchResponse.getCustomPayload());
|
||||
}
|
||||
finally
|
||||
{
|
||||
cqlQueryHandlerField.set(null, queryHandler);
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessagePayloadVersion3() throws Throwable
|
||||
{
|
||||
QueryHandler queryHandler = (QueryHandler) cqlQueryHandlerField.get(null);
|
||||
cqlQueryHandlerField.set(null, new TestQueryHandler());
|
||||
requireNetwork();
|
||||
|
||||
Assert.assertSame(TestQueryHandler.class, ClientState.getCQLQueryHandler().getClass());
|
||||
|
||||
SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, ProtocolVersion.V3);
|
||||
try
|
||||
{
|
||||
requireNetwork();
|
||||
client.connect(false);
|
||||
|
||||
Assert.assertSame(TestQueryHandler.class, ClientState.getCQLQueryHandler().getClass());
|
||||
Map<String, ByteBuffer> reqMap;
|
||||
|
||||
SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, ProtocolVersion.V3);
|
||||
QueryMessage queryMessage = new QueryMessage(
|
||||
"CREATE TABLE " + KEYSPACE + ".atable (pk int PRIMARY KEY, v text)",
|
||||
QueryOptions.DEFAULT
|
||||
);
|
||||
PrepareMessage prepareMessage = new PrepareMessage("SELECT * FROM " + KEYSPACE + ".atable", null);
|
||||
|
||||
reqMap = Collections.singletonMap("foo", bytes(42));
|
||||
responsePayload = Collections.singletonMap("bar", bytes(42));
|
||||
queryMessage.setCustomPayload(reqMap);
|
||||
try
|
||||
{
|
||||
client.connect(false);
|
||||
|
||||
Map<String, ByteBuffer> reqMap;
|
||||
|
||||
QueryMessage queryMessage = new QueryMessage(
|
||||
"CREATE TABLE " + KEYSPACE + ".atable (pk int PRIMARY KEY, v text)",
|
||||
QueryOptions.DEFAULT
|
||||
);
|
||||
PrepareMessage prepareMessage = new PrepareMessage("SELECT * FROM " + KEYSPACE + ".atable", null);
|
||||
|
||||
reqMap = Collections.singletonMap("foo", bytes(42));
|
||||
responsePayload = Collections.singletonMap("bar", bytes(42));
|
||||
queryMessage.setCustomPayload(reqMap);
|
||||
try
|
||||
{
|
||||
client.execute(queryMessage);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
Assert.assertTrue(e.getCause() instanceof ProtocolException);
|
||||
}
|
||||
// when a protocol exception is thrown by the server the connection is closed, so need to re-connect
|
||||
client.close();
|
||||
client.connect(false);
|
||||
|
||||
queryMessage.setCustomPayload(null);
|
||||
client.execute(queryMessage);
|
||||
|
||||
reqMap = Collections.singletonMap("foo", bytes(43));
|
||||
responsePayload = Collections.singletonMap("bar", bytes(43));
|
||||
prepareMessage.setCustomPayload(reqMap);
|
||||
try
|
||||
{
|
||||
client.execute(prepareMessage);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
Assert.assertTrue(e.getCause() instanceof ProtocolException);
|
||||
}
|
||||
// when a protocol exception is thrown by the server the connection is closed, so need to re-connect
|
||||
client.close();
|
||||
client.connect(false);
|
||||
|
||||
prepareMessage.setCustomPayload(null);
|
||||
ResultMessage.Prepared prepareResponse = (ResultMessage.Prepared) client.execute(prepareMessage);
|
||||
|
||||
ExecuteMessage executeMessage = new ExecuteMessage(prepareResponse.statementId, prepareResponse.resultMetadataId, QueryOptions.DEFAULT);
|
||||
reqMap = Collections.singletonMap("foo", bytes(44));
|
||||
responsePayload = Collections.singletonMap("bar", bytes(44));
|
||||
executeMessage.setCustomPayload(reqMap);
|
||||
try
|
||||
{
|
||||
client.execute(executeMessage);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
Assert.assertTrue(e.getCause() instanceof ProtocolException);
|
||||
}
|
||||
// when a protocol exception is thrown by the server the connection is closed, so need to re-connect
|
||||
client.close();
|
||||
client.connect(false);
|
||||
|
||||
BatchMessage batchMessage = new BatchMessage(BatchStatement.Type.UNLOGGED,
|
||||
Collections.<Object>singletonList("INSERT INTO " + KEYSPACE + ".atable (pk,v) VALUES (1, 'foo')"),
|
||||
Collections.singletonList(ByteArrayUtil.EMPTY_ARRAY_OF_BYTE_ARRAYS),
|
||||
QueryOptions.DEFAULT);
|
||||
reqMap = Collections.singletonMap("foo", bytes(45));
|
||||
responsePayload = Collections.singletonMap("bar", bytes(45));
|
||||
batchMessage.setCustomPayload(reqMap);
|
||||
try
|
||||
{
|
||||
client.execute(batchMessage);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
Assert.assertTrue(e.getCause() instanceof ProtocolException);
|
||||
}
|
||||
Assert.fail();
|
||||
}
|
||||
finally
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
client.close();
|
||||
Assert.assertTrue(e.getCause() instanceof ProtocolException);
|
||||
}
|
||||
// when a protocol exception is thrown by the server the connection is closed, so need to re-connect
|
||||
client.close();
|
||||
client.connect(false);
|
||||
|
||||
queryMessage.setCustomPayload(null);
|
||||
client.execute(queryMessage);
|
||||
|
||||
reqMap = Collections.singletonMap("foo", bytes(43));
|
||||
responsePayload = Collections.singletonMap("bar", bytes(43));
|
||||
prepareMessage.setCustomPayload(reqMap);
|
||||
try
|
||||
{
|
||||
client.execute(prepareMessage);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
Assert.assertTrue(e.getCause() instanceof ProtocolException);
|
||||
}
|
||||
// when a protocol exception is thrown by the server the connection is closed, so need to re-connect
|
||||
client.close();
|
||||
client.connect(false);
|
||||
|
||||
prepareMessage.setCustomPayload(null);
|
||||
ResultMessage.Prepared prepareResponse = (ResultMessage.Prepared) client.execute(prepareMessage);
|
||||
|
||||
ExecuteMessage executeMessage = new ExecuteMessage(prepareResponse.statementId, prepareResponse.resultMetadataId, QueryOptions.DEFAULT);
|
||||
reqMap = Collections.singletonMap("foo", bytes(44));
|
||||
responsePayload = Collections.singletonMap("bar", bytes(44));
|
||||
executeMessage.setCustomPayload(reqMap);
|
||||
try
|
||||
{
|
||||
client.execute(executeMessage);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
Assert.assertTrue(e.getCause() instanceof ProtocolException);
|
||||
}
|
||||
// when a protocol exception is thrown by the server the connection is closed, so need to re-connect
|
||||
client.close();
|
||||
client.connect(false);
|
||||
|
||||
BatchMessage batchMessage = new BatchMessage(BatchStatement.Type.UNLOGGED,
|
||||
Collections.<Object>singletonList("INSERT INTO " + KEYSPACE + ".atable (pk,v) VALUES (1, 'foo')"),
|
||||
Collections.singletonList(ByteArrayUtil.EMPTY_ARRAY_OF_BYTE_ARRAYS),
|
||||
QueryOptions.DEFAULT);
|
||||
reqMap = Collections.singletonMap("foo", bytes(45));
|
||||
responsePayload = Collections.singletonMap("bar", bytes(45));
|
||||
batchMessage.setCustomPayload(reqMap);
|
||||
try
|
||||
{
|
||||
client.execute(batchMessage);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
Assert.assertTrue(e.getCause() instanceof ProtocolException);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
cqlQueryHandlerField.set(null, queryHandler);
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ import org.apache.cassandra.utils.MerkleTree.TreeRange;
|
|||
import org.apache.cassandra.utils.MerkleTree.TreeRangeIterator;
|
||||
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
import static org.apache.cassandra.config.CassandraRelevantProperties.JAVA_VERSION;
|
||||
import static org.apache.cassandra.utils.JavaUtils.parseJavaVersion;
|
||||
import static org.apache.cassandra.utils.MerkleTree.RECOMMENDED_DEPTH;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
|
@ -619,8 +621,12 @@ public class MerkleTreeTest
|
|||
Assert.assertEquals(12, MerkleTree.estimatedMaxDepthForBytes(Murmur3Partitioner.instance,
|
||||
1048576, 32));
|
||||
|
||||
// With 100 mebibytes we should get a limit of 19
|
||||
Assert.assertEquals(19, MerkleTree.estimatedMaxDepthForBytes(Murmur3Partitioner.instance,
|
||||
// With 100 mebibytes we should get a limit of 19 on JDK's < 21, 18 on JDK21
|
||||
// Object size impl details can be expected to change on different JDK's so this impl will be brittle
|
||||
// in the face of future JDK changes.
|
||||
int version = parseJavaVersion(JAVA_VERSION.getString());
|
||||
int expectedLimit = version < 21 ? 19 : 18;
|
||||
Assert.assertEquals(expectedLimit, MerkleTree.estimatedMaxDepthForBytes(Murmur3Partitioner.instance,
|
||||
100 * 1048576, 32));
|
||||
|
||||
// With 300 mebibytes we should get the old limit of 20
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ import java.util.function.Supplier;
|
|||
|
||||
import net.openhft.chronicle.queue.ChronicleQueue;
|
||||
import net.openhft.chronicle.queue.ExcerptTailer;
|
||||
import net.openhft.chronicle.queue.RollCycles;
|
||||
import net.openhft.chronicle.queue.impl.single.SingleChronicleQueueBuilder;
|
||||
import net.openhft.chronicle.queue.rollcycles.TestRollCycles;
|
||||
import net.openhft.chronicle.wire.WireOut;
|
||||
|
||||
import org.junit.After;
|
||||
|
|
@ -75,7 +75,7 @@ public class BinLogTest
|
|||
{
|
||||
path = tempDir();
|
||||
binLog = new BinLog.Builder().path(path)
|
||||
.rollCycle(RollCycles.TEST_SECONDLY.toString())
|
||||
.rollCycle(TestRollCycles.TEST_SECONDLY.toString())
|
||||
.maxQueueWeight(10)
|
||||
.maxLogSize(1024 * 1024 * 128)
|
||||
.blocking(false)
|
||||
|
|
@ -110,13 +110,13 @@ public class BinLogTest
|
|||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testConstructorZeroWeight() throws Exception
|
||||
{
|
||||
new BinLog.Builder().path(tempDir()).rollCycle(RollCycles.TEST_SECONDLY.toString()).maxQueueWeight(0).build(false);
|
||||
new BinLog.Builder().path(tempDir()).rollCycle(TestRollCycles.TEST_SECONDLY.toString()).maxQueueWeight(0).build(false);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testConstructorLogSize() throws Exception
|
||||
{
|
||||
new BinLog.Builder().path(tempDir()).rollCycle(RollCycles.TEST_SECONDLY.toString()).maxLogSize(0).build(false);
|
||||
new BinLog.Builder().path(tempDir()).rollCycle(TestRollCycles.TEST_SECONDLY.toString()).maxLogSize(0).build(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -383,7 +383,7 @@ public class BinLogTest
|
|||
public void testCleanupOnOversize() throws Exception
|
||||
{
|
||||
tearDown();
|
||||
binLog = new BinLog.Builder().path(path).rollCycle(RollCycles.TEST_SECONDLY.toString()).maxQueueWeight(1).maxLogSize(10000).blocking(false).build(false);
|
||||
binLog = new BinLog.Builder().path(path).rollCycle(TestRollCycles.TEST_SECONDLY.toString()).maxQueueWeight(1).maxLogSize(10000).blocking(false).build(false);
|
||||
for (int ii = 0; ii < 5; ii++)
|
||||
{
|
||||
binLog.put(record(String.valueOf(ii)));
|
||||
|
|
@ -496,7 +496,7 @@ public class BinLogTest
|
|||
List<String> readBinLogRecords(Path path)
|
||||
{
|
||||
List<String> records = new ArrayList<String>();
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(path.toFile()).rollCycle(RollCycles.TEST_SECONDLY).build())
|
||||
try (ChronicleQueue queue = SingleChronicleQueueBuilder.single(path.toFile()).rollCycle(TestRollCycles.TEST_SECONDLY).build())
|
||||
{
|
||||
ExcerptTailer tailer = queue.createTailer();
|
||||
while (true)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ import org.apache.cassandra.utils.ObjectSizes;
|
|||
import org.apache.cassandra.utils.Pair;
|
||||
import org.apache.cassandra.utils.concurrent.Ref.Visitor;
|
||||
|
||||
import static org.apache.cassandra.config.CassandraRelevantProperties.JAVA_VERSION;
|
||||
import static org.apache.cassandra.utils.JavaUtils.parseJavaVersion;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@SuppressWarnings({"unused", "unchecked", "rawtypes"})
|
||||
|
|
@ -468,10 +470,10 @@ public class RefCountedTest
|
|||
private Set<Ref.GlobalState> testCycles(Function<LambdaTestClass, Runnable> runOnCloseSupplier)
|
||||
{
|
||||
LambdaTestClass test = new LambdaTestClass();
|
||||
Runnable weakRef = runOnCloseSupplier.apply(test);
|
||||
Runnable supplierRef = runOnCloseSupplier.apply(test);
|
||||
RefCounted.Tidy tidier = new RefCounted.Tidy()
|
||||
{
|
||||
Runnable ref = weakRef;
|
||||
Runnable ref = supplierRef;
|
||||
|
||||
public void tidy()
|
||||
{
|
||||
|
|
@ -505,7 +507,17 @@ public class RefCountedTest
|
|||
public void testCycles()
|
||||
{
|
||||
assertThat(testCycles(LambdaTestClass::getRunOnCloseLambdaWithThis)).isNotEmpty(); // sanity test
|
||||
assertThat(testCycles(LambdaTestClass::getRunOnCloseInner)).isNotEmpty(); // sanity test
|
||||
|
||||
// Behavior changed in JDK21; this was a sanity check to explore the way things worked but doesn't impact
|
||||
// the correctness of the final actual check of the test.
|
||||
int version = parseJavaVersion(JAVA_VERSION.getString());
|
||||
boolean runOnCloseInnerState = version >= 21;
|
||||
|
||||
var result = testCycles(LambdaTestClass::getRunOnCloseInner);
|
||||
if (runOnCloseInnerState)
|
||||
assertThat(result).isEmpty();
|
||||
else
|
||||
assertThat(result).isNotEmpty();
|
||||
|
||||
assertThat(testCycles(LambdaTestClass::getRunOnCloseLambda)).isEmpty();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,57 +85,37 @@ if [ -z $JAVA ] ; then
|
|||
fi
|
||||
|
||||
# Matches variable 'java.supported' in build.xml
|
||||
java_versions_supported=11,17
|
||||
java_versions_supported="11 17 21"
|
||||
java_version_string=$(IFS=" "; echo "${java_versions_supported}")
|
||||
|
||||
# Determine the sort of JVM we'll be running on.
|
||||
java_ver_output=`"${JAVA:-java}" -version 2>&1`
|
||||
jvmver=`echo "$java_ver_output" | grep '[openjdk|java] version' | awk -F'"' 'NR==1 {print $2}' | cut -d\- -f1`
|
||||
JVM_VERSION=${jvmver%_*}
|
||||
short=$(echo "${jvmver}" | cut -c1-2)
|
||||
JAVA_VERSION=$(java -version 2>&1 | grep '[openjdk|java] version' | cut -d '"' -f2 | cut -d '.' -f1)
|
||||
|
||||
# Unsupported JDKs below the upper supported version are not allowed
|
||||
if [ "$short" != "$(echo "$java_versions_supported" | cut -d, -f1)" ] && [ "$JVM_VERSION" \< "$(echo "$java_versions_supported" | cut -d, -f2)" ] ; then
|
||||
echo "Unsupported Java $JVM_VERSION. Supported are $java_versions_supported"
|
||||
exit 1;
|
||||
supported=0
|
||||
for version in ${java_versions_supported}; do
|
||||
if [ "$version" -eq "$JAVA_VERSION" ]; then
|
||||
supported=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$supported" -eq 0 ]; then
|
||||
if [ -z "$CASSANDRA_JDK_UNSUPPORTED" ]; then
|
||||
echo "Unsupported Java $JAVA_VERSION. Supported are $java_version_string"
|
||||
echo "If you would like to test with newer Java versions set CASSANDRA_JDK_UNSUPPORTED to any value (for example, CASSANDRA_JDK_UNSUPPORTED=true). Unset the parameter for default behavior"
|
||||
exit 1
|
||||
else
|
||||
echo "######################################################################"
|
||||
echo "Warning! You are using JDK$JAVA_VERSION. This Cassandra version only supports $java_version_string"
|
||||
echo "######################################################################"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Allow execution of supported Java versions, and newer if CASSANDRA_JDK_UNSUPPORTED is set
|
||||
is_supported_version=$(echo "$java_versions_supported" | tr "," '\n' | grep -F -x "$short")
|
||||
if [ -z "$is_supported_version" ] ; then
|
||||
if [ -z "$CASSANDRA_JDK_UNSUPPORTED" ] ; then
|
||||
echo "Unsupported Java $JVM_VERSION. Supported are $java_versions_supported"
|
||||
echo "If you would like to test with newer Java versions set CASSANDRA_JDK_UNSUPPORTED to any value (for example, CASSANDRA_JDK_UNSUPPORTED=true). Unset the parameter for default behavior"
|
||||
exit 1;
|
||||
else
|
||||
echo "######################################################################"
|
||||
echo "Warning! You are using JDK$short. This Cassandra version only supports $java_versions_supported."
|
||||
echo "######################################################################"
|
||||
fi
|
||||
fi
|
||||
JAVA_VERSION=$short
|
||||
|
||||
jvm=`echo "$java_ver_output" | grep -A 1 '[openjdk|java] version' | awk 'NR==2 {print $1}'`
|
||||
case "$jvm" in
|
||||
OpenJDK)
|
||||
JVM_VENDOR=OpenJDK
|
||||
# this will be "64-Bit" or "32-Bit"
|
||||
JVM_ARCH=`echo "$java_ver_output" | awk 'NR==3 {print $2}'`
|
||||
;;
|
||||
"Java(TM)")
|
||||
JVM_VENDOR=Oracle
|
||||
# this will be "64-Bit" or "32-Bit"
|
||||
JVM_ARCH=`echo "$java_ver_output" | awk 'NR==3 {print $3}'`
|
||||
;;
|
||||
*)
|
||||
# Help fill in other JVM values
|
||||
JVM_VENDOR=other
|
||||
JVM_ARCH=unknown
|
||||
;;
|
||||
esac
|
||||
|
||||
# Read user-defined JVM options from jvm-server.options file
|
||||
JVM_OPTS_FILE=$CASSANDRA_CONF/jvm${jvmoptions_variant:--clients}.options
|
||||
if [ $JAVA_VERSION -ge 17 ] ; then
|
||||
if [ $JAVA_VERSION -ge 21 ] ; then
|
||||
JVM_DEP_OPTS_FILE=$CASSANDRA_CONF/jvm21${jvmoptions_variant:--clients}.options
|
||||
elif [ $JAVA_VERSION -ge 17 ] ; then
|
||||
JVM_DEP_OPTS_FILE=$CASSANDRA_CONF/jvm17${jvmoptions_variant:--clients}.options
|
||||
elif [ $JAVA_VERSION -ge 11 ] ; then
|
||||
JVM_DEP_OPTS_FILE=$CASSANDRA_CONF/jvm11${jvmoptions_variant:--clients}.options
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ public class Dump implements Runnable
|
|||
@Parameters(paramLabel = "path", description = "Path containing the full query logs to dump.", arity = "1..*")
|
||||
private List<String> arguments = new ArrayList<>();
|
||||
|
||||
@Option(paramLabel = "roll_cycle", names = { "--roll-cycle" }, description = "How often to roll the log file was rolled. May be necessary for Chronicle to correctly parse file names. (MINUTELY, HOURLY, DAILY). Default HOURLY.")
|
||||
private String rollCycle = "HOURLY";
|
||||
@Option(paramLabel = "roll_cycle", names = { "--roll-cycle" }, description = "How often to roll the log file was rolled. May be necessary for Chronicle to correctly parse file names. (FAST_MINUTELY, FAST_HOURLY, FAST_DAILY). Default FAST_HOURLY.")
|
||||
private String rollCycle = "FAST_HOURLY";
|
||||
|
||||
@Option(paramLabel = "follow", names = { "--follow" }, description = "Upon reacahing the end of the log continue indefinitely waiting for more records")
|
||||
private boolean follow = false;
|
||||
|
|
|
|||
Loading…
Reference in New Issue