git-annex/Logs/SingleValue/Pure.hs
Joey Hess 2d46038754
converting more log files to use Builder
Probably not any particular speedup in this, since most of these logs
are not written to often. Possibly chunk log writing is sped up, but
writes to chunk logs are interleaved with expensive data transfers to
remotes, so unlikely to be a noticiable speedup.
2019-01-09 13:06:37 -04:00

55 lines
1.5 KiB
Haskell

{- git-annex single-value log, pure operations
-
- Copyright 2014-2019 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU GPL version 3 or higher.
-}
module Logs.SingleValue.Pure where
import Annex.Common
import Logs.Line
import Annex.VectorClock
import qualified Data.Set as S
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
import qualified Data.Attoparsec.ByteString.Lazy as A
import Data.Attoparsec.ByteString.Char8 (char)
import Data.ByteString.Builder
class SingleValueSerializable v where
serialize :: v -> B.ByteString
deserialize :: B.ByteString -> Maybe v
data LogEntry v = LogEntry
{ changed :: VectorClock
, value :: v
} deriving (Eq, Ord)
type Log v = S.Set (LogEntry v)
buildLog :: (SingleValueSerializable v) => Log v -> Builder
buildLog = mconcat . map genline . S.toList
where
genline (LogEntry c v) =
buildVectorClock c <> sp <> byteString (serialize v) <> nl
sp = charUtf8 ' '
nl = charUtf8 '\n'
parseLog :: (Ord v, SingleValueSerializable v) => L.ByteString -> Log v
parseLog = S.fromList . fromMaybe []
. A.maybeResult . A.parse (logParser <* A.endOfInput)
logParser :: SingleValueSerializable v => A.Parser [LogEntry v]
logParser = parseLogLines $ LogEntry
<$> vectorClockParser
<* char ' '
<*> (parsevalue =<< A.takeByteString)
where
parsevalue = maybe (fail "log line parse failure") return . deserialize
newestValue :: Log v -> Maybe v
newestValue s
| S.null s = Nothing
| otherwise = Just (value $ S.findMax s)