diff options
Diffstat (limited to 'src/Hakyll/Core/Store.hs')
-rw-r--r-- | src/Hakyll/Core/Store.hs | 51 |
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 |