This is an automated email from the ASF dual-hosted git repository.
smiklosovic pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/trunk by this push:
new 5d46ff2796 Remove dependency on Sigar in favor of OSHI
5d46ff2796 is described below
commit 5d46ff27968050e51425083fc3ab8b7d4a51fcd5
Author: Claude Warren <[email protected]>
AuthorDate: Wed Oct 25 13:00:50 2023 +0200
Remove dependency on Sigar in favor of OSHI
patch by Claude Warren; reviewed by Stefan Miklosovic, Jacek Lewandowski,
Michael Semb Wever for CASSANDRA-16565
Co-authored-by: Stefan Miklosovic <[email protected]>
---
.build/build-resolver.xml | 47 +----
.build/cassandra-deps-template.xml | 4 +-
.build/parent-pom-template.xml | 18 +-
CHANGES.txt | 1 +
bin/cassandra.in.sh | 3 -
conf/cassandra-env.sh | 5 -
debian/cassandra.install | 1 -
ide/idea/workspace.xml | 3 -
ide/nbproject/project.xml | 3 +-
ide/nbproject/update-netbeans-classpaths.sh | 6 +-
redhat/cassandra.spec | 1 -
redhat/noboolean/cassandra.spec | 1 -
.../config/CassandraRelevantProperties.java | 2 -
.../apache/cassandra/service/StartupChecks.java | 16 +-
.../org/apache/cassandra/utils/FBUtilities.java | 52 +----
.../org/apache/cassandra/utils/SigarLibrary.java | 187 -----------------
.../org/apache/cassandra/utils/SystemInfo.java | 228 +++++++++++++++++++++
test/conf/logback-simulator.xml | 2 +-
.../distributed/test/ResourceLeakTest.java | 5 +-
.../cassandra/distributed/test/TestBaseImpl.java | 1 -
.../distributed/upgrade/UpgradeTestBase.java | 1 -
.../cassandra/simulator/SimulationRunner.java | 2 -
.../config/DatabaseDescriptorRefTest.java | 1 +
.../cassandra/service/StartupChecksTest.java | 14 +-
.../apache/cassandra/utils/FBUtilitiesTest.java | 16 --
.../org/apache/cassandra/utils/SystemInfoTest.java | 180 ++++++++++++++++
26 files changed, 461 insertions(+), 339 deletions(-)
diff --git a/.build/build-resolver.xml b/.build/build-resolver.xml
index fa5703a7cd..86d0091a24 100644
--- a/.build/build-resolver.xml
+++ b/.build/build-resolver.xml
@@ -204,8 +204,6 @@
<files dir="${build.lib}"
layout="{artifactId}-{version}-{classifier}.{extension}"
scopes="compile,!provide,!system"/>
</resolve>
</retry>
- <mkdir dir="${local.repository}/org/apache/cassandra/deps/sigar-bin"/>
- <mkdir dir="${build.lib}/sigar-bin"/>
<mkdir dir="${build.lib}/x86_64"/>
<mkdir dir="${build.lib}/aarch64"/> <!-- uname -m on arm prints
aarch64 instead of aarch_64 -->
@@ -237,28 +235,6 @@
<file
file="${local.repository}/org/apache/cassandra/deps/pure_sasl-0.6.2-py2-none-any.zip"/>
<file
file="${local.repository}/org/apache/cassandra/deps/wcwidth-0.2.5-py2.py3-none-any.zip"/>
</copy>
- <copy todir="${build.lib}/sigar-bin/" quiet="true">
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-amd64-freebsd-6.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-amd64-linux.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-amd64-solaris.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-ia64-hpux-11.sl"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-ia64-linux.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-pa-hpux-11.sl"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-ppc-aix-5.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-ppc-linux.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-ppc64-aix-5.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-ppc64-linux.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-ppc64le-linux.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-s390x-linux.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-sparc-solaris.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-sparc64-solaris.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-universal-macosx.dylib"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-universal64-macosx.dylib"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-x86-freebsd-5.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-x86-freebsd-6.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-x86-linux.so"/>
- <file
file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-x86-solaris.so"/>
- </copy>
<!-- as resolver will copy all dependencies into lib dir, and we are
copying jars to lib/{x86_64|aarch64} as well, we would have duplicities -->
<delete
file="${build.lib}/AmazonCorrettoCryptoProvider-2.2.0-linux-x86_64.jar"
failonerror="false"/>
@@ -269,6 +245,7 @@
</target>
<target name="_resolver-dist-lib_get_files">
+ <mkdir dir="${local.repository}/org/apache/cassandra/deps" />
<!-- files.pythonhosted.org/packages -->
<get
src="${artifact.python.pypi}/59/a0/cf4cd997e1750f0c2d91c6ea5abea218251c43c3581bcc2f118b00baf5cf/futures-2.1.6-py2.py3-none-any.whl"
dest="${local.repository}/org/apache/cassandra/deps/futures-2.1.6-py2.py3-none-any.zip"
usetimestamp="true" quiet="true" skipexisting="true"/>
<get
src="${artifact.python.pypi}/37/b2/ef1124540ee2c0b417be8d0f74667957e6aa084a3f26621aa67e2e77f3fb/pure_sasl-0.6.2-py2-none-any.whl"
dest="${local.repository}/org/apache/cassandra/deps/pure_sasl-0.6.2-py2-none-any.zip"
usetimestamp="true" quiet="true" skipexisting="true"/>
@@ -276,28 +253,6 @@
<!-- apache/cassandra/lib -->
<get src="${lib.download.base.url}/lib/geomet-0.1.0.zip"
dest="${local.repository}/org/apache/cassandra/deps/geomet-0.1.0.zip"
usetimestamp="true" quiet="true" skipexisting="true"/>
- <get dest="${local.repository}/org/apache/cassandra/deps/sigar-bin/"
quiet="true" usetimestamp="true" skipexisting="true">
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-amd64-freebsd-6.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-amd64-linux.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-amd64-solaris.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-ia64-hpux-11.sl"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-ia64-linux.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-pa-hpux-11.sl"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-ppc-aix-5.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-ppc-linux.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-ppc64-aix-5.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-ppc64-linux.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-ppc64le-linux.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-s390x-linux.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-sparc-solaris.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-sparc64-solaris.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-universal-macosx.dylib"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-universal64-macosx.dylib"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-x86-freebsd-5.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-x86-freebsd-6.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-x86-linux.so"/>
- <url
url="${lib.download.base.url}/lib/sigar-bin/libsigar-x86-solaris.so"/>
- </get>
</target>
</project>
diff --git a/.build/cassandra-deps-template.xml
b/.build/cassandra-deps-template.xml
index 47e8a6cda6..98cea9626f 100644
--- a/.build/cassandra-deps-template.xml
+++ b/.build/cassandra-deps-template.xml
@@ -244,8 +244,8 @@
<!-- end of chronicle-queue -->
<dependency>
- <groupId>org.fusesource</groupId>
- <artifactId>sigar</artifactId>
+ <groupId>com.github.oshi</groupId>
+ <artifactId>oshi-core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jdt</groupId>
diff --git a/.build/parent-pom-template.xml b/.build/parent-pom-template.xml
index 5440085c97..fd418a44f3 100644
--- a/.build/parent-pom-template.xml
+++ b/.build/parent-pom-template.xml
@@ -993,13 +993,21 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.fusesource</groupId>
- <artifactId>sigar</artifactId>
- <version>1.6.4</version>
+ <groupId>com.github.oshi</groupId>
+ <artifactId>oshi-core</artifactId>
+ <version>6.4.8</version>
<exclusions>
<exclusion>
- <artifactId>log4j</artifactId>
- <groupId>log4j</groupId>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-bom</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-parent</artifactId>
</exclusion>
</exclusions>
</dependency>
diff --git a/CHANGES.txt b/CHANGES.txt
index 728a5d4af2..108096a416 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
5.1
+ * Remove dependency on Sigar in favor of OSHI (CASSANDRA-16565)
* Simplify the bind marker and Term logic (CASSANDRA-18813)
* Limit cassandra startup to supported JDKs, allow higher JDKs by setting
CASSANDRA_JDK_UNSUPPORTED (CASSANDRA-18688)
* Standardize nodetool tablestats formatting of data units (CASSANDRA-19104)
diff --git a/bin/cassandra.in.sh b/bin/cassandra.in.sh
index 86a684b14a..881e425de1 100644
--- a/bin/cassandra.in.sh
+++ b/bin/cassandra.in.sh
@@ -81,9 +81,6 @@ fi
# set JVM javaagent opts to avoid warnings/errors
JAVA_AGENT="$JAVA_AGENT -javaagent:$CASSANDRA_HOME/lib/jamm-0.4.0.jar"
-# Added sigar-bin to the java.library.path CASSANDRA-7838
-JAVA_OPTS="$JAVA_OPTS:-Djava.library.path=$CASSANDRA_HOME/lib/sigar-bin"
-
platform=$(uname -m)
if [ -d "$CASSANDRA_HOME"/lib/"$platform" ]; then
for jar in "$CASSANDRA_HOME"/lib/"$platform"/*.jar ; do
diff --git a/conf/cassandra-env.sh b/conf/cassandra-env.sh
index cf6399560f..0b1dec45ed 100644
--- a/conf/cassandra-env.sh
+++ b/conf/cassandra-env.sh
@@ -271,11 +271,6 @@ JVM_OPTS="$JVM_OPTS
-Dcom.sun.management.jmxremote.password.file=/etc/cassandra/
#MX4J_ADDRESS="127.0.0.1"
#MX4J_PORT="8081"
-# Cassandra uses SIGAR to capture OS metrics CASSANDRA-7838
-# for SIGAR we have to set the java.library.path
-# to the location of the native libraries.
-JVM_OPTS="$JVM_OPTS -Djava.library.path=$CASSANDRA_HOME/lib/sigar-bin"
-
if [ "x$MX4J_ADDRESS" != "x" ]; then
if [[ "$MX4J_ADDRESS" == \-Dmx4jaddress* ]]; then
# Backward compatible with the older style #13578
diff --git a/debian/cassandra.install b/debian/cassandra.install
index 578fd93a61..7ee058bb59 100644
--- a/debian/cassandra.install
+++ b/debian/cassandra.install
@@ -30,6 +30,5 @@ tools/bin/hash_password usr/bin
tools/bin/sstablepartitions usr/bin
lib/*.jar usr/share/cassandra/lib
lib/*.zip usr/share/cassandra/lib
-lib/sigar-bin/* usr/share/cassandra/lib/sigar-bin
lib/x86_64/* usr/share/cassandra/lib/x86_64
lib/aarch64/* usr/share/cassandra/lib/aarch64
diff --git a/ide/idea/workspace.xml b/ide/idea/workspace.xml
index 89528b2408..c5c0e28b96 100644
--- a/ide/idea/workspace.xml
+++ b/ide/idea/workspace.xml
@@ -149,7 +149,6 @@
-Dcassandra.logdir=$PROJECT_DIR$/data/logs
-Dcassandra.reads.thresholds.coordinator.defensive_checks_enabled=true
-Dcassandra.storagedir=$PROJECT_DIR$/data
-
-Djava.library.path=$PROJECT_DIR$/lib/sigar-bin
-Dlogback.configurationFile=file://$PROJECT_DIR$/conf/logback.xml
-XX:HeapDumpPath=build/test
-ea" />
@@ -194,7 +193,6 @@
-Dcassandra.tolerate_sstable_size=true
-Dcassandra.use_nix_recursive_delete=true
-Dinvalid-legacy-sstable-root=$PROJECT_DIR$/test/data/invalid-legacy-sstables
-
-Djava.library.path=$PROJECT_DIR$/lib/sigar-bin
-Dlegacy-sstable-root=$PROJECT_DIR$/test/data/legacy-sstables
-Dlogback.configurationFile=file://$PROJECT_DIR$/test/conf/logback-test.xml
-Dmigration-sstable-root=$PROJECT_DIR$/test/data/migration-sstables
@@ -231,7 +229,6 @@
-Dcassandra.reads.thresholds.coordinator.defensive_checks_enabled=true
-Dcassandra.storagedir=$PROJECT_DIR$/data
-Dcassandra.triggers_dir=$PROJECT_DIR$/conf/triggers
-
-Djava.library.path=$PROJECT_DIR$/lib/sigar-bin
-Dlogback.configurationFile=file://$PROJECT_DIR$/conf/logback.xml
-XX:HeapDumpPath=build/test
-Xmx1G
diff --git a/ide/nbproject/project.xml b/ide/nbproject/project.xml
index ea9a486aa5..038b2b1cf9 100644
--- a/ide/nbproject/project.xml
+++ b/ide/nbproject/project.xml
@@ -7,7 +7,8 @@
<properties>
<property name="project.dir">..</property>
<!-- the compile classpaths should be distinct per compilation
unit… but it is kept simple and the build will catch errors -->
- <property
name="cassandra.classpath.jars">${project.dir}/build/lib/jars/AmazonCorrettoCryptoProvider-2.2.0-linux-x86_64.jar:${project.dir}/build/lib/jars/HdrHistogram-2.1.9.jar:${project.dir}/build/lib/jars/ST4-4.0.8.jar:${project.dir}/build/lib/jars/affinity-3.23.3.jar:${project.dir}/build/lib/jars/agrona-1.17.1.jar:${project.dir}/build/lib/jars/airline-0.8.jar:${project.dir}/build/lib/jars/antlr-3.5.2.jar:${project.dir}/build/lib/jars/antlr-runtime-3.5.2.jar:${project.d
[...]
+ <!-- DO NOT EDIT THE FOLLOWING LINE DIRECTLY: Use the
update-netbeans-classpath.sh script -->
+ <property
name="cassandra.classpath.jars">${project.dir}/build/lib/jars/affinity-3.23.3.jar:${project.dir}/build/lib/jars/agrona-1.17.1.jar:${project.dir}/build/lib/jars/airline-0.8.jar:${project.dir}/build/lib/jars/AmazonCorrettoCryptoProvider-2.2.0-linux-x86_64.jar:${project.dir}/build/lib/jars/antlr-3.5.2.jar:${project.dir}/build/lib/jars/antlr-runtime-3.5.2.jar:${project.dir}/build/lib/jars/asm-9.4.jar:${project.dir}/build/lib/jars/bcpkix-jdk15on-1.70.jar:${project.di
[...]
</properties>
<folders>
<source-folder>
diff --git a/ide/nbproject/update-netbeans-classpaths.sh
b/ide/nbproject/update-netbeans-classpaths.sh
index 219ee303e1..6822cf5516 100755
--- a/ide/nbproject/update-netbeans-classpaths.sh
+++ b/ide/nbproject/update-netbeans-classpaths.sh
@@ -27,5 +27,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1
&& pwd )"
cd $DIR/../..
CLASSPATH=`for f in build/lib/jars/*.jar ; do echo -n '${project.dir}/'$f: ;
done ; for f in build/test/lib/jars/*.jar ; do echo -n '${project.dir}/'$f: ;
done ;`
-sed -i ''
's/cassandra\.classpath\.jars\">.*<\/property>/cassandra\.classpath\.jars\">NEW_CLASSPATH<\/property>/'
$DIR/project.xml
-sed -i '' "s@NEW_CLASSPATH@"$CLASSPATH"@" $DIR/project.xml
+sed
's/cassandra\.classpath\.jars\">.*<\/property>/cassandra\.classpath\.jars\">NEW_CLASSPATH<\/property>/'
$DIR/project.xml > $DIR/project.xml.tmp
+mv $DIR/project.xml.tmp $DIR/project.xml
+sed "s@NEW_CLASSPATH@"$CLASSPATH"@" $DIR/project.xml > $DIR/project.xml.tmp
+mv $DIR/project.xml.tmp $DIR/project.xml
diff --git a/redhat/cassandra.spec b/redhat/cassandra.spec
index 923ed9fa80..f55899e13c 100644
--- a/redhat/cassandra.spec
+++ b/redhat/cassandra.spec
@@ -103,7 +103,6 @@ sed -i 's/^# hints_directory:/hints_directory:/'
conf/cassandra.yaml
rm -f bin/stop-server
rm -f bin/*.orig
rm -f bin/cassandra.in.sh
-rm -f lib/sigar-bin/*winnt* # strip segfaults on dll..
rm -f tools/bin/cassandra.in.sh
# copy default configs
diff --git a/redhat/noboolean/cassandra.spec b/redhat/noboolean/cassandra.spec
index c6b1a69888..e151f03878 100644
--- a/redhat/noboolean/cassandra.spec
+++ b/redhat/noboolean/cassandra.spec
@@ -103,7 +103,6 @@ sed -i 's/^# hints_directory:/hints_directory:/'
conf/cassandra.yaml
rm -f bin/stop-server
rm -f bin/*.orig
rm -f bin/cassandra.in.sh
-rm -f lib/sigar-bin/*winnt* # strip segfaults on dll..
rm -f tools/bin/cassandra.in.sh
# copy default configs
diff --git
a/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
b/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
index 5f9289e048..ed92ee6a41 100644
--- a/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
+++ b/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
@@ -567,7 +567,6 @@ public enum CassandraRelevantProperties
* can be also done manually for that particular case: {@code
flush(SchemaConstants.SCHEMA_KEYSPACE_NAME);}. */
TEST_FLUSH_LOCAL_SCHEMA_CHANGES("cassandra.test.flush_local_schema_changes",
"true"),
TEST_HARRY_SWITCH_AFTER("cassandra.test.harry.progression.switch-after",
"1"),
- TEST_IGNORE_SIGAR("cassandra.test.ignore_sigar"),
TEST_INVALID_LEGACY_SSTABLE_ROOT("invalid-legacy-sstable-root"),
TEST_JVM_DTEST_DISABLE_SSL("cassandra.test.disable_ssl"),
TEST_JVM_SHUTDOWN_MESSAGING_GRACEFULLY("cassandra.test.messagingService.gracefulShutdown",
"false"),
@@ -579,7 +578,6 @@ public enum CassandraRelevantProperties
TEST_REUSE_PREPARED("cassandra.test.reuse_prepared", "true"),
TEST_ROW_CACHE_SIZE("cassandra.test.row_cache_size"),
TEST_SERIALIZATION_WRITES("cassandra.test-serialization-writes"),
- TEST_SIGAR_NATIVE_LOGGING("sigar.nativeLogging", "true"),
TEST_SIMULATOR_DEBUG("cassandra.test.simulator.debug"),
TEST_SIMULATOR_DETERMINISM_CHECK("cassandra.test.simulator.determinismcheck",
"none"),
TEST_SIMULATOR_LIVENESS_CHECK("cassandra.test.simulator.livenesscheck",
"true"),
diff --git a/src/java/org/apache/cassandra/service/StartupChecks.java
b/src/java/org/apache/cassandra/service/StartupChecks.java
index ba83c5881b..5dc11a6c6b 100644
--- a/src/java/org/apache/cassandra/service/StartupChecks.java
+++ b/src/java/org/apache/cassandra/service/StartupChecks.java
@@ -73,7 +73,6 @@ import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.JavaUtils;
import org.apache.cassandra.utils.NativeLibrary;
-import org.apache.cassandra.utils.SigarLibrary;
import static
org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_LOCAL_PORT;
import static
org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_PORT;
@@ -89,7 +88,7 @@ import static
org.apache.cassandra.utils.Clock.Global.currentTimeMillis;
* Each individual test is modelled as an implementation of StartupCheck,
these are run
* at the start of CassandraDaemon#setup() before any local state is mutated.
The default
* checks are a mix of informational tests (inspectJvmOptions), initialization
- * (initSigarLibrary, checkCacheServiceInitialization) and invariant checking
+ * (checkProcessEnvironment, checkCacheServiceInitialization) and invariant
checking
* (checkValidLaunchDate, checkSystemKeyspaceState, checkSSTablesFormat).
*
* In addition, if checkSystemKeyspaceState determines that the release
version has
@@ -138,7 +137,7 @@ public class StartupChecks
checkJMXProperties,
inspectJvmOptions,
checkNativeLibraryInitialization,
-
initSigarLibrary,
+
checkProcessEnvironment,
checkMaxMapCount,
checkReadAheadKbSetting,
checkDataDirs,
@@ -417,14 +416,17 @@ public class StartupChecks
}
};
- public static final StartupCheck initSigarLibrary = new StartupCheck()
+ public static final StartupCheck checkProcessEnvironment = new
StartupCheck()
{
@Override
public void execute(StartupChecksOptions options)
{
- if (options.isDisabled(getStartupCheckType()))
- return;
- SigarLibrary.instance.warnIfRunningInDegradedMode();
+ Optional<String> degradations =
FBUtilities.getSystemInfo().isDegraded();
+
+ if (degradations.isPresent())
+ logger.warn("Cassandra server running in degraded mode. " +
degradations.get());
+ else
+ logger.info("Checked OS settings and found them configured for
optimal performance.");
}
};
diff --git a/src/java/org/apache/cassandra/utils/FBUtilities.java
b/src/java/org/apache/cassandra/utils/FBUtilities.java
index 2a02933e0f..d3728f95d8 100644
--- a/src/java/org/apache/cassandra/utils/FBUtilities.java
+++ b/src/java/org/apache/cassandra/utils/FBUtilities.java
@@ -47,7 +47,6 @@ import java.util.Map;
import java.util.NavigableSet;
import java.util.Optional;
import java.util.Properties;
-import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@@ -138,7 +137,7 @@ public class FBUtilities
private static int availableProcessors =
CASSANDRA_AVAILABLE_PROCESSORS.getInt(DatabaseDescriptor.getAvailableProcessors());
- private static volatile Supplier<Semver> kernelVersionSupplier =
Suppliers.memoize(FBUtilities::getKernelVersionFromUname);
+ private static volatile Supplier<SystemInfo> systemInfoSupplier =
Suppliers.memoize(SystemInfo::new);
public static void setAvailableProcessors(int value)
{
@@ -146,9 +145,9 @@ public class FBUtilities
}
@VisibleForTesting
- public static void setKernelVersionSupplier(Supplier<Semver> supplier)
+ public static void setSystemInfoSupplier(Supplier<SystemInfo> supplier)
{
- kernelVersionSupplier = supplier;
+ systemInfoSupplier = supplier;
}
public static int getAvailableProcessors()
@@ -1449,50 +1448,11 @@ public class FBUtilities
public static Semver getKernelVersion()
{
- return kernelVersionSupplier.get();
+ return systemInfoSupplier.get().getKernelVersion();
}
- @VisibleForTesting
- static Semver getKernelVersionFromUname()
- {
- // TODO rewrite this method with Oshi when it is eventually included
in the project
- if (!isLinux)
- return null;
-
- try
- {
- String output = exec(Map.of(), Duration.ofSeconds(5), 1024, 1024,
"uname", "-r");
-
- if (output.isEmpty())
- throw new RuntimeException("Error while trying to get kernel
version, 'uname -r' returned empty output");
-
- return parseKernelVersion(output);
- }
- catch (IOException | TimeoutException e)
- {
- throw new RuntimeException("Error while trying to get kernel
version", e);
- }
- catch (InterruptedException e)
- {
- Thread.currentThread().interrupt();
- throw new RuntimeException(e);
- }
- }
-
- @VisibleForTesting
- static Semver parseKernelVersion(String versionString)
+ public static SystemInfo getSystemInfo()
{
- Preconditions.checkNotNull(versionString, "kernel version cannot be
null");
- try (Scanner scanner = new Scanner(versionString))
- {
- while (scanner.hasNextLine())
- {
- String version = scanner.nextLine().trim();
- if (version.isEmpty())
- continue;
- return new Semver(version, Semver.SemverType.LOOSE);
- }
- }
- throw new IllegalArgumentException("Error while trying to parse kernel
version - no version found");
+ return systemInfoSupplier.get();
}
}
\ No newline at end of file
diff --git a/src/java/org/apache/cassandra/utils/SigarLibrary.java
b/src/java/org/apache/cassandra/utils/SigarLibrary.java
deleted file mode 100644
index 830f7cab8e..0000000000
--- a/src/java/org/apache/cassandra/utils/SigarLibrary.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.utils;
-
-import org.hyperic.sigar.*;
-import org.slf4j.LoggerFactory;
-import org.slf4j.Logger;
-
-import org.apache.cassandra.config.CassandraRelevantProperties;
-
-@Shared
-public class SigarLibrary
-{
- private Logger logger = LoggerFactory.getLogger(SigarLibrary.class);
-
- public static final SigarLibrary instance = new SigarLibrary();
-
- private Sigar sigar;
- private FileSystemMap mounts = null;
- private boolean initialized = false;
- private long INFINITY = -1;
- private long EXPECTED_MIN_NOFILE = 10000l; // number of files that can be
opened
- private long EXPECTED_NPROC = 32768l; // number of processes
- private long EXPECTED_AS = INFINITY; // address space
-
- // TODO: Determine memlock limits if possible
- // TODO: Determine if file system is remote or local
- // TODO: Determine if disk latency is within acceptable limits
-
- private SigarLibrary()
- {
- logger.info("Initializing SIGAR library");
- try
- {
- sigar = new Sigar();
- mounts = sigar.getFileSystemMap();
- initialized = true;
- }
- catch (SigarException e)
- {
- logger.info("Could not initialize SIGAR library {} ",
e.getMessage());
- }
- catch (UnsatisfiedLinkError linkError)
- {
- logger.info("Could not initialize SIGAR library {} ",
linkError.getMessage());
- }
- }
-
- /**
- *
- * @return true or false indicating if sigar was successfully initialized
- */
- public boolean initialized()
- {
- return initialized;
- }
-
- private boolean hasAcceptableProcNumber()
- {
- try
- {
- long fileMax = sigar.getResourceLimit().getProcessesMax();
- if (fileMax >= EXPECTED_NPROC || fileMax == INFINITY)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- catch (SigarException sigarException)
- {
- logger.warn("Could not determine if max processes was acceptable.
Error message: {}", sigarException);
- return false;
- }
- }
-
- private boolean hasAcceptableFileLimits()
- {
- try
- {
- long fileMax = sigar.getResourceLimit().getOpenFilesMax();
- if (fileMax >= EXPECTED_MIN_NOFILE || fileMax == INFINITY)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- catch (SigarException sigarException)
- {
- logger.warn("Could not determine if max open file handle limit is
correctly configured. Error message: {}", sigarException);
- return false;
- }
- }
-
- private boolean hasAcceptableAddressSpace()
- {
- try
- {
- long fileMax = sigar.getResourceLimit().getVirtualMemoryMax();
- if (fileMax == EXPECTED_AS)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- catch (SigarException sigarException)
- {
- logger.warn("Could not determine if VirtualMemoryMax was
acceptable. Error message: {}", sigarException);
- return false;
- }
- }
-
- private boolean isSwapEnabled()
- {
- try
- {
- Swap swap = sigar.getSwap();
- long swapSize = swap.getTotal();
- if (swapSize > 0)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- catch (SigarException sigarException)
- {
- logger.warn("Could not determine if swap configuration is
acceptable. Error message: {}", sigarException);
- return false;
- }
- }
-
- public long getPid()
- {
- return initialized ? sigar.getPid() : -1;
- }
-
- public void warnIfRunningInDegradedMode()
- {
- if (initialized)
- {
- boolean swapEnabled = isSwapEnabled();
- boolean goodAddressSpace = hasAcceptableAddressSpace();
- boolean goodFileLimits = hasAcceptableFileLimits();
- boolean goodProcNumber = hasAcceptableProcNumber();
- if (swapEnabled || !goodAddressSpace || !goodFileLimits ||
!goodProcNumber || CassandraRelevantProperties.TEST_IGNORE_SIGAR.getBoolean())
- {
- logger.warn("Cassandra server running in degraded mode. Is
swap disabled? : {}, Address space adequate? : {}, " +
- " nofile limit adequate? : {}, nproc limit
adequate? : {} ", !swapEnabled, goodAddressSpace,
- goodFileLimits, goodProcNumber );
- }
- else
- {
- logger.info("Checked OS settings and found them configured for
optimal performance.");
- }
- }
- else
- {
- logger.info("Sigar could not be initialized, test for checking
degraded mode omitted.");
- }
- }
-}
diff --git a/src/java/org/apache/cassandra/utils/SystemInfo.java
b/src/java/org/apache/cassandra/utils/SystemInfo.java
new file mode 100644
index 0000000000..ec793a692b
--- /dev/null
+++ b/src/java/org/apache/cassandra/utils/SystemInfo.java
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.utils;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Supplier;
+import java.util.regex.Pattern;
+
+import com.vdurmont.semver4j.Semver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.cassandra.io.util.File;
+import org.apache.cassandra.io.util.FileUtils;
+import oshi.PlatformEnum;
+
+import static java.lang.String.format;
+import static java.util.Optional.empty;
+import static java.util.Optional.of;
+
+/**
+ * An abstraction of System information, this class provides access to system
information without specifying how
+ * it is retrieved.
+ */
+public class SystemInfo
+{
+ // TODO: Determine memlock limits if possible
+ // TODO: Determine if file system is remote or local
+ // TODO: Determine if disk latency is within acceptable limits
+
+ private static final Logger logger =
LoggerFactory.getLogger(SystemInfo.class);
+
+ private static final long INFINITY = -1L;
+ static final long EXPECTED_MIN_NUMBER_OF_OPENED_FILES = 10000L; // number
of files that can be opened
+ static final long EXPECTED_MIN_NUMBER_OF_PROCESSES = 32768L; // number of
processes
+ static final long EXPECTED_ADDRESS_SPACE = 0x7FFFFFFFL; // address space
+
+ static final String OPEN_FILES_VIOLATION_MESSAGE = format("Minimum value
for max open files should be >= %s. ", EXPECTED_MIN_NUMBER_OF_OPENED_FILES);
+ static final String NUMBER_OF_PROCESSES_VIOLATION_MESSAGE = format("Number
of processes should be >= %s. ", EXPECTED_MIN_NUMBER_OF_PROCESSES);
+ static final String ADDRESS_SPACE_VIOLATION_MESSAGE = format("Amount of
available address space should be >= %s. ", EXPECTED_ADDRESS_SPACE);
+ static final String SWAP_VIOLATION_MESSAGE = "Swap should be disabled. ";
+
+ /**
+ * The default number of processes that are reported if the actual value
can not be retrieved.
+ */
+ private static final long DEFAULT_MAX_PROCESSES = 1024;
+
+ private static final Pattern SPACES_PATTERN = Pattern.compile("\\s+");
+
+ /**
+ * The oshi.SystemInfo has the following note:
+ * Platform-specific Hardware and Software objects are retrieved via
memoized suppliers. To conserve memory at the
+ * cost of additional processing time, create a new version of
SystemInfo() for subsequent calls. To conserve
+ * processing time at the cost of additional memory usage, re-use the same
{@link SystemInfo} object for future
+ * queries.
+ * <p>
+ * We are opting for minimal memory footprint.
+ */
+ private final oshi.SystemInfo si;
+
+ public SystemInfo()
+ {
+ si = new oshi.SystemInfo();
+ }
+
+ /**
+ * @return The PlatformEnum for the current platform. (e.g. Linux,
Windows, AIX, etc.)
+ */
+ public PlatformEnum platform()
+ {
+ return oshi.SystemInfo.getCurrentPlatform();
+ }
+
+ /**
+ * Gets the maximum number of processes the user can create.
+ * Note: if not on a Linux system this always return the
+ *
+ * @return The maximum number of processes.
+ * @see #DEFAULT_MAX_PROCESSES
+ */
+ public long getMaxProcess()
+ {
+ // this check only works on Linux systems. Errors fall through to
return default.
+ if (platform() == PlatformEnum.LINUX)
+ {
+ String path = format("/proc/%s/limits", getPid());
+ try
+ {
+ List<String> lines = FileUtils.readLines(new File(path));
+ for (String line : lines)
+ {
+ if (line.startsWith("Max processes"))
+ {
+ String[] parts = SPACES_PATTERN.split(line);
+
+ if (parts.length < 3)
+ continue;
+
+ String limit = parts[2];
+ return "unlimited".equals(limit) ? INFINITY :
Long.parseLong(limit);
+ }
+ }
+ logger.error("'Max processes' not found in {}", path);
+ }
+ catch (Exception t)
+ {
+ logger.error(format("Unable to read %s", path), t);
+ }
+ }
+
+ /* return the default value for non-Linux systems or parsing error.
+ * Can not return 0 as we know there is at least 1 process (this one)
and
+ * -1 historically represents infinity.
+ */
+ return DEFAULT_MAX_PROCESSES;
+ }
+
+ /**
+ * @return The maximum number of open files allowd to the current
process/user.
+ */
+ public long getMaxOpenFiles()
+ {
+ // ulimit -H -n
+ return
si.getOperatingSystem().getCurrentProcess().getHardOpenFileLimit();
+ }
+
+ /**
+ * Gets the Virtual Memory Size (VSZ). Includes all memory that the
process can access,
+ * including memory that is swapped out and memory that is from shared
libraries.
+ *
+ * @return The amount of virtual memory allowed to be allocatedby the
current process/user.
+ */
+ public long getVirtualMemoryMax()
+ {
+ return si.getOperatingSystem().getCurrentProcess().getVirtualSize();
+ }
+
+ /**
+ * @return The amount of swap space allocated on the system.
+ */
+ public long getSwapSize()
+ {
+ return si.getHardware().getMemory().getVirtualMemory().getSwapTotal();
+ }
+
+ /**
+ * @return the PID of the current system.
+ */
+ public long getPid()
+ {
+ return si.getOperatingSystem().getProcessId();
+ }
+
+ /**
+ * @return the Semver for the kernel version of the OS.
+ */
+ public Semver getKernelVersion()
+ {
+ return new
Semver(si.getOperatingSystem().getVersionInfo().getBuildNumber(),
Semver.SemverType.LOOSE);
+ }
+
+ /**
+ * Tests if the system is running in degraded mode.
+ *
+ * @return non-empty optional with degradation messages if the system is
in degraded mode, empty optional otherwise.
+ */
+ public Optional<String> isDegraded()
+ {
+ Supplier<String> expectedNumProc = () -> {
+ // only check proc on nproc linux
+ if (platform() == PlatformEnum.LINUX)
+ return invalid(getMaxProcess(),
EXPECTED_MIN_NUMBER_OF_PROCESSES) ? NUMBER_OF_PROCESSES_VIOLATION_MESSAGE
+
: null;
+ else
+ return format("System is running %s, Linux OS is recommended.
", platform());
+ };
+
+ Supplier<String> swapShouldBeDisabled = () -> (getSwapSize() > 0) ?
SWAP_VIOLATION_MESSAGE : null;
+
+ Supplier<String> expectedAddressSpace = () ->
invalid(getVirtualMemoryMax(), EXPECTED_ADDRESS_SPACE)
+ ?
ADDRESS_SPACE_VIOLATION_MESSAGE
+ : null;
+
+ Supplier<String> expectedMinNoFile = () -> invalid(getMaxOpenFiles(),
EXPECTED_MIN_NUMBER_OF_OPENED_FILES)
+ ?
OPEN_FILES_VIOLATION_MESSAGE
+ : null;
+
+ StringBuilder sb = new StringBuilder();
+
+ for (Supplier<String> check : List.of(expectedNumProc,
swapShouldBeDisabled, expectedAddressSpace, expectedMinNoFile))
+ Optional.ofNullable(check.get()).map(sb::append);
+
+ String message = sb.toString();
+ return message.isEmpty() ? empty() : of(message);
+ }
+
+ /**
+ * Checks if a value is invalid.
+ * <p>
+ * Value is invalid if it is smaller than {@code min} and it is not {@code
INFINITY},
+ * here represented as a value of -1;
+ *
+ * @param value the value to check
+ * @param min the minimum value
+ * @return true if value is valid
+ */
+ private boolean invalid(long value, long min)
+ {
+ return value < min && value != INFINITY;
+ }
+}
diff --git a/test/conf/logback-simulator.xml b/test/conf/logback-simulator.xml
index 3a9fabc380..d0082d43fa 100644
--- a/test/conf/logback-simulator.xml
+++ b/test/conf/logback-simulator.xml
@@ -43,7 +43,7 @@
<logger name="org.apache.cassandra.net.Message" level="ERROR"/>
<logger name="org.reflections.Reflections" level="ERROR"/>
<logger name="org.apache.hadoop" level="WARN"/>
- <logger name="org.apache.cassandra.utils.SigarLibrary" level="ERROR"/>
+ <logger name="org.apache.cassandra.utils.SystemInfo" level="ERROR"/>
<logger name="org.apache.cassandra.utils.FBUtilities" level="ERROR"/>
<logger name="org.apache.cassandra.config.DatabaseDescriptor" level="ERROR"/>
<logger name="org.apache.cassandra.service.StartupChecks" level="ERROR"/>
diff --git
a/test/distributed/org/apache/cassandra/distributed/test/ResourceLeakTest.java
b/test/distributed/org/apache/cassandra/distributed/test/ResourceLeakTest.java
index b90b895662..736112c6d4 100644
---
a/test/distributed/org/apache/cassandra/distributed/test/ResourceLeakTest.java
+++
b/test/distributed/org/apache/cassandra/distributed/test/ResourceLeakTest.java
@@ -41,7 +41,7 @@ import org.apache.cassandra.distributed.api.IInstanceConfig;
import org.apache.cassandra.distributed.api.IInvokableInstance;
import org.apache.cassandra.distributed.shared.JMXUtil;
import org.apache.cassandra.io.util.File;
-import org.apache.cassandra.utils.SigarLibrary;
+import org.apache.cassandra.utils.FBUtilities;
import static org.apache.cassandra.distributed.api.Feature.GOSSIP;
import static org.apache.cassandra.distributed.api.Feature.JMX;
@@ -91,8 +91,7 @@ public class ResourceLeakTest extends TestBaseImpl
*/
private static Long getProcessId()
{
- // Once Java 9 is ready the process API should provide a better way to
get the process ID.
- long pid = SigarLibrary.instance.getPid();
+ long pid = FBUtilities.getSystemInfo().getPid();
if (pid >= 0)
return Long.valueOf(pid);
diff --git
a/test/distributed/org/apache/cassandra/distributed/test/TestBaseImpl.java
b/test/distributed/org/apache/cassandra/distributed/test/TestBaseImpl.java
index 6bd41a7e1b..72ba9d4f04 100644
--- a/test/distributed/org/apache/cassandra/distributed/test/TestBaseImpl.java
+++ b/test/distributed/org/apache/cassandra/distributed/test/TestBaseImpl.java
@@ -81,7 +81,6 @@ public class TestBaseImpl extends DistributedTestBase
{
ICluster.setup();
SKIP_GC_INSPECTOR.setBoolean(true);
- System.setProperty("sigar.nativeLogging", "false");
}
@Override
diff --git
a/test/distributed/org/apache/cassandra/distributed/upgrade/UpgradeTestBase.java
b/test/distributed/org/apache/cassandra/distributed/upgrade/UpgradeTestBase.java
index 4b2d0ae374..017c1c5a44 100644
---
a/test/distributed/org/apache/cassandra/distributed/upgrade/UpgradeTestBase.java
+++
b/test/distributed/org/apache/cassandra/distributed/upgrade/UpgradeTestBase.java
@@ -71,7 +71,6 @@ public class UpgradeTestBase extends DistributedTestBase
{
ICluster.setup();
SKIP_GC_INSPECTOR.setBoolean(true);
- System.setProperty("sigar.nativeLogging", "false");
}
diff --git
a/test/simulator/main/org/apache/cassandra/simulator/SimulationRunner.java
b/test/simulator/main/org/apache/cassandra/simulator/SimulationRunner.java
index 71acd6d95d..026078c9b8 100644
--- a/test/simulator/main/org/apache/cassandra/simulator/SimulationRunner.java
+++ b/test/simulator/main/org/apache/cassandra/simulator/SimulationRunner.java
@@ -74,7 +74,6 @@ import static
org.apache.cassandra.config.CassandraRelevantProperties.PAXOS_REPA
import static
org.apache.cassandra.config.CassandraRelevantProperties.RING_DELAY;
import static
org.apache.cassandra.config.CassandraRelevantProperties.SHUTDOWN_ANNOUNCE_DELAY_IN_MS;
import static
org.apache.cassandra.config.CassandraRelevantProperties.SYSTEM_AUTH_DEFAULT_RF;
-import static
org.apache.cassandra.config.CassandraRelevantProperties.TEST_IGNORE_SIGAR;
import static
org.apache.cassandra.config.CassandraRelevantProperties.DISABLE_GOSSIP_ENDPOINT_REMOVAL;
import static
org.apache.cassandra.config.CassandraRelevantProperties.TEST_JVM_DTEST_DISABLE_SSL;
import static org.apache.cassandra.simulator.debug.Reconcile.reconcileWith;
@@ -121,7 +120,6 @@ public class SimulationRunner
DISABLE_SSTABLE_ACTIVITY_TRACKING.setBoolean(false);
DETERMINISM_SSTABLE_COMPRESSION_DEFAULT.setBoolean(false); //
compression causes variation in file size for e.g. UUIDs, IP addresses, random
file paths
CONSISTENT_DIRECTORY_LISTINGS.setBoolean(true);
- TEST_IGNORE_SIGAR.setBoolean(true);
SYSTEM_AUTH_DEFAULT_RF.setInt(3);
DISABLE_GOSSIP_ENDPOINT_REMOVAL.setBoolean(true);
MEMTABLE_OVERHEAD_SIZE.setInt(100);
diff --git
a/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java
b/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java
index b4da790360..8df889a5bd 100644
--- a/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java
+++ b/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java
@@ -276,6 +276,7 @@ public class DatabaseDescriptorRefTest
"org.apache.cassandra.utils.CloseableIterator",
"org.apache.cassandra.utils.FBUtilities",
"org.apache.cassandra.utils.FBUtilities$1",
+ "org.apache.cassandra.utils.SystemInfo",
"org.apache.cassandra.utils.Pair",
"org.apache.cassandra.utils.binlog.BinLogOptions",
"org.apache.cassandra.utils.concurrent.RefCounted",
diff --git a/test/unit/org/apache/cassandra/service/StartupChecksTest.java
b/test/unit/org/apache/cassandra/service/StartupChecksTest.java
index 6916f35424..d5ed25a89f 100644
--- a/test/unit/org/apache/cassandra/service/StartupChecksTest.java
+++ b/test/unit/org/apache/cassandra/service/StartupChecksTest.java
@@ -57,6 +57,7 @@ import org.apache.cassandra.schema.SchemaConstants;
import org.apache.cassandra.service.DataResurrectionCheck.Heartbeat;
import org.apache.cassandra.utils.Clock;
import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.SystemInfo;
import static java.util.Collections.singletonList;
import static
org.apache.cassandra.config.CassandraRelevantProperties.TEST_INVALID_LEGACY_SSTABLE_ROOT;
@@ -312,14 +313,21 @@ public class StartupChecksTest
String savedCommitLogLocation =
DatabaseDescriptor.getCommitLogLocation();
DiskAccessMode savedCommitLogWriteDiskAccessMode =
DatabaseDescriptor.getCommitLogWriteDiskAccessMode();
- Semver savedKernelVersion = FBUtilities.getKernelVersion();
+ SystemInfo savedSystemInfo = FBUtilities.getSystemInfo();
try
{
DatabaseDescriptor.setCommitLogLocation(commitLogLocation);
DatabaseDescriptor.setCommitLogWriteDiskAccessMode(diskAccessMode);
DatabaseDescriptor.initializeCommitLogDiskAccessMode();
assertThat(DatabaseDescriptor.getCommitLogWriteDiskAccessMode()).isEqualTo(diskAccessMode);
- FBUtilities.setKernelVersionSupplier(() -> kernelVersion);
+ FBUtilities.setSystemInfoSupplier(() -> new SystemInfo()
+ {
+ @Override
+ public Semver getKernelVersion()
+ {
+ return kernelVersion;
+ }
+ });
withPathOverriddingFileSystem(Map.of(commitLogLocation, fsType),
() -> {
if (expectToFail)
assertThatExceptionOfType(StartupException.class).isThrownBy(() ->
StartupChecks.checkKernelBug1057843.execute(options));
@@ -333,7 +341,7 @@ public class StartupChecksTest
DatabaseDescriptor.setCommitLogLocation(savedCommitLogLocation);
DatabaseDescriptor.setCommitLogWriteDiskAccessMode(savedCommitLogWriteDiskAccessMode);
DatabaseDescriptor.initializeCommitLogDiskAccessMode();
- FBUtilities.setKernelVersionSupplier(() -> savedKernelVersion);
+ FBUtilities.setSystemInfoSupplier(() -> savedSystemInfo);
}
}
diff --git a/test/unit/org/apache/cassandra/utils/FBUtilitiesTest.java
b/test/unit/org/apache/cassandra/utils/FBUtilitiesTest.java
index 28059f5784..17b59400e7 100644
--- a/test/unit/org/apache/cassandra/utils/FBUtilitiesTest.java
+++ b/test/unit/org/apache/cassandra/utils/FBUtilitiesTest.java
@@ -59,9 +59,7 @@ import org.apache.cassandra.dht.Murmur3Partitioner;
import org.apache.cassandra.dht.OrderPreservingPartitioner;
import org.apache.cassandra.dht.RandomPartitioner;
-import static org.apache.cassandra.utils.FBUtilities.parseKernelVersion;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
@@ -409,20 +407,6 @@ public class FBUtilitiesTest
Assert.assertEquals("Infinity",
FBUtilities.prettyPrintAverage(Double.POSITIVE_INFINITY));
}
- @Test
- public void testParseKernelVersion()
- {
-
assertThat(parseKernelVersion("4.4.0-21-generic").toString()).isEqualTo("4.4.0-21-generic");
-
assertThat(parseKernelVersion("4.4.0-pre21-generic").toString()).isEqualTo("4.4.0-pre21-generic");
-
assertThat(parseKernelVersion("4.4-pre21-generic").toString()).isEqualTo("4.4-pre21-generic");
-
assertThat(parseKernelVersion("4.4.0-21-generic\n").toString()).isEqualTo("4.4.0-21-generic");
-
assertThat(parseKernelVersion("\n4.4.0-21-generic\n").toString()).isEqualTo("4.4.0-21-generic");
- assertThat(parseKernelVersion("\n 4.4.0-21-generic
\n").toString()).isEqualTo("4.4.0-21-generic");
-
-
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
parseKernelVersion("\n \n"))
-
.withMessageContaining("no version found");
- }
-
@Test
public void testGetKernelVersion()
{
diff --git a/test/unit/org/apache/cassandra/utils/SystemInfoTest.java
b/test/unit/org/apache/cassandra/utils/SystemInfoTest.java
new file mode 100644
index 0000000000..61fec64818
--- /dev/null
+++ b/test/unit/org/apache/cassandra/utils/SystemInfoTest.java
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.utils;
+
+import java.util.Optional;
+
+import org.junit.Assume;
+import org.junit.Test;
+
+import com.vdurmont.semver4j.Semver;
+import oshi.PlatformEnum;
+
+import static
org.apache.cassandra.utils.SystemInfo.ADDRESS_SPACE_VIOLATION_MESSAGE;
+import static
org.apache.cassandra.utils.SystemInfo.NUMBER_OF_PROCESSES_VIOLATION_MESSAGE;
+import static
org.apache.cassandra.utils.SystemInfo.OPEN_FILES_VIOLATION_MESSAGE;
+import static org.apache.cassandra.utils.SystemInfo.SWAP_VIOLATION_MESSAGE;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class SystemInfoTest
+{
+ private static class TestSystemInfo extends SystemInfo
+ {
+ @Override
+ public PlatformEnum platform()
+ {
+ return PlatformEnum.LINUX;
+ }
+
+ @Override
+ public long getMaxProcess()
+ {
+ return EXPECTED_MIN_NUMBER_OF_PROCESSES;
+ }
+
+ @Override
+ public long getMaxOpenFiles()
+ {
+ return EXPECTED_MIN_NUMBER_OF_OPENED_FILES;
+ }
+
+ @Override
+ public long getVirtualMemoryMax()
+ {
+ return EXPECTED_ADDRESS_SPACE;
+ }
+
+ @Override
+ public long getSwapSize()
+ {
+ return 0;
+ }
+ }
+
+ @Test
+ public void testSystemInfo()
+ {
+ SystemInfo oldSystemInfo = FBUtilities.getSystemInfo();
+
+ try
+ {
+ // valid testing system info does not violate anything
+ TestSystemInfo testSystemInfo = new TestSystemInfo();
+ assertFalse(testSystemInfo.isDegraded().isPresent());
+
+ // platform
+
+ assertDegradation(new TestSystemInfo()
+ {
+ @Override
+ public PlatformEnum platform()
+ {
+ return PlatformEnum.FREEBSD;
+ }
+ }, "System is running FREEBSD, Linux OS is recommended. ");
+
+ // swap
+
+
+ assertDegradation(new TestSystemInfo()
+ {
+ @Override
+ public long getSwapSize()
+ {
+ return 100;
+ }
+ }, SWAP_VIOLATION_MESSAGE);
+
+ // address space
+
+ assertDegradation(new TestSystemInfo()
+ {
+ @Override
+ public long getVirtualMemoryMax()
+ {
+ return 1234;
+ }
+ }, ADDRESS_SPACE_VIOLATION_MESSAGE);
+
+ // expected minimal number of opened files
+
+ assertDegradation(new TestSystemInfo()
+ {
+ @Override
+ public long getMaxOpenFiles()
+ {
+ return 10;
+ }
+ }, OPEN_FILES_VIOLATION_MESSAGE);
+
+ // expected number of processes
+
+ assertDegradation(new TestSystemInfo()
+ {
+ @Override
+ public long getMaxProcess()
+ {
+ return 5;
+ }
+ }, NUMBER_OF_PROCESSES_VIOLATION_MESSAGE);
+
+ // test multiple violations
+
+ assertDegradation(new TestSystemInfo()
+ {
+ @Override
+ public PlatformEnum platform()
+ {
+ return PlatformEnum.FREEBSD;
+ }
+
+ @Override
+ public long getSwapSize()
+ {
+ return 10;
+ }
+ }, "System is running FREEBSD, Linux OS is recommended. " +
SWAP_VIOLATION_MESSAGE);
+ }
+ finally
+ {
+ FBUtilities.setSystemInfoSupplier(() -> oldSystemInfo);
+ }
+ }
+
+ @Test
+ public void testGetKernelVersion()
+ {
+ Assume.assumeTrue(FBUtilities.isLinux);
+ Semver kernelVersion = FBUtilities.getSystemInfo().getKernelVersion();
+ assertThat(kernelVersion).isGreaterThan(new Semver("0.0.0",
Semver.SemverType.LOOSE))
+ .isLessThan(new Semver("100.0.0",
Semver.SemverType.LOOSE));
+ }
+
+ private void assertDegradation(final SystemInfo systemInfo, String
expectedDegradation)
+ {
+ FBUtilities.setSystemInfoSupplier(() -> systemInfo);
+ Optional<String> degradations =
FBUtilities.getSystemInfo().isDegraded();
+
+ assertTrue(degradations.isPresent());
+ assertEquals(expectedDegradation, degradations.get());
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]