Revision 6eeaf385

b/src/Ganeti/Utils.hs
70 70
  , getFStat
71 71
  , getFStatSafe
72 72
  , needsReload
73
  , watchFile
73 74
  ) where
74 75

  
76
import Control.Concurrent
75 77
import Control.Exception (try)
76 78
import Data.Char (toUpper, isAlphaNum, isDigit, isSpace)
77 79
import Data.Function (on)
80
import Data.IORef
78 81
import Data.List
79 82
import qualified Data.Map as M
80 83
import Control.Monad (foldM, liftM)
81 84
import System.Directory (renameFile)
82 85
import System.FilePath.Posix (takeDirectory, takeBaseName)
86
import System.INotify
83 87
import System.Posix.Types
84 88

  
85 89
import Debug.Trace
......
581 585
  return $ if newstat /= oldstat
582 586
             then Just newstat
583 587
             else Nothing
588

  
589
-- | Until the given point in time (useconds since the epoch), wait
590
-- for the output of a given method to change and return the new value;
591
-- make use of the promise that the output only changes if the reference
592
-- has a value different than the given one.
593
watchFileEx :: (Eq a, Eq b) => Integer -> b -> IORef b -> a -> IO a -> IO a
594
watchFileEx endtime base ref old read_fn = do
595
  current <- getCurrentTimeUSec
596
  if current > endtime then read_fn else do
597
    val <- readIORef ref
598
    if val /= base
599
      then do
600
        new <- read_fn
601
        if new /= old then return new else do
602
          threadDelay 100000
603
          watchFileEx endtime val ref old read_fn
604
      else do 
605
       threadDelay 100000
606
       watchFileEx endtime base ref old read_fn
607

  
608
-- | Within the given timeout (in seconds), wait for for the output
609
-- of the given method to change and return the new value; make use of
610
-- the promise that the method will only change its value, if
611
-- the given file changes on disk. If the file does not exist on disk, return
612
-- immediately.
613
watchFile :: Eq a => FilePath -> Int -> a -> IO a -> IO a
614
watchFile fpath timeout old read_fn = do
615
  current <- getCurrentTimeUSec
616
  let endtime = current + fromIntegral timeout * 1000000
617
  fstat <- getFStatSafe fpath
618
  ref <- newIORef fstat
619
  inotify <- initINotify
620
  _ <- addWatch inotify [Modify, Delete] fpath . const $ do
621
    logDebug $ "Notified of change in " ++ fpath
622
    fstat' <- getFStatSafe fpath
623
    writeIORef ref fstat'
624
  result <- watchFileEx endtime fstat ref old read_fn
625
  killINotify inotify
626
  return result
627
  

Also available in: Unified diff