-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A transcatoinal, 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 -- https://github.com/haskell-haskey/haskey @package haskey @version 0.1.0.0 -- | 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 where maxKeySize = do { f <- nodePageSize; fmax <- maxPageSize; return $ calculateMaxKeySize fmax (f zeroHeight) } maxValueSize = do { f <- nodePageSize; key <- maxKeySize; fmax <- maxPageSize; return $ calculateMaxValueSize fmax key (f zeroHeight) } -- | Open a database handle for reading and writing. openHandle :: 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 -- calculateMaxKeySize. 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 -- calculateMaxValueSize. 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 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) 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 -- | Storage back-ends that manage physical storage of pages. module Database.Haskey.Store -- | This module implements mechanisms to work with transactions. module Database.Haskey.Alloc.Transaction -- | A committed or aborted transaction, with a return value of type -- a. data Transaction key val a Commit :: (Tree key val) -> a -> Transaction key val a Abort :: a -> Transaction key val a -- | Commit the new tree and return a computed value. commit :: AllocM n => a -> Tree key val -> n (Transaction key val a) -- | Commit the new tree, without return a computed value. commit_ :: AllocM n => Tree key val -> n (Transaction key val ()) -- | Abort the transaction and return a computed value. abort :: AllocM n => a -> n (Transaction key val a) -- | Abort the transaction, without returning a computed value. abort_ :: AllocM n => n (Transaction key val ()) -- | Module describing the tree structure of the free page database. module Database.Haskey.Alloc.Concurrent.FreePages.Tree -- | The main tree structure of the free page database. -- -- The main free page database tree maps a TxId to a -- FreeSubtree. type FreeTree = Tree TxId FreeSubtree -- | the subtree structure of the free page database. -- -- Just a collection of free PageIds. type FreeSubtree = NonEmptyTree PageId () -- | Replace the subtree of a certain TxId. replaceSubtree :: AllocM m => TxId -> NonEmpty PageId -> FreeTree -> m FreeTree -- | Delete the subtree of a certain TxId. -- -- The TxId 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 TxId. insertSubtree :: AllocM m => TxId -> NonEmpty PageId -> FreeTree -> m FreeTree -- | Environments of a read or write transaction. module Database.Haskey.Alloc.Concurrent.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) -> !(S stateType (Set DirtyFree)) -> !(S stateType FreeTree) -> !(Set DirtyOldFree) -> ![OldFree] -> !(Maybe TxId) -> 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 fileStateOriginalNumPages to -- fileStateNewNumPages (excluding) are freshly allocated in the -- ongoing transaction. [fileStateNewNumPages] :: FileState stateType -> !(S stateType PageId) -- | Pages freshly allocated AND free'd in this transaction. Immediately -- ready for reuse. [fileStateFreedDirtyPages] :: FileState stateType -> !(S stateType (Set DirtyFree)) -- | The root of the free tree, might change during a transaction. [fileStateFreeTree] :: FileState stateType -> !(S stateType FreeTree) -- | All pages queried from the free page database for -- fileStateReusablePagesTxId, and actually used once already. [fileStateDirtyReusablePages] :: FileState stateType -> !(Set DirtyOldFree) -- | Pages queried from the free pages database and ready for immediate -- reuse. [fileStateReusablePages] :: FileState stateType -> ![OldFree] -- | The TxId of the pages in fileStateReusablePages, or -- Nothing if no pages were queried yet from the free database. [fileStateReusablePagesTxId] :: FileState stateType -> !(Maybe TxId) 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 -- | Used to turn of querying the free page database for free pages. [writerReusablePagesOn] :: 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 (Set DirtyFree) -> S TypeIndex (Set DirtyFree) -> S TypeData FreeTree -> S TypeIndex FreeTree -> WriterEnv hnd -- | Wrapper around PageId indicating it is a fresh page, allocated -- at the end of the database. newtype Fresh Fresh :: PageId -> Fresh -- | Wrapper around PageId indicating it is newly free'd and cannot -- be reused in the same transaction. newtype NewlyFreed NewlyFreed :: PageId -> NewlyFreed -- | Wrapper around PageId indicating it is a dirty page. newtype Dirty Dirty :: PageId -> Dirty -- | Wrapper around PageId indicating the page is dirty and free for -- reuse. newtype DirtyFree DirtyFree :: PageId -> DirtyFree -- | Wrapper around PageId inidcating it was fetched from the free -- database and is ready for reuse. newtype OldFree OldFree :: PageId -> OldFree -- | Wrapper around PageId indicating it wa fetched from the free -- database and is actually dirty. newtype DirtyOldFree DirtyOldFree :: PageId -> DirtyOldFree -- | A sum type repesenting any type of free page, that can immediately be -- used to write something to. data SomeFreePage FreshFreePage :: Fresh -> SomeFreePage DirtyFreePage :: DirtyFree -> SomeFreePage OldFreePage :: OldFree -> SomeFreePage getSomeFreePageId :: SomeFreePage -> PageId -- | Try to free a page, given a set of dirty pages. -- -- If the page was dirty, a DirtyFree page is added to the -- environment, if not a NewlyFreed 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 -> Maybe DirtyOldFree -> PageId -> FileState t -- | Get a Dirty page, by first proving it is in fact dirty. dirty :: (Functor m, MonadState (WriterEnv hnd) m) => S stateType PageId -> m (Maybe Dirty) -- | Get a DirtyOldFree page, by first proving it is in fact a dirty -- old free page. dirtyOldFree :: (Functor m, MonadState (WriterEnv hnd) m) => S stateType PageId -> m (Maybe DirtyOldFree) -- | Touch a fresh page, make it dirty. -- -- We really need lenses... touchPage :: MonadState (WriterEnv hnd) m => S stateType SomeFreePage -> m () -- | Wrapper around OverflowId indicating that it is dirty. newtype DirtyOverflow DirtyOverflow :: OverflowId -> DirtyOverflow -- | Wrapper around OverflowId 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.Environment.OldOverflow instance GHC.Classes.Ord Database.Haskey.Alloc.Concurrent.Environment.OldOverflow instance GHC.Classes.Eq Database.Haskey.Alloc.Concurrent.Environment.OldOverflow instance GHC.Show.Show Database.Haskey.Alloc.Concurrent.Environment.DirtyOverflow instance GHC.Classes.Ord Database.Haskey.Alloc.Concurrent.Environment.DirtyOverflow instance GHC.Classes.Eq Database.Haskey.Alloc.Concurrent.Environment.DirtyOverflow instance GHC.Show.Show Database.Haskey.Alloc.Concurrent.Environment.DirtyOldFree instance GHC.Classes.Ord Database.Haskey.Alloc.Concurrent.Environment.DirtyOldFree instance GHC.Classes.Eq Database.Haskey.Alloc.Concurrent.Environment.DirtyOldFree instance GHC.Show.Show Database.Haskey.Alloc.Concurrent.Environment.OldFree instance GHC.Classes.Ord Database.Haskey.Alloc.Concurrent.Environment.OldFree instance GHC.Classes.Eq Database.Haskey.Alloc.Concurrent.Environment.OldFree instance GHC.Show.Show Database.Haskey.Alloc.Concurrent.Environment.DirtyFree instance GHC.Classes.Ord Database.Haskey.Alloc.Concurrent.Environment.DirtyFree instance GHC.Classes.Eq Database.Haskey.Alloc.Concurrent.Environment.DirtyFree instance Data.Binary.Class.Binary Database.Haskey.Alloc.Concurrent.Environment.DirtyFree instance GHC.Show.Show Database.Haskey.Alloc.Concurrent.Environment.Dirty instance GHC.Classes.Ord Database.Haskey.Alloc.Concurrent.Environment.Dirty instance GHC.Classes.Eq Database.Haskey.Alloc.Concurrent.Environment.Dirty instance GHC.Show.Show Database.Haskey.Alloc.Concurrent.Environment.NewlyFreed instance GHC.Classes.Ord Database.Haskey.Alloc.Concurrent.Environment.NewlyFreed instance GHC.Classes.Eq Database.Haskey.Alloc.Concurrent.Environment.NewlyFreed instance GHC.Show.Show Database.Haskey.Alloc.Concurrent.Environment.Fresh instance GHC.Classes.Ord Database.Haskey.Alloc.Concurrent.Environment.Fresh instance GHC.Classes.Eq Database.Haskey.Alloc.Concurrent.Environment.Fresh instance GHC.Show.Show a => GHC.Show.Show (Database.Haskey.Alloc.Concurrent.Environment.S t a) instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Database.Haskey.Alloc.Concurrent.Environment.S 'Database.Haskey.Alloc.Concurrent.Environment.TypeData a) instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Database.Haskey.Alloc.Concurrent.Environment.S 'Database.Haskey.Alloc.Concurrent.Environment.TypeIndex a) instance GHC.Base.Functor (Database.Haskey.Alloc.Concurrent.Environment.S t) module Database.Haskey.Alloc.Concurrent.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 -- writerReusablePages. 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 SomeFreePage) -- | Get a free'd dirty page. -- -- Get a free'd dirty page, that is immediately suitable for reuse in the -- current transaction. getFreedDirtyPageId :: (Functor m, MonadState (WriterEnv hnd) m) => S stateType () -> m (Maybe DirtyFree) -- | Get a cached free page. -- -- Get a free page from the free database cache stored in -- writerReusablePages. getCachedFreePageId :: (Functor m, MonadState (WriterEnv hnd) m) => S stateType () -> m (Maybe OldFree) -- | 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. -- -- This function will delete the lastly used entry from the free -- database, query a new one, and then update the free page cache in the -- state. -- -- This function only works when writerReusablePagesOn is -- True. -- -- This function expects writerReusablePages to be empty. queryNewFreePageIds :: (AllocM m, MonadIO m, MonadState (WriterEnv hnd) m) => S stateType () -> m (Maybe OldFree) -- | 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 -- Nothing. checkFreePages :: (Functor m, MonadIO m, MonadState (WriterEnv hnd) m) => Unchecked (TxId, NonEmpty PageId) -> m (Maybe (TxId, NonEmpty PageId)) module Database.Haskey.Alloc.Concurrent.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 -- writerNewlyFreedPages. saveNewlyFreedPages :: AllocM m => TxId -> FileState t -> FreeTree -> m FreeTree -- | Save the free apges from the free page cache in -- writerReusablePages using writerReuseablePagesTxId. saveCachedFreePages :: AllocM m => FileState t -> FreeTree -> m FreeTree -- | Data structures and functions related to handling overflow pages. module Database.Haskey.Alloc.Concurrent.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.Meta -- | 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. data ConcurrentMeta k v ConcurrentMeta :: TxId -> S TypeData PageId -> S TypeIndex PageId -> Tree k v -> S TypeData FreeTree -> S TypeIndex FreeTree -> OverflowTree -> S TypeData (Set DirtyFree) -> S TypeIndex (Set DirtyFree) -> ConcurrentMeta k v [concurrentMetaRevision] :: ConcurrentMeta k v -> TxId [concurrentMetaDataNumPages] :: ConcurrentMeta k v -> S TypeData PageId [concurrentMetaIndexNumPages] :: ConcurrentMeta k v -> S TypeIndex PageId [concurrentMetaTree] :: ConcurrentMeta k v -> Tree k v [concurrentMetaDataFreeTree] :: ConcurrentMeta k v -> S TypeData FreeTree [concurrentMetaIndexFreeTree] :: ConcurrentMeta k v -> S TypeIndex FreeTree [concurrentMetaOverflowTree] :: ConcurrentMeta k v -> OverflowTree [concurrentMetaDataFreshUnusedPages] :: ConcurrentMeta k v -> S TypeData (Set DirtyFree) [concurrentMetaIndexFreshUnusedPages] :: ConcurrentMeta k v -> S TypeIndex (Set DirtyFree) -- | 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, Key k, Value v) => FilePath -> ConcurrentMeta k v -> m () -- | Try to read the meta-data structure from a handle, or return -- Nothing if the handle doesn't contain a meta page. readConcurrentMeta :: (ConcurrentMetaStoreM m, Key k, Value v) => FilePath -> Proxy k -> Proxy v -> m (Maybe (ConcurrentMeta k v)) instance GHC.Generics.Generic (Database.Haskey.Alloc.Concurrent.Meta.ConcurrentMeta k v) instance (GHC.Show.Show k, GHC.Show.Show v) => GHC.Show.Show (Database.Haskey.Alloc.Concurrent.Meta.ConcurrentMeta k v) instance (Data.Binary.Class.Binary k, Data.Binary.Class.Binary v) => Data.Binary.Class.Binary (Database.Haskey.Alloc.Concurrent.Meta.ConcurrentMeta k v) -- | This module implements the ConcurrentT monad. -- -- The ConcurrentT monad is used to implement a page allocator -- with concurrent readers and serialized writers. module Database.Haskey.Alloc.Concurrent.Monad -- | All necessary database handles. data ConcurrentHandles ConcurrentHandles :: FilePath -> FilePath -> FilePath -> FilePath -> FilePath -> ConcurrentHandles [concurrentHandlesData] :: ConcurrentHandles -> FilePath [concurrentHandlesIndex] :: ConcurrentHandles -> FilePath [concurrentHandlesMetadata1] :: ConcurrentHandles -> FilePath [concurrentHandlesMetadata2] :: ConcurrentHandles -> FilePath [concurrentHandlesOverflowDir] :: ConcurrentHandles -> FilePath -- | Construct a set of ConcurrentHandles from a root directory. concurrentHandles :: FilePath -> ConcurrentHandles -- | Monad in which page allocations can take place. -- -- The monad has access to a ConcurrentMetaStoreM 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 ConcurrentT 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 ConcurrentT 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.Monad.ConcurrentT env hnd m) instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Database.Haskey.Alloc.Concurrent.Monad.ConcurrentT env hnd m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Database.Haskey.Alloc.Concurrent.Monad.ConcurrentT env hnd m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Database.Haskey.Alloc.Concurrent.Monad.ConcurrentT env hnd m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Database.Haskey.Alloc.Concurrent.Monad.ConcurrentT env hnd m) instance GHC.Base.Monad m => GHC.Base.Monad (Database.Haskey.Alloc.Concurrent.Monad.ConcurrentT env hnd m) instance GHC.Base.Monad m => GHC.Base.Applicative (Database.Haskey.Alloc.Concurrent.Monad.ConcurrentT env hnd m) instance GHC.Base.Functor m => GHC.Base.Functor (Database.Haskey.Alloc.Concurrent.Monad.ConcurrentT env hnd m) instance GHC.Show.Show Database.Haskey.Alloc.Concurrent.Monad.ConcurrentHandles instance Control.Monad.Trans.Class.MonadTrans (Database.Haskey.Alloc.Concurrent.Monad.ConcurrentT env hnd) instance (Database.Haskey.Alloc.Concurrent.Meta.ConcurrentMetaStoreM m, Control.Monad.IO.Class.MonadIO m) => Data.BTree.Alloc.Class.AllocM (Database.Haskey.Alloc.Concurrent.Monad.ConcurrentT Database.Haskey.Alloc.Concurrent.Environment.WriterEnv Database.Haskey.Alloc.Concurrent.Monad.ConcurrentHandles m) instance Database.Haskey.Alloc.Concurrent.Meta.ConcurrentMetaStoreM m => Data.BTree.Alloc.Class.AllocReaderM (Database.Haskey.Alloc.Concurrent.Monad.ConcurrentT Database.Haskey.Alloc.Concurrent.Environment.WriterEnv Database.Haskey.Alloc.Concurrent.Monad.ConcurrentHandles m) instance Database.Haskey.Alloc.Concurrent.Meta.ConcurrentMetaStoreM m => Data.BTree.Alloc.Class.AllocReaderM (Database.Haskey.Alloc.Concurrent.Monad.ConcurrentT Database.Haskey.Alloc.Concurrent.Environment.ReaderEnv Database.Haskey.Alloc.Concurrent.Monad.ConcurrentHandles m) -- | This module implements data structures and functions related to the -- database. module Database.Haskey.Alloc.Concurrent.Database -- | An active concurrent database. -- -- This can be shared amongst threads. data ConcurrentDb k v ConcurrentDb :: ConcurrentHandles -> RLock -> TVar CurrentMetaPage -> TVar (ConcurrentMeta k v) -> TVar (ConcurrentMeta k v) -> Map TxId Integer -> ConcurrentDb k v [concurrentDbHandles] :: ConcurrentDb k v -> ConcurrentHandles [concurrentDbWriterLock] :: ConcurrentDb k v -> RLock [concurrentDbCurrentMeta] :: ConcurrentDb k v -> TVar CurrentMetaPage [concurrentDbMeta1] :: ConcurrentDb k v -> TVar (ConcurrentMeta k v) [concurrentDbMeta2] :: ConcurrentDb k v -> TVar (ConcurrentMeta k v) [concurrentDbReaders] :: ConcurrentDb k v -> Map TxId Integer -- | Open all concurrent handles. openConcurrentHandles :: ConcurrentMetaStoreM m => ConcurrentHandles -> m () -- | Open a new concurrent database, with the given handles. createConcurrentDb :: (Key k, Value v, MonadIO m, ConcurrentMetaStoreM m) => ConcurrentHandles -> m (ConcurrentDb k v) -- | Open the an existing database, with the given handles. openConcurrentDb :: (Key k, Value v, MonadIO m, MonadMask m, ConcurrentMetaStoreM m) => ConcurrentHandles -> m (Maybe (ConcurrentDb k v)) -- | Close the handles of the database. closeConcurrentHandles :: (MonadIO m, ConcurrentMetaStoreM m) => ConcurrentHandles -> m () -- | Create a new concurrent database with handles and metadata provided. newConcurrentDb :: (Key k, Value v, MonadIO m) => ConcurrentHandles -> ConcurrentMeta k v -> m (ConcurrentDb k v) -- | Get the current meta data. getCurrentMeta :: (Key k, Value v) => ConcurrentDb k v -> STM (ConcurrentMeta k v) -- | Write the new metadata, and switch the pointer to the current one. setCurrentMeta :: (MonadIO m, ConcurrentMetaStoreM m, Key k, Value v) => ConcurrentMeta k v -> ConcurrentDb k v -> m () -- | Execute a write transaction, with a result. transact :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Key key, Value val) => (forall n. (AllocM n, MonadMask n) => Tree key val -> n (Transaction key val a)) -> ConcurrentDb key val -> m a -- | Execute a write transaction, without cleaning up old overflow pages. transactNow :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Key k, Value v) => (forall n. (AllocM n, MonadMask n) => Tree k v -> n (Transaction k v a)) -> ConcurrentDb k v -> m a -- | Execute a write transaction, without a result. transact_ :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Key k, Value v) => (forall n. (AllocM n, MonadMask n) => Tree k v -> n (Transaction k v ())) -> ConcurrentDb k v -> m () -- | Execute a read-only transaction. transactReadOnly :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Key key, Value val) => (forall n. (AllocReaderM n, MonadMask m) => Tree key val -> n a) -> ConcurrentDb key val -> m a -- | Run a write action that takes the current meta-data and returns new -- meta-data to be commited, or Nothing if the write transaction -- should be aborted. actAndCommit :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Key k, Value v) => ConcurrentDb k v -> (forall n. (MonadIO n, MonadMask n, ConcurrentMetaStoreM n) => ConcurrentMeta k v -> ConcurrentT WriterEnv ConcurrentHandles n (Maybe (ConcurrentMeta k v), a)) -> m a -- | Cleanup after an exception occurs, or after a program crash. -- -- The TxId 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 k v -> ConcurrentMeta k v -- | Save the newly free'd overflow pages, for deletion on the next tx. saveOverflowIds :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m) => StateT (ConcurrentMeta k v, 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 k v, WriterEnv ConcurrentHandles) m () -- | Handle the dirty pages. -- -- Save the newly created free dirty pages to the metadata for later use. -- -- Update the database size. handleFreedDirtyPages :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m) => StateT (ConcurrentMeta k v, 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 k v ConcurrentDb :: ConcurrentHandles -> RLock -> TVar CurrentMetaPage -> TVar (ConcurrentMeta k v) -> TVar (ConcurrentMeta k v) -> Map TxId Integer -> ConcurrentDb k v [concurrentDbHandles] :: ConcurrentDb k v -> ConcurrentHandles [concurrentDbWriterLock] :: ConcurrentDb k v -> RLock [concurrentDbCurrentMeta] :: ConcurrentDb k v -> TVar CurrentMetaPage [concurrentDbMeta1] :: ConcurrentDb k v -> TVar (ConcurrentMeta k v) [concurrentDbMeta2] :: ConcurrentDb k v -> TVar (ConcurrentMeta k v) [concurrentDbReaders] :: ConcurrentDb k v -> Map TxId Integer -- | All necessary database handles. data ConcurrentHandles ConcurrentHandles :: FilePath -> FilePath -> FilePath -> FilePath -> FilePath -> ConcurrentHandles [concurrentHandlesData] :: ConcurrentHandles -> FilePath [concurrentHandlesIndex] :: ConcurrentHandles -> FilePath [concurrentHandlesMetadata1] :: ConcurrentHandles -> FilePath [concurrentHandlesMetadata2] :: ConcurrentHandles -> FilePath [concurrentHandlesOverflowDir] :: ConcurrentHandles -> FilePath -- | Construct a set of ConcurrentHandles from a root directory. concurrentHandles :: FilePath -> ConcurrentHandles -- | Open a new concurrent database, with the given handles. createConcurrentDb :: (Key k, Value v, MonadIO m, ConcurrentMetaStoreM m) => ConcurrentHandles -> m (ConcurrentDb k v) -- | Open the an existing database, with the given handles. openConcurrentDb :: (Key k, Value v, MonadIO m, MonadMask m, ConcurrentMetaStoreM m) => ConcurrentHandles -> m (Maybe (ConcurrentDb k v)) -- | 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, Key key, Value val) => (forall n. (AllocM n, MonadMask n) => Tree key val -> n (Transaction key val a)) -> ConcurrentDb key val -> m a -- | Execute a write transaction, without a result. transact_ :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Key k, Value v) => (forall n. (AllocM n, MonadMask n) => Tree k v -> n (Transaction k v ())) -> ConcurrentDb k v -> m () -- | Execute a read-only transaction. transactReadOnly :: (MonadIO m, MonadMask m, ConcurrentMetaStoreM m, Key key, Value val) => (forall n. (AllocReaderM n, MonadMask m) => Tree key val -> n a) -> ConcurrentDb key val -> m a -- | Meta data of the page allocator. data ConcurrentMeta k v ConcurrentMeta :: TxId -> S TypeData PageId -> S TypeIndex PageId -> Tree k v -> S TypeData FreeTree -> S TypeIndex FreeTree -> OverflowTree -> S TypeData (Set DirtyFree) -> S TypeIndex (Set DirtyFree) -> ConcurrentMeta k v [concurrentMetaRevision] :: ConcurrentMeta k v -> TxId [concurrentMetaDataNumPages] :: ConcurrentMeta k v -> S TypeData PageId [concurrentMetaIndexNumPages] :: ConcurrentMeta k v -> S TypeIndex PageId [concurrentMetaTree] :: ConcurrentMeta k v -> Tree k v [concurrentMetaDataFreeTree] :: ConcurrentMeta k v -> S TypeData FreeTree [concurrentMetaIndexFreeTree] :: ConcurrentMeta k v -> S TypeIndex FreeTree [concurrentMetaOverflowTree] :: ConcurrentMeta k v -> OverflowTree [concurrentMetaDataFreshUnusedPages] :: ConcurrentMeta k v -> S TypeData (Set DirtyFree) [concurrentMetaIndexFreshUnusedPages] :: ConcurrentMeta k v -> S TypeIndex (Set DirtyFree) -- | 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, Key k, Value v) => FilePath -> ConcurrentMeta k v -> m () -- | Try to read the meta-data structure from a handle, or return -- Nothing if the handle doesn't contain a meta page. readConcurrentMeta :: (ConcurrentMetaStoreM m, Key k, Value v) => FilePath -> Proxy k -> Proxy v -> m (Maybe (ConcurrentMeta k v)) -- | 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 t of kind PageType. data Page (t :: PageType) [EmptyPage] :: Page TypeEmpty [ConcurrentMetaPage] :: (Key k, Value v) => ConcurrentMeta k v -> 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 Page. 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 decode decodeM :: MonadThrow m => SGet t -> ByteString -> m (Page t) -- | The encoder of a Page. 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 :: (Key k, Value v) => Proxy k -> Proxy v -> 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 Data.Binary.Class.Binary Database.Haskey.Store.Page.PageType instance GHC.Exception.Exception Database.Haskey.Store.Page.DecodeError -- | On-disk storage back-end. Can be used as a storage back-end for the -- append-only page allocator (see Data.BTree.Alloc). module Database.Haskey.Store.File -- | A decoded page, of a certain type t of kind PageType. data Page (t :: PageType) [EmptyPage] :: Page TypeEmpty [ConcurrentMetaPage] :: (Key k, Value v) => ConcurrentMeta k v -> 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 collection of files, each associated with a certain fp -- handle. -- -- Each file is a Handle opened in ReadWriteMode and -- contains a collection of physical pages. -- -- These files can be safely shared between threads. type Files fp = IORef (Map fp FHandle) -- | File store configuration. -- -- The default configuration can be obtained by using -- defFileStoreConfig -- -- A configuration with a specific page size can be obtained by using -- fileStoreConfigWithPageSize. data FileStoreConfig FileStoreConfig :: !PageSize -> !Word64 -> !Word64 -> FileStoreConfig [fileStoreConfigPageSize] :: FileStoreConfig -> !PageSize [fileStoreConfigMaxKeySize] :: FileStoreConfig -> !Word64 [fileStoreConfigMaxValueSize] :: FileStoreConfig -> !Word64 -- | The default configuration -- -- This is an unwrapped fileStoreConfigWithPageSize 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 -- calculateMaxKeySize and calculateMaxValueSize. -- -- If the page size is too small, Nothing is returned. fileStoreConfigWithPageSize :: PageSize -> Maybe FileStoreConfig -- | Monad in which on-disk storage operations can take place. -- -- Two important instances are StoreM making it a storage -- back-end, and ConcurrentMetaStoreM making it a storage back-end -- compatible with the concurrent page allocator. data FileStoreT fp m a -- | Run the storage operations in the FileStoreT monad, given a -- collection of open files. runFileStoreT :: FileStoreT fp m a -> FileStoreConfig -> Files fp -> m a -- | An empty file store, with no open files. newFileStore :: IO (Files fp) -- | Encode a page padding it to the maxim page size. -- -- Return Nothing 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 putNodePage. data PageOverflowError PageOverflowError :: PageOverflowError -- | Exception thrown when a node cannot be cast to the right type. -- -- As used in getNodePage. data WrongNodeTypeError WrongNodeTypeError :: WrongNodeTypeError -- | Exception thrown when a value from an overflow page cannot be cast. -- -- As used in getOverflow. 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.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.Applicative 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.Base.Applicative m, GHC.Base.Monad m, Control.Monad.IO.Class.MonadIO m, Control.Monad.Catch.MonadThrow m) => Database.Haskey.Alloc.Concurrent.Meta.ConcurrentMetaStoreM (Database.Haskey.Store.File.FileStoreT GHC.IO.FilePath m) instance (Data.Typeable.Internal.Typeable hnd, GHC.Show.Show hnd) => GHC.Exception.Exception (Database.Haskey.Store.File.FileNotFoundError hnd) instance GHC.Exception.Exception Database.Haskey.Store.File.PageOverflowError instance GHC.Exception.Exception Database.Haskey.Store.File.WrongNodeTypeError instance GHC.Exception.Exception Database.Haskey.Store.File.WrongOverflowValueError -- | Binary in-memory storage back-end. Can be used as a storage back-end -- for the append-only page allocator (see Data.BTree.Alloc). module Database.Haskey.Store.InMemory -- | A decoded page, of a certain type t of kind PageType. data Page (t :: PageType) [EmptyPage] :: Page TypeEmpty [ConcurrentMetaPage] :: (Key k, Value v) => ConcurrentMeta k v -> 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 Files, each associated with a certain -- fp handle. -- -- This is shareable amongst multiple threads. type MemoryFiles fp = IORef (Map fp MemoryFile) -- | Memory store configuration. -- -- The default configuration can be obtained by using -- defMemoryStoreConfig. -- -- A configuration with a specific page size can be obtained by using -- memoryStoreConfigWithPageSize. data MemoryStoreConfig MemoryStoreConfig :: !PageSize -> !Word64 -> !Word64 -> MemoryStoreConfig [memoryStoreConfigPageSize] :: MemoryStoreConfig -> !PageSize [memoryStoreConfigMaxKeySize] :: MemoryStoreConfig -> !Word64 [memoryStoreConfigMaxValueSize] :: MemoryStoreConfig -> !Word64 -- | The default configuration. -- -- This is an unwrapped memoryStoreConfigWithPageSize 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 -- calculateMaxKeySize and calculateMaxValueSize. -- -- If the page size is too small, Nothing is returned. memoryStoreConfigWithPageSize :: PageSize -> Maybe MemoryStoreConfig -- | Monad in which binary storage operations can take place. -- -- Two important instances are StoreM making it a storage -- back-end, and ConcurrentMetaStoreM making it a storage back-end -- compatible with the concurrent page allocator. data MemoryStoreT fp m a -- | Run the storage operations in the MemoryStoreT monad, given a -- collection of Files. runMemoryStoreT :: MemoryStoreT fp m a -> MemoryStoreConfig -> MemoryFiles fp -> m a -- | Construct a store with an empty database with name of type -- hnd. 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 getNodePage. data WrongNodeTypeError WrongNodeTypeError :: WrongNodeTypeError -- | Exception thrown when a value from an overflow page cannot be cast. -- -- As used in getOverflow. 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.Base.Applicative m, GHC.Base.Monad m, Control.Monad.IO.Class.MonadIO m, Control.Monad.Catch.MonadThrow m) => Database.Haskey.Alloc.Concurrent.Meta.ConcurrentMetaStoreM (Database.Haskey.Store.InMemory.MemoryStoreT GHC.IO.FilePath m) instance (Data.Typeable.Internal.Typeable hnd, GHC.Show.Show hnd) => GHC.Exception.Exception (Database.Haskey.Store.InMemory.FileNotFoundError hnd) instance (Data.Typeable.Internal.Typeable hnd, GHC.Show.Show hnd) => GHC.Exception.Exception (Database.Haskey.Store.InMemory.PageNotFoundError hnd) instance GHC.Exception.Exception Database.Haskey.Store.InMemory.WrongNodeTypeError instance GHC.Exception.Exception Database.Haskey.Store.InMemory.WrongOverflowValueError