git-annex/Logs/UUIDBased.hs
Joey Hess e2c44bf656 implement chunk logs
Slightly tricky as they are not normal UUIDBased logs, but are instead maps
from (uuid, chunksize) to chunkcount.

This commit was sponsored by Frank Thomas.
2014-07-24 16:23:36 -04:00

93 lines
2.4 KiB
Haskell

{- git-annex uuid-based logs
-
- This is used to store information about UUIDs in a way that can
- be union merged.
-
- A line of the log will look like: "UUID[ INFO[ timestamp=foo]]"
- The timestamp is last for backwards compatability reasons,
- and may not be present on old log lines.
-
- New uuid based logs instead use the form: "timestamp UUID INFO"
-
- Copyright 2011-2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
module Logs.UUIDBased (
Log,
LogEntry(..),
TimeStamp(..),
parseLog,
parseLogNew,
parseLogWithUUID,
showLog,
showLogNew,
changeLog,
addLog,
simpleMap,
) where
import qualified Data.Map as M
import Data.Time.Clock.POSIX
import Data.Time
import System.Locale
import Common
import Types.UUID
import Logs.MapLog
type Log v = MapLog UUID v
showLog :: (v -> String) -> Log v -> String
showLog shower = unlines . map showpair . M.toList
where
showpair (k, LogEntry (Date p) v) =
unwords [fromUUID k, shower v, tskey ++ show p]
showpair (k, LogEntry Unknown v) =
unwords [fromUUID k, shower v]
parseLog :: (String -> Maybe a) -> String -> Log a
parseLog = parseLogWithUUID . const
parseLogWithUUID :: (UUID -> String -> Maybe a) -> String -> Log a
parseLogWithUUID parser = M.fromListWith best . mapMaybe parse . lines
where
parse line
-- This is a workaround for a bug that caused
-- NoUUID items to be stored in the log.
-- It can be removed at any time; is just here to clean
-- up logs where that happened temporarily.
| " " `isPrefixOf` line = Nothing
| null ws = Nothing
| otherwise = parser u (unwords info) >>= makepair
where
makepair v = Just (u, LogEntry ts v)
ws = words line
u = toUUID $ Prelude.head ws
t = Prelude.last ws
ts
| tskey `isPrefixOf` t =
pdate $ drop 1 $ dropWhile (/= '=') t
| otherwise = Unknown
info
| ts == Unknown = drop 1 ws
| otherwise = drop 1 $ beginning ws
pdate s = case parseTime defaultTimeLocale "%s%Qs" s of
Nothing -> Unknown
Just d -> Date $ utcTimeToPOSIXSeconds d
showLogNew :: (v -> String) -> Log v -> String
showLogNew = showMapLog fromUUID
parseLogNew :: (String -> Maybe v) -> String -> Log v
parseLogNew = parseMapLog (Just . toUUID)
changeLog :: POSIXTime -> UUID -> v -> Log v -> Log v
changeLog = changeMapLog
addLog :: UUID -> LogEntry v -> Log v -> Log v
addLog = addMapLog
tskey :: String
tskey = "timestamp="