{- Copyright 2015,2016 Markus Ongyerth, Stephan Guenther This file is part of Monky. Monky is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Monky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Monky. If not, see . -} {-# LANGUAGE OverloadedStrings #-} {-| Module : Monky.Memory Description : Allows to access information about they systems main memory Maintainer : ongy Stability : testing Portability : Linux -} module Monky.Memory ( MemoryHandle , getMemoryAvailable , getMemoryHandle , getMemoryTotal , getMemoryUsed , getMemoryFree , getMemoryStats ) where import Monky.Utility (fopen, readContent, File) import Data.Maybe (fromMaybe, listToMaybe) import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as BS -- |The memory handle used for all functions newtype MemoryHandle = MemoryH File path :: String path = "/proc/meminfo" getVal :: ByteString -> Int getVal = fst . fromMaybe (error "Failed to read as int in memory module") . BS.readInt . (!! 1) . BS.words findLine :: ByteString -> [ByteString] -> Maybe ByteString findLine x = listToMaybe . filter (x `BS.isPrefixOf`) {- |Return the memory available to userspace This is accurate (read from kernel) for current kernels. Old kernel (~3.13) estimates this. Old kernels may overestimate. -} getMemoryAvailable :: MemoryHandle -> IO Int getMemoryAvailable (MemoryH f) = do contents <- readContent f let line = findLine "MemAvailable" contents case line of Nothing -> do let buffs = fromMaybe err $ findLine "Buffers" contents cached = fromMaybe err $ findLine "Cached" contents free <- getMemoryFree (MemoryH f) return $ getVal buffs + getVal cached + free (Just x) -> return . getVal $ x where err = error "Could not find one of the fallback values for MemAvailable, please report this together with the content of /proc/meminfo" -- |Get the total amount of memory in the system getMemoryTotal :: MemoryHandle -> IO Int getMemoryTotal (MemoryH f) = do contents <- readContent f return . getVal . fromMaybe err . findLine "MemTotal" $ contents where err = error "Could not find MemTotal in /proc/meminfo. Please report this bug with the content of /proc/meminfo" -- |Get the amount of memory rported as free by the kernel getMemoryFree :: MemoryHandle -> IO Int getMemoryFree (MemoryH f) = do contents <- readContent f return . getVal . fromMaybe err . findLine "MemFree" $ contents where err = error "Could not find MemFree in /proc/meminfo. Please report this bug with the content of /proc/meminfo" -- |Get the amount of memory used by the kernel and processes getMemoryUsed :: MemoryHandle -> IO Int getMemoryUsed h = do (_, _, _, used) <- getMemoryStats h return used -- |Get memory statistics in one got (with only one read) (total, avail, free, used) getMemoryStats :: MemoryHandle -> IO (Int, Int, Int, Int) getMemoryStats (MemoryH f) = do contents <- readContent f let avail = getVal . fromMaybe "a 0" . findLine "MemAvailable" $ contents total = getVal . fromMaybe "a 0" . findLine "MemTotal" $ contents free = getVal . fromMaybe "a 0" . findLine "MemFree" $ contents used = total - avail return (total, avail, free, used) -- |Get a memory handle getMemoryHandle :: IO MemoryHandle getMemoryHandle = do file <- fopen path return $MemoryH file