@@ -7,25 +7,45 @@ module Hakyll.Core.Store
77 , storeGet
88 ) where
99
10−import Control.Applicative ((<$>))
10+import Control.Concurrent.MVar (MVar, newMVar, readMVar, modifyMVar_)
1111import System.FilePath ((</>))
1212import System.Directory (doesFileExist)
13+import Data.Map (Map)
14+import qualified Data.Map as M
1315
1416import Data.Binary (Binary, encodeFile, decodeFile)
17+import Data.Typeable (Typeable)
1518
19+import Hakyll.Core.CompiledItem
20+import Hakyll.Core.Writable
1621import Hakyll.Core.Identifier
1722import Hakyll.Core.Util.File
1823
1924-- | Data structure used for the store
2025--
2126data Store = Store
22− { storeDirectory :: FilePath
27+ { -- | All items are stored on the filesystem
28+ storeDirectory :: FilePath
29+ , -- | And some items are also kept in-memory
30+ storeMap :: MVar (Map FilePath CompiledItem)
2331 }
2432
2533-- | Initialize the store
2634--
2735makeStore :: FilePath -> IO Store
28−makeStore directory = return Store {storeDirectory = directory}
36+makeStore directory = do
37+ mvar <- newMVar M.empty
38+ return Store
39+ { storeDirectory = directory
40+ , storeMap = mvar
41+ }
42+
43+-- | Auxiliary: add an item to the map
44+--
45+addToMap :: (Binary a, Typeable a, Writable a)
46+ => Store -> FilePath -> a -> IO ()
47+addToMap store path value =
48+ modifyMVar_ (storeMap store) $ return . M.insert path (compiledItem value)
2949
3050-- | Create a path
3151--
@@ -35,19 +55,34 @@ makePath store name identifier =
3555
3656-- | Store an item
3757--
38−storeSet :: Binary a => Store -> String -> Identifier -> a -> IO ()
58+storeSet :: (Binary a, Typeable a, Writable a)
59+ => Store -> String -> Identifier -> a -> IO ()
3960storeSet store name identifier value = do
4061 makeDirectories path
4162 encodeFile path value
63+ addToMap store path value
4264 where
4365 path = makePath store name identifier
4466
4567-- | Load an item
4668--
47−storeGet :: Binary a => Store -> String -> Identifier -> IO (Maybe a)
69+storeGet :: (Binary a, Typeable a, Writable a)
70+ => Store -> String -> Identifier -> IO (Maybe a)
4871storeGet store name identifier = do
49− exists <- doesFileExist path
50− if exists then Just <$> decodeFile path
51− else return Nothing
72+ -- First check the in-memory map
73+ map' <- readMVar $ storeMap store
74+ case M.lookup path map' of
75+ -- Found in the in-memory map
76+ Just c -> return $ Just $ unCompiledItem c
77+ -- Not found in the map, try the filesystem
78+ Nothing -> do
79+ exists <- doesFileExist path
80+ if not exists
81+ -- Not found in the filesystem either
82+ then return Nothing
83+ -- Found in the filesystem
84+ else do v <- decodeFile path
85+ addToMap store path v
86+ return $ Just v
5287 where
5388 path = makePath store name identifier