Behaviour of System.Directory.getModificationTime

Hello, I am writing a program which scans a bunch of directories to detect changes (added, modified, deleted files). To detect modification, I would like to use getModification, doing something like the following: -- |Stores last modified timestamp of the file -- Yes, I come from Java... type HashMap = M.Map FilePath ClockTime data (Show a, Eq a) => Edit a = Mod a | Add a | Del a deriving (Eq,Show) checkChanges :: [String] -> HashMap -> IO ([Edit FilePath], HashMap) checkChanges [fs] m = do addedFilesList <- lsRecursive fs timestamps <- mapM getModificationTime addedFilesList let allts = zip addedFilesList timestamps let ret = (findDeletedFiles allts.updateScannedFiles allts) ([],m) return ret -- | Returns an updated map and a list of modified/added/deleted files updateScannedFiles :: [(FilePath,ClockTime)] -> ([Edit FilePath], HashMap) -> ([Edit FilePath], HashMap) updateScannedFiles [] r = r updateScannedFiles ((path,ts):files) (updates,m) = case M.lookup path m of Nothing -> updateScannedFiles files ((Add path:updates), M.insert path ts m) Just ts' -> if ts' < ts then updateScannedFiles files ((Mod path:updates), M.adjust (const ts) path m) else updateScannedFiles files (updates, m) -- omitting findDeletedFiles which is obvious and works I got the following test case that fails: "recursively marks changed files as modified" `for` do complexFileSetup -- create a small FS tree with 3 files root <- tempDir state <- checkChanges [root] M.empty writeFile (root > "subdir" > "cFile.txt") "this is another toast" checkChanges [root] (snd state) >>= (\r -> assertEqual "there should be 1 changed file in 3 files" 1 ((length.modified.fst) r)), In words: the getModificationTime of the overwritten file appears identical before and after the write. What am I doing wrong ? BTW, I checked the content of the file which has been correctly updated. Thanks for your help Arnaud

actually, IRL the code works as expected. Might it be possible that the speed of test execution is greater than the granularity of the system's modification timestamp?

Yes, modification times are reported in seconds, so you'll have to
wait on average 0.5s for a file change to be visible via the
modification date. Due to buffers and filesystem optimisations it
might even take longer.
On 16 December 2010 16:50, Arnaud Bailly
actually, IRL the code works as expected. Might it be possible that the speed of test execution is greater than the granularity of the system's modification timestamp?
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Push the envelope. Watch it bend.

If this is not a toy program I would really suggest using something that is
builtin in the OS of choice. On Linux there is inotify (
http://en.wikipedia.org/wiki/Inotify), but I'm pretty sure that other OSes
have similar interfaces. The "modification time" method seems really fragile
and I probably not very efficient as well.
Best regards,
Krzysztof Skrzętnicki
On Thu, Dec 16, 2010 at 17:50, Arnaud Bailly
actually, IRL the code works as expected. Might it be possible that the speed of test execution is greater than the granularity of the system's modification timestamp?
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Thanks for your answers. I am a little bit surprised, I thought
timestamps were on the milliseconds scale.
@Krzysztof: Yes, you are right, an event-based interface is far
superior to the basic polling approach I took. At present, a couple
seconds granularity is fine with my use case so I don't care too much
getting more precise notifications, but I'd rather be notified by the
kernel than going through the hassle of polling it myself.
I played a bit with inotify (through a Java binding) a year ago and
found it a bit cumbersome to wield as one has to monitor explicitly
all nodes in a tree. Maybe I am wrong. Moreover, I am not aware of a
portable way of doing this.
I would appreciate pointers and advices on these matters.
Thanks again,
arnaud
2010/12/16 Krzysztof Skrzętnicki
If this is not a toy program I would really suggest using something that is builtin in the OS of choice. On Linux there is inotify (http://en.wikipedia.org/wiki/Inotify), but I'm pretty sure that other OSes have similar interfaces. The "modification time" method seems really fragile and I probably not very efficient as well. Best regards, Krzysztof Skrzętnicki
On Thu, Dec 16, 2010 at 17:50, Arnaud Bailly
wrote: actually, IRL the code works as expected. Might it be possible that the speed of test execution is greater than the granularity of the system's modification timestamp?
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 12/17/10 06:22 , Arnaud Bailly wrote:
Thanks for your answers. I am a little bit surprised, I thought timestamps were on the milliseconds scale.
POSIX timestamps are seconds. - -- brandon s. allbery [linux,solaris,freebsd,perl] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.10 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk0Ss28ACgkQIn7hlCsL25XpygCgziZm1KyO+dP00ACtIrfsueJg 0dQAoI6hNz3oSmiIO2kAiXtRmowWwAg1 =wAHu -----END PGP SIGNATURE-----
participants (4)
-
Arnaud Bailly
-
Brandon S Allbery KF8NH
-
Krzysztof Skrzętnicki
-
Thomas Schilling