{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module Ouroboros.Consensus.Storage.VolatileDB.API (
VolatileDB (..)
, BlockInfo (..)
, VolatileDBError (..)
, ApiMisuse (..)
, UnexpectedFailure (..)
, withDB
, getIsMember
, getPredecessor
, getKnownBlockComponent
) where
import qualified Codec.CBOR.Read as CBOR
import qualified Data.ByteString.Lazy as Lazy
import Data.Maybe (isJust)
import Data.Set (Set)
import Data.Typeable (Typeable)
import Data.Word (Word16)
import GHC.Generics (Generic)
import GHC.Stack (HasCallStack)
import NoThunks.Class (OnlyCheckWhnfNamed (..))
import Ouroboros.Network.Block (MaxSlotNo)
import Ouroboros.Consensus.Block
import Ouroboros.Consensus.Util.IOLike
import Ouroboros.Consensus.Storage.Common (BlockComponent (..))
import Ouroboros.Consensus.Storage.FS.API.Types (FsError, FsPath)
data VolatileDB m blk = VolatileDB {
VolatileDB m blk -> HasCallStack => m ()
closeDB :: HasCallStack => m ()
, VolatileDB m blk
-> forall b.
HasCallStack =>
BlockComponent blk b -> HeaderHash blk -> m (Maybe b)
getBlockComponent :: forall b. HasCallStack
=> BlockComponent blk b
-> HeaderHash blk
-> m (Maybe b)
, VolatileDB m blk -> HasCallStack => blk -> m ()
putBlock :: HasCallStack => blk -> m ()
, VolatileDB m blk
-> HasCallStack => STM m (ChainHash blk -> Set (HeaderHash blk))
filterByPredecessor :: HasCallStack => STM m (ChainHash blk -> Set (HeaderHash blk))
, VolatileDB m blk
-> HasCallStack => STM m (HeaderHash blk -> Maybe (BlockInfo blk))
getBlockInfo :: HasCallStack => STM m (HeaderHash blk -> Maybe (BlockInfo blk))
, VolatileDB m blk -> HasCallStack => SlotNo -> m ()
garbageCollect :: HasCallStack => SlotNo -> m ()
, VolatileDB m blk -> HasCallStack => STM m MaxSlotNo
getMaxSlotNo :: HasCallStack => STM m MaxSlotNo
}
deriving Context -> VolatileDB m blk -> IO (Maybe ThunkInfo)
Proxy (VolatileDB m blk) -> String
(Context -> VolatileDB m blk -> IO (Maybe ThunkInfo))
-> (Context -> VolatileDB m blk -> IO (Maybe ThunkInfo))
-> (Proxy (VolatileDB m blk) -> String)
-> NoThunks (VolatileDB m blk)
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> String)
-> NoThunks a
forall (m :: * -> *) blk.
Context -> VolatileDB m blk -> IO (Maybe ThunkInfo)
forall (m :: * -> *) blk. Proxy (VolatileDB m blk) -> String
showTypeOf :: Proxy (VolatileDB m blk) -> String
$cshowTypeOf :: forall (m :: * -> *) blk. Proxy (VolatileDB m blk) -> String
wNoThunks :: Context -> VolatileDB m blk -> IO (Maybe ThunkInfo)
$cwNoThunks :: forall (m :: * -> *) blk.
Context -> VolatileDB m blk -> IO (Maybe ThunkInfo)
noThunks :: Context -> VolatileDB m blk -> IO (Maybe ThunkInfo)
$cnoThunks :: forall (m :: * -> *) blk.
Context -> VolatileDB m blk -> IO (Maybe ThunkInfo)
NoThunks via OnlyCheckWhnfNamed "VolatileDB" (VolatileDB m blk)
data BlockInfo blk = BlockInfo {
BlockInfo blk -> HeaderHash blk
biHash :: !(HeaderHash blk)
, BlockInfo blk -> SlotNo
biSlotNo :: !SlotNo
, BlockInfo blk -> BlockNo
biBlockNo :: !BlockNo
, BlockInfo blk -> ChainHash blk
biPrevHash :: !(ChainHash blk)
, BlockInfo blk -> IsEBB
biIsEBB :: !IsEBB
, :: !Word16
, :: !Word16
}
deriving (BlockInfo blk -> BlockInfo blk -> Bool
(BlockInfo blk -> BlockInfo blk -> Bool)
-> (BlockInfo blk -> BlockInfo blk -> Bool) -> Eq (BlockInfo blk)
forall blk.
StandardHash blk =>
BlockInfo blk -> BlockInfo blk -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BlockInfo blk -> BlockInfo blk -> Bool
$c/= :: forall blk.
StandardHash blk =>
BlockInfo blk -> BlockInfo blk -> Bool
== :: BlockInfo blk -> BlockInfo blk -> Bool
$c== :: forall blk.
StandardHash blk =>
BlockInfo blk -> BlockInfo blk -> Bool
Eq, Int -> BlockInfo blk -> ShowS
[BlockInfo blk] -> ShowS
BlockInfo blk -> String
(Int -> BlockInfo blk -> ShowS)
-> (BlockInfo blk -> String)
-> ([BlockInfo blk] -> ShowS)
-> Show (BlockInfo blk)
forall blk. StandardHash blk => Int -> BlockInfo blk -> ShowS
forall blk. StandardHash blk => [BlockInfo blk] -> ShowS
forall blk. StandardHash blk => BlockInfo blk -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BlockInfo blk] -> ShowS
$cshowList :: forall blk. StandardHash blk => [BlockInfo blk] -> ShowS
show :: BlockInfo blk -> String
$cshow :: forall blk. StandardHash blk => BlockInfo blk -> String
showsPrec :: Int -> BlockInfo blk -> ShowS
$cshowsPrec :: forall blk. StandardHash blk => Int -> BlockInfo blk -> ShowS
Show, (forall x. BlockInfo blk -> Rep (BlockInfo blk) x)
-> (forall x. Rep (BlockInfo blk) x -> BlockInfo blk)
-> Generic (BlockInfo blk)
forall x. Rep (BlockInfo blk) x -> BlockInfo blk
forall x. BlockInfo blk -> Rep (BlockInfo blk) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall blk x. Rep (BlockInfo blk) x -> BlockInfo blk
forall blk x. BlockInfo blk -> Rep (BlockInfo blk) x
$cto :: forall blk x. Rep (BlockInfo blk) x -> BlockInfo blk
$cfrom :: forall blk x. BlockInfo blk -> Rep (BlockInfo blk) x
Generic, Context -> BlockInfo blk -> IO (Maybe ThunkInfo)
Proxy (BlockInfo blk) -> String
(Context -> BlockInfo blk -> IO (Maybe ThunkInfo))
-> (Context -> BlockInfo blk -> IO (Maybe ThunkInfo))
-> (Proxy (BlockInfo blk) -> String)
-> NoThunks (BlockInfo blk)
forall blk.
(StandardHash blk, Typeable blk) =>
Context -> BlockInfo blk -> IO (Maybe ThunkInfo)
forall blk.
(StandardHash blk, Typeable blk) =>
Proxy (BlockInfo blk) -> String
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> String)
-> NoThunks a
showTypeOf :: Proxy (BlockInfo blk) -> String
$cshowTypeOf :: forall blk.
(StandardHash blk, Typeable blk) =>
Proxy (BlockInfo blk) -> String
wNoThunks :: Context -> BlockInfo blk -> IO (Maybe ThunkInfo)
$cwNoThunks :: forall blk.
(StandardHash blk, Typeable blk) =>
Context -> BlockInfo blk -> IO (Maybe ThunkInfo)
noThunks :: Context -> BlockInfo blk -> IO (Maybe ThunkInfo)
$cnoThunks :: forall blk.
(StandardHash blk, Typeable blk) =>
Context -> BlockInfo blk -> IO (Maybe ThunkInfo)
NoThunks)
data VolatileDBError =
ApiMisuse ApiMisuse
| UnexpectedFailure UnexpectedFailure
deriving (Int -> VolatileDBError -> ShowS
[VolatileDBError] -> ShowS
VolatileDBError -> String
(Int -> VolatileDBError -> ShowS)
-> (VolatileDBError -> String)
-> ([VolatileDBError] -> ShowS)
-> Show VolatileDBError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [VolatileDBError] -> ShowS
$cshowList :: [VolatileDBError] -> ShowS
show :: VolatileDBError -> String
$cshow :: VolatileDBError -> String
showsPrec :: Int -> VolatileDBError -> ShowS
$cshowsPrec :: Int -> VolatileDBError -> ShowS
Show)
instance Exception VolatileDBError where
displayException :: VolatileDBError -> String
displayException = \case
ApiMisuse {} ->
String
"VolatileDB incorrectly used, indicative of a bug"
UnexpectedFailure (FileSystemError FsError
fse) ->
FsError -> String
forall e. Exception e => e -> String
displayException FsError
fse
UnexpectedFailure {} ->
String
"The VolatileDB got corrupted, full validation will be enabled for the next startup"
data ApiMisuse =
ClosedDBError (Maybe SomeException)
deriving (Int -> ApiMisuse -> ShowS
[ApiMisuse] -> ShowS
ApiMisuse -> String
(Int -> ApiMisuse -> ShowS)
-> (ApiMisuse -> String)
-> ([ApiMisuse] -> ShowS)
-> Show ApiMisuse
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ApiMisuse] -> ShowS
$cshowList :: [ApiMisuse] -> ShowS
show :: ApiMisuse -> String
$cshow :: ApiMisuse -> String
showsPrec :: Int -> ApiMisuse -> ShowS
$cshowsPrec :: Int -> ApiMisuse -> ShowS
Show)
data UnexpectedFailure =
FileSystemError FsError
| forall blk. (Typeable blk, StandardHash blk) =>
ParseError FsPath (RealPoint blk) CBOR.DeserialiseFailure
| forall blk. (Typeable blk, StandardHash blk) =>
TrailingDataError FsPath (RealPoint blk) Lazy.ByteString
| forall blk. (Typeable blk, StandardHash blk) =>
MissingBlockError (Proxy blk) (HeaderHash blk)
| forall blk. (Typeable blk, StandardHash blk) =>
CorruptBlockError (Proxy blk) (HeaderHash blk)
deriving instance Show UnexpectedFailure
withDB ::
(HasCallStack, MonadThrow m)
=> m (VolatileDB m blk)
-> (VolatileDB m blk -> m a)
-> m a
withDB :: m (VolatileDB m blk) -> (VolatileDB m blk -> m a) -> m a
withDB m (VolatileDB m blk)
openDB = m (VolatileDB m blk)
-> (VolatileDB m blk -> m ()) -> (VolatileDB m blk -> m a) -> m a
forall (m :: * -> *) a b c.
MonadThrow m =>
m a -> (a -> m b) -> (a -> m c) -> m c
bracket m (VolatileDB m blk)
openDB VolatileDB m blk -> m ()
forall (m :: * -> *) blk. VolatileDB m blk -> HasCallStack => m ()
closeDB
getIsMember ::
Functor (STM m)
=> VolatileDB m blk
-> STM m (HeaderHash blk -> Bool)
getIsMember :: VolatileDB m blk -> STM m (HeaderHash blk -> Bool)
getIsMember = ((HeaderHash blk -> Maybe (BlockInfo blk))
-> HeaderHash blk -> Bool)
-> STM m (HeaderHash blk -> Maybe (BlockInfo blk))
-> STM m (HeaderHash blk -> Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Maybe (BlockInfo blk) -> Bool
forall a. Maybe a -> Bool
isJust (Maybe (BlockInfo blk) -> Bool)
-> (HeaderHash blk -> Maybe (BlockInfo blk))
-> HeaderHash blk
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) (STM m (HeaderHash blk -> Maybe (BlockInfo blk))
-> STM m (HeaderHash blk -> Bool))
-> (VolatileDB m blk
-> STM m (HeaderHash blk -> Maybe (BlockInfo blk)))
-> VolatileDB m blk
-> STM m (HeaderHash blk -> Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. VolatileDB m blk -> STM m (HeaderHash blk -> Maybe (BlockInfo blk))
forall (m :: * -> *) blk.
VolatileDB m blk
-> HasCallStack => STM m (HeaderHash blk -> Maybe (BlockInfo blk))
getBlockInfo
getPredecessor ::
Functor (STM m)
=> VolatileDB m blk
-> STM m (HeaderHash blk -> Maybe (ChainHash blk))
getPredecessor :: VolatileDB m blk -> STM m (HeaderHash blk -> Maybe (ChainHash blk))
getPredecessor = ((HeaderHash blk -> Maybe (BlockInfo blk))
-> HeaderHash blk -> Maybe (ChainHash blk))
-> STM m (HeaderHash blk -> Maybe (BlockInfo blk))
-> STM m (HeaderHash blk -> Maybe (ChainHash blk))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((BlockInfo blk -> ChainHash blk)
-> Maybe (BlockInfo blk) -> Maybe (ChainHash blk)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap BlockInfo blk -> ChainHash blk
forall blk. BlockInfo blk -> ChainHash blk
biPrevHash (Maybe (BlockInfo blk) -> Maybe (ChainHash blk))
-> (HeaderHash blk -> Maybe (BlockInfo blk))
-> HeaderHash blk
-> Maybe (ChainHash blk)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) (STM m (HeaderHash blk -> Maybe (BlockInfo blk))
-> STM m (HeaderHash blk -> Maybe (ChainHash blk)))
-> (VolatileDB m blk
-> STM m (HeaderHash blk -> Maybe (BlockInfo blk)))
-> VolatileDB m blk
-> STM m (HeaderHash blk -> Maybe (ChainHash blk))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. VolatileDB m blk -> STM m (HeaderHash blk -> Maybe (BlockInfo blk))
forall (m :: * -> *) blk.
VolatileDB m blk
-> HasCallStack => STM m (HeaderHash blk -> Maybe (BlockInfo blk))
getBlockInfo
getKnownBlockComponent ::
(MonadThrow m, HasHeader blk)
=> VolatileDB m blk
-> BlockComponent blk b
-> HeaderHash blk
-> m b
getKnownBlockComponent :: VolatileDB m blk -> BlockComponent blk b -> HeaderHash blk -> m b
getKnownBlockComponent VolatileDB m blk
db BlockComponent blk b
blockComponent HeaderHash blk
hash = do
Either VolatileDBError b
mBlock <- VolatileDB m blk
-> HeaderHash blk -> Maybe b -> Either VolatileDBError b
forall (proxy :: * -> *) blk b.
(StandardHash blk, Typeable blk) =>
proxy blk -> HeaderHash blk -> Maybe b -> Either VolatileDBError b
mustExist VolatileDB m blk
db HeaderHash blk
hash (Maybe b -> Either VolatileDBError b)
-> m (Maybe b) -> m (Either VolatileDBError b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
VolatileDB m blk
-> BlockComponent blk b -> HeaderHash blk -> m (Maybe b)
forall (m :: * -> *) blk.
VolatileDB m blk
-> forall b.
HasCallStack =>
BlockComponent blk b -> HeaderHash blk -> m (Maybe b)
getBlockComponent VolatileDB m blk
db BlockComponent blk b
blockComponent HeaderHash blk
hash
case Either VolatileDBError b
mBlock of
Right b
b -> b -> m b
forall (m :: * -> *) a. Monad m => a -> m a
return b
b
Left VolatileDBError
err -> VolatileDBError -> m b
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO VolatileDBError
err
mustExist ::
forall proxy blk b. (StandardHash blk, Typeable blk)
=> proxy blk
-> HeaderHash blk
-> Maybe b
-> Either VolatileDBError b
mustExist :: proxy blk -> HeaderHash blk -> Maybe b -> Either VolatileDBError b
mustExist proxy blk
_ HeaderHash blk
hash = \case
Maybe b
Nothing -> VolatileDBError -> Either VolatileDBError b
forall a b. a -> Either a b
Left (VolatileDBError -> Either VolatileDBError b)
-> VolatileDBError -> Either VolatileDBError b
forall a b. (a -> b) -> a -> b
$ UnexpectedFailure -> VolatileDBError
UnexpectedFailure (UnexpectedFailure -> VolatileDBError)
-> UnexpectedFailure -> VolatileDBError
forall a b. (a -> b) -> a -> b
$ Proxy blk -> HeaderHash blk -> UnexpectedFailure
forall blk.
(Typeable blk, StandardHash blk) =>
Proxy blk -> HeaderHash blk -> UnexpectedFailure
MissingBlockError (Proxy blk
forall k (t :: k). Proxy t
Proxy @blk) HeaderHash blk
hash
Just b
b -> b -> Either VolatileDBError b
forall a b. b -> Either a b
Right (b -> Either VolatileDBError b) -> b -> Either VolatileDBError b
forall a b. (a -> b) -> a -> b
$ b
b