on master help sign in
Use mtime instead of hashing files, much faster
d34d56bJasper Van der Jeugt
src/Hakyll/Core/Provider/Modified.hs+36−22
@@ -1,5 +1,6 @@
1--------------------------------------------------------------------------------
1--------------------------------------------------------------------------------
2−{-# LANGUAGE CPP #-}
2+{-# LANGUAGE CPP #-}
3+{-# LANGUAGE DeriveDataTypeable #-}
3module Hakyll.Core.Provider.Modified
4module Hakyll.Core.Provider.Modified
4 ( resourceModified
5 ( resourceModified
5 , resourceModificationTime
6 , resourceModificationTime
@@ -9,12 +10,12 @@ module Hakyll.Core.Provider.Modified
9--------------------------------------------------------------------------------
10--------------------------------------------------------------------------------
10import Control.Applicative ((<$>), (<*>))
11import Control.Applicative ((<$>), (<*>))
11import Control.Monad (when)
12import Control.Monad (when)
12−import qualified Crypto.Hash.MD5 as MD5
13+import Data.Binary (Binary (..))
13−import qualified Data.ByteString as B
14−import qualified Data.ByteString.Lazy as BL
15import Data.IORef
14import Data.IORef
16import qualified Data.Map as M
15import qualified Data.Map as M
17−import Data.Time (UTCTime)
16+import Data.Time (Day (..), UTCTime (..),
17+ secondsToDiffTime)
18+import Data.Typeable (Typeable)
18import System.Directory (getModificationTime)
19import System.Directory (getModificationTime)
19
20
20
21
@@ -48,7 +49,7 @@ resourceModified p r
48 -- Check if the actual file was modified, and do a recursive
49 -- Check if the actual file was modified, and do a recursive
49 -- call to check if the metadata file was modified
50 -- call to check if the metadata file was modified
50 m <- (||)
51 m <- (||)
51− <$> fileDigestModified store filePath
52+ <$> fileModified store filePath
52 <*> resourceModified p (resourceMetadataResource r)
53 <*> resourceModified p (resourceMetadataResource r)
53 modifyIORef cacheRef (M.insert normalized m)
54 modifyIORef cacheRef (M.insert normalized m)
54
55
@@ -65,37 +66,50 @@ resourceModified p r
65
66
66
67
67--------------------------------------------------------------------------------
68--------------------------------------------------------------------------------
68−-- | Utility: Check if a the digest of a file was modified
69+-- | Utility: Check if a file was modified recently
69−fileDigestModified :: Store -> FilePath -> IO Bool
70+fileModified :: Store -> FilePath -> IO Bool
70−fileDigestModified store fp = do
71+fileModified store fp = do
71− -- Get the latest seen digest from the store, and calculate the current
72− -- digest for the
73− lastDigest <- Store.get store key
72+ lastModified <- Store.get store key
74− newDigest <- fileDigest fp
73+ newModified <- BinaryTime <$> fileModificationTime fp
75− if Store.Found newDigest == lastDigest
74+ if maybe False (>= newModified) (Store.toMaybe lastModified)
76 -- All is fine, not modified
75 -- All is fine, not modified
77 then return False
76 then return False
78 -- Resource modified; store new digest
77 -- Resource modified; store new digest
79 else do
78 else do
80− Store.set store key newDigest
79+ Store.set store key newModified
81 return True
80 return True
82 where
81 where
83 key = ["Hakyll.Core.Resource.Provider.fileModified", fp]
82 key = ["Hakyll.Core.Resource.Provider.fileModified", fp]
84
83
85
84
86--------------------------------------------------------------------------------
85--------------------------------------------------------------------------------
87−-- | Utility: Retrieve a digest for a given file
86+resourceModificationTime :: Provider -> Identifier -> IO UTCTime
88−fileDigest :: FilePath -> IO B.ByteString
87+resourceModificationTime p i = fileModificationTime $ resourceFilePath p i
89−fileDigest = fmap MD5.hashlazy . BL.readFile
90
88
91
89
92--------------------------------------------------------------------------------
90--------------------------------------------------------------------------------
93−resourceModificationTime :: Provider -> Identifier -> IO UTCTime
91+fileModificationTime :: FilePath -> IO UTCTime
94−resourceModificationTime p i = do
92+fileModificationTime fp = do
95#if MIN_VERSION_directory(1,2,0)
93#if MIN_VERSION_directory(1,2,0)
96− getModificationTime $ resourceFilePath p i
94+ getModificationTime fp
97#else
95#else
98− ct <- toCalendarTime =<< getModificationTime (resourceFilePath p i)
96+ ct <- toCalendarTime =<< getModificationTime fp
99 let str = formatCalendarTime defaultTimeLocale "%s" ct
97 let str = formatCalendarTime defaultTimeLocale "%s" ct
100 return $ readTime defaultTimeLocale "%s" str
98 return $ readTime defaultTimeLocale "%s" str
101#endif
99#endif
100+
101+
102+--------------------------------------------------------------------------------
103+-- | Because UTCTime doesn't have a Binary instance...
104+newtype BinaryTime = BinaryTime UTCTime
105+ deriving (Eq, Ord, Typeable)
106+
107+
108+--------------------------------------------------------------------------------
109+instance Binary BinaryTime where
110+ put (BinaryTime (UTCTime (ModifiedJulianDay d) dt)) =
111+ put d >> put (floor dt :: Integer)
112+
113+ get = fmap BinaryTime $ UTCTime
114+ <$> (ModifiedJulianDay <$> get)
115+ <*> (secondsToDiffTime <$> get)
src/Hakyll/Core/Store.hs+8
@@ -5,6 +5,7 @@
5module Hakyll.Core.Store
5module Hakyll.Core.Store
6 ( Store
6 ( Store
7 , Result (..)
7 , Result (..)
8+ , toMaybe
8 , new
9 , new
9 , set
10 , set
10 , get
11 , get
@@ -53,6 +54,13 @@ data Result a
53 deriving (Show, Eq)
54 deriving (Show, Eq)
54
55
55
56
57+--------------------------------------------------------------------------------
58+-- | Convert result to 'Maybe'
59+toMaybe :: Result a -> Maybe a
60+toMaybe (Found x) = Just x
61+toMaybe _ = Nothing
62+
63+
56--------------------------------------------------------------------------------
64--------------------------------------------------------------------------------
57-- | Initialize the store
65-- | Initialize the store
58new :: Bool -- ^ Use in-memory caching
66new :: Bool -- ^ Use in-memory caching