This commit is contained in:
Dmitry Zuikov 2024-05-29 15:56:42 +03:00
parent eb0dfe0b2d
commit 3d4ec7b3a4
2 changed files with 71 additions and 6 deletions

View File

@ -67,6 +67,7 @@ library
, atomic-write , atomic-write
, bytestring , bytestring
, bytestring-mmap , bytestring-mmap
, binary
, cache , cache
, containers , containers
, directory , directory

View File

@ -1,14 +1,20 @@
module HBS2.Storage.Compact module HBS2.Storage.Compact
( CompactStorage (
) where ) where
import Data.Word import Data.Word
import Data.ByteString import Data.ByteString (ByteString)
import Data.ByteString qualified as BS
import Data.ByteString.Lazy qualified as LBS
import Data.ByteString.Builder as B
import Data.Binary.Get
import Data.Coerce import Data.Coerce
import Codec.Serialise import Codec.Serialise
import GHC.Generics import GHC.Generics
import System.IO -- import System.IO
import Lens.Micro.Platform
import Control.Monad.Except
import UnliftIO import UnliftIO
-- compact storage -- compact storage
@ -34,16 +40,74 @@ data IndexEntry =
deriving stock Generic deriving stock Generic
data Header =
Header
{ hdrMagic :: Word16
, hdrVersion :: Word16
, hdrIndexOffset :: EntryOffset
}
deriving stock Generic
data CompactStorage = data CompactStorage =
CompactStorage CompactStorage
{ csHandle :: Handle { csHandle :: MVar Handle
} }
type ForCompactStorage m = MonadIO m type ForCompactStorage m = MonadIO m
data CompactStorageOpenOpt = Default
deriving stock (Eq,Ord)
compactStorageOpen :: ForCompactStorage m => FilePath -> m CompactStorage data CompactStorageOpenError =
compactStorageOpen fp = undefined InvalidHeader
deriving stock (Typeable,Show)
instance Exception CompactStorageOpenError
compactStorageOpen :: ForCompactStorage m
=> CompactStorageOpenOpt
-> FilePath
-> m CompactStorage
compactStorageOpen _ fp = do
ha <- openFile fp ReadWriteMode
mha <- newMVar ha
header <- readHeader mha >>= maybe (throwIO InvalidHeader) pure
pure $ CompactStorage mha
compactStorageCommit :: ForCompactStorage m => CompactStorage -> m ()
compactStorageCommit sto = do
pure ()
appendHeader :: ForCompactStorage m => Handle -> EntryOffset -> m ()
appendHeader ha offset = do
let bs = word16BE headerMagic
<> word16BE headerVersion
<> word64BE (coerce offset)
<> byteString (BS.replicate 52 0)
liftIO $ LBS.hPut ha (B.toLazyByteString bs)
readHeader :: ForCompactStorage m => MVar Handle -> m (Maybe Header)
readHeader mha = do
bs <- liftIO $ withMVar mha $ \ha -> do
hSeek ha SeekFromEnd (-64)
LBS.hGet ha 64
let what = flip runGetOrFail bs do
Header <$> getWord16be
<*> getWord16be
<*> getOffset
pure $ either (const Nothing) (Just . view _3) what
where
getOffset = EntryOffset <$> getWord64be
headerMagic :: Word16
headerMagic = 32264
headerVersion :: Word16
headerVersion = 1