summaryrefslogtreecommitdiffhomepage
path: root/Plugins/Monitors/Top.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Plugins/Monitors/Top.hs')
-rw-r--r--Plugins/Monitors/Top.hs78
1 files changed, 49 insertions, 29 deletions
diff --git a/Plugins/Monitors/Top.hs b/Plugins/Monitors/Top.hs
index 38686f6..6ca75c7 100644
--- a/Plugins/Monitors/Top.hs
+++ b/Plugins/Monitors/Top.hs
@@ -21,6 +21,7 @@ import Plugins.Monitors.Common
import Control.Exception (SomeException, handle, evaluate)
import System.Directory
import System.FilePath
+import System.IO
import System.Posix.Unistd (getSysVar, SysVar(ClockTick))
import Foreign.C.Types
import Data.List (sortBy)
@@ -40,19 +41,13 @@ topCpuConfig = mkMConfig "<both1>" [ k ++ n | n <- map show [1..maxProc]
, k <- ["name", "cpu", "both"]]
+
foreign import ccall "unistd.h getpagesize"
c_getpagesize :: CInt
pageSize :: Int
pageSize = fromIntegral c_getpagesize `div` 1024
-processes :: IO [FilePath]
-processes =
- fmap (filter isPid) $ getDirectoryContents "/proc"
- where
- isPid (x:_) = x `elem` ['0'..'9']
- isPid _ = False
-
showInfo :: String -> String -> Float -> Monitor [String]
showInfo nm sms mms = do
mnw <- getConfigValue maxWidth
@@ -65,29 +60,53 @@ showInfo nm sms mms = do
both <- showWithColors' (rnm ++ " " ++ sms) mms
return [nm, mstr, both]
-defHandle :: a -> SomeException -> IO a
-defHandle def _ = evaluate def
+strictReadFile :: FilePath -> IO String
+strictReadFile f =
+ do hdl <- openFile f ReadMode
+ xs <- getc hdl
+ hClose hdl
+ return xs
+ where getc hdl = do e <- hIsEOF hdl
+ if e then return []
+ else do c <- hGetChar hdl
+ cs <- getc hdl
+ return (c:cs)
+
+getProcessData :: FilePath -> IO [String]
+getProcessData pidf =
+ handle ((\_ -> evaluate []) :: SomeException -> IO [String])
+ (do s <- strictReadFile $ "/proc" </> pidf </> "stat"
+ evaluate $ words $! s)
-handlePidFile :: a -> ([String] -> IO a) -> FilePath -> IO a
-handlePidFile def action pidf =
- handle (defHandle def) (fmap words (readFile f) >>= action)
- where f = "/proc" </> pidf </> "stat"
+processes :: IO [FilePath]
+processes = do
+ fs <- getDirectoryContents "/proc"
+ return $! filter isPid $! fs
+ where
+ isPid (x:_) = x `elem` ['0'..'9']
+ isPid _ = False
+
+handleProcesses :: a -> ([String] -> a) -> IO [a]
+handleProcesses def f = do
+ ps <- processes
+ pd <- mapM getProcessData $! ps
+ return $! map (\x -> if x == [] then def else f x) pd
+
+processName :: [String] -> String
+processName = drop 1 . init . (!!1)
maxProc :: Int
maxProc = 5
type Meminfo = (String, Int)
-meminfo :: FilePath -> IO Meminfo
-meminfo = handlePidFile ("", 0) $ \fs ->
- let !m = pageSize * read (fs !! 23)
- !n = drop 1 $ init (fs !! 1)
- in evaluate (n, m)
+meminfo :: [String] -> Meminfo
+meminfo fs = (n, r)
+ where !n = processName fs
+ !r = pageSize * (read (fs!!23))
meminfos :: IO [Meminfo]
-meminfos = do
- fs <- processes
- mapM meminfo fs
+meminfos = handleProcesses ("", 0) meminfo
topMemProcesses :: Int -> IO [Meminfo]
topMemProcesses n = fmap (take n . sbm) meminfos
@@ -111,16 +130,17 @@ type TimeEntry = (Pid, TimeInfo)
type Times = IntMap TimeInfo
type TimesRef = IORef Times
-timeEntry :: FilePath -> IO TimeEntry
-timeEntry = handlePidFile (0, ("", 0)) $ \fs ->
- let rf = read . (fs!!)
- !pid = read (head fs)
- !n = drop 1 $ init (fs!!1)
- !t = rf 13 + rf 14
- in evaluate (pid, (n, t))
+timeEntry :: [String] -> TimeEntry
+timeEntry fs = (p, (n, t))
+ where !p = read (head fs)
+ !n = processName fs
+ !t = read (fs!!13) + read (fs!!14)
+
+timeEntries :: IO [TimeEntry]
+timeEntries = handleProcesses (0, ("", 0)) timeEntry
timeinfos :: IO Times
-timeinfos = fmap M.fromList (processes >>= mapM timeEntry)
+timeinfos = fmap M.fromList timeEntries
combineTimeInfos :: Times -> Times -> Times
combineTimeInfos !t0 !t1 = M.intersectionWith timeDiff t1 t0