Compare commits

..

21 Commits

Author SHA1 Message Date
Hagit Segev
9002c6d517 release: prepare for 3.1.4 2020-02-24 23:53:19 +02:00
Hagit Segev
cc446862c8 release: prepare for 3.1.3 2020-01-28 14:10:14 +02:00
Yaron Kaikov
5a383709b3 release: prepare for 3.1.2 2019-11-27 10:25:00 +02:00
Yaron Kaikov
4f73c69863 release: prepare for 3.1.1 2019-10-24 21:56:07 +03:00
Yaron Kaikov
d17d5bc73d release: prepare for 3.1.0 2019-10-12 08:46:07 +03:00
yaronkaikov
e3b5c65895 release: prepare for 3.1.0.rc9 2019-10-06 10:51:52 +03:00
Hagit Segev
7a13ae97bb release: prepare for 3.1.0.rc8 2019-09-23 07:01:20 +03:00
yaronkaikov
61dbbb3254 release: prepare for3.1.0.rc7 2019-09-10 18:57:13 +03:00
Hagit Segev
b7efec5e99 release: prepare for3.1.0.rc6 2019-09-08 10:32:39 +03:00
Amnon Heiman
a8b9849480 ColumnFamilyStore: Mbean API support the hex format param (#69)
Cassandra 3.0 version of the JMX added a parameter that allows accepting
the parameter as hex.

This breaks the current implementation with a NoSuchMethodException.

This patch adds the missing implementation.

For a full support, a follow up patch in Scylla is needed, but for the
current functionality it would work.

After this patch usage example:

nodetool getsstables keyspace1 standard1 39303138374b4d343830

Fixes #78

Signed-off-by: Amnon Heiman <amnon@scylladb.com>
(cherry picked from commit ff0723abc6c2dd23313f93cd5ec396ffd731d743)
2019-09-03 13:28:39 +03:00
yaronkaikov
3d7226bf3d release: prepare for3.1.0.rc5 2019-09-02 14:43:01 +03:00
Hagit Segev
fb3d56d033 release: prepare for 3.1.0.rc4 2019-08-22 21:12:55 +03:00
yaronkaikov
f4e5fefd3b release: prepare for 3.1.0.rc3 2019-07-25 12:16:16 +03:00
Amnon Heiman
ae74b2e865 APIMBeanServer: Support both Table and Tables as metric name
Fixes #71

Signed-off-by: Amnon Heiman <amnon@scylladb.com>
(cherry picked from commit c7bce65919bce196f13d398eec6695b5bb48068b)
2019-07-24 15:09:49 +03:00
Amnon Heiman
095cbd02e5 APIClient: delete command should check for errors
delete commands do not return a value, still, it is possible that the
command will return a value different than OK.

In such a case, the error should be propagate to the caller via an
exception.

Fixes #65

Signed-off-by: Amnon Heiman <amnon@scylladb.com>
Message-Id: <20190618135312.2776-1-amnon@scylladb.com>
(cherry picked from commit 2fac82434bc8985bb150bc203a24fd3cc2181675)
2019-07-24 15:06:56 +03:00
Amnon Heiman
3619024b44 ColumnFamilyStore: finishLocalSampling should respect count limit
When calling nodetool toppartitions with size limit, finishLocalSampling
should respect that and limit the number of the results.

Example:
$ nodetool toppartitions -k 2 keyspace1 standard1 20
WRITES Sampler:
  Cardinality: ~2 (256 capacity)
  Top 2 partitions:
	Partition                Count       +/-
	38333032394d4f4d5030         4         3
	4e353937383137503330         4         3

READS Sampler:
  Cardinality: ~2 (256 capacity)
  Top 2 partitions:
	Nothing recorded during sampling period...

Fixes #66

Signed-off-by: Amnon Heiman <amnon@scylladb.com>
(cherry picked from commit 9dae28e2f0354bcfb9408a781e8ffb9201fd6e10)
2019-06-27 13:09:15 +03:00
Calle Wilund
b925da76d8 APIMBeanServer: Handle nodeprobe wildcard queries in CF refresh
Fixes #63
Message-Id: <20190311082942.3310-2-calle@scylladb.com>

(cherry picked from commit 512638ed6e4ee2b50835483e532cdb4f6283e2a6)
2019-06-27 13:08:26 +03:00
Calle Wilund
76b30ba915 ColumnFamilyStore: Propapgate exception cause in sampling wait
Message-Id: <20190311082942.3310-1-calle@scylladb.com>
(cherry picked from commit 5f974bc2bb37e58e47953cf62ea86c6a35f9629c)
2019-06-27 13:08:26 +03:00
Hagit Segev
d8a8651de9 release: prepare for 3.1.0.rc2 2019-06-16 20:28:47 +03:00
Hagit Segev
b12549c260 release: prepare for 3.1.0.rc1 2019-06-06 18:16:21 +03:00
Hagit Segev
ce502ed3b7 release: prepare for 3.1.0.rc0 2019-05-13 15:03:45 +03:00
67 changed files with 690 additions and 1552 deletions

1
.github/CODEOWNERS vendored
View File

@ -1 +0,0 @@
* @penberg

9
.gitignore vendored
View File

@ -1,9 +0,0 @@
/target/
/bin/
dependency-reduced-pom.xml
scylla-apiclient/target/
.classpath
.project
.settings
build/
/.idea/

View File

@ -7,7 +7,7 @@ Scylla JMX server implements the Apache Cassandra JMX interface for compatibilit
To compile JMX server, run: To compile JMX server, run:
```console ```console
$ mvn --file scylla-jmx-parent/pom.xml package $ mvn package
``` ```
## Running ## Running

View File

@ -1,47 +1,19 @@
#!/bin/sh #!/bin/sh
PRODUCT=scylla PRODUCT=scylla
VERSION=666.development VERSION=3.1.4
if test -f version if test -f version
then then
SCYLLA_VERSION=$(cat version | awk -F'-' '{print $1}') SCYLLA_VERSION=$(cat version | awk -F'-' '{print $1}')
SCYLLA_RELEASE=$(cat version | awk -F'-' '{print $2}') SCYLLA_RELEASE=$(cat version | awk -F'-' '{print $2}')
else else
DATE=$(date --utc +%Y%m%d) DATE=$(date +%Y%m%d)
GIT_COMMIT=$(git log --pretty=format:'%h' -n 1) GIT_COMMIT=$(git log --pretty=format:'%h' -n 1)
SCYLLA_VERSION=$VERSION SCYLLA_VERSION=$VERSION
SCYLLA_RELEASE=$DATE.$GIT_COMMIT SCYLLA_RELEASE=$DATE.$GIT_COMMIT
fi fi
usage() {
echo "usage: $0"
echo " [--version product-version-release] # override p-v-r"
exit 1
}
OVERRIDE=
while [[ $# > 0 ]]; do
case "$1" in
--version)
OVERRIDE="$2"
shift 2
;;
*)
usage
;;
esac
done
if [[ -n "$OVERRIDE" ]]; then
# regular expression for p-v-r: alphabetic+dashes for product, trailing non-dashes
# for release, everything else for version
RE='^([-a-z]+)-(.+)-([^-]+)$'
PRODUCT="$(sed -E "s/$RE/\\1/" <<<"$OVERRIDE")"
SCYLLA_VERSION="$(sed -E "s/$RE/\\2/" <<<"$OVERRIDE")"
SCYLLA_RELEASE="$(sed -E "s/$RE/\\3/" <<<"$OVERRIDE")"
fi
echo "$SCYLLA_VERSION-$SCYLLA_RELEASE" echo "$SCYLLA_VERSION-$SCYLLA_RELEASE"
mkdir -p build mkdir -p build
echo "$SCYLLA_VERSION" > build/SCYLLA-VERSION-FILE echo "$SCYLLA_VERSION" > build/SCYLLA-VERSION-FILE

View File

@ -20,13 +20,10 @@ SCYLLA_CONF=/etc/scylla
#SCYLLA_JMX_FILE="-cf /etc/scylla.d/scylla-user.cfg" #SCYLLA_JMX_FILE="-cf /etc/scylla.d/scylla-user.cfg"
# The location of the jmx proxy jar file # The location of the jmx proxy jar file
SCYLLA_JMX_LOCAL="-l /opt/scylladb/jmx" SCYLLA_JMX_LOCAL="-l /usr/lib/scylla/jmx"
# allow to run remotely # allow to run remotely
#SCYLLA_JMX_REMOTE="-r" #SCYLLA_JMX_REMOTE="-r"
# allow debug # allow debug
#SCYLLA_JMX_DEBUG="-d" #SCYLLA_JMX_DEBUG="-d"
# specify JVM options
JAVA_TOOL_OPTIONS=""

View File

@ -1,18 +0,0 @@
[Unit]
Description=Scylla JMX
Requires=scylla-server.service
After=scylla-server.service
[Service]
Type=simple
EnvironmentFile=/etc/sysconfig/scylla-jmx
User=scylla
Group=scylla
ExecStart=/opt/scylladb/jmx/scylla-jmx $SCYLLA_JMX_PORT $SCYLLA_API_PORT $SCYLLA_API_ADDR $SCYLLA_JMX_ADDR $SCYLLA_JMX_FILE $SCYLLA_JMX_LOCAL $SCYLLA_JMX_REMOTE $SCYLLA_JMX_DEBUG
KillMode=process
Restart=on-abnormal
Slice=scylla-helper.slice
WorkingDirectory=/var/lib/scylla
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,21 @@
[Unit]
Description=Scylla JMX
Requires=scylla-server.service
After=scylla-server.service
[Service]
Type=simple
{{#debian}}
EnvironmentFile=/etc/default/scylla-jmx
{{/debian}}
{{#redhat}}
EnvironmentFile=/etc/sysconfig/scylla-jmx
{{/redhat}}
User=scylla
Group=scylla
ExecStart=/usr/lib/scylla/jmx/scylla-jmx $SCYLLA_JMX_PORT $SCYLLA_API_PORT $SCYLLA_API_ADDR $SCYLLA_JMX_ADDR $SCYLLA_JMX_FILE $SCYLLA_JMX_LOCAL $SCYLLA_JMX_REMOTE $SCYLLA_JMX_DEBUG
KillMode=process
Restart=on-abnormal
[Install]
WantedBy=multi-user.target

126
dist/debian/build_deb.sh vendored Executable file
View File

@ -0,0 +1,126 @@
#!/bin/bash -e
PRODUCT=$(cat SCYLLA-PRODUCT-FILE)
. /etc/os-release
print_usage() {
echo "build_deb.sh --reloc-pkg build/scylla-jmx-package.tar.gz"
echo " --reloc-pkg specify relocatable package path"
exit 1
}
TARGET=stable
RELOC_PKG=
while [ $# -gt 0 ]; do
case "$1" in
"--reloc-pkg")
RELOC_PKG=$2
shift 2
;;
*)
print_usage
;;
esac
done
is_redhat_variant() {
[ -f /etc/redhat-release ]
}
is_debian_variant() {
[ -f /etc/debian_version ]
}
pkg_install() {
if is_redhat_variant; then
sudo yum install -y $1
elif is_debian_variant; then
sudo apt-get install -y $1
else
echo "Requires to install following command: $1"
exit 1
fi
}
if [ ! -e SCYLLA-RELOCATABLE-FILE ]; then
echo "do not directly execute build_rpm.sh, use reloc/build_rpm.sh instead."
exit 1
fi
if [ "$(arch)" != "x86_64" ]; then
echo "Unsupported architecture: $(arch)"
exit 1
fi
if [ -z "$RELOC_PKG" ]; then
print_usage
exit 1
fi
if [ ! -f "$RELOC_PKG" ]; then
echo "$RELOC_PKG is not found."
exit 1
fi
if [ -e debian ] || [ -e build/release ]; then
sudo rm -rf debian build
mkdir build
fi
if is_debian_variant; then
sudo apt-get -y update
fi
# this hack is needed since some environment installs 'git-core' package, it's
# subset of the git command and doesn't works for our git-archive-all script.
if is_redhat_variant && [ ! -f /usr/libexec/git-core/git-submodule ]; then
sudo yum install -y git
fi
if [ ! -f /usr/bin/git ]; then
pkg_install git
fi
if [ ! -f /usr/bin/python ]; then
pkg_install python
fi
if [ ! -f /usr/sbin/debuild ]; then
pkg_install devscripts
fi
if [ ! -f /usr/bin/dh_testdir ]; then
pkg_install debhelper
fi
if [ ! -f /usr/bin/fakeroot ]; then
pkg_install fakeroot
fi
if [ ! -f /usr/bin/pystache ]; then
if is_redhat_variant; then
sudo yum install -y /usr/bin/pystache
elif is_debian_variant; then
sudo apt-get install -y python-pystache
fi
fi
if [ "$ID" = "ubuntu" ] && [ ! -f /usr/share/keyrings/debian-archive-keyring.gpg ]; then
sudo apt-get install -y debian-archive-keyring
fi
if [ "$ID" = "debian" ] && [ ! -f /usr/share/keyrings/ubuntu-archive-keyring.gpg ]; then
sudo apt-get install -y ubuntu-archive-keyring
fi
RELOC_PKG_FULLPATH=$(readlink -f $RELOC_PKG)
RELOC_PKG_BASENAME=$(basename $RELOC_PKG)
SCYLLA_VERSION=$(cat SCYLLA-VERSION-FILE | sed 's/\.rc/~rc/')
SCYLLA_RELEASE=$(cat SCYLLA-RELEASE-FILE)
ln -fv $RELOC_PKG_FULLPATH ../$PRODUCT-jmx_$SCYLLA_VERSION-$SCYLLA_RELEASE.orig.tar.gz
cp -al dist/debian/debian debian
if [ "$PRODUCT" != "scylla" ]; then
for i in debian/scylla-*;do
mv $i ${i/scylla-/$PRODUCT-}
done
fi
REVISION="1"
MUSTACHE_DIST="\"debian\": true, \"$TARGET\": true, \"product\": \"$PRODUCT\", \"$PRODUCT\": true"
pystache dist/debian/changelog.mustache "{ $MUSTACHE_DIST, \"version\": \"$SCYLLA_VERSION\", \"release\": \"$SCYLLA_RELEASE\", \"revision\": \"$REVISION\", \"codename\": \"$TARGET\" }" > debian/changelog
pystache dist/debian/rules.mustache "{ $MUSTACHE_DIST }" > debian/rules
chmod a+rx debian/rules
pystache dist/debian/control.mustache "{ $MUSTACHE_DIST }" > debian/control
pystache dist/common/systemd/scylla-jmx.service.mustache "{ $MUSTACHE_DIST }" > debian/scylla-jmx.service
debuild -rfakeroot -us -uc

View File

@ -1,4 +1,4 @@
%{product}-jmx (%{version}-%{release}-%{revision}) %{codename}; urgency=medium {{product}}-jmx ({{version}}-{{release}}-{{revision}}) {{codename}}; urgency=medium
* Initial release. * Initial release.

View File

@ -1,14 +1,13 @@
Source: %{product}-jmx Source: {{product}}-jmx
Maintainer: Takuya ASADA <syuu@scylladb.com> Maintainer: Takuya ASADA <syuu@scylladb.com>
Homepage: http://scylladb.com Homepage: http://scylladb.com
Section: database Section: database
Priority: optional Priority: optional
Standards-Version: 3.9.5 Standards-Version: 3.9.5
Rules-Requires-Root: no
Package: %{product}-jmx Package: {{product}}-jmx
Architecture: all Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}, openjdk-8-jre-headless | openjdk-8-jre | oracle-java8-set-default | adoptopenjdk-8-hotspot-jre | openjdk-11-jre-headless | openjdk-11-jre |oracle-java11-set-default , %{product}-server Depends: ${shlibs:Depends}, ${misc:Depends}, openjdk-8-jre-headless | openjdk-8-jre | oracle-java8-set-default, {{product}}-server
Description: Scylla JMX server binaries Description: Scylla JMX server binaries
Scylla is a highly scalable, eventually consistent, distributed, Scylla is a highly scalable, eventually consistent, distributed,
partitioned row DB. partitioned row DB.

View File

@ -1,23 +0,0 @@
#!/usr/bin/make -f
include /usr/share/dpkg/pkg-info.mk
override_dh_auto_build:
override_dh_auto_clean:
override_dh_auto_install:
dh_auto_install
cd scylla-jmx; ./install.sh --packaging --root "$(CURDIR)/debian/tmp" --sysconfdir /etc/default
override_dh_installinit:
ifeq ($(DEB_SOURCE),scylla-jmx)
dh_installinit --no-start
else
dh_installinit --no-start --name scylla-jmx
endif
override_dh_strip_nondeterminism:
%:
dh $@

View File

@ -1,4 +0,0 @@
etc/default/scylla-jmx
etc/systemd/system/scylla-jmx.service.d/sysconfdir.conf
opt/scylladb/jmx/*
usr/lib/scylla/jmx/*

View File

@ -1,7 +0,0 @@
#!/bin/sh
if [ -d /run/systemd/system ]; then
systemctl --system daemon-reload >/dev/null || true
fi
#DEBHELPER#

View File

@ -1,7 +0,0 @@
#!/bin/sh
if [ -d /run/systemd/system ]; then
systemctl --system daemon-reload >/dev/null || true
fi
#DEBHELPER#

View File

@ -1 +0,0 @@
../../common/systemd/scylla-jmx.service

21
dist/debian/debian/scylla-jmx.upstart vendored Normal file
View File

@ -0,0 +1,21 @@
# scylla-jmx - ScyllaDB
#
# ScyllaDB
description "ScyllaDB jmx"
start on started scylla-server
stop on stopping scylla-server
umask 022
console log
setuid scylla
setgid scylla
script
. /etc/default/scylla-jmx
export SCYLLA_HOME SCYLLA_CONF
exec /usr/lib/scylla/jmx/scylla-jmx -l /usr/lib/scylla/jmx
end script

View File

@ -1,80 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020 ScyllaDB
#
#
# This file is part of Scylla.
#
# Scylla is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Scylla is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Scylla. If not, see <http://www.gnu.org/licenses/>.
#
import string
import os
import shutil
import re
from pathlib import Path
class DebianFilesTemplate(string.Template):
delimiter = '%'
scriptdir = os.path.dirname(__file__)
with open(os.path.join(scriptdir, 'changelog.template')) as f:
changelog_template = f.read()
with open(os.path.join(scriptdir, 'control.template')) as f:
control_template = f.read()
with open('build/SCYLLA-PRODUCT-FILE') as f:
product = f.read().strip()
with open('build/SCYLLA-VERSION-FILE') as f:
version = f.read().strip().replace('.rc', '~rc').replace('_', '-')
with open('build/SCYLLA-RELEASE-FILE') as f:
release = f.read().strip()
if os.path.exists('build/debian/debian'):
shutil.rmtree('build/debian/debian')
shutil.copytree('dist/debian/debian', 'build/debian/debian')
if product != 'scylla':
for p in Path('build/debian/debian').glob('scylla-*'):
# pat1: scylla-server.service
# -> scylla-enterprise-server.scylla-server.service
# pat2: scylla-server.scylla-fstrim.service
# -> scylla-enterprise-server.scylla-fstrim.service
# pat3: scylla-conf.install
# -> scylla-enterprise-conf.install
if m := re.match(r'^scylla(-[^.]+)\.service$', p.name):
p.rename(p.parent / f'{product}{m.group(1)}.{p.name}')
elif m := re.match(r'^scylla(-[^.]+\.scylla-[^.]+\.[^.]+)$', p.name):
p.rename(p.parent / f'{product}{m.group(1)}')
else:
p.rename(p.parent / p.name.replace('scylla', product, 1))
s = DebianFilesTemplate(changelog_template)
changelog_applied = s.substitute(product=product, version=version, release=release, revision='1', codename='stable')
s = DebianFilesTemplate(control_template)
control_applied = s.substitute(product=product)
with open('build/debian/debian/changelog', 'w') as f:
f.write(changelog_applied)
with open('build/debian/debian/control', 'w') as f:
f.write(control_applied)

37
dist/debian/rules.mustache vendored Executable file
View File

@ -0,0 +1,37 @@
#!/usr/bin/make -f
DOC = $(CURDIR)/debian/{{product}}-jmx/usr/share/doc/{{product}}-jmx
DEST = $(CURDIR)/debian/{{product}}-jmx/usr/lib/scylla/jmx
M2_REPO= $(CURDIR)/m2
override_dh_auto_build:
override_dh_auto_clean:
override_dh_auto_install:
mkdir -p $(CURDIR)/debian/{{product}}-jmx/etc/default/ && \
cp $(CURDIR)/dist/common/sysconfig/scylla-jmx \
$(CURDIR)/debian/{{product}}-jmx/etc/default/
mkdir -p $(DOC) && \
cp $(CURDIR)/*.md $(DOC)
cp $(CURDIR)/NOTICE $(DOC)
mkdir -p $(DEST)
cp $(CURDIR)/scylla-jmx $(DEST)
cp $(CURDIR)/scylla-jmx-1.0.jar $(DEST)
mkdir $(DEST)/symlinks
ln -sf /usr/bin/java $(DEST)/symlinks/scylla-jmx
override_dh_installinit:
{{#scylla}}
dh_installinit --no-start
{{/scylla}}
{{^scylla}}
dh_installinit --no-start --name scylla-jmx
{{/scylla}}
override_dh_strip_nondeterminism:
%:
dh $@

75
dist/redhat/build_rpm.sh vendored Executable file
View File

@ -0,0 +1,75 @@
#!/bin/bash -e
PRODUCT=$(cat SCYLLA-PRODUCT-FILE)
. /etc/os-release
print_usage() {
echo "build_rpm.sh --reloc-pkg build/scylla-jmx-package.tar.gz"
echo " --reloc-pkg specify relocatable package path"
exit 1
}
RELOC_PKG=
while [ $# -gt 0 ]; do
case "$1" in
"--reloc-pkg")
RELOC_PKG=$2
shift 2
;;
*)
print_usage
;;
esac
done
is_redhat_variant() {
[ -f /etc/redhat-release ]
}
pkg_install() {
if is_redhat_variant; then
sudo yum install -y $1
else
echo "Requires to install following command: $1"
exit 1
fi
}
if [ ! -e SCYLLA-RELOCATABLE-FILE ]; then
echo "do not directly execute build_rpm.sh, use reloc/build_rpm.sh instead."
exit 1
fi
if [ -z "$RELOC_PKG" ]; then
print_usage
exit 1
fi
if [ ! -f "$RELOC_PKG" ]; then
echo "$RELOC_PKG is not found."
exit 1
fi
if [ ! -f /usr/bin/rpmbuild ]; then
pkg_install rpm-build
fi
if [ ! -f /usr/bin/git ]; then
pkg_install git
fi
if [ ! -f /usr/bin/pystache ]; then
if is_redhat_variant; then
sudo yum install -y python2-pystache || sudo yum install -y pystache
elif is_debian_variant; then
sudo apt-get install -y python-pystache
fi
fi
SCYLLA_VERSION=$(cat SCYLLA-VERSION-FILE)
SCYLLA_RELEASE=$(cat SCYLLA-RELEASE-FILE)
VERSION=$SCYLLA_VERSION-$SCYLLA_RELEASE
RPMBUILD=$(readlink -f ../)
mkdir -p $RPMBUILD/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
ln -fv $RELOC_PKG $RPMBUILD/SOURCES/
pystache dist/redhat/scylla-jmx.spec.mustache "{ \"version\": \"$SCYLLA_VERSION\", \"release\": \"$SCYLLA_RELEASE\", \"product\": \"$PRODUCT\", \"$PRODUCT\": true }" > $RPMBUILD/SPECS/scylla-jmx.spec
# this rpm can be install on both fedora / centos7, so drop distribution name from the file name
rpmbuild -ba --define "_topdir $RPMBUILD" --undefine "dist" $RPM_JOBS_OPTS $RPMBUILD/SPECS/scylla-jmx.spec

View File

@ -1,75 +0,0 @@
Name: %{product}-jmx
Version: %{version}
Release: %{release}%{?dist}
Summary: Scylla JMX
Group: Applications/Databases
License: AGPLv3
URL: http://www.scylladb.com/
Source0: %{reloc_pkg}
BuildArch: noarch
BuildRequires: systemd-units
Requires: %{product}-server jre-1.8.0-headless
AutoReqProv: no
%description
%prep
%setup -q -n scylla-jmx
%build
%install
./install.sh --packaging --root "$RPM_BUILD_ROOT"
%pre
/usr/sbin/groupadd scylla 2> /dev/null || :
/usr/sbin/useradd -g scylla -s /sbin/nologin -r -d ${_sharedstatedir}/scylla scylla 2> /dev/null || :
ping -c1 `hostname` > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo
echo "**************************************************************"
echo "* WARNING: You need to add hostname on /etc/hosts, otherwise *"
echo "* scylla-jmx will not able to start up. *"
echo "**************************************************************"
echo
fi
%post
if [ $1 -eq 1 ] ; then
/usr/bin/systemctl preset scylla-jmx.service ||:
fi
/usr/bin/systemctl daemon-reload ||:
%preun
if [ $1 -eq 0 ] ; then
/usr/bin/systemctl --no-reload disable scylla-jmx.service ||:
/usr/bin/systemctl stop scylla-jmx.service ||:
fi
%postun
/usr/bin/systemctl daemon-reload ||:
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%config(noreplace) %{_sysconfdir}/sysconfig/scylla-jmx
%{_unitdir}/scylla-jmx.service
/opt/scylladb/jmx/scylla-jmx
/opt/scylladb/jmx/scylla-jmx-1.1.jar
/opt/scylladb/jmx/symlinks/scylla-jmx
%{_prefix}/lib/scylla/jmx/scylla-jmx
%{_prefix}/lib/scylla/jmx/scylla-jmx-1.1.jar
%{_prefix}/lib/scylla/jmx/symlinks/scylla-jmx
%changelog
* Fri Aug 7 2015 Takuya ASADA Takuya ASADA <syuu@cloudius-systems.com>
- inital version of scylla-tools.spec

80
dist/redhat/scylla-jmx.spec.mustache vendored Normal file
View File

@ -0,0 +1,80 @@
Name: {{product}}-jmx
Version: {{version}}
Release: {{release}}%{?dist}
Summary: Scylla JMX
Group: Applications/Databases
License: AGPLv3
URL: http://www.scylladb.com/
Source0: scylla-jmx-package.tar.gz
BuildArch: noarch
BuildRequires: systemd-units
BuildRequires: pystache
%{?rhel:BuildRequires: python-setuptools}
Requires: {{product}}-server java-1.8.0-openjdk-headless
%description
%prep
%setup -c
%build
MUSTACHE_DIST="\"redhat\": true"
pystache dist/common/systemd/scylla-jmx.service.mustache "{ $MUSTACHE_DIST }" > scylla-jmx.service
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/
mkdir -p $RPM_BUILD_ROOT%{_unitdir}
mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/scylla/
install -m644 dist/common/sysconfig/scylla-jmx $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/
install -m644 scylla-jmx.service $RPM_BUILD_ROOT%{_unitdir}/
install -d -m755 $RPM_BUILD_ROOT%{_prefix}/lib/scylla
install -d -m755 $RPM_BUILD_ROOT%{_prefix}/lib/scylla/jmx
install -d -m755 $RPM_BUILD_ROOT%{_prefix}/lib/scylla/jmx/symlinks
install -m644 scylla-jmx-1.0.jar $RPM_BUILD_ROOT%{_prefix}/lib/scylla/jmx/
install -m755 scylla-jmx $RPM_BUILD_ROOT%{_prefix}/lib/scylla/jmx
ln -sf /usr/bin/java $RPM_BUILD_ROOT%{_prefix}/lib/scylla/jmx/symlinks/scylla-jmx
%pre
/usr/sbin/groupadd scylla 2> /dev/null || :
/usr/sbin/useradd -g scylla -s /sbin/nologin -r -d ${_sharedstatedir}/scylla scylla 2> /dev/null || :
ping -c1 `hostname` > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo
echo "**************************************************************"
echo "* WARNING: You need to add hostname on /etc/hosts, otherwise *"
echo "* scylla-jmx will not able to start up. *"
echo "**************************************************************"
echo
fi
%post
%systemd_post scylla-jmx.service
%preun
%systemd_preun scylla-jmx.service
%postun
%systemd_postun
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%config(noreplace) %{_sysconfdir}/sysconfig/scylla-jmx
%{_unitdir}/scylla-jmx.service
%{_prefix}/lib/scylla/jmx/scylla-jmx
%{_prefix}/lib/scylla/jmx/scylla-jmx-1.0.jar
%{_prefix}/lib/scylla/jmx/symlinks/scylla-jmx
%changelog
* Fri Aug 7 2015 Takuya ASADA Takuya ASADA <syuu@cloudius-systems.com>
- inital version of scylla-tools.spec

View File

@ -22,5 +22,5 @@
if [ "$ID" = "ubuntu" ] || [ "$ID" = "debian" ]; then if [ "$ID" = "ubuntu" ] || [ "$ID" = "debian" ]; then
apt -y install maven openjdk-8-jdk-headless apt -y install maven openjdk-8-jdk-headless
elif [ "$ID" = "fedora" ] || [ "$ID" = "centos" ]; then elif [ "$ID" = "fedora" ] || [ "$ID" = "centos" ]; then
dnf install -y maven java-1.8.0-openjdk-devel yum install -y maven java-1.8.0-openjdk-devel
fi fi

View File

@ -1,173 +0,0 @@
#!/bin/bash
#
# Copyright (C) 2019 ScyllaDB
#
#
# This file is part of Scylla.
#
# Scylla is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Scylla is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Scylla. If not, see <http://www.gnu.org/licenses/>.
#
set -e
print_usage() {
cat <<EOF
Usage: install.sh [options]
Options:
--root /path/to/root alternative install root (default /)
--prefix /prefix directory prefix (default /usr)
--nonroot shortcut of '--disttype nonroot'
--sysconfdir /etc/sysconfig specify sysconfig directory name
--packaging use install.sh for packaging
--without-systemd skip installing systemd units
--help this helpful message
EOF
exit 1
}
root=/
sysconfdir=/etc/sysconfig
nonroot=false
packaging=false
without_systemd=false
while [ $# -gt 0 ]; do
case "$1" in
"--root")
root="$2"
shift 2
;;
"--prefix")
prefix="$2"
shift 2
;;
"--nonroot")
nonroot=true
shift 1
;;
"--sysconfdir")
sysconfdir="$2"
shift 2
;;
"--packaging")
packaging=true
shift 1
;;
"--without-systemd")
without_systemd=true
shift 1
;;
"--help")
shift 1
print_usage
;;
*)
print_usage
;;
esac
done
check_usermode_support() {
user=$(systemctl --help|grep -e '--user')
[ -n "$user" ]
}
if ! $packaging; then
has_java=false
if [ -x /usr/bin/java ]; then
javaver=$(/usr/bin/java -version 2>&1|head -n1|cut -f 3 -d " ")
has_java=true
fi
if ! $has_java; then
echo "Please install openjdk-8, openjdk-11, or openjdk-17 before running install.sh."
exit 1
fi
fi
if [ -z "$prefix" ]; then
if $nonroot; then
prefix=~/scylladb
else
prefix=/opt/scylladb
fi
fi
rprefix=$(realpath -m "$root/$prefix")
if ! $nonroot; then
retc="$root/etc"
rsysconfdir="$root/$sysconfdir"
rusr="$root/usr"
rsystemd="$rusr/lib/systemd/system"
else
retc="$rprefix/etc"
rsysconfdir="$rprefix/$sysconfdir"
rsystemd="$HOME/.config/systemd/user"
fi
install -d -m755 "$rsysconfdir"
if ! $without_systemd; then
install -d -m755 "$rsystemd"
fi
install -d -m755 "$rprefix/scripts" "$rprefix/jmx" "$rprefix/jmx/symlinks"
install -m644 dist/common/sysconfig/scylla-jmx -Dt "$rsysconfdir"
if ! $without_systemd; then
install -m644 dist/common/systemd/scylla-jmx.service -Dt "$rsystemd"
fi
if ! $nonroot && ! $without_systemd; then
if [ "$sysconfdir" != "/etc/sysconfig" ]; then
install -d -m755 "$retc"/systemd/system/scylla-jmx.service.d
cat << EOS > "$retc"/systemd/system/scylla-jmx.service.d/sysconfdir.conf
[Service]
EnvironmentFile=
EnvironmentFile=$sysconfdir/scylla-jmx
EOS
fi
elif ! $without_systemd; then
install -d -m755 "$rsystemd"/scylla-jmx.service.d
cat << EOS > "$rsystemd"/scylla-jmx.service.d/nonroot.conf
[Service]
EnvironmentFile=
EnvironmentFile=$retc/sysconfig/scylla-jmx
ExecStart=
ExecStart=$rprefix/jmx/scylla-jmx \$SCYLLA_JMX_PORT \$SCYLLA_API_PORT \$SCYLLA_API_ADDR \$SCYLLA_JMX_ADDR \$SCYLLA_JMX_FILE \$SCYLLA_JMX_LOCAL \$SCYLLA_JMX_REMOTE \$SCYLLA_JMX_DEBUG
User=
Group=
WorkingDirectory=$rprefix
EOS
fi
install -m644 scylla-jmx-1.1.jar "$rprefix/jmx"
install -m755 scylla-jmx "$rprefix/jmx"
ln -sf /usr/bin/java "$rprefix/jmx/symlinks/scylla-jmx"
if ! $nonroot; then
install -m755 -d "$rusr"/lib/scylla/jmx/symlinks
ln -srf "$rprefix"/jmx/scylla-jmx-1.1.jar "$rusr"/lib/scylla/jmx/
ln -srf "$rprefix"/jmx/scylla-jmx "$rusr"/lib/scylla/jmx/
ln -sf /usr/bin/java "$rusr"/lib/scylla/jmx/symlinks/scylla-jmx
fi
if $nonroot; then
sed -i -e "s#/var/lib/scylla#$rprefix#g" "$rsysconfdir"/scylla-jmx
sed -i -e "s#/etc/scylla#$rprefix/etc/scylla#g" "$rsysconfdir"/scylla-jmx
sed -i -e "s#/opt/scylladb/jmx#$rprefix/jmx#g" "$rsysconfdir"/scylla-jmx
if ! $without_systemd && check_usermode_support; then
systemctl --user daemon-reload
fi
echo "Scylla-JMX non-root install completed."
elif ! $without_systemd && ! $packaging; then
systemctl --system daemon-reload
fi

123
pom.xml
View File

@ -2,81 +2,92 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.scylladb.jmx</groupId>
<artifactId>scylla-jmx</artifactId> <artifactId>scylla-jmx</artifactId>
<version>1.1</version> <version>1.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<parent>
<groupId>it.cavallium.scylladb.jmx</groupId>
<artifactId>scylla-jmx-parent</artifactId>
<version>1.1</version>
<relativePath>./scylla-jmx-parent/pom.xml</relativePath>
</parent>
<name>Scylla JMX</name> <name>Scylla JMX</name>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>it.cavallium.scylladb.jmx</groupId> <groupId>org.yaml</groupId>
<artifactId>scylla-apiclient</artifactId> <artifactId>snakeyaml</artifactId>
<version>1.1</version> <version>1.16</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.13.1</version> <version>4.8.2</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>com.google.collections</groupId>
<artifactId>google-collections</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>11</source>
<target>11</target>
<compilerArgs>
<arg>--add-exports</arg>
<arg>java.management/com.sun.jmx.mbeanserver=scylla.jmx</arg>
<arg>--add-exports</arg>
<arg>java.management/com.sun.jmx.interceptor=scylla.jmx</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version> <version>2.4.1</version>
<configuration>
<artifactSet>
<includes>
<include>*:*</include>
</includes>
<excludes>
<exclude>com.sun.activation:jakarta.activation</exclude>
</excludes>
</artifactSet>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>module-info.class</exclude>
<exclude>META-INF/versions/*/module-info.class</exclude>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
<exclude>META-INF/MANIFEST.MF</exclude>
<exclude>META-INF/*.MD</exclude>
<exclude>META-INF/*.md</exclude>
<exclude>META-INF/LICENSE</exclude>
<exclude>META-INF/LICENSE.txt</exclude>
<exclude>META-INF/NOTICE</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>

View File

@ -1,42 +1,31 @@
#!/bin/bash -e #!/bin/bash -e
. /etc/os-release
print_usage() { print_usage() {
echo "build_deb.sh --reloc-pkg build/scylla-jmx-package.tar.gz" echo "build_deb.sh --reloc-pkg build/scylla-jmx-package.tar.gz"
echo " --reloc-pkg specify relocatable package path" echo " --reloc-pkg specify relocatable package path"
echo " --builddir specify Debian package build path"
exit 1 exit 1
} }
RELOC_PKG=build/scylla-jmx-package.tar.gz RELOC_PKG=$(readlink -f build/scylla-jmx-package.tar.gz)
BUILDDIR=build/debian OPTS=""
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case "$1" in case "$1" in
"--reloc-pkg") "--reloc-pkg")
OPTS="$OPTS $1 $(readlink -f $2)"
RELOC_PKG=$2 RELOC_PKG=$2
shift 2 shift 2
;; ;;
"--builddir")
BUILDDIR="$2"
shift 2
;;
*) *)
print_usage print_usage
;; ;;
esac esac
done done
RELOC_PKG=$(readlink -f $RELOC_PKG) if [[ ! $OPTS =~ --reloc-pkg ]]; then
rm -rf "$BUILDDIR"/scylla-package "$BUILDDIR"/scylla-package.orig "$BUILDDIR"/debian OPTS="$OPTS --reloc-pkg $RELOC_PKG"
mkdir -p "$BUILDDIR"/scylla-package fi
tar -C "$BUILDDIR"/scylla-package -xpf $RELOC_PKG mkdir -p build/debian/scylla-package
cd "$BUILDDIR"/scylla-package tar -C build/debian/scylla-package -xpf $RELOC_PKG
cd build/debian/scylla-package
RELOC_PKG=$(readlink -f $RELOC_PKG) exec ./dist/debian/build_deb.sh $OPTS
mv scylla-jmx/debian debian
PKG_NAME=$(dpkg-parsechangelog --show-field Source)
# XXX: Drop revision number from version string.
# Since it always '1', this should be okay for now.
PKG_VERSION=$(dpkg-parsechangelog --show-field Version |sed -e 's/-1$//')
ln -fv $RELOC_PKG ../"$PKG_NAME"_"$PKG_VERSION".orig.tar.gz
debuild -rfakeroot -us -uc

View File

@ -6,13 +6,11 @@ print_usage() {
echo "build_reloc.sh --clean --nodeps" echo "build_reloc.sh --clean --nodeps"
echo " --clean clean build directory" echo " --clean clean build directory"
echo " --nodeps skip installing dependencies" echo " --nodeps skip installing dependencies"
echo " --version V product-version-release string (overriding SCYLLA-VERSION-GEN)"
exit 1 exit 1
} }
CLEAN= CLEAN=
NODEPS= NODEPS=
VERSION_OVERRIDE=
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case "$1" in case "$1" in
"--clean") "--clean")
@ -23,22 +21,12 @@ while [ $# -gt 0 ]; do
NODEPS=yes NODEPS=yes
shift 1 shift 1
;; ;;
"--version")
VERSION_OVERRIDE="$2"
shift 2
;;
*) *)
print_usage print_usage
;; ;;
esac esac
done done
VERSION=$(./SCYLLA-VERSION-GEN ${VERSION_OVERRIDE:+ --version "$VERSION_OVERRIDE"})
# the former command should generate build/SCYLLA-PRODUCT-FILE and some other version
# related files
PRODUCT=`cat build/SCYLLA-PRODUCT-FILE`
DEST="build/$PRODUCT-jmx-$VERSION.noarch.tar.gz"
is_redhat_variant() { is_redhat_variant() {
[ -f /etc/redhat-release ] [ -f /etc/redhat-release ]
} }
@ -56,15 +44,14 @@ if [ "$CLEAN" = "yes" ]; then
rm -rf build target rm -rf build target
fi fi
if [ -f "$DEST" ]; then if [ -f build/scylla-jmx-package.tar.gz ]; then
rm "$DEST" rm build/scylla-jmx-package.tar.gz
fi fi
if [ -z "$NODEPS" ]; then if [ -z "$NODEPS" ]; then
sudo ./install-dependencies.sh sudo ./install-dependencies.sh
fi fi
mvn -B --file scylla-jmx-parent/pom.xml install mvn -B install
./SCYLLA-VERSION-GEN ${VERSION_OVERRIDE:+ --version "$VERSION_OVERRIDE"} ./SCYLLA-VERSION-GEN
./dist/debian/debian_files_gen.py scripts/create-relocatable-package.py build/scylla-jmx-package.tar.gz
scripts/create-relocatable-package.py "$DEST"

View File

@ -1,52 +1,30 @@
#!/bin/bash -e #!/bin/bash -e
. /etc/os-release
print_usage() { print_usage() {
echo "build_rpm.sh --reloc-pkg build/scylla-jmx-package.tar.gz" echo "build_rpm.sh --reloc-pkg build/scylla-jmx-package.tar.gz"
echo " --reloc-pkg specify relocatable package path" echo " --reloc-pkg specify relocatable package path"
echo " --builddir specify rpmbuild directory"
exit 1 exit 1
} }
RELOC_PKG=build/scylla-jmx-package.tar.gz RELOC_PKG=$(readlink -f build/scylla-jmx-package.tar.gz)
BUILDDIR=build/redhat OPTS=""
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case "$1" in case "$1" in
"--reloc-pkg") "--reloc-pkg")
OPTS="$OPTS $1 $(readlink -f $2)"
RELOC_PKG=$2 RELOC_PKG=$2
shift 2 shift 2
;; ;;
"--builddir")
BUILDDIR="$2"
shift 2
;;
*) *)
print_usage print_usage
;; ;;
esac esac
done done
RELOC_PKG=$(readlink -f $RELOC_PKG) if [[ ! $OPTS =~ --reloc-pkg ]]; then
RPMBUILD=$(readlink -f $BUILDDIR) OPTS="$OPTS --reloc-pkg $RELOC_PKG"
mkdir -p "$BUILDDIR" fi
tar -C "$BUILDDIR" -xpf $RELOC_PKG scylla-jmx/SCYLLA-RELEASE-FILE scylla-jmx/SCYLLA-RELOCATABLE-FILE scylla-jmx/SCYLLA-VERSION-FILE scylla-jmx/SCYLLA-PRODUCT-FILE scylla-jmx/dist/redhat mkdir -p build/redhat/scylla-package
cd "$BUILDDIR"/scylla-jmx tar -C build/redhat/scylla-package -xpf $RELOC_PKG SCYLLA-RELEASE-FILE SCYLLA-RELOCATABLE-FILE SCYLLA-VERSION-FILE SCYLLA-PRODUCT-FILE dist/redhat
cd build/redhat/scylla-package
RELOC_PKG_BASENAME=$(basename "$RELOC_PKG") exec ./dist/redhat/build_rpm.sh $OPTS
SCYLLA_VERSION=$(cat SCYLLA-VERSION-FILE)
SCYLLA_RELEASE=$(cat SCYLLA-RELEASE-FILE)
VERSION=$SCYLLA_VERSION-$SCYLLA_RELEASE
PRODUCT=$(cat SCYLLA-PRODUCT-FILE)
mkdir -p $RPMBUILD/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
ln -fv $RELOC_PKG $RPMBUILD/SOURCES/
parameters=(
-D"version $SCYLLA_VERSION"
-D"release $SCYLLA_RELEASE"
-D"product $PRODUCT"
-D"reloc_pkg $RELOC_PKG_BASENAME"
)
cp dist/redhat/scylla-jmx.spec $RPMBUILD/SPECS
# this rpm can be install on both fedora / centos7, so drop distribution name from the file name
rpmbuild -ba "${parameters[@]}" --define '_binary_payload w2.xzdio' --define "_topdir $RPMBUILD" --undefine "dist" $RPMBUILD/SPECS/scylla-jmx.spec

View File

@ -27,14 +27,6 @@ import os
import tarfile import tarfile
import pathlib import pathlib
RELOC_PREFIX='scylla-jmx'
def reloc_add(self, name, arcname=None, recursive=True, *, filter=None):
if arcname:
return self.add(name, arcname="{}/{}".format(RELOC_PREFIX, arcname))
else:
return self.add(name, arcname="{}/{}".format(RELOC_PREFIX, name))
tarfile.TarFile.reloc_add = reloc_add
ap = argparse.ArgumentParser(description='Create a relocatable scylla package.') ap = argparse.ArgumentParser(description='Create a relocatable scylla package.')
ap.add_argument('dest', ap.add_argument('dest',
@ -45,20 +37,13 @@ args = ap.parse_args()
output = args.dest output = args.dest
ar = tarfile.open(output, mode='w|gz') ar = tarfile.open(output, mode='w|gz')
# relocatable package format version = 2.2
with open('build/.relocatable_package_version', 'w') as f:
f.write('2.2\n')
ar.add('build/.relocatable_package_version', arcname='.relocatable_package_version')
pathlib.Path('build/SCYLLA-RELOCATABLE-FILE').touch() pathlib.Path('build/SCYLLA-RELOCATABLE-FILE').touch()
ar.reloc_add('build/SCYLLA-RELOCATABLE-FILE', arcname='SCYLLA-RELOCATABLE-FILE') ar.add('build/SCYLLA-RELOCATABLE-FILE', arcname='SCYLLA-RELOCATABLE-FILE')
ar.reloc_add('build/SCYLLA-RELEASE-FILE', arcname='SCYLLA-RELEASE-FILE') ar.add('build/SCYLLA-RELEASE-FILE', arcname='SCYLLA-RELEASE-FILE')
ar.reloc_add('build/SCYLLA-VERSION-FILE', arcname='SCYLLA-VERSION-FILE') ar.add('build/SCYLLA-VERSION-FILE', arcname='SCYLLA-VERSION-FILE')
ar.reloc_add('build/SCYLLA-PRODUCT-FILE', arcname='SCYLLA-PRODUCT-FILE') ar.add('build/SCYLLA-PRODUCT-FILE', arcname='SCYLLA-PRODUCT-FILE')
ar.reloc_add('dist') ar.add('dist')
ar.reloc_add('install.sh') ar.add('target/scylla-jmx-1.0.jar', arcname='scylla-jmx-1.0.jar')
ar.reloc_add('target/scylla-jmx-1.1.jar', arcname='scylla-jmx-1.1.jar') ar.add('scripts/scylla-jmx', arcname='scylla-jmx')
ar.reloc_add('scripts/scylla-jmx', arcname='scylla-jmx') ar.add('README.md')
ar.reloc_add('README.md') ar.add('NOTICE')
ar.reloc_add('NOTICE')
ar.reloc_add('build/debian/debian', arcname='debian')

View File

@ -131,13 +131,11 @@ else
fi fi
fi fi
"$LOCATION_SCRIPTS"/symlinks/scylla-jmx $DEBUG \ exec "$LOCATION_SCRIPTS"/symlinks/scylla-jmx $DEBUG \
$API_PORT $API_ADDR $CONF_FILE -Xmx256m -XX:+UseSerialGC \ $API_PORT $API_ADDR $CONF_FILE -Xmx256m -XX:+UseSerialGC \
-XX:+HeapDumpOnOutOfMemoryError \ -XX:+HeapDumpOnOutOfMemoryError \
$JMX_AUTH $JMX_SSL $JMX_ADDR $JMX_LOCAL \ $JMX_AUTH $JMX_SSL $JMX_ADDR $JMX_LOCAL \
--add-exports java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED \
--add-exports java.management/com.sun.jmx.interceptor=ALL-UNNAMED \
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=$JMX_PORT \ -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=$JMX_PORT \
-Djava.rmi.server.hostname=$HOSTNAME -Dcom.sun.management.jmxremote.rmi.port=$JMX_PORT \ -Djava.rmi.server.hostname=$HOSTNAME -Dcom.sun.management.jmxremote.rmi.port=$JMX_PORT \
-Djavax.management.builder.initial=com.scylladb.jmx.utils.APIBuilder \ -Djavax.management.builder.initial=com.scylladb.jmx.utils.APIBuilder \
$PROPERTIES -jar $LOCATION/scylla-jmx-1.1.jar $PROPERTIES -jar $LOCATION/scylla-jmx-1.0.jar

View File

@ -1,99 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>scylla-apiclient</artifactId>
<packaging>jar</packaging>
<version>1.1</version>
<parent>
<relativePath>../scylla-jmx-parent/pom.xml</relativePath>
<groupId>it.cavallium.scylladb.jmx</groupId>
<artifactId>scylla-jmx-parent</artifactId>
<version>1.1</version>
</parent>
<name>Scylla REST API client</name>
<properties>
<jackson.version>2.14.0</jackson.version>
<jackson.databind.version>2.14.0</jackson.databind.version>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.parsson</groupId>
<artifactId>parsson</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.33</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
<dependency>
<groupId>jakarta.activation</groupId>
<artifactId>jakarta.activation-api</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.databind.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jakarta.rs</groupId>
<artifactId>jackson-jakarta-rs-json-provider</artifactId>
<version>2.14.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,15 +0,0 @@
module scylla.apiclient {
exports com.scylladb.jmx.api;
exports com.scylladb.jmx.api.utils;
requires org.eclipse.parsson;
requires jakarta.ws.rs;
requires com.fasterxml.jackson.jakarta.rs.json;
requires jersey.client;
requires java.logging;
requires jakarta.json;
requires java.management;
requires org.yaml.snakeyaml;
requires com.google.common;
requires jersey.common;
requires jersey.hk2;
}

View File

@ -1,29 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>it.cavallium.scylladb.jmx</groupId>
<artifactId>scylla-jmx-parent</artifactId>
<version>1.1</version>
<packaging>pom</packaging>
<modules>
<module>../</module>
<module>../scylla-apiclient</module>
</modules>
<name>Scylla JMX Parent</name>
<distributionManagement>
<repository>
<id>mchv-release-distribution</id>
<name>MCHV Release Apache Maven Packages Distribution</name>
<url>https://mvn.mchv.eu/repository/mchv</url>
</repository>
<snapshotRepository>
<id>mchv-snapshot-distribution</id>
<name>MCHV Snapshot Apache Maven Packages Distribution</name>
<url>https://mvn.mchv.eu/repository/mchv-snapshot</url>
</snapshotRepository>
</distributionManagement>
</project>

View File

@ -3,24 +3,7 @@
*/ */
package com.scylladb.jmx.api; package com.scylladb.jmx.api;
import com.fasterxml.jackson.jakarta.rs.json.JacksonJsonProvider;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonReader;
import jakarta.json.JsonReaderFactory;
import jakarta.json.JsonString;
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.client.Invocation;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
import java.io.StringReader; import java.io.StringReader;
import java.lang.System.Logger.Level;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.ArrayList; import java.util.ArrayList;
@ -35,28 +18,30 @@ import java.util.Set;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonReaderFactory;
import javax.json.JsonString;
import javax.management.openmbean.TabularData; import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport; import javax.management.openmbean.TabularDataSupport;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.client.ClientConfig;
import com.scylladb.jmx.api.utils.SnapshotDetailsTabularData; import com.scylladb.jmx.utils.SnapshotDetailsTabularData;
public class APIClient { public class APIClient {
private Map<String, CacheEntry> cache = new HashMap<String, CacheEntry>(); private Map<String, CacheEntry> cache = new HashMap<String, CacheEntry>();
private final APIConfig config;
private final ClientConfig clientConfig;
private final Client client;
private JsonReaderFactory factory = Json.createReaderFactory(null);
private static final Logger logger = Logger.getLogger(APIClient.class.getName());
public APIClient(APIConfig config) {
this.config = config;
this.clientConfig = new ClientConfig();
clientConfig.register(new JacksonJsonProvider());
this.client = ClientBuilder.newClient(clientConfig);
}
private String getCacheKey(String key, MultivaluedMap<String, String> param, long duration) { private String getCacheKey(String key, MultivaluedMap<String, String> param, long duration) {
if (duration <= 0) { if (duration <= 0) {
@ -89,12 +74,21 @@ public class APIClient {
return (value != null && value.valid(duration)) ? value.jsonObject() : null; return (value != null && value.valid(duration)) ? value.jsonObject() : null;
} }
private JsonReaderFactory factory = Json.createReaderFactory(null);
private static final Logger logger = Logger.getLogger(APIClient.class.getName());
private final APIConfig config;
public APIClient(APIConfig config) {
this.config = config;
}
private String getBaseUrl() { private String getBaseUrl() {
return config.getBaseUrl(); return config.getBaseUrl();
} }
public Invocation.Builder get(String path, MultivaluedMap<String, String> queryParams) { public Invocation.Builder get(String path, MultivaluedMap<String, String> queryParams) {
Client client = ClientBuilder.newClient(new ClientConfig());
WebTarget webTarget = client.target(getBaseUrl()).path(path); WebTarget webTarget = client.target(getBaseUrl()).path(path);
if (queryParams != null) { if (queryParams != null) {
for (Entry<String, List<String>> qp : queryParams.entrySet()) { for (Entry<String, List<String>> qp : queryParams.entrySet()) {

View File

@ -21,8 +21,7 @@
package com.scylladb.jmx.api; package com.scylladb.jmx.api;
import javax.json.JsonObject;
import jakarta.json.JsonObject;
class CacheEntry { class CacheEntry {
private long time; private long time;

View File

@ -27,27 +27,12 @@ import com.scylladb.jmx.api.APIConfig;
import com.scylladb.jmx.metrics.APIMBean; import com.scylladb.jmx.metrics.APIMBean;
public class Main { public class Main {
// todo: command line options. Make us an agent class (also)
private static APIConfig config; private static final APIConfig config = new APIConfig();
private static APIClient client; public static final APIClient client = new APIClient(config);
public static synchronized APIConfig getApiConfig() {
if (config == null) {
config = new APIConfig();
}
return config;
}
public static synchronized APIClient getApiClient() {
if (client == null) {
client = new APIClient(getApiConfig());
}
return client;
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
System.out.printf("Java %s%n", System.getProperty("java.version")); System.out.println("Connecting to " + config.getBaseUrl());
System.out.printf("Connecting to %s%n", getApiConfig().getBaseUrl());
System.out.println("Starting the JMX server"); System.out.println("Starting the JMX server");
MBeanServer server = getPlatformMBeanServer(); MBeanServer server = getPlatformMBeanServer();
@ -55,7 +40,7 @@ public class Main {
CommitLog.class, Gossiper.class, EndpointSnitchInfo.class, FailureDetector.class, CacheService.class, CommitLog.class, Gossiper.class, EndpointSnitchInfo.class, FailureDetector.class, CacheService.class,
CompactionManager.class, GCInspector.class, StreamManager.class)) { CompactionManager.class, GCInspector.class, StreamManager.class)) {
Constructor<? extends APIMBean> c = clazz.getDeclaredConstructor(APIClient.class); Constructor<? extends APIMBean> c = clazz.getDeclaredConstructor(APIClient.class);
APIMBean m = c.newInstance(getApiClient()); APIMBean m = c.newInstance(client);
server.registerMBean(m, null); server.registerMBean(m, null);
} }

View File

@ -1,7 +1,6 @@
package com.scylladb.jmx.metrics; package com.scylladb.jmx.metrics;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.EnumSet;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
@ -56,39 +55,35 @@ public class APIMBean implements MBeanRegistration {
* @param generator * @param generator
* {@link Function} to create a new MBean instance for a given * {@link Function} to create a new MBean instance for a given
* {@link ObjectName} * {@link ObjectName}
*
* @return * @return
* @throws MalformedObjectNameException * @throws MalformedObjectNameException
*/ */
public static boolean checkRegistration(JmxMBeanServer server, Set<ObjectName> all, public static boolean checkRegistration(JmxMBeanServer server, Set<ObjectName> all,
EnumSet<RegistrationMode> mode, final Predicate<ObjectName> predicate, final Predicate<ObjectName> predicate, Function<ObjectName, Object> generator)
Function<ObjectName, Object> generator) throws MalformedObjectNameException { throws MalformedObjectNameException {
Set<ObjectName> registered = queryNames(server, predicate); Set<ObjectName> registered = queryNames(server, predicate);
if (mode.contains(RegistrationMode.Remove)) { for (ObjectName name : registered) {
for (ObjectName name : registered) { if (!all.contains(name)) {
if (!all.contains(name)) { try {
try { server.getMBeanServerInterceptor().unregisterMBean(name);
server.getMBeanServerInterceptor().unregisterMBean(name); } catch (MBeanRegistrationException | InstanceNotFoundException e) {
} catch (MBeanRegistrationException | InstanceNotFoundException e) { }
} }
} }
}
}
int added = 0; int added = 0;
if (mode.contains(RegistrationMode.Add)) { for (ObjectName name : all) {
for (ObjectName name : all) { if (!registered.contains(name)) {
if (!registered.contains(name)) { try {
try { server.getMBeanServerInterceptor().registerMBean(generator.apply(name), name);
server.getMBeanServerInterceptor().registerMBean(generator.apply(name), name); added++;
added++; } catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) {
} catch (InstanceAlreadyExistsException | MBeanRegistrationException }
| NotCompliantMBeanException e) { }
} }
} return added > 0;
} }
}
return added > 0;
}
/** /**
* Helper method to query {@link ObjectName}s from an {@link MBeanServer} * Helper method to query {@link ObjectName}s from an {@link MBeanServer}

View File

@ -1,69 +0,0 @@
package com.scylladb.jmx.metrics;
import static com.scylladb.jmx.metrics.RegistrationMode.Remove;
import static com.scylladb.jmx.metrics.RegistrationMode.Wait;
import static java.util.EnumSet.allOf;
import static java.util.EnumSet.of;
import java.net.UnknownHostException;
import java.util.EnumSet;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.management.OperationsException;
import com.scylladb.jmx.api.APIClient;
import com.sun.jmx.mbeanserver.JmxMBeanServer;
/**
* Helper type to do optional locking for registration. Allows for
* per-bind-point locks and registration, instead of per-type or per-instance
* locks which may be misguiding, since for example one instance can be bound to
* many MBeanServers etc.
*
* Also allows for polled checks, i.e. try-lock and either wait or skip. Wait,
* because we probably should not repeat things hidden by this type too often,
* and skip because for example a periodic task checking can just skip if a
* user-initiated registration check is being done.
*
* @author calle
*
*/
@SuppressWarnings("restriction")
public abstract class RegistrationChecker {
private final Lock lock = new ReentrantLock();
public static final EnumSet<RegistrationMode> REMOVE_NO_WAIT = of(Remove);
public static final EnumSet<RegistrationMode> ADD_AND_REMOVE = allOf(RegistrationMode.class);
public final void reap(APIClient client, JmxMBeanServer server) throws OperationsException, UnknownHostException {
check(client, server, REMOVE_NO_WAIT);
}
public final void check(APIClient client, JmxMBeanServer server) throws OperationsException, UnknownHostException {
check(client, server, ADD_AND_REMOVE);
}
public final void check(APIClient client, JmxMBeanServer server, EnumSet<RegistrationMode> mode)
throws OperationsException, UnknownHostException {
if (!lock.tryLock()) {
if (mode.contains(Wait)) {
// someone is doing update.
// since this is jmx, and sloppy, we'll just
// assume that once he is done, things are
// good enough.
lock.lock();
lock.unlock();
}
return;
}
try {
doCheck(client, server, mode);
} finally {
lock.unlock();
}
}
protected abstract void doCheck(APIClient client, JmxMBeanServer server, EnumSet<RegistrationMode> mode)
throws OperationsException, UnknownHostException;
}

View File

@ -1,5 +0,0 @@
package com.scylladb.jmx.metrics;
public enum RegistrationMode {
Wait, Add, Remove,
}

View File

@ -3,7 +3,7 @@ package com.scylladb.jmx.utils;
* Copyright 2016 ScyllaDB * Copyright 2016 ScyllaDB
*/ */
import static com.scylladb.jmx.main.Main.getApiClient; import static com.scylladb.jmx.main.Main.client;
import static com.sun.jmx.mbeanserver.Util.wildmatch; import static com.sun.jmx.mbeanserver.Util.wildmatch;
import static java.util.logging.Level.SEVERE; import static java.util.logging.Level.SEVERE;
import static javax.management.MBeanServerDelegate.DELEGATE_NAME; import static javax.management.MBeanServerDelegate.DELEGATE_NAME;
@ -172,7 +172,7 @@ public class APIBuilder extends MBeanServerBuilder {
logger.log(SEVERE, "Unexpected error.", x); logger.log(SEVERE, "Unexpected error.", x);
} }
} finally { } finally {
lock.writeLock().unlock(); lock.writeLock().lock();
} }
} }
} }
@ -491,6 +491,6 @@ public class APIBuilder extends MBeanServerBuilder {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
return new APIMBeanServer(getApiClient(), nested); return new APIMBeanServer(client, nested);
} }
} }

View File

@ -1,13 +1,8 @@
package com.scylladb.jmx.utils; package com.scylladb.jmx.utils;
import static java.util.Arrays.asList;
import static java.util.concurrent.Executors.newScheduledThreadPool;
import static java.util.concurrent.TimeUnit.MINUTES;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -39,17 +34,12 @@ import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.metrics.StreamingMetrics; import org.apache.cassandra.metrics.StreamingMetrics;
import com.scylladb.jmx.api.APIClient; import com.scylladb.jmx.api.APIClient;
import com.scylladb.jmx.metrics.RegistrationChecker;
import com.sun.jmx.mbeanserver.JmxMBeanServer; import com.sun.jmx.mbeanserver.JmxMBeanServer;
@SuppressWarnings("restriction") @SuppressWarnings("restriction")
public class APIMBeanServer implements MBeanServer { public class APIMBeanServer implements MBeanServer {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static final Logger logger = Logger.getLogger(APIMBeanServer.class.getName()); private static final Logger logger = Logger.getLogger(APIMBeanServer.class.getName());
private static final ScheduledExecutorService executor = newScheduledThreadPool(1);
private final RegistrationChecker columnFamilyStoreChecker = ColumnFamilyStore.createRegistrationChecker();
private final RegistrationChecker streamingMetricsChecker = StreamingMetrics.createRegistrationChecker();
private final APIClient client; private final APIClient client;
private final JmxMBeanServer server; private final JmxMBeanServer server;
@ -57,16 +47,6 @@ public class APIMBeanServer implements MBeanServer {
public APIMBeanServer(APIClient client, JmxMBeanServer server) { public APIMBeanServer(APIClient client, JmxMBeanServer server) {
this.client = client; this.client = client;
this.server = server; this.server = server;
executor.scheduleWithFixedDelay(() -> {
for (RegistrationChecker c : asList(columnFamilyStoreChecker, streamingMetricsChecker)) {
try {
c.reap(client, server);
} catch (OperationsException | UnknownHostException e) {
// TODO: log?
}
}
}, 1, 5, MINUTES);
} }
private static ObjectInstance prepareForRemote(final ObjectInstance i) { private static ObjectInstance prepareForRemote(final ObjectInstance i) {
@ -85,7 +65,7 @@ public class APIMBeanServer implements MBeanServer {
throw new IllegalArgumentException(n.toString()); throw new IllegalArgumentException(n.toString());
} }
} }
@Override @Override
public ObjectInstance createMBean(String className, ObjectName name) throws ReflectionException, public ObjectInstance createMBean(String className, ObjectName name) throws ReflectionException,
InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException { InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException {
@ -306,22 +286,25 @@ public class APIMBeanServer implements MBeanServer {
} }
static final Pattern tables = Pattern.compile("^\\*?((Index)?ColumnFamil(ies|y)|(Index)?(Table(s)?)?)$"); static final Pattern tables = Pattern.compile("^\\*?((Index)?ColumnFamil(ies|y)|(Index)?(Table(s)?)?)$");
private void checkRegistrations(ObjectName name) { private boolean checkRegistrations(ObjectName name) {
if (name != null && server.isRegistered(name)) { if (name != null && server.isRegistered(name)) {
return; return false;
} }
boolean result = false;
try { try {
String type = name != null ? name.getKeyProperty("type") : null; String type = name != null ? name.getKeyProperty("type") : null;
if (type == null || tables.matcher(type).matches()) { if (type == null || tables.matcher(type).matches()) {
columnFamilyStoreChecker.check(client, server); result |= ColumnFamilyStore.checkRegistration(client, server);
} }
if (type == null || StreamingMetrics.TYPE_NAME.equals(type)) { if (type == null || StreamingMetrics.TYPE_NAME.equals(type)) {
streamingMetricsChecker.check(client, server); result |= StreamingMetrics.checkRegistration(client, server);
} }
} catch (OperationsException | UnknownHostException e) { } catch (MalformedObjectNameException | UnknownHostException e) {
// TODO: log // TODO: log
} }
return result;
} }
} }

View File

@ -1,18 +0,0 @@
package com.scylladb.jmx.utils;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import java.time.Instant;
import java.util.Date;
public class DateXmlAdapter extends XmlAdapter<String, Date> {
@Override
public String marshal(Date v) throws Exception {
return Instant.ofEpochMilli(v.getTime()).toString();
}
@Override
public Date unmarshal(String v) throws Exception {
return new Date(Instant.parse(v).toEpochMilli());
}
}

View File

@ -22,7 +22,7 @@
* Modified by Cloudius Systems * Modified by Cloudius Systems
*/ */
package com.scylladb.jmx.api.utils; package com.scylladb.jmx.utils;
import java.io.File; import java.io.File;
import java.text.DecimalFormat; import java.text.DecimalFormat;

View File

@ -22,7 +22,7 @@
* Modified by Cloudius Systems * Modified by Cloudius Systems
*/ */
package com.scylladb.jmx.api.utils; package com.scylladb.jmx.utils;
import com.google.common.base.Objects; import com.google.common.base.Objects;

View File

@ -20,7 +20,7 @@
* *
* Modified by Cloudius Systems * Modified by Cloudius Systems
*/ */
package com.scylladb.jmx.api.utils; package com.scylladb.jmx.utils;
import java.util.Map; import java.util.Map;

View File

@ -1,16 +0,0 @@
module scylla.jmx {
opens com.scylladb.jmx.utils;
exports com.scylladb.jmx.utils;
opens com.scylladb.jmx.main;
exports com.scylladb.jmx.main;
opens com.scylladb.jmx.metrics;
exports com.scylladb.jmx.metrics;
requires java.logging;
requires java.management;
requires scylla.apiclient;
requires jakarta.json;
requires jakarta.ws.rs;
requires com.google.common;
requires jakarta.xml.bind;
requires com.fasterxml.jackson.annotation;
}

View File

@ -23,22 +23,13 @@
*/ */
package org.apache.cassandra.db; package org.apache.cassandra.db;
import static jakarta.json.Json.createObjectBuilder;
import static java.lang.String.valueOf; import static java.lang.String.valueOf;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toMap;
import static javax.json.Json.createObjectBuilder;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonReader;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import java.io.StringReader; import java.io.StringReader;
import java.io.OutputStream;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -51,10 +42,14 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonReader;
import javax.management.MBeanServer; import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException; import javax.management.MalformedObjectNameException;
import javax.management.ObjectName; import javax.management.ObjectName;
import javax.management.OperationsException;
import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType; import javax.management.openmbean.CompositeType;
@ -63,13 +58,13 @@ import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType; import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularDataSupport; import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType; import javax.management.openmbean.TabularType;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import org.apache.cassandra.metrics.TableMetrics; import org.apache.cassandra.metrics.TableMetrics;
import com.scylladb.jmx.api.APIClient; import com.scylladb.jmx.api.APIClient;
import com.scylladb.jmx.metrics.MetricsMBean; import com.scylladb.jmx.metrics.MetricsMBean;
import com.scylladb.jmx.metrics.RegistrationChecker;
import com.scylladb.jmx.metrics.RegistrationMode;
import com.sun.jmx.mbeanserver.JmxMBeanServer; import com.sun.jmx.mbeanserver.JmxMBeanServer;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
@ -187,22 +182,15 @@ public class ColumnFamilyStore extends MetricsMBean implements ColumnFamilyStore
"org.apache.cassandra.db:type=" + type + ",keyspace=" + keyspace + ",columnfamily=" + name); "org.apache.cassandra.db:type=" + type + ",keyspace=" + keyspace + ",columnfamily=" + name);
} }
public static RegistrationChecker createRegistrationChecker() { public static boolean checkRegistration(APIClient client, JmxMBeanServer server) throws MalformedObjectNameException {
return new RegistrationChecker() { JsonArray mbeans = client.getJsonArray("/column_family/");
@Override Set<ObjectName> all = new HashSet<ObjectName>();
protected void doCheck(APIClient client, JmxMBeanServer server, EnumSet<RegistrationMode> mode) for (int i = 0; i < mbeans.size(); i++) {
throws OperationsException { JsonObject mbean = mbeans.getJsonObject(i);
JsonArray mbeans = client.getJsonArray("/column_family/"); all.add(getName(mbean.getString("type"), mbean.getString("ks"), mbean.getString("cf")));
Set<ObjectName> all = new HashSet<ObjectName>(); }
for (int i = 0; i < mbeans.size(); i++) { return checkRegistration(server, all, n -> TYPE_NAMES.contains(n.getKeyProperty("type")), n -> new ColumnFamilyStore(client, n));
JsonObject mbean = mbeans.getJsonObject(i); }
all.add(getName(mbean.getString("type"), mbean.getString("ks"), mbean.getString("cf")));
}
checkRegistration(server, all, mode,
n -> TYPE_NAMES.contains(n.getKeyProperty("type")), n -> new ColumnFamilyStore(client, n));
}
};
}
/** /**
* @return the name of the column family * @return the name of the column family
@ -332,7 +320,7 @@ public class ColumnFamilyStore extends MetricsMBean implements ColumnFamilyStore
@Override @Override
public boolean isAutoCompactionDisabled() { public boolean isAutoCompactionDisabled() {
log(" isAutoCompactionDisabled()"); log(" isAutoCompactionDisabled()");
return !client.getBooleanValue("column_family/autocompaction/" + getCFName()); return client.getBooleanValue("column_family/autocompaction/" + getCFName());
} }
/** Number of tombstoned cells retreived during the last slicequery */ /** Number of tombstoned cells retreived during the last slicequery */
@ -546,7 +534,6 @@ public class ColumnFamilyStore extends MetricsMBean implements ColumnFamilyStore
TabularDataSupport result = new TabularDataSupport(COUNTER_TYPE); TabularDataSupport result = new TabularDataSupport(COUNTER_TYPE);
JsonArray counters = tableSamplerResult.getJsonArray((samplerType.equalsIgnoreCase("reads")) ? "read" : "write"); JsonArray counters = tableSamplerResult.getJsonArray((samplerType.equalsIgnoreCase("reads")) ? "read" : "write");
long cardinality = tableSamplerResult.getJsonNumber((samplerType.equalsIgnoreCase("reads")) ? "read_cardinality" : "write_cardinality").longValue();
long size = 0; long size = 0;
if (counters != null) { if (counters != null) {
size = (count > counters.size()) ? counters.size() : count; size = (count > counters.size()) ? counters.size() : count;
@ -559,6 +546,7 @@ public class ColumnFamilyStore extends MetricsMBean implements ColumnFamilyStore
counter.getString("partition") })); // string counter.getString("partition") })); // string
} }
} }
return new CompositeDataSupport(SAMPLING_RESULT, SAMPLER_NAMES, new Object[] { cardinality, result }); //FIXME: size is not the cardinality, a true value needs to be propogated
return new CompositeDataSupport(SAMPLING_RESULT, SAMPLER_NAMES, new Object[] { size, result });
} }
} }

View File

@ -22,8 +22,8 @@
*/ */
package org.apache.cassandra.db.compaction; package org.apache.cassandra.db.compaction;
import jakarta.json.JsonArray; import javax.json.JsonArray;
import jakarta.json.JsonObject; import javax.json.JsonObject;
import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType; import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException; import javax.management.openmbean.OpenDataException;

View File

@ -17,18 +17,18 @@
*/ */
package org.apache.cassandra.db.compaction; package org.apache.cassandra.db.compaction;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.management.openmbean.OpenDataException; import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.TabularData; import javax.management.openmbean.TabularData;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import org.apache.cassandra.metrics.CompactionMetrics; import org.apache.cassandra.metrics.CompactionMetrics;
@ -75,7 +75,7 @@ public class CompactionManager extends MetricsMBean implements CompactionManager
result.put("keyspace", compaction.getString("ks")); result.put("keyspace", compaction.getString("ks"));
result.put("columnfamily", compaction.getString("cf")); result.put("columnfamily", compaction.getString("cf"));
result.put("unit", compaction.getString("unit")); result.put("unit", compaction.getString("unit"));
result.put("compactionId", (compaction.containsKey("id"))? compaction.getString("id") : "<none>"); result.put("compactionId", "<none>");
results.add(result); results.add(result);
} }
return results; return results;

View File

@ -24,13 +24,13 @@
package org.apache.cassandra.gms; package org.apache.cassandra.gms;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonValue;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonValue;
import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType; import javax.management.openmbean.CompositeType;

View File

@ -23,11 +23,12 @@
*/ */
package org.apache.cassandra.gms; package org.apache.cassandra.gms;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import com.scylladb.jmx.api.APIClient; import com.scylladb.jmx.api.APIClient;
import com.scylladb.jmx.metrics.APIMBean; import com.scylladb.jmx.metrics.APIMBean;

View File

@ -19,12 +19,13 @@ package org.apache.cassandra.locator;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import com.scylladb.jmx.api.APIClient; import com.scylladb.jmx.api.APIClient;
import com.scylladb.jmx.metrics.APIMBean; import com.scylladb.jmx.metrics.APIMBean;

View File

@ -23,11 +23,11 @@
*/ */
package org.apache.cassandra.metrics; package org.apache.cassandra.metrics;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.management.MalformedObjectNameException; import javax.management.MalformedObjectNameException;
/** /**
@ -55,7 +55,7 @@ public class CompactionMetrics implements Metrics {
registry.register(() -> registry.gauge((client) -> { registry.register(() -> registry.gauge((client) -> {
Map<String, Map<String, Integer>> result = new HashMap<>(); Map<String, Map<String, Integer>> result = new HashMap<>();
JsonArray compactions = client.getJsonArray("compaction_manager/metrics/pending_tasks_by_table"); JsonArray compactions = client.getJsonArray("compaction_manager/compactions");
for (int i = 0; i < compactions.size(); i++) { for (int i = 0; i < compactions.size(); i++) {
JsonObject c = compactions.getJsonObject(i); JsonObject c = compactions.getJsonObject(i);
@ -68,7 +68,7 @@ public class CompactionMetrics implements Metrics {
} }
Map<String, Integer> map = result.get(ks); Map<String, Integer> map = result.get(ks);
map.put(cf, (int)(c.getJsonNumber("task").longValue())); map.put(cf, (int)(c.getJsonNumber("total").longValue() - c.getJsonNumber("completed").longValue()));
} }
return result; return result;
}), factory.createMetricName("PendingTasksByTableName")); }), factory.createMetricName("PendingTasksByTableName"));

View File

@ -21,9 +21,6 @@ import static com.scylladb.jmx.api.APIClient.getReader;
import static java.lang.Math.floor; import static java.lang.Math.floor;
import static java.util.logging.Level.SEVERE; import static java.util.logging.Level.SEVERE;
import jakarta.json.JsonArray;
import jakarta.json.JsonNumber;
import jakarta.json.JsonObject;
import java.util.Arrays; import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -32,6 +29,9 @@ import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.json.JsonArray;
import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException; import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer; import javax.management.MBeanServer;

View File

@ -24,23 +24,20 @@
package org.apache.cassandra.metrics; package org.apache.cassandra.metrics;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.Collections.emptySet;
import static org.apache.cassandra.metrics.DefaultNameFactory.createMetricName; import static org.apache.cassandra.metrics.DefaultNameFactory.createMetricName;
import jakarta.json.JsonArray;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import javax.json.JsonArray;
import javax.management.MalformedObjectNameException; import javax.management.MalformedObjectNameException;
import javax.management.ObjectName; import javax.management.ObjectName;
import javax.management.OperationsException;
import com.scylladb.jmx.api.APIClient; import com.scylladb.jmx.api.APIClient;
import com.scylladb.jmx.metrics.APIMBean; import com.scylladb.jmx.metrics.APIMBean;
import com.scylladb.jmx.metrics.RegistrationChecker;
import com.scylladb.jmx.metrics.RegistrationMode;
import com.sun.jmx.mbeanserver.JmxMBeanServer; import com.sun.jmx.mbeanserver.JmxMBeanServer;
/** /**
@ -67,45 +64,46 @@ public class StreamingMetrics {
private static boolean isStreamingName(ObjectName n) { private static boolean isStreamingName(ObjectName n) {
return TYPE_NAME.equals(n.getKeyProperty("type")); return TYPE_NAME.equals(n.getKeyProperty("type"));
} }
public static RegistrationChecker createRegistrationChecker() {
return new RegistrationChecker() {
@Override
protected void doCheck(APIClient client, JmxMBeanServer server, EnumSet<RegistrationMode> mode) throws OperationsException, UnknownHostException {
Set<ObjectName> all = new HashSet<ObjectName>(globalNames);
JsonArray streams = client.getJsonArray("/stream_manager/");
for (int i = 0; i < streams.size(); i++) {
JsonArray sessions = streams.getJsonObject(i).getJsonArray("sessions");
for (int j = 0; j < sessions.size(); j++) {
String peer = sessions.getJsonObject(j).getString("peer");
String scope = InetAddress.getByName(peer).getHostAddress().replaceAll(":", ".");
all.add(createMetricName(TYPE_NAME, "IncomingBytes", scope));
all.add(createMetricName(TYPE_NAME, "OutgoingBytes", scope));
}
}
MetricsRegistry registry = new MetricsRegistry(client, server); public static void unregister(APIClient client, JmxMBeanServer server) throws MalformedObjectNameException {
APIMBean.checkRegistration(server, all, mode, StreamingMetrics::isStreamingName, n -> { APIMBean.checkRegistration(server, emptySet(), StreamingMetrics::isStreamingName, (n) -> null);
String scope = n.getKeyProperty("scope"); }
String name = n.getKeyProperty("name");
String url = null; public static boolean checkRegistration(APIClient client, JmxMBeanServer server)
if ("ActiveOutboundStreams".equals(name)) { throws MalformedObjectNameException, UnknownHostException {
url = "/stream_manager/metrics/outbound";
} else if ("IncomingBytes".equals(name) || "TotalIncomingBytes".equals(name)) { Set<ObjectName> all = new HashSet<ObjectName>(globalNames);
url = "/stream_manager/metrics/incoming"; JsonArray streams = client.getJsonArray("/stream_manager/");
} else if ("OutgoingBytes".equals(name) || "TotalOutgoingBytes".equals(name)) { for (int i = 0; i < streams.size(); i++) {
url = "/stream_manager/metrics/outgoing"; JsonArray sessions = streams.getJsonObject(i).getJsonArray("sessions");
} for (int j = 0; j < sessions.size(); j++) {
if (url == null) { String peer = sessions.getJsonObject(j).getString("peer");
throw new IllegalArgumentException(); String scope = InetAddress.getByName(peer).getHostAddress().replaceAll(":", ".");
} all.add(createMetricName(TYPE_NAME, "IncomingBytes", scope));
if (scope != null) { all.add(createMetricName(TYPE_NAME, "OutgoingBytes", scope));
url = url + "/" + scope; }
} }
return registry.counter(url);
}); MetricsRegistry registry = new MetricsRegistry(client, server);
} return APIMBean.checkRegistration(server, all, StreamingMetrics::isStreamingName, n -> {
}; String scope = n.getKeyProperty("scope");
} String name = n.getKeyProperty("name");
String url = null;
if ("ActiveOutboundStreams".equals(name)) {
url = "/stream_manager/metrics/outbound";
} else if ("IncomingBytes".equals(name) || "TotalIncomingBytes".equals(name)) {
url = "/stream_manager/metrics/incoming";
} else if ("OutgoingBytes".equals(name) || "TotalOutgoingBytes".equals(name)) {
url = "/stream_manager/metrics/outgoing";
}
if (url == null) {
throw new IllegalArgumentException();
}
if (scope != null) {
url = url + "/" + scope;
}
return registry.counter(url);
});
}
} }

View File

@ -19,8 +19,6 @@ package org.apache.cassandra.metrics;
import static com.scylladb.jmx.api.APIClient.getReader; import static com.scylladb.jmx.api.APIClient.getReader;
import java.io.InvalidObjectException;
import java.io.ObjectStreamException;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
@ -297,6 +295,7 @@ public class TableMetrics implements Metrics {
registry.createDummyTableGauge(Double.class, "PercentRepaired"); registry.createDummyTableGauge(Double.class, "PercentRepaired");
} }
@SuppressWarnings("serial")
static class TableMetricObjectName extends javax.management.ObjectName { static class TableMetricObjectName extends javax.management.ObjectName {
private final TableMetricStringNameFactory factory; private final TableMetricStringNameFactory factory;
private final String metricName; private final String metricName;
@ -401,18 +400,6 @@ public class TableMetrics implements Metrics {
public boolean isPropertyValuePattern() { public boolean isPropertyValuePattern() {
return false; return false;
} }
/**
* This type is not really serializable.
* Replace it with vanilla objectname.
*/
private Object writeReplace() throws ObjectStreamException {
try {
return new ObjectName(getDomain(), getKeyPropertyList());
} catch (MalformedObjectNameException e) {
throw new InvalidObjectException(toString());
}
}
} }
static interface TableMetricStringNameFactory { static interface TableMetricStringNameFactory {

View File

@ -24,8 +24,6 @@ package org.apache.cassandra.net;
import static java.util.Collections.emptyMap; import static java.util.Collections.emptyMap;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -34,6 +32,9 @@ import java.util.logging.Logger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.json.JsonArray;
import javax.json.JsonObject;
import org.apache.cassandra.metrics.DroppedMessageMetrics; import org.apache.cassandra.metrics.DroppedMessageMetrics;
import com.scylladb.jmx.api.APIClient; import com.scylladb.jmx.api.APIClient;

View File

@ -24,11 +24,12 @@
package org.apache.cassandra.service; package org.apache.cassandra.service;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import org.apache.cassandra.metrics.CacheMetrics; import org.apache.cassandra.metrics.CacheMetrics;
import com.scylladb.jmx.api.APIClient; import com.scylladb.jmx.api.APIClient;

View File

@ -1,66 +0,0 @@
package org.apache.cassandra.service;
import static com.sun.jmx.mbeanserver.MXBeanMappingFactory.DEFAULT;
import jakarta.xml.bind.annotation.XmlRootElement;
import java.io.InvalidObjectException;
import java.util.List;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.OpenDataException;
import com.sun.jmx.mbeanserver.MXBeanMapping;
@SuppressWarnings("restriction")
@XmlRootElement
public class PerTableSSTableInfo {
private static final MXBeanMapping mxBeanMapping;
static {
try {
mxBeanMapping = DEFAULT.mappingForType(PerTableSSTableInfo.class, DEFAULT);
} catch (OpenDataException e) {
throw new RuntimeException(e);
}
}
private String keyspace;
private List<SSTableInfo> sstables;
private String table;
public String getTable() {
return table;
}
public void setTable(String table) {
this.table = table;
}
public String getKeyspace() {
return keyspace;
}
public void setKeyspace(String keyspace) {
this.keyspace = keyspace;
}
public List<SSTableInfo> getSSTables() {
return sstables;
}
public void setSSTableInfos(List<SSTableInfo> sstableInfos) {
this.sstables = sstableInfos;
}
public CompositeData toCompositeData() {
try {
return (CompositeData) mxBeanMapping.toOpenValue(this);
} catch (OpenDataException e) {
throw new Error(e); // should not reach.
}
}
public static PerTableSSTableInfo from(CompositeData data) throws InvalidObjectException {
return (PerTableSSTableInfo) mxBeanMapping.fromOpenValue(data);
}
}

View File

@ -1,153 +0,0 @@
package org.apache.cassandra.service;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.scylladb.jmx.utils.DateXmlAdapter;
public class SSTableInfo {
private long size;
@JsonProperty("data_size")
private long dataSize;
@JsonProperty("index_size")
private long indexSize;
@JsonProperty("filter_size")
private long filterSize;
@XmlJavaTypeAdapter(type = Date.class, value = DateXmlAdapter.class)
private Date timestamp;
private long generation;
private long level;
private String version;
private Map<String, String> properties;
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
@JsonIgnore
private Map<String, Map<String, String>> extendedProperties;
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public long getDataSize() {
return dataSize;
}
public void setDataSize(long dataSize) {
this.dataSize = dataSize;
}
public long getIndexSize() {
return indexSize;
}
public void setIndexSize(long indexSize) {
this.indexSize = indexSize;
}
public long getFilterSize() {
return filterSize;
}
public void setFilterSize(long filterSize) {
this.filterSize = filterSize;
}
public Date getTimestamp() {
return timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
public long getGeneration() {
return generation;
}
public void setGeneration(long generation) {
this.generation = generation;
}
public long getLevel() {
return level;
}
public void setLevel(long level) {
this.level = level;
}
public Map<String, String> getProperties() {
return properties;
}
public Map<String, Map<String, String>> getExtendedProperties() {
return extendedProperties;
}
public void setExtendedProperties(Map<String, Map<String, String>> extendedProperties) {
this.extendedProperties = extendedProperties;
}
@JsonProperty("properties")
private void unpackProperties(List<Map<String, String>> maps) {
Map<String, String> result = new HashMap<>();
for (Map<String, String> map : maps) {
String key = map.get("key");
String value = map.get("value");
result.put(key, value);
}
properties = result;
}
@JsonProperty("extended_properties")
private void unpackNested(List<Map<String, Object>> properties) {
Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
for (Map<String, Object> map : properties) {
Object name = map.get("group");
if (name != null) {
Map<String, String> dst = new HashMap<>();
List<?> value = (List<?>) map.get("attributes");
for (Object v : value) {
Map<?, ?> subMap = (Map<?, ?>) v;
dst.put(String.valueOf(subMap.get("key")), String.valueOf(subMap.get("value")));
}
result.put(String.valueOf(name), dst);
} else {
for (Map.Entry<String, Object> e : map.entrySet()) {
result.put(e.getKey(), Collections.singletonMap(String.valueOf(e.getValue()), ""));
}
}
}
extendedProperties = result;
}
}

View File

@ -25,15 +25,18 @@ package org.apache.cassandra.service;
import static java.util.Collections.emptySet; import static java.util.Collections.emptySet;
import jakarta.json.JsonArray;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.management.ObjectName;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import org.apache.cassandra.db.ColumnFamilyStore; import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.metrics.CASClientRequestMetrics; import org.apache.cassandra.metrics.CASClientRequestMetrics;
import org.apache.cassandra.metrics.ClientRequestMetrics; import org.apache.cassandra.metrics.ClientRequestMetrics;
@ -56,8 +59,7 @@ public class StorageProxy extends MetricsMBean implements StorageProxyMBean {
new ClientRequestMetrics("RangeSlice", "/storage_proxy/metrics/range"), new ClientRequestMetrics("RangeSlice", "/storage_proxy/metrics/range"),
new ClientRequestMetrics("Write", "storage_proxy/metrics/write"), new ClientRequestMetrics("Write", "storage_proxy/metrics/write"),
new CASClientRequestMetrics("CASWrite", "storage_proxy/metrics/cas_write"), new CASClientRequestMetrics("CASWrite", "storage_proxy/metrics/cas_write"),
new CASClientRequestMetrics("CASRead", "storage_proxy/metrics/cas_read"), new CASClientRequestMetrics("CASRead", "storage_proxy/metrics/cas_read"));
new ClientRequestMetrics("ViewWrite", "storage_proxy/metrics/view_write"));
} }
@Override @Override

View File

@ -24,16 +24,10 @@ package org.apache.cassandra.service;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -48,8 +42,9 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.management.ListenerNotFoundException; import javax.management.ListenerNotFoundException;
import javax.management.MBeanNotificationInfo; import javax.management.MBeanNotificationInfo;
import javax.management.Notification; import javax.management.Notification;
@ -57,24 +52,19 @@ import javax.management.NotificationBroadcaster;
import javax.management.NotificationBroadcasterSupport; import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationFilter; import javax.management.NotificationFilter;
import javax.management.NotificationListener; import javax.management.NotificationListener;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData; import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport; import javax.ws.rs.core.MultivaluedHashMap;
import javax.management.openmbean.TabularType; import javax.ws.rs.core.MultivaluedMap;
import org.apache.cassandra.metrics.StorageMetrics; import org.apache.cassandra.metrics.StorageMetrics;
import org.apache.cassandra.repair.RepairParallelism; import org.apache.cassandra.repair.RepairParallelism;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.scylladb.jmx.api.APIClient; import com.scylladb.jmx.api.APIClient;
import com.scylladb.jmx.metrics.MetricsMBean; import com.scylladb.jmx.metrics.MetricsMBean;
import com.scylladb.jmx.api.utils.FileUtils; import com.scylladb.jmx.utils.FileUtils;
import com.google.common.base.Throwables;
/** /**
* This abstraction contains the token/identifier of this node on the identifier * This abstraction contains the token/identifier of this node on the identifier
@ -85,41 +75,6 @@ public class StorageService extends MetricsMBean implements StorageServiceMBean,
private static final Logger logger = Logger.getLogger(StorageService.class.getName()); private static final Logger logger = Logger.getLogger(StorageService.class.getName());
private static final Timer timer = new Timer("Storage Service Repair", true); private static final Timer timer = new Timer("Storage Service Repair", true);
private static final String[] COUNTER_NAMES = new String[]{"raw", "count", "error", "string"};
private static final String[] COUNTER_DESCS = new String[]
{ "partition key in raw hex bytes",
"value of this partition for given sampler",
"value is within the error bounds plus or minus of this",
"the partition key turned into a human readable format" };
private static final CompositeType COUNTER_COMPOSITE_TYPE;
private static final TabularType COUNTER_TYPE;
private static final String[] OPERATION_NAMES = new String[]{"read", "write"};
private static final String[] SAMPLER_NAMES = new String[]{"cardinality", "partitions"};
private static final String[] SAMPLER_DESCS = new String[]
{ "cardinality of partitions",
"list of counter results" };
private static final String SAMPLING_RESULTS_NAME = "SAMPLING_RESULTS";
private static final CompositeType SAMPLING_RESULT;
static
{
try
{
OpenType<?>[] counterTypes = new OpenType[] { SimpleType.STRING, SimpleType.LONG, SimpleType.LONG, SimpleType.STRING };
COUNTER_COMPOSITE_TYPE = new CompositeType(SAMPLING_RESULTS_NAME, SAMPLING_RESULTS_NAME, COUNTER_NAMES, COUNTER_DESCS, counterTypes);
COUNTER_TYPE = new TabularType(SAMPLING_RESULTS_NAME, SAMPLING_RESULTS_NAME, COUNTER_COMPOSITE_TYPE, COUNTER_NAMES);
OpenType<?>[] samplerTypes = new OpenType[] { SimpleType.LONG, COUNTER_TYPE };
SAMPLING_RESULT = new CompositeType(SAMPLING_RESULTS_NAME, SAMPLING_RESULTS_NAME, SAMPLER_NAMES, SAMPLER_DESCS, samplerTypes);
} catch (OpenDataException e)
{
throw Throwables.propagate(e);
}
}
private final NotificationBroadcasterSupport notificationBroadcasterSupport = new NotificationBroadcasterSupport(); private final NotificationBroadcasterSupport notificationBroadcasterSupport = new NotificationBroadcasterSupport();
@Override @Override
@ -314,7 +269,7 @@ public class StorageService extends MetricsMBean implements StorageServiceMBean,
@Override @Override
public Map<List<String>, List<String>> getRangeToEndpointMap(String keyspace) { public Map<List<String>, List<String>> getRangeToEndpointMap(String keyspace) {
log(" getRangeToEndpointMap(String keyspace)"); log(" getRangeToEndpointMap(String keyspace)");
return client.getMapListStrValue("/storage_service/range_to_endpoint_map/" + keyspace); return client.getMapListStrValue("/storage_service/range/" + keyspace);
} }
/** /**
@ -520,12 +475,6 @@ public class StorageService extends MetricsMBean implements StorageServiceMBean,
return client.getListInetAddressValue(""); return client.getListInetAddressValue("");
} }
@Override
public void checkAndRepairCdcStreams() throws IOException {
log(" checkAndRepairCdcStreams() throws IOException");
client.post("/storage_service/cdc_streams_check_and_repair");
}
/** /**
* Takes the snapshot for the given keyspaces. A snapshot name must be * Takes the snapshot for the given keyspaces. A snapshot name must be
* specified. * specified.
@ -543,18 +492,16 @@ public class StorageService extends MetricsMBean implements StorageServiceMBean,
@Override @Override
public void takeSnapshot(String tag, Map<String, String> options, String... keyspaceNames) throws IOException { public void takeSnapshot(String tag, Map<String, String> options, String... keyspaceNames) throws IOException {
log(" takeSnapshot(String tag, String... keyspaceNames) throws IOException"); log(" takeSnapshot(String tag, String... keyspaceNames) throws IOException");
MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<String, String>(); MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<String, String>();
APIClient.set_query_param(queryParams, "tag", tag); APIClient.set_query_param(queryParams, "tag", tag);
if (keyspaceNames.length == 1 && keyspaceNames[0].indexOf('.') != -1) { if (keyspaceNames.length == 1 && keyspaceNames[0].indexOf('.') != -1) {
String[] parts = keyspaceNames[0].split("\\."); String[] parts = keyspaceNames[0].split("\\.");
keyspaceNames = new String[] { parts[0] }; keyspaceNames = new String[] { parts[0] };
APIClient.set_query_param(queryParams, "cf", parts[1]); APIClient.set_query_param(queryParams, "cf", parts[1]);
} }
APIClient.set_query_param(queryParams, "kn", APIClient.join(keyspaceNames)); APIClient.set_query_param(queryParams, "kn", APIClient.join(keyspaceNames));
if (options.containsKey("skipFlush")) { // TODO: origin has one recognized option: skip flush. We don't.
APIClient.set_query_param(queryParams, "sf", options.get("skipFlush"));
}
client.post("/storage_service/snapshots", queryParams); client.post("/storage_service/snapshots", queryParams);
} }
@ -656,9 +603,8 @@ public class StorageService extends MetricsMBean implements StorageServiceMBean,
client.post("/storage_service/keyspace_compaction/" + keyspaceName, queryParams); client.post("/storage_service/keyspace_compaction/" + keyspaceName, queryParams);
} }
@Override @Override
public void forceKeyspaceCompactionForTokenRange(String keyspaceName, String startToken, String endToken, public void forceKeyspaceCompactionForTokenRange(String keyspaceName, String startToken, String endToken, String... tableNames) throws IOException, ExecutionException, InterruptedException {
String... tableNames) throws IOException, ExecutionException, InterruptedException {
// TODO: actually handle token ranges. // TODO: actually handle token ranges.
forceKeyspaceCompaction(keyspaceName, tableNames); forceKeyspaceCompaction(keyspaceName, tableNames);
} }
@ -697,7 +643,7 @@ public class StorageService extends MetricsMBean implements StorageServiceMBean,
APIClient.set_bool_query_param(queryParams, "disable_snapshot", disableSnapshot); APIClient.set_bool_query_param(queryParams, "disable_snapshot", disableSnapshot);
APIClient.set_bool_query_param(queryParams, "skip_corrupted", skipCorrupted); APIClient.set_bool_query_param(queryParams, "skip_corrupted", skipCorrupted);
APIClient.set_query_param(queryParams, "cf", APIClient.join(columnFamilies)); APIClient.set_query_param(queryParams, "cf", APIClient.join(columnFamilies));
return client.getIntValue("/storage_service/keyspace_scrub/" + keyspaceName, queryParams); return client.getIntValue("/storage_service/keyspace_scrub/" + keyspaceName);
} }
/** /**
@ -923,7 +869,7 @@ public class StorageService extends MetricsMBean implements StorageServiceMBean,
@Deprecated @Deprecated
public int forceRepairAsync(String keyspace, boolean isSequential, Collection<String> dataCenters, public int forceRepairAsync(String keyspace, boolean isSequential, Collection<String> dataCenters,
Collection<String> hosts, boolean primaryRange, boolean repairedAt, String... columnFamilies) Collection<String> hosts, boolean primaryRange, boolean repairedAt, String... columnFamilies)
throws IOException { throws IOException {
log(" forceRepairAsync(String keyspace, boolean isSequential, Collection<String> dataCenters, Collection<String> hosts, boolean primaryRange, boolean repairedAt, String... columnFamilies) throws IOException"); log(" forceRepairAsync(String keyspace, boolean isSequential, Collection<String> dataCenters, Collection<String> hosts, boolean primaryRange, boolean repairedAt, String... columnFamilies) throws IOException");
return repairRangeAsync(null, null, keyspace, isSequential, dataCenters, hosts, primaryRange, repairedAt, return repairRangeAsync(null, null, keyspace, isSequential, dataCenters, hosts, primaryRange, repairedAt,
columnFamilies); columnFamilies);
@ -991,21 +937,13 @@ public class StorageService extends MetricsMBean implements StorageServiceMBean,
* the host id to remove * the host id to remove
*/ */
@Override @Override
public void removeNode(String hostIdString, String ignoreNodes) { public void removeNode(String hostIdString) {
log(" removeNode(String token, String ignoreNodes)"); log(" removeNode(String token)");
MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<String, String>(); MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<String, String>();
APIClient.set_query_param(queryParams, "host_id", hostIdString); APIClient.set_query_param(queryParams, "host_id", hostIdString);
if (ignoreNodes != null) {
APIClient.set_query_param(queryParams, "ignore_nodes", ignoreNodes);
}
client.post("/storage_service/remove_node", queryParams); client.post("/storage_service/remove_node", queryParams);
} }
public void removeNode(String hostIdString) {
String ignoreNodes = null;
removeNode(hostIdString, ignoreNodes);
}
/** /**
* Get the status of a token removal. * Get the status of a token removal.
*/ */
@ -1360,19 +1298,12 @@ public class StorageService extends MetricsMBean implements StorageServiceMBean,
} }
/** /**
* Same as {@link #rebuild(String)}, but only for specified keyspace and * Same as {@link #rebuild(String)}, but only for specified keyspace and ranges.
* ranges.
* *
* @param sourceDc * @param sourceDc Name of DC from which to select sources for streaming or null to pick any node
* Name of DC from which to select sources for streaming or null * @param keyspace Name of the keyspace which to rebuild or null to rebuild all keyspaces.
* to pick any node * @param tokens Range of tokens to rebuild or null to rebuild all token ranges. In the format of:
* @param keyspace * "(start_token_1,end_token_1],(start_token_2,end_token_2],...(start_token_n,end_token_n]"
* Name of the keyspace which to rebuild or null to rebuild all
* keyspaces.
* @param tokens
* Range of tokens to rebuild or null to rebuild all token
* ranges. In the format of:
* "(start_token_1,end_token_1],(start_token_2,end_token_2],...(start_token_n,end_token_n]"
*/ */
@Override @Override
public void rebuild(String sourceDc, String keyspace, String tokens, String specificSources) { public void rebuild(String sourceDc, String keyspace, String tokens, String specificSources) {
@ -1425,25 +1356,15 @@ public class StorageService extends MetricsMBean implements StorageServiceMBean,
* The parent keyspace name * The parent keyspace name
* @param cfName * @param cfName
* The ColumnFamily name where SSTables belong * The ColumnFamily name where SSTables belong
* @param isLoadAndStream
* Whether or not arbitrary SSTables should be loaded (and streamed to the owning nodes)
*/ */
@Override @Override
public void loadNewSSTables(String ksName, String cfName, boolean isLoadAndStream) { public void loadNewSSTables(String ksName, String cfName) {
log(" loadNewSSTables(String ksName, String cfName, boolean isLoadAndStream)"); log(" loadNewSSTables(String ksName, String cfName)");
MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<String, String>(); MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<String, String>();
queryParams.add("cf", cfName); queryParams.add("cf", cfName);
if (isLoadAndStream) {
queryParams.add("load_and_stream", "true");
}
client.post("/storage_service/sstables/" + ksName, queryParams); client.post("/storage_service/sstables/" + ksName, queryParams);
} }
@Override
public void loadNewSSTables(String ksName, String cfName) {
loadNewSSTables(ksName, cfName, false);
}
/** /**
* Return a List of Tokens representing a sample of keys across all * Return a List of Tokens representing a sample of keys across all
* ColumnFamilyStores. * ColumnFamilyStores.
@ -1514,7 +1435,13 @@ public class StorageService extends MetricsMBean implements StorageServiceMBean,
log("enableAutoCompaction(String ks, String... columnFamilies)"); log("enableAutoCompaction(String ks, String... columnFamilies)");
MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<String, String>(); MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<String, String>();
APIClient.set_query_param(queryParams, "cf", APIClient.join(columnFamilies)); APIClient.set_query_param(queryParams, "cf", APIClient.join(columnFamilies));
client.post("/storage_service/auto_compaction/" + ks, queryParams); try {
client.post("/storage_service/auto_compaction/" + ks, queryParams);
} catch (RuntimeException e) {
// FIXME should throw the right exception
throw new IOException(e.getMessage());
}
} }
@Override @Override
@ -1733,7 +1660,7 @@ public class StorageService extends MetricsMBean implements StorageServiceMBean,
public int scrub(boolean disableSnapshot, boolean skipCorrupted, boolean checkData, int jobs, String keyspaceName, public int scrub(boolean disableSnapshot, boolean skipCorrupted, boolean checkData, int jobs, String keyspaceName,
String... columnFamilies) throws IOException, ExecutionException, InterruptedException { String... columnFamilies) throws IOException, ExecutionException, InterruptedException {
// "jobs" not (yet) relevant for scylla. (though possibly useful...) // "jobs" not (yet) relevant for scylla. (though possibly useful...)
return scrub(disableSnapshot, skipCorrupted, checkData, keyspaceName, columnFamilies); return scrub(disableSnapshot, skipCorrupted, checkData, 0, keyspaceName, columnFamilies);
} }
@Override @Override
@ -1777,99 +1704,4 @@ public class StorageService extends MetricsMBean implements StorageServiceMBean,
log(" resumeBootstrap"); log(" resumeBootstrap");
return false; return false;
} }
@Override
public List<CompositeData> getSSTableInfo(String keyspace, String table) {
if (keyspace == null && table != null) {
throw new IllegalArgumentException("Missing keyspace name");
}
MultivaluedMap<String, String> queryParams = null;
if (keyspace != null) {
queryParams = new MultivaluedHashMap<String, String>();
queryParams.add("keyspace", keyspace);
}
if (table != null) {
queryParams.add("cf", table);
}
return client.get("/storage_service/sstable_info", queryParams)
.get(new GenericType<List<PerTableSSTableInfo>>() {
}).stream().map((i) -> i.toCompositeData()).collect(Collectors.toList());
}
@Override
public List<CompositeData> getSSTableInfo() {
return getSSTableInfo(null, null);
}
@Override
public int scrub(boolean disableSnapshot, boolean skipCorrupted, boolean checkData, boolean reinsertOverflowedTTL,
int jobs, String keyspaceName, String... columnFamilies)
throws IOException, ExecutionException, InterruptedException {
MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<String, String>();
APIClient.set_bool_query_param(queryParams, "disable_snapshot", disableSnapshot);
APIClient.set_bool_query_param(queryParams, "skip_corrupted", skipCorrupted);
APIClient.set_query_param(queryParams, "cf", APIClient.join(columnFamilies));
return client.getIntValue("/storage_service/keyspace_scrub/" + keyspaceName, queryParams);
}
@Override
public int scrub(boolean disableSnapshot, String scrubMode, boolean checkData, boolean reinsertOverflowedTTL,
int jobs, String keyspaceName, String... columnFamilies)
throws IOException, ExecutionException, InterruptedException {
MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<String, String>();
APIClient.set_bool_query_param(queryParams, "disable_snapshot", disableSnapshot);
if (!"".equals(scrubMode)) {
APIClient.set_query_param(queryParams, "scrub_mode", scrubMode);
}
APIClient.set_query_param(queryParams, "cf", APIClient.join(columnFamilies));
return client.getIntValue("/storage_service/keyspace_scrub/" + keyspaceName, queryParams);
}
@Override
public long getUptime() {
log("getUptime()");
return client.getLongValue("/system/uptime_ms");
}
@Override
public CompositeData getToppartitions(String sampler, List<String> keyspaceFilters, List<String> tableFilters, int duration, int capacity, int count) throws OpenDataException {
return getToppartitions(Arrays.asList(sampler), keyspaceFilters, tableFilters, duration, capacity, count).get(sampler.toLowerCase());
}
@Override
public Map<String, CompositeData> getToppartitions(List<String> samplers, List<String> keyspaceFilters, List<String> tableFilters, int duration, int capacity, int count) throws OpenDataException {
MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<String, String>();
APIClient.set_query_param(queryParams, "duration", Integer.toString(duration));
APIClient.set_query_param(queryParams, "capacity", Integer.toString(capacity));
APIClient.set_query_param(queryParams, "keyspace_filters", keyspaceFilters != null ? APIClient.join(keyspaceFilters.toArray(new String[0])) : null);
APIClient.set_query_param(queryParams, "table_filters", tableFilters != null ? APIClient.join(tableFilters.toArray(new String[0])) : null);
JsonObject result = client.getJsonObj("/storage_service/toppartitions", queryParams);
Map<String, CompositeData> resultsMap = new HashMap<>();
for (String operation : OPERATION_NAMES) {
JsonArray counters = result.getJsonArray(operation);
long cardinality = result.getJsonNumber(operation + "_cardinality").longValue();
long size = 0;
TabularDataSupport tabularResult = new TabularDataSupport(COUNTER_TYPE);
if (counters != null) {
size = (count > counters.size()) ? counters.size() : count;
for (int i = 0; i < size; i++) {
JsonObject counter = counters.getJsonObject(i);
tabularResult.put(new CompositeDataSupport(COUNTER_COMPOSITE_TYPE, COUNTER_NAMES,
new Object[] { counter.getString("partition"), // raw
counter.getJsonNumber("count").longValue(), // count
counter.getJsonNumber("error").longValue(), // error
counter.getString("partition") })); // string
}
}
resultsMap.put(operation + "s", new CompositeDataSupport(SAMPLING_RESULT, SAMPLER_NAMES, new Object[] { cardinality, tabularResult }));
}
return resultsMap;
}
} }

View File

@ -35,9 +35,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import javax.management.NotificationEmitter; import javax.management.NotificationEmitter;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.TabularData; import javax.management.openmbean.TabularData;
import javax.management.openmbean.OpenDataException;
public interface StorageServiceMBean extends NotificationEmitter { public interface StorageServiceMBean extends NotificationEmitter {
/** /**
@ -214,7 +212,6 @@ public interface StorageServiceMBean extends NotificationEmitter {
public List<InetAddress> getNaturalEndpoints(String keyspaceName, ByteBuffer key); public List<InetAddress> getNaturalEndpoints(String keyspaceName, ByteBuffer key);
public void checkAndRepairCdcStreams() throws IOException;
/** /**
* Takes the snapshot for the given keyspaces. A snapshot name must be * Takes the snapshot for the given keyspaces. A snapshot name must be
* specified. * specified.
@ -350,10 +347,6 @@ public interface StorageServiceMBean extends NotificationEmitter {
* scrubbed. * scrubbed.
* *
* Scrubbed CFs will be snapshotted first, if disableSnapshot is false * Scrubbed CFs will be snapshotted first, if disableSnapshot is false
*
* scrubMode controls what scrub does when encountering corruption.
* It replaces skipCorrupted where skipCorrupted is equivalent to scrubMode="SKIP".
* Can be one of: "ABORT", "SKIP", "SEGREGATE", or "VALIDATE".
*/ */
@Deprecated @Deprecated
public int scrub(boolean disableSnapshot, boolean skipCorrupted, String keyspaceName, String... tableNames) public int scrub(boolean disableSnapshot, boolean skipCorrupted, String keyspaceName, String... tableNames)
@ -363,19 +356,9 @@ public interface StorageServiceMBean extends NotificationEmitter {
public int scrub(boolean disableSnapshot, boolean skipCorrupted, boolean checkData, String keyspaceName, public int scrub(boolean disableSnapshot, boolean skipCorrupted, boolean checkData, String keyspaceName,
String... tableNames) throws IOException, ExecutionException, InterruptedException; String... tableNames) throws IOException, ExecutionException, InterruptedException;
@Deprecated
public int scrub(boolean disableSnapshot, boolean skipCorrupted, boolean checkData, int jobs, String keyspaceName, public int scrub(boolean disableSnapshot, boolean skipCorrupted, boolean checkData, int jobs, String keyspaceName,
String... columnFamilies) throws IOException, ExecutionException, InterruptedException; String... columnFamilies) throws IOException, ExecutionException, InterruptedException;
@Deprecated
public int scrub(boolean disableSnapshot, boolean skipCorrupted, boolean checkData, boolean reinsertOverflowedTTL,
int jobs, String keyspaceName, String... columnFamilies)
throws IOException, ExecutionException, InterruptedException;
public int scrub(boolean disableSnapshot, String scrubMode, boolean checkData, boolean reinsertOverflowedTTL,
int jobs, String keyspaceName, String... columnFamilies)
throws IOException, ExecutionException, InterruptedException;
/** /**
* Verify (checksums of) the given keyspace. If tableNames array is empty, * Verify (checksums of) the given keyspace. If tableNames array is empty,
* all CFs are verified. * all CFs are verified.
@ -513,11 +496,8 @@ public interface StorageServiceMBean extends NotificationEmitter {
* removeToken removes token (and all data associated with enpoint that had * removeToken removes token (and all data associated with enpoint that had
* it) from the ring * it) from the ring
*/ */
@Deprecated
public void removeNode(String token); public void removeNode(String token);
public void removeNode(String token, String ignoreNodes);
/** /**
* Get the status of a token removal. * Get the status of a token removal.
*/ */
@ -810,16 +790,7 @@ public interface StorageServiceMBean extends NotificationEmitter {
* The parent keyspace name * The parent keyspace name
* @param cfName * @param cfName
* The ColumnFamily name where SSTables belong * The ColumnFamily name where SSTables belong
* @param isLoadAndStream
* Whether or not arbitrary SSTables should be loaded (and streamed to the owning nodes)
*/ */
public void loadNewSSTables(String ksName, String cfName, boolean isLoadAndStream);
/**
* @deprecated use {@link #loadNewSSTables(String ksName, String cfName, boolean isLoadAndStream)} instead.
* This is kept for backward compatibility.
*/
@Deprecated
public void loadNewSSTables(String ksName, String cfName); public void loadNewSSTables(String ksName, String cfName);
/** /**
@ -901,15 +872,4 @@ public interface StorageServiceMBean extends NotificationEmitter {
* Sets the hinted handoff throttle in kb per second, per delivery thread. * Sets the hinted handoff throttle in kb per second, per delivery thread.
*/ */
public boolean resumeBootstrap(); public boolean resumeBootstrap();
public List<CompositeData> getSSTableInfo(String keyspace, String table);
public List<CompositeData> getSSTableInfo();
/** retun the system uptime */
public long getUptime();
public CompositeData getToppartitions(String sampler, List<String> keyspaceFilters, List<String> tableFilters, int duration, int capacity, int count) throws OpenDataException;
public Map<String, CompositeData> getToppartitions(List<String> samplers, List<String> keyspaceFilters, List<String> tableFilters, int duration, int capacity, int count) throws OpenDataException;
} }

View File

@ -24,14 +24,15 @@
package org.apache.cassandra.streaming; package org.apache.cassandra.streaming;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import java.io.Serializable; import java.io.Serializable;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.json.JsonArray;
import javax.json.JsonObject;
import com.google.common.base.Objects; import com.google.common.base.Objects;
/** /**

View File

@ -24,8 +24,6 @@
package org.apache.cassandra.streaming; package org.apache.cassandra.streaming;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import java.io.Serializable; import java.io.Serializable;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
@ -34,6 +32,9 @@ import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.json.JsonArray;
import javax.json.JsonObject;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
/** /**

View File

@ -24,12 +24,12 @@
package org.apache.cassandra.streaming; package org.apache.cassandra.streaming;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.management.ListenerNotFoundException; import javax.management.ListenerNotFoundException;
import javax.management.MBeanNotificationInfo; import javax.management.MBeanNotificationInfo;
import javax.management.NotificationBroadcasterSupport; import javax.management.NotificationBroadcasterSupport;

View File

@ -24,12 +24,13 @@
package org.apache.cassandra.streaming; package org.apache.cassandra.streaming;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.UUID; import java.util.UUID;
import javax.json.JsonArray;
import javax.json.JsonObject;
import com.google.common.base.Objects; import com.google.common.base.Objects;
/** /**