packages feed

breve-0.5.0.0: src/Breve/UrlTable.hs

{-|
This modules defines the data structure used
to store the URLs in memory and on disk.
-}
module Breve.UrlTable
( UrlTable
, load
, save
, insert
, extract
) where

import Breve.Generator

import Control.Monad       (forever)
import Control.Concurrent  (forkIO, threadDelay)
import Text.Read           (readMaybe)
import qualified Data.HashTable.IO as H

-- | The hash table that stores URLs
type UrlTable = H.CuckooHashTable Name Url

-- | Periodically save a 'UrlTable' to a file
sync :: UrlTable -> FilePath -> IO ()
sync table file = forever $ do
  threadDelay (round 3.0e8)
  save table file

-- | Writes a 'UrlTable' to a file
--
-- The table is stored in a text file
-- as Haskell code for semplicity.
save :: UrlTable -> FilePath -> IO ()
save table file = do
  content <- show <$> H.toList table
  writeFile file content
  putStrLn "\n[breve] url table synced."

-- | Loads a URL table from a file
--
-- Once the file is loaded it will be synced
-- periodically (every 5min) on the disk.
load :: FilePath -> IO UrlTable
load file = do
  content <- readFile file
  table <- case readMaybe content of
    Just list -> H.fromList list
    Nothing   -> H.new
  forkIO (sync table file)
  return table

-- | Insert the URL in a table and return the name
insert :: UrlTable -> Url -> IO Name
insert table url = H.insert table new url >> return new
  where new = nameHash url

-- | Lookup a table for the associated URL
extract :: UrlTable -> Name -> IO (Maybe Url)
extract = H.lookup