Revision b57c50de
b/src/Ganeti/WConfd/DeathDetection.hs | ||
---|---|---|
32 | 32 |
|
33 | 33 |
module Ganeti.WConfd.DeathDetection |
34 | 34 |
( isDead |
35 |
, cleanupLocksTask |
|
35 | 36 |
) where |
36 | 37 |
|
38 |
import Control.Concurrent (threadDelay) |
|
37 | 39 |
import Control.Exception (bracket) |
38 | 40 |
import Control.Monad |
39 | 41 |
import System.Directory |
... | ... | |
41 | 43 |
import System.Posix.IO |
42 | 44 |
|
43 | 45 |
import Ganeti.BasicTypes |
46 |
import qualified Ganeti.Constants as C |
|
47 |
import qualified Ganeti.Locking.Allocation as L |
|
48 |
import Ganeti.Logging.Lifted (logDebug, logInfo) |
|
49 |
import Ganeti.WConfd.Monad |
|
44 | 50 |
|
45 | 51 |
-- | Detect whether a the process identified by the given path |
46 | 52 |
-- does not exist any more. This function never fails and only |
... | ... | |
53 | 59 |
when filepresent |
54 | 60 |
$ bracket (openFd fpath ReadOnly Nothing defaultFileFlags) closeFd |
55 | 61 |
(`setLock` (ReadLock, AbsoluteSeek, 0, 0)) |
62 |
|
|
63 |
-- | Interval to run clean-up tasks in microseconds |
|
64 |
cleanupInterval :: Int |
|
65 |
cleanupInterval = C.wconfdDeathdetectionIntervall * 1000000 |
|
66 |
|
|
67 |
-- | Thread periodically cleaning up locks of lock owners that died. |
|
68 |
cleanupLocksTask :: WConfdMonadInt () |
|
69 |
cleanupLocksTask = forever . runResultT $ do |
|
70 |
logDebug "Death detection timer fired" |
|
71 |
owners <- liftM L.lockOwners readLockAllocation |
|
72 |
logDebug $ "Current lock owners: " ++ show owners |
|
73 |
let cleanupIfDead owner@(_, fpath) = do |
|
74 |
died <- liftIO (isDead fpath) |
|
75 |
when died $ do |
|
76 |
logInfo $ show owner ++ " died, releasing locks" |
|
77 |
modifyLockAllocation_ (`L.freeLocks` owner) |
|
78 |
mapM_ cleanupIfDead owners |
|
79 |
liftIO $ threadDelay cleanupInterval |
Also available in: Unified diff