{-# LANGUAGE TemplateHaskell #-}
module System.CGroup.V2.CPU (
getProcessEffectiveCPUQuota,
getEffectiveCPUQuota,
getCPUQuota,
CPUQuota (..),
) where
import Data.Ratio
import Path
import System.CGroup.Types (CPUQuota (..))
import System.CGroup.V2.CGroup
import System.Directory (doesFileExist)
getProcessEffectiveCPUQuota :: IO CPUQuota
getProcessEffectiveCPUQuota :: IO CPUQuota
getProcessEffectiveCPUQuota = CGroup -> IO CPUQuota
getEffectiveCPUQuota (CGroup -> IO CPUQuota) -> IO CGroup -> IO CPUQuota
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO CGroup
resolveCGroup
getEffectiveCPUQuota :: CGroup -> IO CPUQuota
getEffectiveCPUQuota :: CGroup -> IO CPUQuota
getEffectiveCPUQuota CGroup
cgroup = do
[CPUQuota]
quotas <- CGroup -> IO [CPUQuota]
cpuQuotasUntilRoot CGroup
cgroup
CPUQuota -> IO CPUQuota
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((CPUQuota -> CPUQuota -> CPUQuota)
-> CPUQuota -> [CPUQuota] -> CPUQuota
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr CPUQuota -> CPUQuota -> CPUQuota
forall a. Ord a => a -> a -> a
min CPUQuota
NoQuota [CPUQuota]
quotas)
getCPUQuota :: CGroup -> IO CPUQuota
getCPUQuota :: CGroup -> IO CPUQuota
getCPUQuota CGroup
cgroup = do
let path :: Path Abs File
path = CGroup -> Path Abs Dir
cgroupRoot CGroup
cgroup Path Abs Dir -> Path Rel File -> Path Abs File
forall b t. Path b Dir -> Path Rel t -> Path b t
</> CGroup -> Path Rel Dir
cgroupLeaf CGroup
cgroup Path Rel Dir -> Path Rel File -> Path Rel File
forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel File
cpuMaxPath
Bool
exists <- FilePath -> IO Bool
doesFileExist (Path Abs File -> FilePath
forall b t. Path b t -> FilePath
toFilePath Path Abs File
path)
if Bool -> Bool
not Bool
exists
then CPUQuota -> IO CPUQuota
forall (f :: * -> *) a. Applicative f => a -> f a
pure CPUQuota
NoQuota
else do
FilePath
content <- FilePath -> IO FilePath
readFile (Path Abs File -> FilePath
forall b t. Path b t -> FilePath
toFilePath Path Abs File
path)
case FilePath -> [FilePath]
words FilePath
content of
[FilePath
"max", FilePath
_] -> CPUQuota -> IO CPUQuota
forall (f :: * -> *) a. Applicative f => a -> f a
pure CPUQuota
NoQuota
[FilePath
numText, FilePath
denText] -> do
Int
num <- FilePath -> IO Int
forall a. Read a => FilePath -> IO a
readIO FilePath
numText
Int
den <- FilePath -> IO Int
forall a. Read a => FilePath -> IO a
readIO FilePath
denText
CPUQuota -> IO CPUQuota
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Ratio Int -> CPUQuota
CPUQuota (Int
num Int -> Int -> Ratio Int
forall a. Integral a => a -> a -> Ratio a
% Int
den))
[FilePath]
_ -> FilePath -> IO CPUQuota
forall (m :: * -> *) a. MonadFail m => FilePath -> m a
fail FilePath
"Couldn't parse cpu.max"
getParentCGroup :: CGroup -> Maybe CGroup
getParentCGroup :: CGroup -> Maybe CGroup
getParentCGroup CGroup
cgroup =
if CGroup -> Path Rel Dir
cgroupLeaf CGroup
cgroup Path Rel Dir -> Path Rel Dir -> Bool
forall a. Eq a => a -> a -> Bool
== Path Rel Dir -> Path Rel Dir
forall b t. Path b t -> Path b Dir
parent (CGroup -> Path Rel Dir
cgroupLeaf CGroup
cgroup)
then Maybe CGroup
forall a. Maybe a
Nothing
else CGroup -> Maybe CGroup
forall a. a -> Maybe a
Just CGroup
cgroup{cgroupLeaf :: Path Rel Dir
cgroupLeaf = Path Rel Dir -> Path Rel Dir
forall b t. Path b t -> Path b Dir
parent (CGroup -> Path Rel Dir
cgroupLeaf CGroup
cgroup)}
cpuQuotasUntilRoot :: CGroup -> IO [CPUQuota]
cpuQuotasUntilRoot :: CGroup -> IO [CPUQuota]
cpuQuotasUntilRoot = (CGroup -> IO CPUQuota) -> [CGroup] -> IO [CPUQuota]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse CGroup -> IO CPUQuota
getCPUQuota ([CGroup] -> IO [CPUQuota])
-> (CGroup -> [CGroup]) -> CGroup -> IO [CPUQuota]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CGroup -> [CGroup]
cgroupsUntilRoot
cgroupsUntilRoot :: CGroup -> [CGroup]
cgroupsUntilRoot :: CGroup -> [CGroup]
cgroupsUntilRoot = (CGroup -> Maybe CGroup) -> CGroup -> [CGroup]
forall a. (a -> Maybe a) -> a -> [a]
iterateMaybe CGroup -> Maybe CGroup
getParentCGroup
iterateMaybe :: (a -> Maybe a) -> a -> [a]
iterateMaybe :: (a -> Maybe a) -> a -> [a]
iterateMaybe a -> Maybe a
f a
x = a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a] -> (a -> [a]) -> Maybe a -> [a]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] ((a -> Maybe a) -> a -> [a]
forall a. (a -> Maybe a) -> a -> [a]
iterateMaybe a -> Maybe a
f) (a -> Maybe a
f a
x)
cpuMaxPath :: Path Rel File
cpuMaxPath :: Path Rel File
cpuMaxPath = $(mkRelFile "cpu.max")