-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | A transactional, ACID compliant, embeddable key-value store.
--   
--   Haskey is a transactional, ACID compliant, embeddable, scalable
--   key-value store written entirely in Haskell.
--   
--   For more information on how to use this package, visit
--   <a>https://github.com/haskell-haskey/haskey</a>
@package haskey
@version 0.3.0.2


-- | Module describing the tree structure of the free page database.
module Database.Haskey.Alloc.Concurrent.Internal.FreePages.Tree

-- | The main tree structure of the free page database.
--   
--   The main free page database tree maps a <a>TxId</a> to a
--   <a>FreeSubtree</a>.
type FreeTree = Tree TxId FreeSubtree

-- | the subtree structure of the free page database.
--   
--   Just a collection of free <a>PageId</a>s.
type FreeSubtree = NonEmptyTree PageId ()

-- | Replace the subtree of a certain <a>TxId</a>.
replaceSubtree :: AllocM m => TxId -> NonEmpty PageId -> FreeTree -> m FreeTree

-- | Delete the subtree of a certain <a>TxId</a>.
--   
--   The <a>TxId</a> will not be present anymore in the free tree after
--   this call.
deleteSubtree :: AllocM m => TxId -> FreeTree -> m FreeTree

-- | Insert a subtree for a certain <a>TxId</a>.
insertSubtree :: AllocM m => TxId -> NonEmpty PageId -> FreeTree -> m FreeTree


-- | Environments of a read or write transaction.
module Database.Haskey.Alloc.Concurrent.Internal.Environment
data StateType
TypeData :: StateType
TypeIndex :: StateType

-- | Wrapper around a type to indicate it belongs to a file with either
--   data/leaf nodes or index nodes.
data S (t :: StateType) a
[DataState] :: a -> S  'TypeData a
[IndexState] :: a -> S  'TypeIndex a
getSValue :: S t a -> a
newtype ReaderEnv hnds
ReaderEnv :: hnds -> ReaderEnv hnds
[readerHnds] :: ReaderEnv hnds -> hnds
data FileState stateType
FileState :: ![NewlyFreed] -> !(S stateType PageId) -> !(S stateType PageId) -> !(Set PageId) -> !(S stateType FreeTree) -> !(S stateType [FreePage]) -> FileState stateType

-- | Pages free'd in this transaction, not ready for reuse until the
--   transaction is commited.
[fileStateNewlyFreedPages] :: FileState stateType -> ![NewlyFreed]

-- | The original number of pages in the file, before the transaction
--   started.
[fileStateOriginalNumPages] :: FileState stateType -> !(S stateType PageId)

-- | The new uncommited number of pages in the file.
--   
--   All pages in the range <a>fileStateOriginalNumPages</a> to
--   <a>fileStateNewNumPages</a> (excluding) are freshly allocated in the
--   ongoing transaction.
[fileStateNewNumPages] :: FileState stateType -> !(S stateType PageId)

-- | Pages written to in this transaction.
[fileStateDirtyPages] :: FileState stateType -> !(Set PageId)

-- | The root of the free tree, might change during a transaction.
[fileStateFreeTree] :: FileState stateType -> !(S stateType FreeTree)

-- | All pages that are immediately ready for reuse in this and any
--   subsequent transactions.
[fileStateCachedFreePages] :: FileState stateType -> !(S stateType [FreePage])
data WriterEnv hnds
WriterEnv :: !hnds -> !TxId -> Map TxId Integer -> FileState  'TypeIndex -> FileState  'TypeData -> !Bool -> !(Set DirtyOverflow) -> !Word32 -> ![OldOverflow] -> WriterEnv hnds
[writerHnds] :: WriterEnv hnds -> !hnds
[writerTxId] :: WriterEnv hnds -> !TxId
[writerReaders] :: WriterEnv hnds -> Map TxId Integer

-- | State of the file with index nodes.
[writerIndexFileState] :: WriterEnv hnds -> FileState  'TypeIndex

-- | State of the file with data/leaf nodes.
[writerDataFileState] :: WriterEnv hnds -> FileState  'TypeData

-- | Whether or not querying free pages from the free is enabled.
[writerQueryFreeTreeOn] :: WriterEnv hnds -> !Bool

-- | Newly allocated overflow pages in this transaction.
[writerDirtyOverflows] :: WriterEnv hnds -> !(Set DirtyOverflow)

-- | Counts how many overflow pages were already allocated in this
--   transaction.
[writerOverflowCounter] :: WriterEnv hnds -> !Word32

-- | Old overflow pages that were removed in this transaction and should be
--   deleted when no longer in use.
[writerRemovedOverflows] :: WriterEnv hnds -> ![OldOverflow]

-- | Create a new writer.
newWriter :: hnd -> TxId -> Map TxId Integer -> S  'TypeData PageId -> S  'TypeIndex PageId -> S  'TypeData [FreePage] -> S  'TypeIndex [FreePage] -> S  'TypeData FreeTree -> S  'TypeIndex FreeTree -> WriterEnv hnd

-- | Wrapper around <a>PageId</a> indicating it is newly free'd and cannot
--   be reused in the same transaction.
newtype NewlyFreed
NewlyFreed :: PageId -> NewlyFreed

-- | Wrapper around <a>PageId</a> indicating it is free and can be reused
--   in any transaction.
newtype FreePage
FreePage :: PageId -> FreePage

-- | Wrapper around <a>PageId</a> indicating that it is dirty, i.e. written
--   to in this transaction.
newtype Dirty
Dirty :: PageId -> Dirty

-- | Try to free a page, given a set of dirty pages.
--   
--   If the page was dirty, a <a>FreePage</a> page is added to the
--   environment, if not a <a>NewlyFreed</a> page is added to the
--   environment.
--   
--   Btw, give me lenses...
freePage :: (Functor m, MonadState (WriterEnv hnd) m) => S stateType PageId -> m ()
updateFileState :: FileState t -> (forall a. a -> S t a) -> Maybe Dirty -> PageId -> FileState t

-- | Get a <a>Dirty</a> page, by first proving it is in fact dirty.
dirty :: (Functor m, MonadState (WriterEnv hnd) m) => S stateType PageId -> m (Maybe Dirty)

-- | Touch a fresh page, make it dirty.
--   
--   We really need lenses...
touchPage :: MonadState (WriterEnv hnd) m => S stateType PageId -> m ()

-- | Wrapper around <a>OverflowId</a> indicating that it is dirty.
newtype DirtyOverflow
DirtyOverflow :: OverflowId -> DirtyOverflow

-- | Wrapper around <a>OverflowId</a> indicating that it is an overflow
--   page from a previous transaction.
newtype OldOverflow
OldOverflow :: OverflowId -> OldOverflow

-- | Touch a fresh overflow page, making it dirty.
touchOverflow :: MonadState (WriterEnv hnd) m => OverflowId -> m ()

-- | Get the type of the overflow page.
overflowType :: MonadState (WriterEnv hnd) m => OverflowId -> m (Either DirtyOverflow OldOverflow)

-- | Free an old overflow page.
removeOldOverflow :: MonadState (WriterEnv hdn) m => OldOverflow -> m ()
instance GHC.Show.Show Database.Haskey.Alloc.Concurrent.Internal.Environment.OldOverflow
instance GHC.Classes.Ord Database.Haskey.Alloc.Concurrent.Internal.Environment.OldOverflow
instance GHC.Classes.Eq Database.Haskey.Alloc.Concurrent.Internal.Environment.OldOverflow
instance GHC.Show.Show Database.Haskey.Alloc.Concurrent.Internal.Environment.DirtyOverflow
instance GHC.Classes.Ord Database.Haskey.Alloc.Concurrent.Internal.Environment.DirtyOverflow
instance GHC.Classes.Eq Database.Haskey.Alloc.Concurrent.Internal.Environment.DirtyOverflow
instance GHC.Show.Show Database.Haskey.Alloc.Concurrent.Internal.Environment.Dirty
instance GHC.Classes.Ord Database.Haskey.Alloc.Concurrent.Internal.Environment.Dirty
instance GHC.Classes.Eq Database.Haskey.Alloc.Concurrent.Internal.Environment.Dirty
instance GHC.Show.Show Database.Haskey.Alloc.Concurrent.Internal.Environment.FreePage
instance GHC.Classes.Ord Database.Haskey.Alloc.Concurrent.Internal.Environment.FreePage
instance GHC.Classes.Eq Database.Haskey.Alloc.Concurrent.Internal.Environment.FreePage
instance Data.Binary.Class.Binary Database.Haskey.Alloc.Concurrent.Internal.Environment.FreePage
instance GHC.Show.Show Database.Haskey.Alloc.Concurrent.Internal.Environment.NewlyFreed
instance GHC.Classes.Ord Database.Haskey.Alloc.Concurrent.Internal.Environment.NewlyFreed
instance GHC.Classes.Eq Database.Haskey.Alloc.Concurrent.Internal.Environment.NewlyFreed
instance GHC.Show.Show a => GHC.Show.Show (Database.Haskey.Alloc.Concurrent.Internal.Environment.S t a)
instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Database.Haskey.Alloc.Concurrent.Internal.Environment.S 'Database.Haskey.Alloc.Concurrent.Internal.Environment.TypeData a)
instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Database.Haskey.Alloc.Concurrent.Internal.Environment.S 'Database.Haskey.Alloc.Concurrent.Internal.Environment.TypeIndex a)
instance GHC.Base.Functor (Database.Haskey.Alloc.Concurrent.Internal.Environment.S t)

module Database.Haskey.Alloc.Concurrent.Internal.FreePages.Save

-- | Save the free pages from the dirty page list and the free page cache.
saveFreePages :: AllocM m => TxId -> FileState t -> m FreeTree

-- | Save the newly free pages of the current transaction, as stored by
--   <a>fileStateNewlyFreedPages</a>.
saveNewlyFreedPages :: AllocM m => TxId -> FileState t -> FreeTree -> m FreeTree


-- | This module implements mechanisms to work with transactions.
module Database.Haskey.Alloc.Transaction

-- | A committed or aborted transaction, with a return value of type
--   <tt>a</tt>.
data Transaction r a
Commit :: r -> a -> Transaction r a
Abort :: a -> Transaction r a

-- | Commit the new tree and return a computed value.
commit :: AllocM n => a -> r -> n (Transaction r a)

-- | Commit the new tree, without return a computed value.
commit_ :: AllocM n => r -> n (Transaction r ())

-- | Abort the transaction and return a computed value.
abort :: AllocM n => a -> n (Transaction r a)

-- | Abort the transaction, without returning a computed value.
abort_ :: AllocM n => n (Transaction r ())


-- | A storage back-end manages physical storage of pages.
module Database.Haskey.Store.Class

-- | A storage back-end that can store and fetch physical pages.
class (Applicative m, Monad m) => StoreM hnd m | m -> hnd

-- | Open a database handle for reading and writing.
openHandle :: StoreM hnd m => hnd -> m ()

-- | Obtain a lock on the given handle, so no other process can access it.
lockHandle :: StoreM hnd m => hnd -> m ()

-- | Release the lock on the given handle, so other processes can access
--   it.
releaseHandle :: StoreM hnd m => hnd -> m ()

-- | Flush the contents of a handle to disk (or other storage).
flushHandle :: StoreM hnd m => hnd -> m ()

-- | Close a database handle.
closeHandle :: StoreM hnd m => hnd -> m ()

-- | Remove a handle from the storage back-end.
removeHandle :: StoreM hnd m => hnd -> m ()

-- | A function that calculates the hypothetical size of a node, if it were
--   to be written to a page (regardless of the maximum page size).
nodePageSize :: (StoreM hnd m, Key key, Value val) => m (Height height -> Node height key val -> PageSize)

-- | The maximum page size the allocator can handle.
maxPageSize :: StoreM hnd m => m PageSize

-- | Get the maximum key size
--   
--   The default implementation will repeatedly call
--   <a>calculateMaxKeySize</a>. You might want to cache this value in your
--   own implementation.
maxKeySize :: StoreM hnd m => m Word64

-- | Get the maximum value size
--   
--   The default implementation will repeatedly call
--   <a>calculateMaxValueSize</a>. You might want to cache this value in
--   your own implementation.
maxValueSize :: StoreM hnd m => m Word64

-- | Read a page and return the actual node and the transaction id when the
--   node was written.
getNodePage :: (StoreM hnd m, Key key, Value val) => hnd -> Height height -> Proxy key -> Proxy val -> NodeId height key val -> m (Node height key val)

-- | Write a node to a physical page.
putNodePage :: (StoreM hnd m, Key key, Value val) => hnd -> Height height -> NodeId height key val -> Node height key val -> m ()

-- | Read a value from an overflow page
getOverflow :: (StoreM hnd m, (Value val)) => hnd -> Proxy val -> m val

-- | Write a value to an overflow page
putOverflow :: (StoreM hnd m, (Value val)) => hnd -> val -> m ()

-- | List overflow pages in the specific overflow directory.
--   
--   The result should include **AT LEAST** the handles in the specified
--   directory, but it may contain more handles, even handles that do not
--   belong to an overflow page.
listOverflows :: StoreM hnd m => hnd -> m [hnd]

-- | Search an arbitrary number, less than a limit, greater than a starting
--   value.
arbitrarySearch :: (Ord v, Integral n) => n -> (n -> v) -> v -> n

-- | Calculate the maximum key size.
--   
--   Return the size for which at least 4 key-value pairs with keys and
--   values of that size can fit in a leaf node.
calculateMaxKeySize :: PageSize -> (Node  'Z ZeroEncoded ZeroEncoded -> PageSize) -> Word64

-- | Calculate the maximum value size.
--   
--   Return the size for which at least 4 key-value pairs of the specified
--   maximum key size and values of the returned size can fit in a leaf
--   node. that size can fit in a leaf node.
calculateMaxValueSize :: PageSize -> Word64 -> (Node  'Z ZeroEncoded ZeroEncoded -> PageSize) -> Word64

-- | Data type which encodes the integer using a variable amount of NULL or
--   ONE bytes.
data ZeroEncoded
ZeroEncoded :: Word64 -> Word64 -> ZeroEncoded
[getZeroEncoded] :: ZeroEncoded -> Word64
[getZeroEncodedValue] :: ZeroEncoded -> Word64
instance GHC.Show.Show Database.Haskey.Store.Class.ZeroEncoded
instance GHC.Classes.Ord Database.Haskey.Store.Class.ZeroEncoded
instance GHC.Classes.Eq Database.Haskey.Store.Class.ZeroEncoded
instance Data.Binary.Class.Binary Database.Haskey.Store.Class.ZeroEncoded
instance Data.BTree.Primitives.Key.Key Database.Haskey.Store.Class.ZeroEncoded
instance Data.BTree.Primitives.Value.Value Database.Haskey.Store.Class.ZeroEncoded
instance Database.Haskey.Store.Class.StoreM hnd m => Database.Haskey.Store.Class.StoreM hnd (Control.Monad.Trans.State.Lazy.StateT s m)
instance Database.Haskey.Store.Class.StoreM hnd m => Database.Haskey.Store.Class.StoreM hnd (Control.Monad.Trans.Reader.ReaderT s m)


-- | Storage back-ends that manage physical storage of pages.
module Database.Haskey.Store


-- | Data structures and functions related to handling overflow pages.
module Database.Haskey.Alloc.Concurrent.Internal.Overflow
getNewOverflowId :: (Functor m, MonadState (WriterEnv hnd) m) => m OverflowId
getOverflowHandle :: FilePath -> OverflowId -> FilePath
getOverflowDir :: FilePath -> TxId -> FilePath
readOverflowId :: FilePath -> Maybe OverflowId
showHex' :: (Integral a, Show a) => a -> String
readHex' :: (Eq a, Num a) => String -> Maybe (a, String)

-- | The main tree structure of the freed overflow page tree
type OverflowTree = Tree TxId OverflowSubtree

-- | The subtree structure of the freed overflow page tree
type OverflowSubtree = NonEmptyTree OverflowId ()

-- | Save a set of overflow ids that were free'd in the transaction.
insertOverflowIds :: AllocM m => TxId -> NonEmpty OverflowId -> OverflowTree -> m OverflowTree

-- | Delete the set of overflow ids that were free'd in the transaction.
deleteOverflowIds :: AllocM m => TxId -> OverflowTree -> m OverflowTree
deleteOutdatedOverflowIds :: (Functor m, AllocM m, MonadIO m, MonadState (WriterEnv hnd) m) => OverflowTree -> m (Maybe OverflowTree)


-- | This module implements data structures and function related to the
--   metadata of the concurrent page allocator.
module Database.Haskey.Alloc.Concurrent.Internal.Meta

-- | User-defined data root stored inside <a>ConcurrentMeta</a>.
--   
--   This can be a user-defined collection of <a>Tree</a> roots.
class Value root => Root root

-- | Data type used to point to the most recent version of the meta data.
data CurrentMetaPage
Meta1 :: CurrentMetaPage
Meta2 :: CurrentMetaPage

-- | Meta data of the page allocator.
--   
--   The <tt>root</tt> type parameter should be a user-defined collection
--   of <a>Tree</a> roots, instantiating the <a>Root</a> type class.
--   
--   To store store a single tree, use <tt>ConcurrentMeta (Tree k v)</tt>.
data ConcurrentMeta root
ConcurrentMeta :: TxId -> S  'TypeData PageId -> S  'TypeIndex PageId -> root -> S  'TypeData FreeTree -> S  'TypeIndex FreeTree -> OverflowTree -> S  'TypeData [FreePage] -> S  'TypeIndex [FreePage] -> ConcurrentMeta root
[concurrentMetaRevision] :: ConcurrentMeta root -> TxId
[concurrentMetaDataNumPages] :: ConcurrentMeta root -> S  'TypeData PageId
[concurrentMetaIndexNumPages] :: ConcurrentMeta root -> S  'TypeIndex PageId
[concurrentMetaRoot] :: ConcurrentMeta root -> root
[concurrentMetaDataFreeTree] :: ConcurrentMeta root -> S  'TypeData FreeTree
[concurrentMetaIndexFreeTree] :: ConcurrentMeta root -> S  'TypeIndex FreeTree
[concurrentMetaOverflowTree] :: ConcurrentMeta root -> OverflowTree
[concurrentMetaDataCachedFreePages] :: ConcurrentMeta root -> S  'TypeData [FreePage]
[concurrentMetaIndexCachedFreePages] :: ConcurrentMeta root -> S  'TypeIndex [FreePage]

-- | A class representing the storage requirements of the page allocator.
--   
--   A store supporting the page allocator should be an instance of this
--   class.
class StoreM FilePath m => ConcurrentMetaStoreM m

-- | Write the meta-data structure to a certain page.
putConcurrentMeta :: (ConcurrentMetaStoreM m, Root root) => FilePath -> ConcurrentMeta root -> m ()

-- | Try to read the meta-data structure from a handle, or return
--   <a>Nothing</a> if the handle doesn't contain a meta page.
readConcurrentMeta :: (ConcurrentMetaStoreM m, Root root) => FilePath -> Proxy root -> m (Maybe (ConcurrentMeta root))
instance GHC.Generics.Generic (Database.Haskey.Alloc.Concurrent.Internal.Meta.ConcurrentMeta root)
instance GHC.Show.Show root => GHC.Show.Show (Database.Haskey.Alloc.Concurrent.Internal.Meta.ConcurrentMeta root)
instance Data.Binary.Class.Binary root => Data.Binary.Class.Binary (Database.Haskey.Alloc.Concurrent.Internal.Meta.ConcurrentMeta root)
instance (Data.BTree.Primitives.Key.Key k, Data.BTree.Primitives.Value.Value v) => Database.Haskey.Alloc.Concurrent.Internal.Meta.Root (Data.BTree.Impure.Internal.Structures.Tree k v)

module Database.Haskey.Alloc.Concurrent.Internal.FreePages.Query

-- | Get a free page.
--   
--   First try to get one from the in-memory dirty pages. Then try to get
--   one from the in-memory free page cache stored in
--   <a>fileStateCachedFreePages</a>. If that one is empty, actually query
--   one from the free database.
getFreePageId :: (Functor m, AllocM m, MonadIO m, MonadState (WriterEnv hnd) m) => S stateType () -> m (Maybe PageId)

-- | Get a cached free page.
--   
--   Get a free page from the free database cache stored in
--   <a>fileStateCachedFreePages</a>.
getCachedFreePageId :: (Functor m, MonadState (WriterEnv hnd) m) => S stateType () -> m (Maybe PageId)

-- | Try to get a list of free pages from the free page database, return
--   the first free one for immediate use, and store the rest in the
--   environment.
--   
--   Immediately remove the queried free pages from the free tree.
queryNewFreePageIds :: (AllocM m, MonadIO m, MonadState (WriterEnv hnd) m) => S stateType () -> m (Maybe PageId)

-- | Lookup a list of free pages from the free page database, guaranteed to
--   be old enough.
lookupValidFreePageIds :: (MonadIO m, AllocReaderM m, MonadState (WriterEnv hnd) m) => FreeTree -> m (Maybe (TxId, NonEmpty PageId))

-- | Lookup a list of free pages from the free page database.
lookupFreePageIds :: (Functor m, AllocReaderM m, MonadState (WriterEnv hnd) m) => FreeTree -> m (Maybe (Unchecked (TxId, NonEmpty PageId)))

-- | Auxiliry type to ensure the transaction ID of free pages are checked.
newtype Unchecked a
Unchecked :: a -> Unchecked a

-- | Check the transaction ID of the free pages, if it's to old, return
--   <a>Nothing</a>.
checkFreePages :: (Functor m, MonadIO m, MonadState (WriterEnv hnd) m) => Unchecked (TxId, NonEmpty PageId) -> m (Maybe (TxId, NonEmpty PageId))


-- | This module implements the <a>ConcurrentT</a> monad.
--   
--   The <a>ConcurrentT</a> monad is used to implement a page allocator
--   with concurrent readers and serialized writers.
module Database.Haskey.Alloc.Concurrent.Internal.Monad

-- | All necessary database handles.
data ConcurrentHandles
ConcurrentHandles :: FilePath -> FilePath -> FilePath -> FilePath -> FilePath -> FilePath -> ConcurrentHandles
[concurrentHandlesRoot] :: ConcurrentHandles -> FilePath
[concurrentHandlesData] :: ConcurrentHandles -> FilePath
[concurrentHandlesIndex] :: ConcurrentHandles -> FilePath
[concurrentHandlesMetadata1] :: ConcurrentHandles -> FilePath
[concurrentHandlesMetadata2] :: ConcurrentHandles -> FilePath
[concurrentHandlesOverflowDir] :: ConcurrentHandles -> FilePath

-- | Construct a set of <a>ConcurrentHandles</a> from a root directory.
concurrentHandles :: FilePath -> ConcurrentHandles

-- | Monad in which page allocations can take place.
--   
--   The monad has access to a <a>ConcurrentMetaStoreM</a> back-end which
--   manages can store and retreive the corresponding metadata.
newtype ConcurrentT env hnd m a
ConcurrentT :: StateT (env hnd) m a -> ConcurrentT env hnd m a
[fromConcurrentT] :: ConcurrentT env hnd m a -> StateT (env hnd) m a

-- | Run the actions in an <a>ConcurrentT</a> monad, given a reader or
--   writer environment.
runConcurrentT :: ConcurrentMetaStoreM m => ConcurrentT env ConcurrentHandles m a -> env ConcurrentHandles -> m (a, env ConcurrentHandles)

-- | Evaluate the actions in an <a>ConcurrentT</a> monad, given a reader or
--   writer environment.
evalConcurrentT :: ConcurrentMetaStoreM m => ConcurrentT env ConcurrentHandles m a -> env ConcurrentHandles -> m a
readOverflow' :: (ConcurrentMetaStoreM m, Value v) => FilePath -> OverflowId -> ConcurrentT env hnd m v
getWriterHnd :: MonadState (WriterEnv ConcurrentHandles) m => Height height -> m FilePath
getReaderHnd :: MonadState (ReaderEnv ConcurrentHandles) m => Height height -> m FilePath
instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState (env hnd) (Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentT env hnd m)
instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentT env hnd m)
instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentT env hnd m)
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentT env hnd m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentT env hnd m)
instance GHC.Base.Monad m => GHC.Base.Monad (Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentT env hnd m)
instance GHC.Base.Monad m => GHC.Base.Applicative (Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentT env hnd m)
instance GHC.Base.Functor m => GHC.Base.Functor (Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentT env hnd m)
instance GHC.Show.Show Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentHandles
instance Control.Monad.Trans.Class.MonadTrans (Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentT env hnd)
instance (Database.Haskey.Alloc.Concurrent.Internal.Meta.ConcurrentMetaStoreM m, Control.Monad.IO.Class.MonadIO m) => Data.BTree.Alloc.Class.AllocM (Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentT Database.Haskey.Alloc.Concurrent.Internal.Environment.WriterEnv Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentHandles m)
instance Database.Haskey.Alloc.Concurrent.Internal.Meta.ConcurrentMetaStoreM m => Data.BTree.Alloc.Class.AllocReaderM (Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentT Database.Haskey.Alloc.Concurrent.Internal.Environment.WriterEnv Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentHandles m)
instance Database.Haskey.Alloc.Concurrent.Internal.Meta.ConcurrentMetaStoreM m => Data.BTree.Alloc.Class.AllocReaderM (Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentT Database.Haskey.Alloc.Concurrent.Internal.Environment.ReaderEnv Database.Haskey.Alloc.Concurrent.Internal.Monad.ConcurrentHandles m)


-- | This module implements data structures and functions related to the
--   database.
module Database.Haskey.Alloc.Concurrent.Internal.Database

-- | An active concurrent database.
--   
--   This can be shared amongst threads.
data ConcurrentDb root
ConcurrentDb :: ConcurrentHandles -> RLock -> TVar CurrentMetaPage -> TVar (ConcurrentMeta root) -> TVar (ConcurrentMeta root) -> Map TxId Integer -> ConcurrentDb root
[concurrentDbHandles] :: ConcurrentDb root -> ConcurrentHandles
[concurrentDbWriterLock] :: ConcurrentDb root -> RLock
[concurrentDbCurrentMeta] :: ConcurrentDb root -> TVar CurrentMetaPage
[concurrentDbMeta1] :: ConcurrentDb root -> TVar (ConcurrentMeta root)
[concurrentDbMeta2] :: ConcurrentDb root -> TVar (ConcurrentMeta root)
[concurrentDbReaders] :: ConcurrentDb root -> Map TxId Integer

-- | Lock the database.
--   
--   This needs to be called manually, if you want exclusive access, before
--   calling either <a>createConcurrentDb</a> or <a>openConcurrentDb</a>
--   
--   Use <a>unlockConcurrentDb</a> using the <a>bracket</a> pattern to
--   properly unlock the database.
lockConcurrentDb :: ConcurrentMetaStoreM m => ConcurrentHandles -> m ()

-- | Unlock the database.
unlockConcurrentDb :: ConcurrentMetaStoreM m => ConcurrentHandles -> m ()

-- | Open all concurrent handles.
openConcurrentHandles :: ConcurrentMetaStoreM m => ConcurrentHandles -> m ()

-- | Open a new concurrent database, with the given handles.
createConcurrentDb :: (Root root, MonadIO m, MonadMask m, ConcurrentMetaStoreM m) => ConcurrentHandles -> root -> m (ConcurrentDb root)

-- | Open the an existing database, with the given handles.
openConcurrentDb :: (Root root, MonadIO m, MonadMask m, ConcurrentMetaStoreM m) => ConcurrentHandles -> m (Maybe (ConcurrentDb root))

-- | Close the handles of the database.
closeConcurrentHandles :: (MonadIO m, ConcurrentMetaStoreM m) => ConcurrentHandles -> m ()

-- | Create a new concurrent database with handles and metadata provided.
newConcurrentDb :: (Root root, MonadIO m) => ConcurrentHandles -> ConcurrentMeta root -> m (ConcurrentDb root)

-- | Get the current meta data.
getCurrentMeta :: Root root => ConcurrentDb root -> STM (ConcurrentMeta root)

-- | Write the new metadata, and switch the pointer to the current one.
setCurrentMeta :: (Root root, MonadIO m, ConcurrentMetaStoreM m) => ConcurrentMeta root -> ConcurrentDb root -> m ()

-- | Execute a write transaction, with a result.
transact :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Root root) => (forall n. (AllocM n, MonadMask n) => root -> n (Transaction root a)) -> ConcurrentDb root -> m a

-- | Execute a write transaction, without cleaning up old overflow pages.
transactNow :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Root root) => (forall n. (AllocM n, MonadMask n) => root -> n (Transaction root a)) -> ConcurrentDb root -> m a

-- | Execute a write transaction, without a result.
transact_ :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Root root) => (forall n. (AllocM n, MonadMask n) => root -> n (Transaction root ())) -> ConcurrentDb root -> m ()

-- | Execute a read-only transaction.
transactReadOnly :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Root root) => (forall n. (AllocReaderM n, MonadMask n) => root -> n a) -> ConcurrentDb root -> m a

-- | Run a write action that takes the current meta-data and returns new
--   meta-data to be commited, or <a>Nothing</a> if the write transaction
--   should be aborted.
actAndCommit :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Root root) => ConcurrentDb root -> (forall n. (MonadIO n, MonadMask n, ConcurrentMetaStoreM n) => ConcurrentMeta root -> ConcurrentT WriterEnv ConcurrentHandles n (Maybe (ConcurrentMeta root), a)) -> m a

-- | Cleanup after an exception occurs, or after a program crash.
--   
--   The <a>TxId</a> of the aborted transaction should be passed.
cleanupAfterException :: (MonadIO m, MonadCatch m, ConcurrentMetaStoreM m) => ConcurrentHandles -> TxId -> m ()

-- | Remove all overflow pages that were written in the transaction.
--   
--   If the transaction is aborted, all written pages should be deleted.
removeNewlyAllocatedOverflows :: (MonadIO m, ConcurrentMetaStoreM m) => WriterEnv ConcurrentHandles -> m ()

-- | Update the meta-data from a writer environment
updateMeta :: WriterEnv ConcurrentHandles -> ConcurrentMeta root -> ConcurrentMeta root

-- | Save the newly free'd overflow pages, for deletion on the next tx.
saveOverflowIds :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m) => StateT (ConcurrentMeta root, WriterEnv ConcurrentHandles) m ()

-- | Save the free'd pages to the free page database
saveFreePages' :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m) => Int -> (forall a. a -> S t a) -> (forall hnds. WriterEnv hnds -> FileState t) -> (forall hnds. WriterEnv hnds -> FileState t -> WriterEnv hnds) -> StateT (ConcurrentMeta root, WriterEnv ConcurrentHandles) m ()

-- | Handle the cached free pages.
--   
--   Save the cached free pages to the metadata for later use.
--   
--   Update the database size.
handleCachedFreePages :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m) => StateT (ConcurrentMeta root, WriterEnv ConcurrentHandles) m ()


-- | The module implements an page allocator with page reuse and support
--   for multiple readers and serialized writers.
module Database.Haskey.Alloc.Concurrent

-- | An active concurrent database.
--   
--   This can be shared amongst threads.
data ConcurrentDb root
ConcurrentDb :: ConcurrentHandles -> RLock -> TVar CurrentMetaPage -> TVar (ConcurrentMeta root) -> TVar (ConcurrentMeta root) -> Map TxId Integer -> ConcurrentDb root
[concurrentDbHandles] :: ConcurrentDb root -> ConcurrentHandles
[concurrentDbWriterLock] :: ConcurrentDb root -> RLock
[concurrentDbCurrentMeta] :: ConcurrentDb root -> TVar CurrentMetaPage
[concurrentDbMeta1] :: ConcurrentDb root -> TVar (ConcurrentMeta root)
[concurrentDbMeta2] :: ConcurrentDb root -> TVar (ConcurrentMeta root)
[concurrentDbReaders] :: ConcurrentDb root -> Map TxId Integer

-- | All necessary database handles.
data ConcurrentHandles
ConcurrentHandles :: FilePath -> FilePath -> FilePath -> FilePath -> FilePath -> FilePath -> ConcurrentHandles
[concurrentHandlesRoot] :: ConcurrentHandles -> FilePath
[concurrentHandlesData] :: ConcurrentHandles -> FilePath
[concurrentHandlesIndex] :: ConcurrentHandles -> FilePath
[concurrentHandlesMetadata1] :: ConcurrentHandles -> FilePath
[concurrentHandlesMetadata2] :: ConcurrentHandles -> FilePath
[concurrentHandlesOverflowDir] :: ConcurrentHandles -> FilePath

-- | Construct a set of <a>ConcurrentHandles</a> from a root directory.
concurrentHandles :: FilePath -> ConcurrentHandles

-- | Lock the database.
--   
--   This needs to be called manually, if you want exclusive access, before
--   calling either <a>createConcurrentDb</a> or <a>openConcurrentDb</a>
--   
--   Use <a>unlockConcurrentDb</a> using the <a>bracket</a> pattern to
--   properly unlock the database.
lockConcurrentDb :: ConcurrentMetaStoreM m => ConcurrentHandles -> m ()

-- | Unlock the database.
unlockConcurrentDb :: ConcurrentMetaStoreM m => ConcurrentHandles -> m ()

-- | Open a new concurrent database, with the given handles.
createConcurrentDb :: (Root root, MonadIO m, MonadMask m, ConcurrentMetaStoreM m) => ConcurrentHandles -> root -> m (ConcurrentDb root)

-- | Open the an existing database, with the given handles.
openConcurrentDb :: (Root root, MonadIO m, MonadMask m, ConcurrentMetaStoreM m) => ConcurrentHandles -> m (Maybe (ConcurrentDb root))

-- | Close the handles of the database.
closeConcurrentHandles :: (MonadIO m, ConcurrentMetaStoreM m) => ConcurrentHandles -> m ()

-- | Execute a write transaction, with a result.
transact :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Root root) => (forall n. (AllocM n, MonadMask n) => root -> n (Transaction root a)) -> ConcurrentDb root -> m a

-- | Execute a write transaction, without a result.
transact_ :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Root root) => (forall n. (AllocM n, MonadMask n) => root -> n (Transaction root ())) -> ConcurrentDb root -> m ()

-- | Execute a read-only transaction.
transactReadOnly :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Root root) => (forall n. (AllocReaderM n, MonadMask n) => root -> n a) -> ConcurrentDb root -> m a

-- | User-defined data root stored inside <a>ConcurrentMeta</a>.
--   
--   This can be a user-defined collection of <a>Tree</a> roots.
class Value root => Root root

-- | Meta data of the page allocator.
--   
--   The <tt>root</tt> type parameter should be a user-defined collection
--   of <a>Tree</a> roots, instantiating the <a>Root</a> type class.
--   
--   To store store a single tree, use <tt>ConcurrentMeta (Tree k v)</tt>.
data ConcurrentMeta root
ConcurrentMeta :: TxId -> S  'TypeData PageId -> S  'TypeIndex PageId -> root -> S  'TypeData FreeTree -> S  'TypeIndex FreeTree -> OverflowTree -> S  'TypeData [FreePage] -> S  'TypeIndex [FreePage] -> ConcurrentMeta root
[concurrentMetaRevision] :: ConcurrentMeta root -> TxId
[concurrentMetaDataNumPages] :: ConcurrentMeta root -> S  'TypeData PageId
[concurrentMetaIndexNumPages] :: ConcurrentMeta root -> S  'TypeIndex PageId
[concurrentMetaRoot] :: ConcurrentMeta root -> root
[concurrentMetaDataFreeTree] :: ConcurrentMeta root -> S  'TypeData FreeTree
[concurrentMetaIndexFreeTree] :: ConcurrentMeta root -> S  'TypeIndex FreeTree
[concurrentMetaOverflowTree] :: ConcurrentMeta root -> OverflowTree
[concurrentMetaDataCachedFreePages] :: ConcurrentMeta root -> S  'TypeData [FreePage]
[concurrentMetaIndexCachedFreePages] :: ConcurrentMeta root -> S  'TypeIndex [FreePage]

-- | A class representing the storage requirements of the page allocator.
--   
--   A store supporting the page allocator should be an instance of this
--   class.
class StoreM FilePath m => ConcurrentMetaStoreM m

-- | Write the meta-data structure to a certain page.
putConcurrentMeta :: (ConcurrentMetaStoreM m, Root root) => FilePath -> ConcurrentMeta root -> m ()

-- | Try to read the meta-data structure from a handle, or return
--   <a>Nothing</a> if the handle doesn't contain a meta page.
readConcurrentMeta :: (ConcurrentMetaStoreM m, Root root) => FilePath -> Proxy root -> m (Maybe (ConcurrentMeta root))


-- | This module contains structures and functions to decode and encode
--   pages.
module Database.Haskey.Store.Page

-- | The type of a page.
data PageType
TypeEmpty :: PageType
TypeConcurrentMeta :: PageType
TypeOverflow :: PageType
TypeLeafNode :: PageType
TypeIndexNode :: PageType
data SPageType t
[STypeEmpty] :: SPageType  'TypeEmpty
[STypeConcurrentMeta] :: SPageType  'TypeConcurrentMeta
[STypeOverflow] :: SPageType  'TypeOverflow
[STypeLeafNode] :: SPageType  'TypeLeafNode
[STypeIndexNode] :: SPageType  'TypeIndexNode

-- | A decoded page, of a certain type <tt>t</tt> of kind <a>PageType</a>.
data Page (t :: PageType)
[EmptyPage] :: Page  'TypeEmpty
[ConcurrentMetaPage] :: Root root => ConcurrentMeta root -> Page  'TypeConcurrentMeta
[OverflowPage] :: (Value v) => v -> Page  'TypeOverflow
[LeafNodePage] :: (Key k, Value v) => Height  'Z -> Node  'Z k v -> Page  'TypeLeafNode
[IndexNodePage] :: (Key k, Value v) => Height ( 'S h) -> Node ( 'S h) k v -> Page  'TypeIndexNode

-- | A decoder with its type.
data SGet t
SGet :: (SPageType t) -> (Get (Page t)) -> SGet t

-- | Get the type of a <a>Page</a>.
pageType :: SPageType t -> PageType

-- | Encode a page to a lazy byte string, but with the checksum set to
--   zero.
encodeZeroChecksum :: Page t -> ByteString

-- | Encode a page to a lazy byte string, and prepend the calculated
--   checksum.
encode :: Page t -> ByteString

-- | Prepend the xxHash 64-bit checksum of a bytestring to itself.
prependChecksum :: ByteString -> ByteString

-- | Encode a page to a lazy byte string, without prepending the checksum.
encodeNoChecksum :: Page t -> ByteString

-- | Size of a node, if it were to be encoded.
encodedPageSize :: (Key k, Value v) => Height h -> Node h k v -> PageSize

-- | Decode a page, and verify the checksum.
decode :: SGet t -> ByteString -> Either String (Page t)

-- | Decode a page with a specific decoder, or return the error.
decodeNoChecksum :: SGet t -> ByteString -> Either String (Page t)

-- | Monadic wrapper around <a>decode</a>
decodeM :: MonadThrow m => SGet t -> ByteString -> m (Page t)

-- | The encoder of a <a>Page</a>.
putPage :: Page t -> Put

-- | Decoder for an empty page.
emptyPage :: SGet  'TypeEmpty

-- | Decoder for a leaf node page.
leafNodePage :: (Key k, Value v) => Height  'Z -> Proxy k -> Proxy v -> SGet  'TypeLeafNode

-- | Decoder for a leaf node page.
indexNodePage :: (Key k, Value v) => Height ( 'S n) -> Proxy k -> Proxy v -> SGet  'TypeIndexNode

-- | Decoder for an overflow page.
overflowPage :: (Value v) => Proxy v -> SGet  'TypeOverflow
concurrentMetaPage :: Root root => Proxy root -> SGet  'TypeConcurrentMeta

-- | Exception thrown when decoding of a page fails.
newtype DecodeError
DecodeError :: String -> DecodeError
checksumSeed :: Word64
instance GHC.Show.Show Database.Haskey.Store.Page.DecodeError
instance GHC.Show.Show Database.Haskey.Store.Page.PageType
instance GHC.Classes.Eq Database.Haskey.Store.Page.PageType
instance GHC.Exception.Exception Database.Haskey.Store.Page.DecodeError
instance Data.Binary.Class.Binary Database.Haskey.Store.Page.PageType


-- | Binary in-memory storage back-end. Can be used as a storage back-end
--   for the append-only page allocator (see <a>Data.BTree.Alloc</a>).
module Database.Haskey.Store.InMemory

-- | A decoded page, of a certain type <tt>t</tt> of kind <a>PageType</a>.
data Page (t :: PageType)
[EmptyPage] :: Page  'TypeEmpty
[ConcurrentMetaPage] :: Root root => ConcurrentMeta root -> Page  'TypeConcurrentMeta
[OverflowPage] :: (Value v) => v -> Page  'TypeOverflow
[LeafNodePage] :: (Key k, Value v) => Height  'Z -> Node  'Z k v -> Page  'TypeLeafNode
[IndexNodePage] :: (Key k, Value v) => Height ( 'S h) -> Node ( 'S h) k v -> Page  'TypeIndexNode

-- | A file containing a collection of pages.
type MemoryFile = Map PageId ByteString

-- | A collection of <tt>File</tt>s, each associated with a certain
--   <tt>fp</tt> handle.
--   
--   This is shareable amongst multiple threads.
type MemoryFiles fp = MVar (Map fp MemoryFile)

-- | Memory store configuration.
--   
--   The default configuration can be obtained by using
--   <a>defMemoryStoreConfig</a>.
--   
--   A configuration with a specific page size can be obtained by using
--   <a>memoryStoreConfigWithPageSize</a>.
data MemoryStoreConfig
MemoryStoreConfig :: !PageSize -> !Word64 -> !Word64 -> MemoryStoreConfig
[memoryStoreConfigPageSize] :: MemoryStoreConfig -> !PageSize
[memoryStoreConfigMaxKeySize] :: MemoryStoreConfig -> !Word64
[memoryStoreConfigMaxValueSize] :: MemoryStoreConfig -> !Word64

-- | The default configuration.
--   
--   This is an unwrapped <a>memoryStoreConfigWithPageSize</a> with a page
--   size of 4096.
defMemoryStoreConfig :: MemoryStoreConfig

-- | Create a configuration with a specific page size.
--   
--   The maximum key and value sizes are calculated using
--   <a>calculateMaxKeySize</a> and <a>calculateMaxValueSize</a>.
--   
--   If the page size is too small, <a>Nothing</a> is returned.
memoryStoreConfigWithPageSize :: PageSize -> Maybe MemoryStoreConfig

-- | Monad in which binary storage operations can take place.
--   
--   Two important instances are <a>StoreM</a> making it a storage
--   back-end, and <a>ConcurrentMetaStoreM</a> making it a storage back-end
--   compatible with the concurrent page allocator.
data MemoryStoreT fp m a

-- | Run the storage operations in the <a>MemoryStoreT</a> monad, given a
--   collection of <tt>File</tt>s.
runMemoryStoreT :: MemoryStoreT fp m a -> MemoryStoreConfig -> MemoryFiles fp -> m a

-- | Construct a store with an empty database with name of type
--   <tt>hnd</tt>.
newEmptyMemoryStore :: IO (MemoryFiles hnd)

-- | Exception thrown when a file is accessed that doesn't exist.
newtype FileNotFoundError hnd
FileNotFoundError :: hnd -> FileNotFoundError hnd

-- | Exception thrown when a page that is accessed doesn't exist.
data PageNotFoundError hnd
PageNotFoundError :: hnd -> PageId -> PageNotFoundError hnd

-- | Exception thrown when a node cannot be cast to the right type.
--   
--   As used in <a>getNodePage</a>.
data WrongNodeTypeError
WrongNodeTypeError :: WrongNodeTypeError

-- | Exception thrown when a value from an overflow page cannot be cast.
--   
--   As used in <a>getOverflow</a>.
data WrongOverflowValueError
WrongOverflowValueError :: WrongOverflowValueError
instance GHC.Show.Show Database.Haskey.Store.InMemory.WrongOverflowValueError
instance GHC.Show.Show Database.Haskey.Store.InMemory.WrongNodeTypeError
instance GHC.Show.Show hnd => GHC.Show.Show (Database.Haskey.Store.InMemory.PageNotFoundError hnd)
instance GHC.Show.Show hnd => GHC.Show.Show (Database.Haskey.Store.InMemory.FileNotFoundError hnd)
instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader Database.Haskey.Store.InMemory.MemoryStoreConfig (Database.Haskey.Store.InMemory.MemoryStoreT fp m)
instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Database.Haskey.Store.InMemory.MemoryStoreT fp m)
instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Database.Haskey.Store.InMemory.MemoryStoreT fp m)
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Database.Haskey.Store.InMemory.MemoryStoreT fp m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Database.Haskey.Store.InMemory.MemoryStoreT fp m)
instance GHC.Base.Monad m => GHC.Base.Monad (Database.Haskey.Store.InMemory.MemoryStoreT fp m)
instance GHC.Base.Functor m => GHC.Base.Functor (Database.Haskey.Store.InMemory.MemoryStoreT fp m)
instance GHC.Base.Applicative m => GHC.Base.Applicative (Database.Haskey.Store.InMemory.MemoryStoreT fp m)
instance GHC.Show.Show Database.Haskey.Store.InMemory.MemoryStoreConfig
instance (GHC.Base.Applicative m, GHC.Base.Monad m, Control.Monad.IO.Class.MonadIO m, Control.Monad.Catch.MonadThrow m, GHC.Classes.Ord fp, GHC.Show.Show fp, Data.Typeable.Internal.Typeable fp) => Database.Haskey.Store.Class.StoreM fp (Database.Haskey.Store.InMemory.MemoryStoreT fp m)
instance GHC.Exception.Exception Database.Haskey.Store.InMemory.WrongOverflowValueError
instance GHC.Exception.Exception Database.Haskey.Store.InMemory.WrongNodeTypeError
instance (Data.Typeable.Internal.Typeable hnd, GHC.Show.Show hnd) => GHC.Exception.Exception (Database.Haskey.Store.InMemory.PageNotFoundError hnd)
instance (Data.Typeable.Internal.Typeable hnd, GHC.Show.Show hnd) => GHC.Exception.Exception (Database.Haskey.Store.InMemory.FileNotFoundError hnd)
instance (GHC.Base.Applicative m, GHC.Base.Monad m, Control.Monad.IO.Class.MonadIO m, Control.Monad.Catch.MonadCatch m) => Database.Haskey.Alloc.Concurrent.Internal.Meta.ConcurrentMetaStoreM (Database.Haskey.Store.InMemory.MemoryStoreT GHC.IO.FilePath m)


-- | On-disk storage back-end. Can be used as a storage back-end for the
--   append-only page allocator (see <a>Data.BTree.Alloc</a>).
module Database.Haskey.Store.File

-- | A decoded page, of a certain type <tt>t</tt> of kind <a>PageType</a>.
data Page (t :: PageType)
[EmptyPage] :: Page  'TypeEmpty
[ConcurrentMetaPage] :: Root root => ConcurrentMeta root -> Page  'TypeConcurrentMeta
[OverflowPage] :: (Value v) => v -> Page  'TypeOverflow
[LeafNodePage] :: (Key k, Value v) => Height  'Z -> Node  'Z k v -> Page  'TypeLeafNode
[IndexNodePage] :: (Key k, Value v) => Height ( 'S h) -> Node ( 'S h) k v -> Page  'TypeIndexNode

-- | File store configuration.
--   
--   The default configuration can be obtained by using
--   <a>defFileStoreConfig</a>
--   
--   A configuration with a specific page size can be obtained by using
--   <a>fileStoreConfigWithPageSize</a>.
data FileStoreConfig
FileStoreConfig :: !PageSize -> !Word64 -> !Word64 -> FileStoreConfig
[fileStoreConfigPageSize] :: FileStoreConfig -> !PageSize
[fileStoreConfigMaxKeySize] :: FileStoreConfig -> !Word64
[fileStoreConfigMaxValueSize] :: FileStoreConfig -> !Word64

-- | The default configuration
--   
--   This is an unwrapped <a>fileStoreConfigWithPageSize</a> with a page
--   size of 4096 bytes.
defFileStoreConfig :: FileStoreConfig

-- | Create a configuration with a specific page size.
--   
--   The maximum key and value sizes are calculated using
--   <a>calculateMaxKeySize</a> and <a>calculateMaxValueSize</a>.
--   
--   If the page size is too small, <a>Nothing</a> is returned.
fileStoreConfigWithPageSize :: PageSize -> Maybe FileStoreConfig

-- | Monad in which on-disk storage operations can take place.
--   
--   Two important instances are <a>StoreM</a> making it a storage
--   back-end, and <a>ConcurrentMetaStoreM</a> making it a storage back-end
--   compatible with the concurrent page allocator.
data FileStoreT fp m a

-- | Run the storage operations in the <a>FileStoreT</a> monad, given a
--   collection of open files.
runFileStoreT :: Monad m => FileStoreT FilePath m a -> FileStoreConfig -> m a

-- | Encode a page padding it to the maxim page size.
--   
--   Return <a>Nothing</a> of the page is too large to fit into one page
--   size.
encodeAndPad :: PageSize -> Page t -> Maybe ByteString

-- | Exception thrown when a file is accessed that doesn't exist.
newtype FileNotFoundError hnd
FileNotFoundError :: hnd -> FileNotFoundError hnd

-- | Exception thrown when a page that is too large is written.
--   
--   As used in <a>putNodePage</a>.
data PageOverflowError
PageOverflowError :: PageOverflowError

-- | Exception thrown when a node cannot be cast to the right type.
--   
--   As used in <a>getNodePage</a>.
data WrongNodeTypeError
WrongNodeTypeError :: WrongNodeTypeError

-- | Exception thrown when a value from an overflow page cannot be cast.
--   
--   As used in <a>getOverflow</a>.
data WrongOverflowValueError
WrongOverflowValueError :: WrongOverflowValueError
instance GHC.Show.Show Database.Haskey.Store.File.WrongOverflowValueError
instance GHC.Show.Show Database.Haskey.Store.File.WrongNodeTypeError
instance GHC.Show.Show Database.Haskey.Store.File.PageOverflowError
instance GHC.Show.Show hnd => GHC.Show.Show (Database.Haskey.Store.File.FileNotFoundError hnd)
instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState (Database.Haskey.Store.File.Files fp) (Database.Haskey.Store.File.FileStoreT fp m)
instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader Database.Haskey.Store.File.FileStoreConfig (Database.Haskey.Store.File.FileStoreT fp m)
instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Database.Haskey.Store.File.FileStoreT fp m)
instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Database.Haskey.Store.File.FileStoreT fp m)
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Database.Haskey.Store.File.FileStoreT fp m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Database.Haskey.Store.File.FileStoreT fp m)
instance GHC.Base.Monad m => GHC.Base.Monad (Database.Haskey.Store.File.FileStoreT fp m)
instance GHC.Base.Functor m => GHC.Base.Functor (Database.Haskey.Store.File.FileStoreT fp m)
instance GHC.Base.Monad m => GHC.Base.Applicative (Database.Haskey.Store.File.FileStoreT fp m)
instance GHC.Show.Show Database.Haskey.Store.File.FileStoreConfig
instance (GHC.Base.Applicative m, GHC.Base.Monad m, Control.Monad.IO.Class.MonadIO m, Control.Monad.Catch.MonadThrow m) => Database.Haskey.Store.Class.StoreM GHC.IO.FilePath (Database.Haskey.Store.File.FileStoreT GHC.IO.FilePath m)
instance GHC.Exception.Exception Database.Haskey.Store.File.WrongOverflowValueError
instance GHC.Exception.Exception Database.Haskey.Store.File.WrongNodeTypeError
instance GHC.Exception.Exception Database.Haskey.Store.File.PageOverflowError
instance (Data.Typeable.Internal.Typeable hnd, GHC.Show.Show hnd) => GHC.Exception.Exception (Database.Haskey.Store.File.FileNotFoundError hnd)
instance (GHC.Base.Applicative m, GHC.Base.Monad m, Control.Monad.IO.Class.MonadIO m, Control.Monad.Catch.MonadCatch m) => Database.Haskey.Alloc.Concurrent.Internal.Meta.ConcurrentMetaStoreM (Database.Haskey.Store.File.FileStoreT GHC.IO.FilePath m)
