| /* |
| * 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; |
| |
| 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() |
| { |
| // Check is invalid on Windows |
| if (FBUtilities.isWindows()) |
| return true; |
| |
| 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) |
| { |
| 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."); |
| } |
| } |
| } |