diff --git a/CHANGES.txt b/CHANGES.txt index 7ec782c405..aec83707d7 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -65,6 +65,7 @@ * NoReplicationTokenAllocator should work with zero replication factor (CASSANDRA-12983) * Address message coalescing regression (CASSANDRA-12676) Merged from 3.0: + * Use the Kernel32 library to retrieve the PID on Windows and fix startup checks (CASSANDRA-13333) * Fix code to not exchange schema across major versions (CASSANDRA-13274) * Dropping column results in "corrupt" SSTable (CASSANDRA-13337) * Bugs handling range tombstones in the sstable iterators (CASSANDRA-13340) diff --git a/NEWS.txt b/NEWS.txt index 9048121ba1..29e7a5b886 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -54,6 +54,9 @@ Upgrading Upgrading --------- + - The NativeAccessMBean isAvailable method will only return true if the + native library has been successfully linked. Previously it was returning + true if JNA could be found but was not taking into account link failures. - Primary ranges in the system.size_estimates table are now based on the keyspace replication settings and adjacent ranges are no longer merged (CASSANDRA-9639). - In 2.1, the default for otc_coalescing_strategy was 'DISABLED'. diff --git a/src/java/org/apache/cassandra/db/commitlog/CommitLogSegment.java b/src/java/org/apache/cassandra/db/commitlog/CommitLogSegment.java index 0716d47252..5edf72bd4c 100644 --- a/src/java/org/apache/cassandra/db/commitlog/CommitLogSegment.java +++ b/src/java/org/apache/cassandra/db/commitlog/CommitLogSegment.java @@ -40,7 +40,7 @@ import org.apache.cassandra.io.util.FileUtils; import org.apache.cassandra.schema.Schema; import org.apache.cassandra.schema.TableId; import org.apache.cassandra.schema.TableMetadata; -import org.apache.cassandra.utils.CLibrary; +import org.apache.cassandra.utils.NativeLibrary; import org.apache.cassandra.utils.IntegerInterval; import org.apache.cassandra.utils.concurrent.OpOrder; import org.apache.cassandra.utils.concurrent.WaitQueue; @@ -164,7 +164,7 @@ public abstract class CommitLogSegment try { channel = FileChannel.open(logFile.toPath(), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE); - fd = CLibrary.getfd(channel); + fd = NativeLibrary.getfd(channel); } catch (IOException e) { diff --git a/src/java/org/apache/cassandra/db/commitlog/MemoryMappedSegment.java b/src/java/org/apache/cassandra/db/commitlog/MemoryMappedSegment.java index 9b466752d2..250b3e4884 100644 --- a/src/java/org/apache/cassandra/db/commitlog/MemoryMappedSegment.java +++ b/src/java/org/apache/cassandra/db/commitlog/MemoryMappedSegment.java @@ -25,7 +25,7 @@ import java.nio.channels.FileChannel; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.io.FSWriteError; import org.apache.cassandra.io.util.FileUtils; -import org.apache.cassandra.utils.CLibrary; +import org.apache.cassandra.utils.NativeLibrary; import org.apache.cassandra.utils.SyncUtil; /* @@ -86,7 +86,7 @@ public class MemoryMappedSegment extends CommitLogSegment { throw new FSWriteError(e, getPath()); } - CLibrary.trySkipCache(fd, startMarker, nextMarker, logFile.getAbsolutePath()); + NativeLibrary.trySkipCache(fd, startMarker, nextMarker, logFile.getAbsolutePath()); } @Override diff --git a/src/java/org/apache/cassandra/db/lifecycle/LogReplica.java b/src/java/org/apache/cassandra/db/lifecycle/LogReplica.java index fd65f5b44f..a8c39dcba0 100644 --- a/src/java/org/apache/cassandra/db/lifecycle/LogReplica.java +++ b/src/java/org/apache/cassandra/db/lifecycle/LogReplica.java @@ -24,7 +24,7 @@ import java.util.List; import java.util.Map; import org.apache.cassandra.io.util.FileUtils; -import org.apache.cassandra.utils.CLibrary; +import org.apache.cassandra.utils.NativeLibrary; /** * Because a column family may have sstables on different disks and disks can @@ -45,12 +45,12 @@ final class LogReplica implements AutoCloseable static LogReplica create(File directory, String fileName) { - return new LogReplica(new File(fileName), CLibrary.tryOpenDirectory(directory.getPath())); + return new LogReplica(new File(fileName), NativeLibrary.tryOpenDirectory(directory.getPath())); } static LogReplica open(File file) { - return new LogReplica(file, CLibrary.tryOpenDirectory(file.getParentFile().getPath())); + return new LogReplica(file, NativeLibrary.tryOpenDirectory(file.getParentFile().getPath())); } LogReplica(File file, int directoryDescriptor) @@ -93,7 +93,7 @@ final class LogReplica implements AutoCloseable void syncDirectory() { if (directoryDescriptor >= 0) - CLibrary.trySync(directoryDescriptor); + NativeLibrary.trySync(directoryDescriptor); } void delete() @@ -111,7 +111,7 @@ final class LogReplica implements AutoCloseable { if (directoryDescriptor >= 0) { - CLibrary.tryCloseFD(directoryDescriptor); + NativeLibrary.tryCloseFD(directoryDescriptor); directoryDescriptor = -1; } } diff --git a/src/java/org/apache/cassandra/hints/ChecksummedDataInput.java b/src/java/org/apache/cassandra/hints/ChecksummedDataInput.java index 0db95af293..d32faafd47 100644 --- a/src/java/org/apache/cassandra/hints/ChecksummedDataInput.java +++ b/src/java/org/apache/cassandra/hints/ChecksummedDataInput.java @@ -26,7 +26,7 @@ import com.google.common.base.Preconditions; import org.apache.cassandra.io.compress.BufferType; import org.apache.cassandra.io.util.*; -import org.apache.cassandra.utils.CLibrary; +import org.apache.cassandra.utils.NativeLibrary; import org.apache.cassandra.utils.memory.BufferPool; /** @@ -215,7 +215,7 @@ public class ChecksummedDataInput extends RebufferingInputStream public void tryUncacheRead() { - CLibrary.trySkipCache(getChannel().getFileDescriptor(), 0, getSourcePosition(), getPath()); + NativeLibrary.trySkipCache(getChannel().getFileDescriptor(), 0, getSourcePosition(), getPath()); } private void updateCrc() diff --git a/src/java/org/apache/cassandra/hints/HintsCatalog.java b/src/java/org/apache/cassandra/hints/HintsCatalog.java index c2f0972085..5ebe65bf3d 100644 --- a/src/java/org/apache/cassandra/hints/HintsCatalog.java +++ b/src/java/org/apache/cassandra/hints/HintsCatalog.java @@ -27,7 +27,7 @@ import java.util.stream.Stream; import com.google.common.collect.ImmutableMap; import org.apache.cassandra.io.FSReadError; -import org.apache.cassandra.utils.CLibrary; +import org.apache.cassandra.utils.NativeLibrary; import org.apache.cassandra.utils.SyncUtil; import static java.util.stream.Collectors.groupingBy; @@ -130,11 +130,11 @@ final class HintsCatalog void fsyncDirectory() { - int fd = CLibrary.tryOpenDirectory(hintsDirectory.getAbsolutePath()); + int fd = NativeLibrary.tryOpenDirectory(hintsDirectory.getAbsolutePath()); if (fd != -1) { SyncUtil.trySync(fd); - CLibrary.tryCloseFD(fd); + NativeLibrary.tryCloseFD(fd); } } diff --git a/src/java/org/apache/cassandra/hints/HintsWriter.java b/src/java/org/apache/cassandra/hints/HintsWriter.java index dca915aab5..48b8c7c9d1 100644 --- a/src/java/org/apache/cassandra/hints/HintsWriter.java +++ b/src/java/org/apache/cassandra/hints/HintsWriter.java @@ -33,7 +33,7 @@ import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.io.FSWriteError; import org.apache.cassandra.io.util.DataOutputBuffer; import org.apache.cassandra.io.util.DataOutputBufferFixed; -import org.apache.cassandra.utils.CLibrary; +import org.apache.cassandra.utils.NativeLibrary; import org.apache.cassandra.utils.SyncUtil; import org.apache.cassandra.utils.Throwables; @@ -70,7 +70,7 @@ class HintsWriter implements AutoCloseable File file = new File(directory, descriptor.fileName()); FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW); - int fd = CLibrary.getfd(channel); + int fd = NativeLibrary.getfd(channel); CRC32 crc = new CRC32(); @@ -289,7 +289,7 @@ class HintsWriter implements AutoCloseable // don't skip page cache for tiny files, on the assumption that if they are tiny, the target node is probably // alive, and if so, the file will be closed and dispatched shortly (within a minute), and the file will be dropped. if (position >= DatabaseDescriptor.getTrickleFsyncIntervalInKb() * 1024L) - CLibrary.trySkipCache(fd, 0, position - (position % PAGE_SIZE), file.getPath()); + NativeLibrary.trySkipCache(fd, 0, position - (position % PAGE_SIZE), file.getPath()); } } } diff --git a/src/java/org/apache/cassandra/io/sstable/SSTableRewriter.java b/src/java/org/apache/cassandra/io/sstable/SSTableRewriter.java index b43d3d17f5..7e2dad5dbf 100644 --- a/src/java/org/apache/cassandra/io/sstable/SSTableRewriter.java +++ b/src/java/org/apache/cassandra/io/sstable/SSTableRewriter.java @@ -32,7 +32,7 @@ import org.apache.cassandra.db.rows.UnfilteredRowIterator; import org.apache.cassandra.io.sstable.format.SSTableReader; import org.apache.cassandra.io.sstable.format.SSTableWriter; import org.apache.cassandra.db.lifecycle.LifecycleTransaction; -import org.apache.cassandra.utils.CLibrary; +import org.apache.cassandra.utils.NativeLibrary; import org.apache.cassandra.utils.concurrent.Transactional; /** @@ -171,7 +171,7 @@ public class SSTableRewriter extends Transactional.AbstractTransactional impleme for (SSTableReader reader : transaction.originals()) { RowIndexEntry index = reader.getPosition(key, SSTableReader.Operator.GE); - CLibrary.trySkipCache(reader.getFilename(), 0, index == null ? 0 : index.position); + NativeLibrary.trySkipCache(reader.getFilename(), 0, index == null ? 0 : index.position); } } else diff --git a/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java b/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java index 980acbb43c..2a6e405420 100644 --- a/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java +++ b/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java @@ -2243,8 +2243,8 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted= 0) return pid; diff --git a/src/java/org/apache/cassandra/utils/CLibrary.java b/src/java/org/apache/cassandra/utils/NativeLibrary.java similarity index 88% rename from src/java/org/apache/cassandra/utils/CLibrary.java rename to src/java/org/apache/cassandra/utils/NativeLibrary.java index 8824b9a4e8..4cabf79fe5 100644 --- a/src/java/org/apache/cassandra/utils/CLibrary.java +++ b/src/java/org/apache/cassandra/utils/NativeLibrary.java @@ -31,14 +31,14 @@ import org.slf4j.LoggerFactory; import com.sun.jna.LastErrorException; import sun.nio.ch.FileChannelImpl; -import static org.apache.cassandra.utils.CLibrary.OSType.LINUX; -import static org.apache.cassandra.utils.CLibrary.OSType.MAC; -import static org.apache.cassandra.utils.CLibrary.OSType.WINDOWS; -import static org.apache.cassandra.utils.CLibrary.OSType.AIX; +import static org.apache.cassandra.utils.NativeLibrary.OSType.LINUX; +import static org.apache.cassandra.utils.NativeLibrary.OSType.MAC; +import static org.apache.cassandra.utils.NativeLibrary.OSType.WINDOWS; +import static org.apache.cassandra.utils.NativeLibrary.OSType.AIX; -public final class CLibrary +public final class NativeLibrary { - private static final Logger logger = LoggerFactory.getLogger(CLibrary.class); + private static final Logger logger = LoggerFactory.getLogger(NativeLibrary.class); public enum OSType { @@ -69,7 +69,7 @@ public final class CLibrary private static final int POSIX_FADV_DONTNEED = 4; /* fadvise.h */ private static final int POSIX_FADV_NOREUSE = 5; /* fadvise.h */ - private static final CLibraryWrapper wrappedCLibrary; + private static final NativeLibraryWrapper wrappedLibrary; private static boolean jnaLockable = false; private static final Field FILE_DESCRIPTOR_FD_FIELD; @@ -85,12 +85,12 @@ public final class CLibrary osType = getOsType(); switch (osType) { - case MAC: wrappedCLibrary = new CLibraryDarwin(); break; - case WINDOWS: wrappedCLibrary = new CLibraryWindows(); break; + case MAC: wrappedLibrary = new NativeLibraryDarwin(); break; + case WINDOWS: wrappedLibrary = new NativeLibraryWindows(); break; case LINUX: case AIX: case OTHER: - default: wrappedCLibrary = new CLibraryLinux(); + default: wrappedLibrary = new NativeLibraryLinux(); } if (System.getProperty("os.arch").toLowerCase().contains("ppc")) @@ -118,7 +118,7 @@ public final class CLibrary } } - private CLibrary() {} + private NativeLibrary() {} /** * @return the detected OSType of the Operating System running the JVM using crude string matching @@ -155,9 +155,13 @@ public final class CLibrary } } - public static boolean jnaAvailable() + /** + * Checks if the library has been successfully linked. + * @return {@code true} if the library has been successfully linked, {@code false} otherwise. + */ + public static boolean isAvailable() { - return wrappedCLibrary.jnaAvailable(); + return wrappedLibrary.isAvailable(); } public static boolean jnaMemoryLockable() @@ -169,7 +173,7 @@ public final class CLibrary { try { - wrappedCLibrary.callMlockall(MCL_CURRENT); + wrappedLibrary.callMlockall(MCL_CURRENT); jnaLockable = true; logger.info("JNA mlockall successful"); } @@ -235,14 +239,14 @@ public final class CLibrary { if (osType == LINUX) { - int result = wrappedCLibrary.callPosixFadvise(fd, offset, len, POSIX_FADV_DONTNEED); + int result = wrappedLibrary.callPosixFadvise(fd, offset, len, POSIX_FADV_DONTNEED); if (result != 0) NoSpamLogger.log( logger, NoSpamLogger.Level.WARN, 10, TimeUnit.MINUTES, - "Failed trySkipCache on file: {} Error: " + wrappedCLibrary.callStrerror(result).getString(0), + "Failed trySkipCache on file: {} Error: " + wrappedLibrary.callStrerror(result).getString(0), path); } } @@ -267,7 +271,7 @@ public final class CLibrary try { - result = wrappedCLibrary.callFcntl(fd, command, flags); + result = wrappedLibrary.callFcntl(fd, command, flags); } catch (UnsatisfiedLinkError e) { @@ -290,7 +294,7 @@ public final class CLibrary try { - return wrappedCLibrary.callOpen(path, O_RDONLY); + return wrappedLibrary.callOpen(path, O_RDONLY); } catch (UnsatisfiedLinkError e) { @@ -314,7 +318,7 @@ public final class CLibrary try { - wrappedCLibrary.callFsync(fd); + wrappedLibrary.callFsync(fd); } catch (UnsatisfiedLinkError e) { @@ -336,7 +340,7 @@ public final class CLibrary try { - wrappedCLibrary.callClose(fd); + wrappedLibrary.callClose(fd); } catch (UnsatisfiedLinkError e) { @@ -391,7 +395,7 @@ public final class CLibrary { try { - return wrappedCLibrary.callGetpid(); + return wrappedLibrary.callGetpid(); } catch (Exception e) { diff --git a/src/java/org/apache/cassandra/utils/CLibraryDarwin.java b/src/java/org/apache/cassandra/utils/NativeLibraryDarwin.java similarity index 88% rename from src/java/org/apache/cassandra/utils/CLibraryDarwin.java rename to src/java/org/apache/cassandra/utils/NativeLibraryDarwin.java index e0a43ec066..d6f1a9e887 100644 --- a/src/java/org/apache/cassandra/utils/CLibraryDarwin.java +++ b/src/java/org/apache/cassandra/utils/NativeLibraryDarwin.java @@ -26,7 +26,7 @@ import com.sun.jna.Native; import com.sun.jna.Pointer; /** - * A CLibraryWrapper implementation for Darwin/Mac. + * A {@code NativeLibraryWrapper} implementation for Darwin/Mac. *

* When JNA is initialized, all methods that have the 'native' keyword * will be attmpted to be linked against. As Java doesn't have the equivalent @@ -37,35 +37,33 @@ import com.sun.jna.Pointer; * native calls that are supported on that target operating system will be * unavailable simply because of one native defined method not supported * on the runtime operating system. - * @see org.apache.cassandra.utils.CLibraryWrapper - * @see CLibrary + * @see org.apache.cassandra.utils.NativeLibraryWrapper + * @see NativeLibrary */ -public class CLibraryDarwin implements CLibraryWrapper +public class NativeLibraryDarwin implements NativeLibraryWrapper { - private static final Logger logger = LoggerFactory.getLogger(CLibraryDarwin.class); + private static final Logger logger = LoggerFactory.getLogger(NativeLibraryDarwin.class); - private static boolean jnaAvailable = true; + private static boolean available; static { try { Native.register("c"); + available = true; } catch (NoClassDefFoundError e) { logger.warn("JNA not found. Native methods will be disabled."); - jnaAvailable = false; } catch (UnsatisfiedLinkError e) { - logger.warn("JNA link failure, one or more native method will be unavailable."); - logger.error("JNA link failure details: {}", e.getMessage()); + logger.error("Failed to link the C library against JNA. Native methods will be unavailable.", e); } catch (NoSuchMethodError e) { logger.warn("Obsolete version of JNA present; unable to register C library. Upgrade to JNA 3.2.7 or later"); - jnaAvailable = false; } } @@ -124,8 +122,8 @@ public class CLibraryDarwin implements CLibraryWrapper return getpid(); } - public boolean jnaAvailable() + public boolean isAvailable() { - return jnaAvailable; + return available; } } diff --git a/src/java/org/apache/cassandra/utils/CLibraryLinux.java b/src/java/org/apache/cassandra/utils/NativeLibraryLinux.java similarity index 88% rename from src/java/org/apache/cassandra/utils/CLibraryLinux.java rename to src/java/org/apache/cassandra/utils/NativeLibraryLinux.java index 1822bdf4bd..b6667e428f 100644 --- a/src/java/org/apache/cassandra/utils/CLibraryLinux.java +++ b/src/java/org/apache/cassandra/utils/NativeLibraryLinux.java @@ -26,7 +26,7 @@ import com.sun.jna.Native; import com.sun.jna.Pointer; /** - * A CLibraryWrapper implementation for Linux. + * A {@code NativeLibraryWrapper} implementation for Linux. *

* When JNA is initialized, all methods that have the 'native' keyword * will be attmpted to be linked against. As Java doesn't have the equivalent @@ -37,35 +37,33 @@ import com.sun.jna.Pointer; * native calls that are supported on that target operating system will be * unavailable simply because of one native defined method not supported * on the runtime operating system. - * @see org.apache.cassandra.utils.CLibraryWrapper - * @see CLibrary + * @see org.apache.cassandra.utils.NativeLibraryWrapper + * @see NativeLibrary */ -public class CLibraryLinux implements CLibraryWrapper +public class NativeLibraryLinux implements NativeLibraryWrapper { - private static boolean jnaAvailable = true; + private static boolean available; - private static final Logger logger = LoggerFactory.getLogger(CLibraryLinux.class); + private static final Logger logger = LoggerFactory.getLogger(NativeLibraryLinux.class); static { try { Native.register("c"); + available = true; } catch (NoClassDefFoundError e) { logger.warn("JNA not found. Native methods will be disabled."); - jnaAvailable = false; } catch (UnsatisfiedLinkError e) { - logger.warn("JNA link failure, one or more native method will be unavailable."); - logger.error("JNA link failure details: {}", e.getMessage()); + logger.error("Failed to link the C library against JNA. Native methods will be unavailable.", e); } catch (NoSuchMethodError e) { logger.warn("Obsolete version of JNA present; unable to register C library. Upgrade to JNA 3.2.7 or later"); - jnaAvailable = false; } } @@ -124,8 +122,8 @@ public class CLibraryLinux implements CLibraryWrapper return getpid(); } - public boolean jnaAvailable() + public boolean isAvailable() { - return jnaAvailable; + return available; } } diff --git a/src/java/org/apache/cassandra/utils/CLibraryWindows.java b/src/java/org/apache/cassandra/utils/NativeLibraryWindows.java similarity index 62% rename from src/java/org/apache/cassandra/utils/CLibraryWindows.java rename to src/java/org/apache/cassandra/utils/NativeLibraryWindows.java index c8b5bbb63d..e6e823c62a 100644 --- a/src/java/org/apache/cassandra/utils/CLibraryWindows.java +++ b/src/java/org/apache/cassandra/utils/NativeLibraryWindows.java @@ -21,21 +21,51 @@ package org.apache.cassandra.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.sun.jna.LastErrorException; +import com.sun.jna.Native; import com.sun.jna.Pointer; /** - * A CLibraryWrapper implementation for Windows. - *

- * As libc isn't available on Windows these implementations - * will obviously be a no-op, however when possible implementations - * are used that are Windows friendly that will return the same - * return value. - * @see org.apache.cassandra.utils.CLibraryWrapper - * @see CLibrary + * A {@code NativeLibraryWrapper} implementation for Windows. + *

This implementation only offers support for the {@code callGetpid} method + * using the Windows/Kernel32 library.

+ * + * @see org.apache.cassandra.utils.NativeLibraryWrapper + * @see NativeLibrary */ -public class CLibraryWindows implements CLibraryWrapper +public class NativeLibraryWindows implements NativeLibraryWrapper { - private static final Logger logger = LoggerFactory.getLogger(CLibraryWindows.class); + private static final Logger logger = LoggerFactory.getLogger(NativeLibraryWindows.class); + + private static boolean available; + + static + { + try + { + Native.register("kernel32"); + available = true; + } + catch (NoClassDefFoundError e) + { + logger.warn("JNA not found. Native methods will be disabled."); + } + catch (UnsatisfiedLinkError e) + { + logger.error("Failed to link the Windows/Kernel32 library against JNA. Native methods will be unavailable.", e); + } + catch (NoSuchMethodError e) + { + logger.warn("Obsolete version of JNA present; unable to register Windows/Kernel32 library. Upgrade to JNA 3.2.7 or later"); + } + } + + /** + * Retrieves the process identifier of the calling process (GetCurrentProcessId function). + * + * @return the process identifier of the calling process + */ + private static native long GetCurrentProcessId() throws LastErrorException; public int callMlockall(int flags) throws UnsatisfiedLinkError, RuntimeException { @@ -84,20 +114,11 @@ public class CLibraryWindows implements CLibraryWrapper */ public long callGetpid() throws UnsatisfiedLinkError, RuntimeException { - try - { - return SigarLibrary.instance.getPid(); - } - catch (Exception e) - { - logger.error("Failed to initialize or use Sigar Library", e); - } - - return -1; + return GetCurrentProcessId(); } - public boolean jnaAvailable() + public boolean isAvailable() { - return false; + return available; } } diff --git a/src/java/org/apache/cassandra/utils/CLibraryWrapper.java b/src/java/org/apache/cassandra/utils/NativeLibraryWrapper.java similarity index 87% rename from src/java/org/apache/cassandra/utils/CLibraryWrapper.java rename to src/java/org/apache/cassandra/utils/NativeLibraryWrapper.java index b97fa64afa..879ea88605 100644 --- a/src/java/org/apache/cassandra/utils/CLibraryWrapper.java +++ b/src/java/org/apache/cassandra/utils/NativeLibraryWrapper.java @@ -22,11 +22,15 @@ import com.sun.jna.Pointer; /** * An interface to implement for using OS specific native methods. - * @see CLibrary + * @see NativeLibrary */ -interface CLibraryWrapper +interface NativeLibraryWrapper { - boolean jnaAvailable(); + /** + * Checks if the library has been successfully linked. + * @return {@code true} if the library has been successfully linked, {@code false} otherwise. + */ + boolean isAvailable(); int callMlockall(int flags) throws UnsatisfiedLinkError, RuntimeException; int callMunlockall() throws UnsatisfiedLinkError, RuntimeException; diff --git a/src/java/org/apache/cassandra/utils/SyncUtil.java b/src/java/org/apache/cassandra/utils/SyncUtil.java index 4c0d89d99c..64d64cf9f8 100644 --- a/src/java/org/apache/cassandra/utils/SyncUtil.java +++ b/src/java/org/apache/cassandra/utils/SyncUtil.java @@ -176,7 +176,7 @@ public class SyncUtil if (SKIP_SYNC) return; else - CLibrary.trySync(fd); + NativeLibrary.trySync(fd); } public static void trySyncDir(File dir) @@ -184,14 +184,14 @@ public class SyncUtil if (SKIP_SYNC) return; - int directoryFD = CLibrary.tryOpenDirectory(dir.getPath()); + int directoryFD = NativeLibrary.tryOpenDirectory(dir.getPath()); try { trySync(directoryFD); } finally { - CLibrary.tryCloseFD(directoryFD); + NativeLibrary.tryCloseFD(directoryFD); } } } diff --git a/src/java/org/apache/cassandra/utils/UUIDGen.java b/src/java/org/apache/cassandra/utils/UUIDGen.java index 2e89b667f5..8fac8163d6 100644 --- a/src/java/org/apache/cassandra/utils/UUIDGen.java +++ b/src/java/org/apache/cassandra/utils/UUIDGen.java @@ -385,7 +385,7 @@ public class UUIDGen messageDigest.update(addr.getAddress()); // Identify the process on the load: we use both the PID and class loader hash. - long pid = CLibrary.getProcessID(); + long pid = NativeLibrary.getProcessID(); if (pid < 0) pid = new Random(System.currentTimeMillis()).nextLong(); FBUtilities.updateWithLong(messageDigest, pid); diff --git a/src/java/org/apache/cassandra/utils/WindowsTimer.java b/src/java/org/apache/cassandra/utils/WindowsTimer.java index eed8eb28de..bbd162c8c2 100644 --- a/src/java/org/apache/cassandra/utils/WindowsTimer.java +++ b/src/java/org/apache/cassandra/utils/WindowsTimer.java @@ -34,6 +34,10 @@ public final class WindowsTimer { Native.register("winmm"); } + catch (NoClassDefFoundError e) + { + logger.warn("JNA not found. winmm.dll cannot be registered. Performance will be negatively impacted on this node."); + } catch (Exception e) { logger.error("Failed to register winmm.dll. Performance will be negatively impacted on this node."); diff --git a/test/unit/org/apache/cassandra/utils/CLibraryTest.java b/test/unit/org/apache/cassandra/utils/NativeLibraryTest.java similarity index 89% rename from test/unit/org/apache/cassandra/utils/CLibraryTest.java rename to test/unit/org/apache/cassandra/utils/NativeLibraryTest.java index d07b1ff726..226653eb71 100644 --- a/test/unit/org/apache/cassandra/utils/CLibraryTest.java +++ b/test/unit/org/apache/cassandra/utils/NativeLibraryTest.java @@ -25,20 +25,20 @@ import org.junit.Test; import org.apache.cassandra.io.util.FileUtils; -public class CLibraryTest +public class NativeLibraryTest { @Test public void testSkipCache() { File file = FileUtils.createTempFile("testSkipCache", "1"); - CLibrary.trySkipCache(file.getPath(), 0, 0); + NativeLibrary.trySkipCache(file.getPath(), 0, 0); } @Test public void getPid() { - long pid = CLibrary.getProcessID(); + long pid = NativeLibrary.getProcessID(); Assert.assertTrue(pid > 0); } }