summaryrefslogtreecommitdiff
path: root/src/Hakyll/Core/Store.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Hakyll/Core/Store.hs')
-rw-r--r--src/Hakyll/Core/Store.hs51
1 files changed, 43 insertions, 8 deletions
diff --git a/src/Hakyll/Core/Store.hs b/src/Hakyll/Core/Store.hs
index 02b9b4e..ab739a1 100644
--- a/src/Hakyll/Core/Store.hs
+++ b/src/Hakyll/Core/Store.hs
@@ -7,25 +7,45 @@ module Hakyll.Core.Store
, storeGet
) where
-import Control.Applicative ((<$>))
+import Control.Concurrent.MVar (MVar, newMVar, readMVar, modifyMVar_)
import System.FilePath ((</>))
import System.Directory (doesFileExist)
+import Data.Map (Map)
+import qualified Data.Map as M
import Data.Binary (Binary, encodeFile, decodeFile)
+import Data.Typeable (Typeable)
+import Hakyll.Core.CompiledItem
+import Hakyll.Core.Writable
import Hakyll.Core.Identifier
import Hakyll.Core.Util.File
-- | Data structure used for the store
--
data Store = Store
- { storeDirectory :: FilePath
+ { -- | All items are stored on the filesystem
+ storeDirectory :: FilePath
+ , -- | And some items are also kept in-memory
+ storeMap :: MVar (Map FilePath CompiledItem)
}
-- | Initialize the store
--
makeStore :: FilePath -> IO Store
-makeStore directory = return Store {storeDirectory = directory}
+makeStore directory = do
+ mvar <- newMVar M.empty
+ return Store
+ { storeDirectory = directory
+ , storeMap = mvar
+ }
+
+-- | Auxiliary: add an item to the map
+--
+addToMap :: (Binary a, Typeable a, Writable a)
+ => Store -> FilePath -> a -> IO ()
+addToMap store path value =
+ modifyMVar_ (storeMap store) $ return . M.insert path (compiledItem value)
-- | Create a path
--
@@ -35,19 +55,34 @@ makePath store name identifier =
-- | Store an item
--
-storeSet :: Binary a => Store -> String -> Identifier -> a -> IO ()
+storeSet :: (Binary a, Typeable a, Writable a)
+ => Store -> String -> Identifier -> a -> IO ()
storeSet store name identifier value = do
makeDirectories path
encodeFile path value
+ addToMap store path value
where
path = makePath store name identifier
-- | Load an item
--
-storeGet :: Binary a => Store -> String -> Identifier -> IO (Maybe a)
+storeGet :: (Binary a, Typeable a, Writable a)
+ => Store -> String -> Identifier -> IO (Maybe a)
storeGet store name identifier = do
- exists <- doesFileExist path
- if exists then Just <$> decodeFile path
- else return Nothing
+ -- First check the in-memory map
+ map' <- readMVar $ storeMap store
+ case M.lookup path map' of
+ -- Found in the in-memory map
+ Just c -> return $ Just $ unCompiledItem c
+ -- Not found in the map, try the filesystem
+ Nothing -> do
+ exists <- doesFileExist path
+ if not exists
+ -- Not found in the filesystem either
+ then return Nothing
+ -- Found in the filesystem
+ else do v <- decodeFile path
+ addToMap store path v
+ return $ Just v
where
path = makePath store name identifier