mirror of https://github.com/apache/cassandra
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 <smiklosovic@apache.org>
This commit is contained in:
parent
34fa4e279a
commit
5d46ff2796
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
public static SystemInfo getSystemInfo()
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -81,7 +81,6 @@ public class TestBaseImpl extends DistributedTestBase
|
|||
{
|
||||
ICluster.setup();
|
||||
SKIP_GC_INSPECTOR.setBoolean(true);
|
||||
System.setProperty("sigar.nativeLogging", "false");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@ public class UpgradeTestBase extends DistributedTestBase
|
|||
{
|
||||
ICluster.setup();
|
||||
SKIP_GC_INSPECTOR.setBoolean(true);
|
||||
System.setProperty("sigar.nativeLogging", "false");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue