Safe Haskell | Safe-Inferred |
---|---|
Language | GHC2021 |
Database.LSMTree.Monoidal
Description
On disk key-value tables, implemented as Log Structured Merge (LSM) trees.
This module is the API for "monoidal" tables, as opposed to "normal" tables (that do not support monoidal updates and unions).
Key features:
- Basic key/value operations: lookup, insert, delete
- Monoidal operations: mupsert
- Merging of tables
- Range lookups by key or key prefix
- On-disk durability is only via named snapshots: ordinary operations are otherwise not durable
- Opening tables from previous named snapshots
- Full persistent data structure by cheap table duplication: all duplicate tables can be both accessed and modified
- High performance lookups on SSDs by I/O batching and concurrency
This module is intended to be imported qualified.
import qualified Database.LSMTree.Monoidal as LSMT
Synopsis
- data SessionDirDoesNotExistError = ErrSessionDirDoesNotExist !FsErrorPath
- data SessionDirLockedError = ErrSessionDirLocked !FsErrorPath
- data SessionDirCorruptedError = ErrSessionDirCorrupted !FsErrorPath
- data SessionClosedError = ErrSessionClosed
- data TableClosedError = ErrTableClosed
- data TableCorruptedError = ErrLookupByteCountDiscrepancy !ByteCount !ByteCount
- data TableTooLargeError = ErrTableTooLarge
- data TableUnionNotCompatibleError
- data SnapshotExistsError = ErrSnapshotExists !SnapshotName
- data SnapshotDoesNotExistError = ErrSnapshotDoesNotExist !SnapshotName
- data SnapshotCorruptedError = ErrSnapshotCorrupted !SnapshotName !FileCorruptedError
- data SnapshotNotCompatibleError
- data BlobRefInvalidError = ErrBlobRefInvalid !Int
- data CursorClosedError = ErrCursorClosed
- data FileFormat
- data FileCorruptedError
- data InvalidSnapshotNameError = ErrSnapshotNameInvalid !String
- data LSMTreeTrace
- = TraceOpenSession FsPath
- | TraceNewSession
- | TraceRestoreSession
- | TraceCloseSession
- | TraceNewTable
- | TraceOpenSnapshot SnapshotName TableConfigOverride
- | TraceTable TableId TableTrace
- | TraceDeleteSnapshot SnapshotName
- | TraceListSnapshots
- | TraceCursor CursorId CursorTrace
- | TraceUnions (NonEmpty TableId)
- data TableTrace
- data MergeTrace
- = TraceFlushWriteBuffer NumEntries RunNumber RunParams
- | TraceAddLevel
- | TraceAddRun RunNumber (Vector RunNumber)
- | TraceNewMerge (Vector NumEntries) RunNumber RunParams MergePolicyForLevel LevelMergeType
- | TraceNewMergeSingleRun NumEntries RunNumber
- | TraceCompletedMerge NumEntries RunNumber
- | TraceExpectCompletedMerge RunNumber
- type Session = Session'
- withSession :: (IOLike m, Typeable h) => Tracer m LSMTreeTrace -> HasFS m h -> HasBlockIO m h -> FsPath -> (Session m -> m a) -> m a
- openSession :: forall m h. (IOLike m, Typeable h) => Tracer m LSMTreeTrace -> HasFS m h -> HasBlockIO m h -> FsPath -> m (Session m)
- closeSession :: IOLike m => Session m -> m ()
- type Table = MonoidalTable
- data TableConfig = TableConfig {}
- defaultTableConfig :: TableConfig
- data SizeRatio = Four
- data MergePolicy = MergePolicyLazyLevelling
- data WriteBufferAlloc = AllocNumEntries !NumEntries
- newtype NumEntries = NumEntries Int
- data BloomFilterAlloc
- defaultBloomFilterAlloc :: BloomFilterAlloc
- data FencePointerIndexType
- data DiskCachePolicy
- data MergeSchedule
- defaultMergeSchedule :: MergeSchedule
- withTable :: forall m k v a. IOLike m => Session m -> TableConfig -> (Table m k v -> m a) -> m a
- new :: forall m k v. IOLike m => Session m -> TableConfig -> m (Table m k v)
- close :: forall m k v. IOLike m => Table m k v -> m ()
- lookups :: forall m k v. (IOLike m, SerialiseKey k, SerialiseValue v, ResolveValue v) => Table m k v -> Vector k -> m (Vector (LookupResult v))
- data LookupResult v
- rangeLookup :: forall m k v. (IOLike m, SerialiseKey k, SerialiseValue v, ResolveValue v) => Table m k v -> Range k -> m (Vector (QueryResult k v))
- data Range k
- = FromToExcluding k k
- | FromToIncluding k k
- data QueryResult k v = FoundInQuery !k !v
- type Cursor = MonoidalCursor
- withCursor :: forall m k v a. IOLike m => Table m k v -> (Cursor m k v -> m a) -> m a
- withCursorAtOffset :: forall m k v a. (IOLike m, SerialiseKey k) => k -> Table m k v -> (Cursor m k v -> m a) -> m a
- newCursor :: forall m k v. IOLike m => Table m k v -> m (Cursor m k v)
- newCursorAtOffset :: forall m k v. (IOLike m, SerialiseKey k) => k -> Table m k v -> m (Cursor m k v)
- closeCursor :: forall m k v. IOLike m => Cursor m k v -> m ()
- readCursor :: forall m k v. (IOLike m, SerialiseKey k, SerialiseValue v, ResolveValue v) => Int -> Cursor m k v -> m (Vector (QueryResult k v))
- inserts :: forall m k v. (IOLike m, SerialiseKey k, SerialiseValue v, ResolveValue v) => Table m k v -> Vector (k, v) -> m ()
- deletes :: forall m k v. (IOLike m, SerialiseKey k, SerialiseValue v, ResolveValue v) => Table m k v -> Vector k -> m ()
- mupserts :: forall m k v. (IOLike m, SerialiseKey k, SerialiseValue v, ResolveValue v) => Table m k v -> Vector (k, v) -> m ()
- updates :: forall m k v. (IOLike m, SerialiseKey k, SerialiseValue v, ResolveValue v) => Table m k v -> Vector (k, Update v) -> m ()
- data Update v
- data SnapshotName
- toSnapshotName :: String -> SnapshotName
- isValidSnapshotName :: String -> Bool
- newtype SnapshotLabel = SnapshotLabel Text
- createSnapshot :: forall m k v. IOLike m => SnapshotLabel -> SnapshotName -> Table m k v -> m ()
- openSnapshot :: forall m k v. (IOLike m, ResolveValue v) => Session m -> TableConfigOverride -> SnapshotLabel -> SnapshotName -> m (Table m k v)
- data TableConfigOverride
- configNoOverride :: TableConfigOverride
- configOverrideDiskCachePolicy :: DiskCachePolicy -> TableConfigOverride
- deleteSnapshot :: IOLike m => Session m -> SnapshotName -> m ()
- listSnapshots :: IOLike m => Session m -> m [SnapshotName]
- duplicate :: forall m k v. IOLike m => Table m k v -> m (Table m k v)
- union :: forall m k v. IOLike m => Table m k v -> Table m k v -> m (Table m k v)
- unions :: forall m k v. IOLike m => NonEmpty (Table m k v) -> m (Table m k v)
- newtype UnionDebt = UnionDebt Int
- remainingUnionDebt :: IOLike m => Table m k v -> m UnionDebt
- newtype UnionCredits = UnionCredits Int
- supplyUnionCredits :: forall m k v. (IOLike m, ResolveValue v) => Table m k v -> UnionCredits -> m UnionCredits
- class SerialiseKey k
- class SerialiseValue v
- class ResolveValue v where
- resolveValue :: Proxy v -> RawBytes -> RawBytes -> RawBytes
- resolveDeserialised :: forall v. SerialiseValue v => (v -> v -> v) -> Proxy v -> RawBytes -> RawBytes -> RawBytes
- resolveValueValidOutput :: forall v. (SerialiseValue v, ResolveValue v, NFData v) => v -> v -> Bool
- resolveValueAssociativity :: forall v. (SerialiseValue v, ResolveValue v) => v -> v -> v -> Bool
- type IOLike m = (MonadAsync m, MonadMVar m, MonadThrow (STM m), MonadThrow m, MonadCatch m, MonadMask m, PrimMonad m, MonadST m)
Exceptions
data SessionDirDoesNotExistError Source #
The session directory does not exist.
Constructors
ErrSessionDirDoesNotExist !FsErrorPath |
Instances
Exception SessionDirDoesNotExistError Source # | |
Defined in Database.LSMTree.Internal | |
Show SessionDirDoesNotExistError Source # | |
Defined in Database.LSMTree.Internal Methods showsPrec :: Int -> SessionDirDoesNotExistError -> ShowS # show :: SessionDirDoesNotExistError -> String # showList :: [SessionDirDoesNotExistError] -> ShowS # | |
Eq SessionDirDoesNotExistError Source # | |
Defined in Database.LSMTree.Internal Methods (==) :: SessionDirDoesNotExistError -> SessionDirDoesNotExistError -> Bool # (/=) :: SessionDirDoesNotExistError -> SessionDirDoesNotExistError -> Bool # |
data SessionDirLockedError Source #
The session directory is locked by another active session.
Constructors
ErrSessionDirLocked !FsErrorPath |
Instances
Exception SessionDirLockedError Source # | |
Defined in Database.LSMTree.Internal | |
Show SessionDirLockedError Source # | |
Defined in Database.LSMTree.Internal Methods showsPrec :: Int -> SessionDirLockedError -> ShowS # show :: SessionDirLockedError -> String # showList :: [SessionDirLockedError] -> ShowS # | |
Eq SessionDirLockedError Source # | |
Defined in Database.LSMTree.Internal Methods (==) :: SessionDirLockedError -> SessionDirLockedError -> Bool # (/=) :: SessionDirLockedError -> SessionDirLockedError -> Bool # |
data SessionDirCorruptedError Source #
The session directory is corrupted, e.g., it misses required files or contains unexpected files.
Constructors
ErrSessionDirCorrupted !FsErrorPath |
Instances
Exception SessionDirCorruptedError Source # | |
Defined in Database.LSMTree.Internal | |
Show SessionDirCorruptedError Source # | |
Defined in Database.LSMTree.Internal Methods showsPrec :: Int -> SessionDirCorruptedError -> ShowS # show :: SessionDirCorruptedError -> String # showList :: [SessionDirCorruptedError] -> ShowS # | |
Eq SessionDirCorruptedError Source # | |
Defined in Database.LSMTree.Internal Methods (==) :: SessionDirCorruptedError -> SessionDirCorruptedError -> Bool # (/=) :: SessionDirCorruptedError -> SessionDirCorruptedError -> Bool # |
data SessionClosedError Source #
The session is closed.
Constructors
ErrSessionClosed |
Instances
Exception SessionClosedError Source # | |
Defined in Database.LSMTree.Internal Methods toException :: SessionClosedError -> SomeException # fromException :: SomeException -> Maybe SessionClosedError # | |
Show SessionClosedError Source # | |
Defined in Database.LSMTree.Internal Methods showsPrec :: Int -> SessionClosedError -> ShowS # show :: SessionClosedError -> String # showList :: [SessionClosedError] -> ShowS # | |
Eq SessionClosedError Source # | |
Defined in Database.LSMTree.Internal Methods (==) :: SessionClosedError -> SessionClosedError -> Bool # (/=) :: SessionClosedError -> SessionClosedError -> Bool # |
data TableClosedError Source #
The table is closed.
Constructors
ErrTableClosed |
Instances
Exception TableClosedError Source # | |
Defined in Database.LSMTree.Internal Methods toException :: TableClosedError -> SomeException # | |
Show TableClosedError Source # | |
Defined in Database.LSMTree.Internal Methods showsPrec :: Int -> TableClosedError -> ShowS # show :: TableClosedError -> String # showList :: [TableClosedError] -> ShowS # | |
Eq TableClosedError Source # | |
Defined in Database.LSMTree.Internal Methods (==) :: TableClosedError -> TableClosedError -> Bool # (/=) :: TableClosedError -> TableClosedError -> Bool # |
data TableCorruptedError Source #
The table data is corrupted.
Constructors
ErrLookupByteCountDiscrepancy | |
Instances
Exception TableCorruptedError Source # | |
Defined in Database.LSMTree.Internal.Lookup Methods toException :: TableCorruptedError -> SomeException # fromException :: SomeException -> Maybe TableCorruptedError # | |
Show TableCorruptedError Source # | |
Defined in Database.LSMTree.Internal.Lookup Methods showsPrec :: Int -> TableCorruptedError -> ShowS # show :: TableCorruptedError -> String # showList :: [TableCorruptedError] -> ShowS # | |
Eq TableCorruptedError Source # | |
Defined in Database.LSMTree.Internal.Lookup Methods (==) :: TableCorruptedError -> TableCorruptedError -> Bool # (/=) :: TableCorruptedError -> TableCorruptedError -> Bool # |
data TableTooLargeError Source #
The table contains a run that has more than \(2^{40}\) physical entries.
Constructors
ErrTableTooLarge |
Instances
Exception TableTooLargeError Source # | |
Defined in Database.LSMTree.Internal.MergingRun Methods toException :: TableTooLargeError -> SomeException # fromException :: SomeException -> Maybe TableTooLargeError # | |
Show TableTooLargeError Source # | |
Defined in Database.LSMTree.Internal.MergingRun Methods showsPrec :: Int -> TableTooLargeError -> ShowS # show :: TableTooLargeError -> String # showList :: [TableTooLargeError] -> ShowS # | |
Eq TableTooLargeError Source # | |
Defined in Database.LSMTree.Internal.MergingRun Methods (==) :: TableTooLargeError -> TableTooLargeError -> Bool # (/=) :: TableTooLargeError -> TableTooLargeError -> Bool # |
data TableUnionNotCompatibleError Source #
A table union was constructed with two tables that are not compatible.
Constructors
ErrTableUnionHandleTypeMismatch | |
ErrTableUnionSessionMismatch | |
Fields
|
Instances
Exception TableUnionNotCompatibleError Source # | |
Show TableUnionNotCompatibleError Source # | |
Defined in Database.LSMTree.Internal Methods showsPrec :: Int -> TableUnionNotCompatibleError -> ShowS # show :: TableUnionNotCompatibleError -> String # showList :: [TableUnionNotCompatibleError] -> ShowS # | |
Eq TableUnionNotCompatibleError Source # | |
Defined in Database.LSMTree.Internal Methods (==) :: TableUnionNotCompatibleError -> TableUnionNotCompatibleError -> Bool # (/=) :: TableUnionNotCompatibleError -> TableUnionNotCompatibleError -> Bool # |
data SnapshotExistsError Source #
The named snapshot already exists.
Constructors
ErrSnapshotExists !SnapshotName |
Instances
Exception SnapshotExistsError Source # | |
Defined in Database.LSMTree.Internal Methods toException :: SnapshotExistsError -> SomeException # fromException :: SomeException -> Maybe SnapshotExistsError # | |
Show SnapshotExistsError Source # | |
Defined in Database.LSMTree.Internal Methods showsPrec :: Int -> SnapshotExistsError -> ShowS # show :: SnapshotExistsError -> String # showList :: [SnapshotExistsError] -> ShowS # | |
Eq SnapshotExistsError Source # | |
Defined in Database.LSMTree.Internal Methods (==) :: SnapshotExistsError -> SnapshotExistsError -> Bool # (/=) :: SnapshotExistsError -> SnapshotExistsError -> Bool # |
data SnapshotDoesNotExistError Source #
The named snapshot does not exist.
Constructors
ErrSnapshotDoesNotExist !SnapshotName |
Instances
Exception SnapshotDoesNotExistError Source # | |
Defined in Database.LSMTree.Internal | |
Show SnapshotDoesNotExistError Source # | |
Defined in Database.LSMTree.Internal Methods showsPrec :: Int -> SnapshotDoesNotExistError -> ShowS # show :: SnapshotDoesNotExistError -> String # showList :: [SnapshotDoesNotExistError] -> ShowS # | |
Eq SnapshotDoesNotExistError Source # | |
Defined in Database.LSMTree.Internal Methods (==) :: SnapshotDoesNotExistError -> SnapshotDoesNotExistError -> Bool # (/=) :: SnapshotDoesNotExistError -> SnapshotDoesNotExistError -> Bool # |
data SnapshotCorruptedError Source #
The named snapshot is corrupted.
Constructors
ErrSnapshotCorrupted !SnapshotName !FileCorruptedError |
Instances
Exception SnapshotCorruptedError Source # | |
Defined in Database.LSMTree.Internal | |
Show SnapshotCorruptedError Source # | |
Defined in Database.LSMTree.Internal Methods showsPrec :: Int -> SnapshotCorruptedError -> ShowS # show :: SnapshotCorruptedError -> String # showList :: [SnapshotCorruptedError] -> ShowS # | |
Eq SnapshotCorruptedError Source # | |
Defined in Database.LSMTree.Internal Methods (==) :: SnapshotCorruptedError -> SnapshotCorruptedError -> Bool # (/=) :: SnapshotCorruptedError -> SnapshotCorruptedError -> Bool # |
data SnapshotNotCompatibleError Source #
The named snapshot is not compatible with the expected type.
Constructors
ErrSnapshotWrongTableType | The named snapshot is not compatible with the current public API module. For instance, the snapshot was created using the simple API, but was opened using the full API. |
Fields
| |
ErrSnapshotWrongLabel | The named snapshot is not compatible with the given label. |
Fields
|
Instances
Exception SnapshotNotCompatibleError Source # | |
Defined in Database.LSMTree.Internal | |
Show SnapshotNotCompatibleError Source # | |
Defined in Database.LSMTree.Internal Methods showsPrec :: Int -> SnapshotNotCompatibleError -> ShowS # show :: SnapshotNotCompatibleError -> String # showList :: [SnapshotNotCompatibleError] -> ShowS # | |
Eq SnapshotNotCompatibleError Source # | |
Defined in Database.LSMTree.Internal Methods (==) :: SnapshotNotCompatibleError -> SnapshotNotCompatibleError -> Bool # (/=) :: SnapshotNotCompatibleError -> SnapshotNotCompatibleError -> Bool # |
data BlobRefInvalidError Source #
A BlobRef
used with retrieveBlobs
was invalid.
BlobRef
s are obtained from lookups in a Table
, but they may be
invalidated by subsequent changes in that Table
. In general the
reliable way to retrieve blobs is not to change the Table
before
retrieving the blobs. To allow later retrievals, duplicate the table
before making modifications and keep the table open until all blob
retrievals are complete.
Constructors
ErrBlobRefInvalid !Int | The |
Instances
Exception BlobRefInvalidError Source # | |
Defined in Database.LSMTree.Internal Methods toException :: BlobRefInvalidError -> SomeException # fromException :: SomeException -> Maybe BlobRefInvalidError # | |
Show BlobRefInvalidError Source # | |
Defined in Database.LSMTree.Internal Methods showsPrec :: Int -> BlobRefInvalidError -> ShowS # show :: BlobRefInvalidError -> String # showList :: [BlobRefInvalidError] -> ShowS # | |
Eq BlobRefInvalidError Source # | |
Defined in Database.LSMTree.Internal Methods (==) :: BlobRefInvalidError -> BlobRefInvalidError -> Bool # (/=) :: BlobRefInvalidError -> BlobRefInvalidError -> Bool # |
data CursorClosedError Source #
The cursor is closed.
Constructors
ErrCursorClosed |
Instances
Exception CursorClosedError Source # | |
Defined in Database.LSMTree.Internal Methods toException :: CursorClosedError -> SomeException # | |
Show CursorClosedError Source # | |
Defined in Database.LSMTree.Internal Methods showsPrec :: Int -> CursorClosedError -> ShowS # show :: CursorClosedError -> String # showList :: [CursorClosedError] -> ShowS # | |
Eq CursorClosedError Source # | |
Defined in Database.LSMTree.Internal Methods (==) :: CursorClosedError -> CursorClosedError -> Bool # (/=) :: CursorClosedError -> CursorClosedError -> Bool # |
data FileFormat Source #
Constructors
FormatChecksumsFile | |
FormatBloomFilterFile | |
FormatIndexFile | |
FormatWriteBufferFile | |
FormatSnapshotMetaData |
Instances
Show FileFormat Source # | |
Defined in Database.LSMTree.Internal.CRC32C Methods showsPrec :: Int -> FileFormat -> ShowS # show :: FileFormat -> String # showList :: [FileFormat] -> ShowS # | |
Eq FileFormat Source # | |
Defined in Database.LSMTree.Internal.CRC32C |
data FileCorruptedError Source #
The file is corrupted.
Constructors
ErrFileFormatInvalid | The file fails to parse. |
Fields
| |
ErrFileChecksumMismatch | The file CRC32 checksum is invalid. |
Instances
Exception FileCorruptedError Source # | |
Defined in Database.LSMTree.Internal.CRC32C Methods toException :: FileCorruptedError -> SomeException # fromException :: SomeException -> Maybe FileCorruptedError # | |
Show FileCorruptedError Source # | |
Defined in Database.LSMTree.Internal.CRC32C Methods showsPrec :: Int -> FileCorruptedError -> ShowS # show :: FileCorruptedError -> String # showList :: [FileCorruptedError] -> ShowS # | |
Eq FileCorruptedError Source # | |
Defined in Database.LSMTree.Internal.CRC32C Methods (==) :: FileCorruptedError -> FileCorruptedError -> Bool # (/=) :: FileCorruptedError -> FileCorruptedError -> Bool # |
data InvalidSnapshotNameError Source #
Constructors
ErrSnapshotNameInvalid !String |
Instances
Exception InvalidSnapshotNameError Source # | |
Defined in Database.LSMTree.Internal.Paths | |
Show InvalidSnapshotNameError Source # | |
Defined in Database.LSMTree.Internal.Paths Methods showsPrec :: Int -> InvalidSnapshotNameError -> ShowS # show :: InvalidSnapshotNameError -> String # showList :: [InvalidSnapshotNameError] -> ShowS # |
Tracing
data LSMTreeTrace Source #
Constructors
Instances
Show LSMTreeTrace Source # | |
Defined in Database.LSMTree.Internal Methods showsPrec :: Int -> LSMTreeTrace -> ShowS # show :: LSMTreeTrace -> String # showList :: [LSMTreeTrace] -> ShowS # |
data TableTrace Source #
Constructors
TraceCreateTable TableConfig | A table is created with the specified config. This message is traced in addition to messages like |
TraceCloseTable | |
TraceLookups Int | |
TraceRangeLookup (Range SerialisedKey) | |
TraceUpdates Int | |
TraceMerge (AtLevel MergeTrace) | |
TraceSnapshot SnapshotName | |
TraceDuplicate | |
TraceRemainingUnionDebt | |
TraceSupplyUnionCredits UnionCredits |
Instances
Show TableTrace Source # | |
Defined in Database.LSMTree.Internal Methods showsPrec :: Int -> TableTrace -> ShowS # show :: TableTrace -> String # showList :: [TableTrace] -> ShowS # |
data MergeTrace Source #
Constructors
TraceFlushWriteBuffer | |
Fields
| |
TraceAddLevel | |
TraceAddRun | |
TraceNewMerge | |
Fields
| |
TraceNewMergeSingleRun | |
Fields
| |
TraceCompletedMerge | |
Fields
| |
TraceExpectCompletedMerge RunNumber | This is traced at the latest point the merge could complete. |
Instances
Show MergeTrace Source # | |
Defined in Database.LSMTree.Internal.MergeSchedule Methods showsPrec :: Int -> MergeTrace -> ShowS # show :: MergeTrace -> String # showList :: [MergeTrace] -> ShowS # |
Table sessions
type Session = Session' Source #
A session provides context that is shared across multiple tables.
Sessions are needed to support sharing between multiple table instances.
Sharing occurs when tables are duplicated using duplicate
, or when tables
are combined using union
. Sharing is not fully preserved by snapshots:
existing runs are shared, but ongoing merges are not. As such, restoring of
snapshots (using open
) is expensive, but snapshotting (using snapshot
) is
relatively cheap.
The "monoidal" table types support a union
operation, which has the
constraint that the two input tables must be from the same Session
.
Each session places files for table data under a given directory. It is not permitted to open multiple sessions for the same directory at once. Instead a session should be opened once and shared for all uses of tables. This restriction implies that tables cannot be shared between OS processes. The restriction is enforced using file locks.
Sessions support both related and unrelated tables. Related tables are
created using duplicate
, while unrelated tables can be created using new
.
It is possible to have multiple unrelated tables with different configuration
and key and value types in the same session. Similarly, a session can have
both "normal" and "monoidal" tables. For unrelated tables (that are not
involved in a union
) one has a choice between using multiple sessions or a
shared session. Using multiple sessions requires using separate directories,
while a shared session will place all files under one directory.
withSession :: (IOLike m, Typeable h) => Tracer m LSMTreeTrace -> HasFS m h -> HasBlockIO m h -> FsPath -> (Session m -> m a) -> m a Source #
(Asynchronous) exception-safe, bracketed opening and closing of a session.
If possible, it is recommended to use this function instead of openSession
and closeSession
.
Arguments
:: forall m h. (IOLike m, Typeable h) | |
=> Tracer m LSMTreeTrace | |
-> HasFS m h | |
-> HasBlockIO m h | |
-> FsPath | Path to the session directory |
-> m (Session m) |
Create either a new empty table session or open an existing table session, given the path to the session directory.
A new empty table session is created if the given directory is entirely empty. Otherwise it is intended to open an existing table session.
Sessions should be closed using closeSession
when no longer needed.
Consider using withSession
instead.
Exceptions:
- Throws an exception if the directory does not exist (regardless of whether it is empty or not).
- This can throw exceptions if the directory does not have the expected file layout for a table session
- It will throw an exception if the session is already open (in the current process or another OS process)
closeSession :: IOLike m => Session m -> m () Source #
Close the table session. closeSession
is idempotent. All subsequent
operations on the session or the tables within it will throw an exception.
This also closes any open tables and cursors in the session. It would typically be good practice however to close all tables first rather than relying on this for cleanup.
Closing a table session allows the session to be opened again elsewhere, for example in a different process. Note that the session will be closed automatically if the process is terminated (in particular the session file lock will be released).
Table
type Table = MonoidalTable Source #
A handle to an on-disk key/value table.
An LSMT table is an individual key value mapping with in-memory and on-disk parts. A table is the object/reference by which an in-use LSM table will be operated upon. In this API it identifies a single mutable instance of an LSM table. The duplicate tables feature allows for there to may be many such instances in use at once.
data TableConfig Source #
Table configuration parameters, including LSM tree tuning parameters.
Some config options are fixed (for now):
- Merge policy: Tiering
- Size ratio: 4
Constructors
TableConfig | |
Fields
|
Instances
Show TableConfig Source # | |
Defined in Database.LSMTree.Internal.Config Methods showsPrec :: Int -> TableConfig -> ShowS # show :: TableConfig -> String # showList :: [TableConfig] -> ShowS # | |
NFData TableConfig Source # | |
Defined in Database.LSMTree.Internal.Config Methods rnf :: TableConfig -> () # | |
Eq TableConfig Source # | |
Defined in Database.LSMTree.Internal.Config | |
DecodeVersioned TableConfig Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods decodeVersioned :: SnapshotVersion -> Decoder s TableConfig Source # | |
Encode TableConfig Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods encode :: TableConfig -> Encoding Source # |
defaultTableConfig :: TableConfig Source #
A reasonable default TableConfig
.
This uses a write buffer with up to 20,000 elements and a generous amount of memory for Bloom filters (FPR of 2%).
Constructors
Four |
Instances
Show SizeRatio Source # | |
NFData SizeRatio Source # | |
Defined in Database.LSMTree.Internal.Config | |
Eq SizeRatio Source # | |
DecodeVersioned SizeRatio Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods decodeVersioned :: SnapshotVersion -> Decoder s SizeRatio Source # | |
Encode SizeRatio Source # | |
data MergePolicy Source #
Constructors
MergePolicyLazyLevelling | Use tiering on intermediate levels, and levelling on the last level. This makes it easier for delete operations to disappear on the last level. |
Instances
Show MergePolicy Source # | |
Defined in Database.LSMTree.Internal.Config Methods showsPrec :: Int -> MergePolicy -> ShowS # show :: MergePolicy -> String # showList :: [MergePolicy] -> ShowS # | |
NFData MergePolicy Source # | |
Defined in Database.LSMTree.Internal.Config Methods rnf :: MergePolicy -> () # | |
Eq MergePolicy Source # | |
Defined in Database.LSMTree.Internal.Config | |
DecodeVersioned MergePolicy Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods decodeVersioned :: SnapshotVersion -> Decoder s MergePolicy Source # | |
Encode MergePolicy Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods encode :: MergePolicy -> Encoding Source # |
data WriteBufferAlloc Source #
Allocation method for the write buffer.
Constructors
AllocNumEntries !NumEntries | Total number of key/value pairs that can be present in the write buffer before flushing the write buffer to disk. NOTE: if the sizes of values vary greatly, this can lead to wonky runs on disk, and therefore unpredictable performance. |
Instances
Show WriteBufferAlloc Source # | |
Defined in Database.LSMTree.Internal.Config Methods showsPrec :: Int -> WriteBufferAlloc -> ShowS # show :: WriteBufferAlloc -> String # showList :: [WriteBufferAlloc] -> ShowS # | |
NFData WriteBufferAlloc Source # | |
Defined in Database.LSMTree.Internal.Config Methods rnf :: WriteBufferAlloc -> () # | |
Eq WriteBufferAlloc Source # | |
Defined in Database.LSMTree.Internal.Config Methods (==) :: WriteBufferAlloc -> WriteBufferAlloc -> Bool # (/=) :: WriteBufferAlloc -> WriteBufferAlloc -> Bool # | |
DecodeVersioned WriteBufferAlloc Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods decodeVersioned :: SnapshotVersion -> Decoder s WriteBufferAlloc Source # | |
Encode WriteBufferAlloc Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods encode :: WriteBufferAlloc -> Encoding Source # |
newtype NumEntries Source #
A count of entries, for example the number of entries in a run.
This number is limited by the machine's word size. On 32-bit systems, the
maximum number we can represent is 2^31
which is roughly 2 billion. This
should be a sufficiently large limit that we never reach it in practice. By
extension for 64-bit and higher-bit systems this limit is also sufficiently
large.
Constructors
NumEntries Int |
Instances
data BloomFilterAlloc Source #
Allocation method for bloom filters.
NOTE: a physical database entry is a key/operation pair that exists in a file, i.e., a run. Multiple physical entries that have the same key constitute a logical database entry.
Constructors
AllocFixed | Allocate a fixed number of bits per physical entry in each bloom filter. |
Fields
| |
AllocRequestFPR | Allocate as many bits as required per physical entry to get the requested false-positive rate. Do this for each bloom filter. |
Fields
|
Instances
Show BloomFilterAlloc Source # | |
Defined in Database.LSMTree.Internal.Config Methods showsPrec :: Int -> BloomFilterAlloc -> ShowS # show :: BloomFilterAlloc -> String # showList :: [BloomFilterAlloc] -> ShowS # | |
NFData BloomFilterAlloc Source # | |
Defined in Database.LSMTree.Internal.Config Methods rnf :: BloomFilterAlloc -> () # | |
Eq BloomFilterAlloc Source # | |
Defined in Database.LSMTree.Internal.Config Methods (==) :: BloomFilterAlloc -> BloomFilterAlloc -> Bool # (/=) :: BloomFilterAlloc -> BloomFilterAlloc -> Bool # | |
DecodeVersioned BloomFilterAlloc Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods decodeVersioned :: SnapshotVersion -> Decoder s BloomFilterAlloc Source # | |
Encode BloomFilterAlloc Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods encode :: BloomFilterAlloc -> Encoding Source # |
data FencePointerIndexType Source #
Configure the type of fence pointer index.
Constructors
CompactIndex | Use a compact fence pointer index. Compact indexes are designed to work with keys that are large (for example, 32 bytes long) cryptographic hashes. When using a compact index, it is vital that the
Use |
OrdinaryIndex | Use an ordinary fence pointer index Ordinary indexes do not have any constraints on keys other than that their serialised forms may not be 64 KiB or more in size. |
Instances
Show FencePointerIndexType Source # | |
Defined in Database.LSMTree.Internal.Config Methods showsPrec :: Int -> FencePointerIndexType -> ShowS # show :: FencePointerIndexType -> String # showList :: [FencePointerIndexType] -> ShowS # | |
NFData FencePointerIndexType Source # | |
Defined in Database.LSMTree.Internal.Config Methods rnf :: FencePointerIndexType -> () # | |
Eq FencePointerIndexType Source # | |
Defined in Database.LSMTree.Internal.Config Methods (==) :: FencePointerIndexType -> FencePointerIndexType -> Bool # (/=) :: FencePointerIndexType -> FencePointerIndexType -> Bool # | |
DecodeVersioned FencePointerIndexType Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods decodeVersioned :: SnapshotVersion -> Decoder s FencePointerIndexType Source # | |
Encode FencePointerIndexType Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods |
data DiskCachePolicy Source #
The policy for caching data from disk in memory (using the OS page cache).
Caching data in memory can improve performance if the access pattern has good access locality or if the overall data size fits within memory. On the other hand, caching is determental to performance and wastes memory if the access pattern has poor spatial or temporal locality.
This implementation is designed to have good performance using a cacheless policy, where main memory is used only to cache Bloom filters and indexes, but none of the key/value data itself. Nevertheless, some use cases will be faster if some or all of the key/value data is also cached in memory. This implementation does not do any custom caching of key/value data, relying simply on the OS page cache. Thus caching is done in units of 4kb disk pages (as opposed to individual key/value pairs for example).
Constructors
DiskCacheAll | Use the OS page cache to cache any/all key/value data in the table. Use this policy if the expected access pattern for the table has a good spatial or temporal locality. |
DiskCacheLevelsAtOrBelow !Int | Use the OS page cache to cache data in all LSMT levels at or below a given level number. For example, use 1 to cache the first level. (The write buffer is considered to be level 0.) Use this policy if the expected access pattern for the table has good temporal locality for recently inserted keys. |
DiskCacheNone | Do not cache any key/value data in any level (except the write buffer). Use this policy if expected access pattern for the table has poor spatial or temporal locality, such as uniform random access. |
Instances
Show DiskCachePolicy Source # | |
Defined in Database.LSMTree.Internal.Config Methods showsPrec :: Int -> DiskCachePolicy -> ShowS # show :: DiskCachePolicy -> String # showList :: [DiskCachePolicy] -> ShowS # | |
NFData DiskCachePolicy Source # | |
Defined in Database.LSMTree.Internal.Config Methods rnf :: DiskCachePolicy -> () # | |
Eq DiskCachePolicy Source # | |
Defined in Database.LSMTree.Internal.Config Methods (==) :: DiskCachePolicy -> DiskCachePolicy -> Bool # (/=) :: DiskCachePolicy -> DiskCachePolicy -> Bool # | |
DecodeVersioned DiskCachePolicy Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods decodeVersioned :: SnapshotVersion -> Decoder s DiskCachePolicy Source # | |
Encode DiskCachePolicy Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods encode :: DiskCachePolicy -> Encoding Source # |
data MergeSchedule Source #
A configuration option that determines how merges are stepped to completion. This does not affect the amount of work that is done by merges, only how the work is spread out over time.
Constructors
OneShot | Complete merges immediately when started. The |
Incremental | Schedule merges for incremental construction, and step the merge when updates are performed on a table. The |
Instances
Show MergeSchedule Source # | |
Defined in Database.LSMTree.Internal.Config Methods showsPrec :: Int -> MergeSchedule -> ShowS # show :: MergeSchedule -> String # showList :: [MergeSchedule] -> ShowS # | |
NFData MergeSchedule Source # | |
Defined in Database.LSMTree.Internal.Config Methods rnf :: MergeSchedule -> () # | |
Eq MergeSchedule Source # | |
Defined in Database.LSMTree.Internal.Config Methods (==) :: MergeSchedule -> MergeSchedule -> Bool # (/=) :: MergeSchedule -> MergeSchedule -> Bool # | |
DecodeVersioned MergeSchedule Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods decodeVersioned :: SnapshotVersion -> Decoder s MergeSchedule Source # | |
Encode MergeSchedule Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods encode :: MergeSchedule -> Encoding Source # |
defaultMergeSchedule :: MergeSchedule Source #
The default MergeSchedule
.
>>>
defaultMergeSchedule
Incremental
withTable :: forall m k v a. IOLike m => Session m -> TableConfig -> (Table m k v -> m a) -> m a Source #
new :: forall m k v. IOLike m => Session m -> TableConfig -> m (Table m k v) Source #
Create a new empty table, returning a fresh table.
NOTE: tables hold open resources (such as open files) and should be
closed using close
as soon as they are no longer used.
close :: forall m k v. IOLike m => Table m k v -> m () Source #
Close a table. close
is idempotent. All operations on a closed
handle will throw an exception.
Any on-disk files and in-memory data that are no longer referenced after
closing the table are lost forever. Use Snapshot
s to ensure data is
not lost.
Resource management
Exception safety
Table queries and updates
Queries
lookups :: forall m k v. (IOLike m, SerialiseKey k, SerialiseValue v, ResolveValue v) => Table m k v -> Vector k -> m (Vector (LookupResult v)) Source #
Perform a batch of lookups.
Lookups can be performed concurrently from multiple Haskell threads.
data LookupResult v Source #
Result of a single point lookup.
Instances
rangeLookup :: forall m k v. (IOLike m, SerialiseKey k, SerialiseValue v, ResolveValue v) => Table m k v -> Range k -> m (Vector (QueryResult k v)) Source #
Perform a range lookup.
Range lookups can be performed concurrently from multiple Haskell threads.
A range of keys.
Constructors
FromToExcluding k k | Inclusive lower bound, exclusive upper bound |
FromToIncluding k k | Inclusive lower bound, inclusive upper bound |
data QueryResult k v Source #
A result for one point in a cursor read or range query.
Constructors
FoundInQuery !k !v |
Instances
Cursor
type Cursor = MonoidalCursor Source #
A read-only view into a table.
A cursor allows reading from a table sequentially (according to serialised key ordering) in an incremental fashion. For example, this allows doing a table scan in small chunks. Once a cursor has been created, updates to the referenced table don't affect the cursor.
withCursor :: forall m k v a. IOLike m => Table m k v -> (Cursor m k v -> m a) -> m a Source #
(Asynchronous) exception-safe, bracketed opening and closing of a cursor.
If possible, it is recommended to use this function instead of newCursor
and closeCursor
.
withCursorAtOffset :: forall m k v a. (IOLike m, SerialiseKey k) => k -> Table m k v -> (Cursor m k v -> m a) -> m a Source #
A variant of withCursor
that allows initialising the cursor at an offset
within the table such that the first entry the cursor returns will be the
one with the lowest key that is greater than or equal to the given key.
In other words, it uses an inclusive lower bound.
NOTE: The ordering of the serialised keys will be used, which can lead to
unexpected results if the SerialiseKey
instance is not order-preserving!
newCursor :: forall m k v. IOLike m => Table m k v -> m (Cursor m k v) Source #
Create a new cursor to read from a given table. Future updates to the table will not be reflected in the cursor. The cursor starts at the beginning, i.e. the minimum key of the table.
Consider using withCursor
instead.
NOTE: cursors hold open resources (such as open files) and should be closed
using close
as soon as they are no longer used.
newCursorAtOffset :: forall m k v. (IOLike m, SerialiseKey k) => k -> Table m k v -> m (Cursor m k v) Source #
A variant of newCursor
that allows initialising the cursor at an offset
within the table such that the first entry the cursor returns will be the
one with the lowest key that is greater than or equal to the given key.
In other words, it uses an inclusive lower bound.
NOTE: The ordering of the serialised keys will be used, which can lead to
unexpected results if the SerialiseKey
instance is not order-preserving!
closeCursor :: forall m k v. IOLike m => Cursor m k v -> m () Source #
Close a cursor. closeCursor
is idempotent. All operations on a closed
cursor will throw an exception.
readCursor :: forall m k v. (IOLike m, SerialiseKey k, SerialiseValue v, ResolveValue v) => Int -> Cursor m k v -> m (Vector (QueryResult k v)) Source #
Read the next n
entries from the cursor. The resulting vector is shorter
than n
if the end of the table has been reached. The cursor state is
updated, so the next read will continue where this one ended.
The cursor gets locked for the duration of the call, preventing concurrent reads.
NOTE: entries are returned in order of the serialised keys, which might not
agree with Ord k
. See SerialiseKey
for more information.
Updates
inserts :: forall m k v. (IOLike m, SerialiseKey k, SerialiseValue v, ResolveValue v) => Table m k v -> Vector (k, v) -> m () Source #
Perform a batch of inserts.
Inserts can be performed concurrently from multiple Haskell threads.
deletes :: forall m k v. (IOLike m, SerialiseKey k, SerialiseValue v, ResolveValue v) => Table m k v -> Vector k -> m () Source #
Perform a batch of deletes.
Deletes can be performed concurrently from multiple Haskell threads.
mupserts :: forall m k v. (IOLike m, SerialiseKey k, SerialiseValue v, ResolveValue v) => Table m k v -> Vector (k, v) -> m () Source #
Perform a batch of monoidal upserts.
Monoidal upserts can be performed concurrently from multiple Haskell threads.
updates :: forall m k v. (IOLike m, SerialiseKey k, SerialiseValue v, ResolveValue v) => Table m k v -> Vector (k, Update v) -> m () Source #
Perform a mixed batch of inserts, deletes and monoidal upserts.
If there are duplicate keys in the same batch, then keys nearer to the front of the vector take precedence.
Updates can be performed concurrently from multiple Haskell threads.
Monoidal tables support insert, delete and monoidal upsert operations.
An update is a term that groups all types of table-manipulating operations, like inserts, deletes and mupserts.
Durability (snapshots)
data SnapshotName Source #
Instances
IsString SnapshotName Source # | The given string must satsify |
Defined in Database.LSMTree.Internal.Paths Methods fromString :: String -> SnapshotName # | |
Show SnapshotName Source # | |
Defined in Database.LSMTree.Internal.Paths Methods showsPrec :: Int -> SnapshotName -> ShowS # show :: SnapshotName -> String # showList :: [SnapshotName] -> ShowS # | |
Eq SnapshotName Source # | |
Defined in Database.LSMTree.Internal.Paths | |
Ord SnapshotName Source # | |
Defined in Database.LSMTree.Internal.Paths Methods compare :: SnapshotName -> SnapshotName -> Ordering # (<) :: SnapshotName -> SnapshotName -> Bool # (<=) :: SnapshotName -> SnapshotName -> Bool # (>) :: SnapshotName -> SnapshotName -> Bool # (>=) :: SnapshotName -> SnapshotName -> Bool # max :: SnapshotName -> SnapshotName -> SnapshotName # min :: SnapshotName -> SnapshotName -> SnapshotName # |
toSnapshotName :: String -> SnapshotName Source #
Create snapshot name.
The given string must satsify isValidSnapshotName
.
Throws the following exceptions:
InvalidSnapshotNameError
- If the given string is not a valid snapshot name.
isValidSnapshotName :: String -> Bool Source #
Check if a String
would be a valid snapshot name.
Snapshot names consist of lowercase characters, digits, dashes -
,
and underscores _
, and must be between 1 and 64 characters long.
>>> isValidSnapshotName "main"
True
>>>
isValidSnapshotName "temporary-123-test_"
True
>>>
isValidSnapshotName "UPPER"
False>>>
isValidSnapshotName "dir/dot.exe"
False>>>
isValidSnapshotName ".."
False>>>
isValidSnapshotName "\\"
False>>>
isValidSnapshotName ""
False>>>
isValidSnapshotName (replicate 100 'a')
False
Snapshot names must be valid directory on both POSIX and Windows. This rules out the following reserved file and directory names on Windows:
>>>
isValidSnapshotName "con"
False>>>
isValidSnapshotName "prn"
False>>>
isValidSnapshotName "aux"
False>>>
isValidSnapshotName "nul"
False>>>
isValidSnapshotName "com1" -- "com2", "com3", etc.
False>>>
isValidSnapshotName "lpt1" -- "lpt2", "lpt3", etc.
False
See, e.g., the VBA docs for the "Bad file name or number" error.
newtype SnapshotLabel Source #
Custom, user-supplied text that is included in the metadata.
The main use case for a SnapshotLabel
is for the user to supply textual
information about the key/value/blob type for the table that corresponds to
the snapshot. This information is used to dynamically check that a snapshot
is opened at the correct key/value/blob type.
Constructors
SnapshotLabel Text |
Instances
IsString SnapshotLabel Source # | |
Defined in Database.LSMTree.Internal.Snapshot Methods fromString :: String -> SnapshotLabel # | |
Show SnapshotLabel Source # | |
Defined in Database.LSMTree.Internal.Snapshot Methods showsPrec :: Int -> SnapshotLabel -> ShowS # show :: SnapshotLabel -> String # showList :: [SnapshotLabel] -> ShowS # | |
NFData SnapshotLabel Source # | |
Defined in Database.LSMTree.Internal.Snapshot Methods rnf :: SnapshotLabel -> () # | |
Eq SnapshotLabel Source # | |
Defined in Database.LSMTree.Internal.Snapshot Methods (==) :: SnapshotLabel -> SnapshotLabel -> Bool # (/=) :: SnapshotLabel -> SnapshotLabel -> Bool # | |
DecodeVersioned SnapshotLabel Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods decodeVersioned :: SnapshotVersion -> Decoder s SnapshotLabel Source # | |
Encode SnapshotLabel Source # | |
Defined in Database.LSMTree.Internal.Snapshot.Codec Methods encode :: SnapshotLabel -> Encoding Source # |
createSnapshot :: forall m k v. IOLike m => SnapshotLabel -> SnapshotName -> Table m k v -> m () Source #
Make the current value of a table durable on-disk by taking a snapshot and giving the snapshot a name. This is the only mechanism to make a table durable -- ordinary insert/delete operations are otherwise not preserved.
Snapshots have names and the table may be opened later using openSnapshot
via that name. Names are strings and the management of the names is up to the
user of the library.
The names correspond to disk files, which imposes some constraints on length and what characters can be used.
Snapshotting does not close the table.
Taking a snapshot is relatively cheap, but it is not so cheap that one can use it after every operation. In the implementation, it must at least flush the write buffer to disk.
Concurrency:
- It is safe to concurrently make snapshots from any table, provided that the snapshot names are distinct (otherwise this would be a race).
Arguments
:: forall m k v. (IOLike m, ResolveValue v) | |
=> Session m | |
-> TableConfigOverride | Optional config override |
-> SnapshotLabel | |
-> SnapshotName | |
-> m (Table m k v) |
Open a table from a named snapshot, returning a new table.
NOTE: close tables using close
as soon as they are
unused.
Exceptions:
- Opening a non-existent snapshot is an error.
- Opening a snapshot but expecting the wrong type of table is an error. e.g., the following will fail:
example session = do t <-new
@IO @Int @Int @Int session _createSnapshot
"intTable" topenSnapshot
@IO @Bool @Bool @Bool session "intTable"
data TableConfigOverride Source #
Override configuration options in TableConfig
that can be changed dynamically.
Some parts of the TableConfig
are considered fixed after a table is
created. That is, these options should (i) should stay the same over the
lifetime of a table, and (ii) these options should not be changed when a
snapshot is created or loaded. Other options can be changed dynamically
without sacrificing correctness.
This type has Semigroup
and Monoid
instances for composing override
options.
Instances
Monoid TableConfigOverride Source # | Behaves like a point-wise |
Defined in Database.LSMTree.Internal.Config Methods mempty :: TableConfigOverride # mappend :: TableConfigOverride -> TableConfigOverride -> TableConfigOverride # | |
Semigroup TableConfigOverride Source # | Behaves like a point-wise |
Defined in Database.LSMTree.Internal.Config Methods (<>) :: TableConfigOverride -> TableConfigOverride -> TableConfigOverride # sconcat :: NonEmpty TableConfigOverride -> TableConfigOverride # stimes :: Integral b => b -> TableConfigOverride -> TableConfigOverride # | |
Show TableConfigOverride Source # | |
Defined in Database.LSMTree.Internal.Config Methods showsPrec :: Int -> TableConfigOverride -> ShowS # show :: TableConfigOverride -> String # showList :: [TableConfigOverride] -> ShowS # |
deleteSnapshot :: IOLike m => Session m -> SnapshotName -> m () Source #
Delete a named snapshot.
NOTE: has similar behaviour to removeDirectory
.
Exceptions:
- Deleting a snapshot that doesn't exist is an error.
listSnapshots :: IOLike m => Session m -> m [SnapshotName] Source #
List snapshots by name.
Persistence
duplicate :: forall m k v. IOLike m => Table m k v -> m (Table m k v) Source #
Create a logically independent duplicate of a table. This returns a new table.
A table and its duplicate are logically independent: changes to one are not visible to the other. However, in-memory and on-disk data are shared internally.
This operation enables fully persistent use of tables by duplicating the table prior to a batch of mutating operations. The duplicate retains the original table value, and can still be modified independently.
This is persistence in the sense of persistent data structures (not of on-disk persistence). The usual definition of a persistent data structure is one in which each operation preserves the previous version of the structure when the structure is modified. Full persistence is if every version can be both accessed and modified. This API does not directly fit the definition because the update operations do mutate the table value, however full persistence can be emulated by duplicating the table prior to a mutating operation.
Duplication itself is cheap. In particular it requires no disk I/O, and requires little additional memory. Just as with normal persistent data structures, making use of multiple tables will have corresponding costs in terms of memory and disk space. Initially the two tables will share everything (both in memory and on disk) but as more and more update operations are performed on each, the sharing will decrease. Ultimately the memory and disk cost will be the same as if each table were entirely independent.
NOTE: duplication create a new table, which should be closed when no longer needed.
Table union
union :: forall m k v. IOLike m => Table m k v -> Table m k v -> m (Table m k v) Source #
Union two full tables, creating a new table.
A good mental model of this operation is
on
unionWith
(<>)
.Map
k v
Multiple tables of the same type but with different configuration parameters
can live in the same session. However, union
only works for tables that
have the same key/value types and configuration parameters.
NOTE: unioning tables creates a new table, but does not close the tables that were used as inputs.
unions :: forall m k v. IOLike m => NonEmpty (Table m k v) -> m (Table m k v) Source #
Like union
, but for n
tables.
A good mental model of this operation is
on
unionsWith
(<>)
.Map
k v
The current upper bound on the number of UnionCredits
that have to be
supplied before a union
is completed.
The union debt is the number of merging steps that need to be performed /at
most/ until the delayed work of performing a union
is completed. This
includes the cost of completing merges that were part of the union's input
tables.
Instances
Show UnionDebt Source # | |
Eq UnionDebt Source # | |
Ord UnionDebt Source # | |
remainingUnionDebt :: IOLike m => Table m k v -> m UnionDebt Source #
Return the current union debt. This debt can be reduced until it is paid
off using supplyUnionCredits
.
newtype UnionCredits Source #
Credits are used to pay off UnionDebt
, completing a union
in the
process.
A union credit corresponds to a single merging step being performed.
Constructors
UnionCredits Int |
Instances
Show UnionCredits Source # | |
Defined in Database.LSMTree.Common Methods showsPrec :: Int -> UnionCredits -> ShowS # show :: UnionCredits -> String # showList :: [UnionCredits] -> ShowS # | |
Eq UnionCredits Source # | |
Defined in Database.LSMTree.Common | |
Ord UnionCredits Source # | |
Defined in Database.LSMTree.Common Methods compare :: UnionCredits -> UnionCredits -> Ordering # (<) :: UnionCredits -> UnionCredits -> Bool # (<=) :: UnionCredits -> UnionCredits -> Bool # (>) :: UnionCredits -> UnionCredits -> Bool # (>=) :: UnionCredits -> UnionCredits -> Bool # max :: UnionCredits -> UnionCredits -> UnionCredits # min :: UnionCredits -> UnionCredits -> UnionCredits # |
supplyUnionCredits :: forall m k v. (IOLike m, ResolveValue v) => Table m k v -> UnionCredits -> m UnionCredits Source #
Supply union credits to reduce union debt.
Supplying union credits leads to union merging work being performed in
batches. This reduces the union debt returned by remainingUnionDebt
. Union
debt will be reduced by at least the number of supplied union credits. It
is therefore advisable to query remainingUnionDebt
every once in a while to
see what the current debt is.
This function returns any surplus of union credits as leftover credits when a union has finished. In particular, if the returned number of credits is non-negative, then the union is finished.
Concurrency
Serialisation
class SerialiseKey k Source #
Serialisation of keys.
Instances should satisfy the following:
- Identity
deserialiseKey
(serialiseKey
x) == x- Identity up to slicing
deserialiseKey
(packSlice
prefix (serialiseKey
x) suffix) == x
Instances may satisfy the following:
- Ordering-preserving
x `
compare
` y ==serialiseKey
x `compare
`serialiseKey
y
Raw bytes are lexicographically ordered, so in particular this means that values should be serialised into big-endian formats. This constraint mainly exists for range queries, where the range is specified in terms of unserialised values, but the internal implementation works on the serialised representation.
Minimal complete definition
Instances
SerialiseKey Word64 Source # | |
Defined in Database.LSMTree.Internal.Serialise.Class | |
SerialiseKey ByteString Source # | Placeholder instance, not optimised |
Defined in Database.LSMTree.Internal.Serialise.Class Methods serialiseKey :: ByteString -> RawBytes Source # deserialiseKey :: RawBytes -> ByteString Source # | |
SerialiseKey ByteString Source # | Placeholder instance, not optimised |
Defined in Database.LSMTree.Internal.Serialise.Class Methods serialiseKey :: ByteString -> RawBytes Source # deserialiseKey :: RawBytes -> ByteString Source # | |
SerialiseKey ShortByteString Source # | |
Defined in Database.LSMTree.Internal.Serialise.Class Methods |
class SerialiseValue v Source #
Serialisation of values and blobs.
Instances should satisfy the following:
- Identity
deserialiseValue
(serialiseValue
x) == x- Identity up to slicing
deserialiseValue
(packSlice
prefix (serialiseValue
x) suffix) == x
Minimal complete definition
Instances
Monoidal value resolution
class ResolveValue v where Source #
A class to specify how to resolve/merge values when using monoidal updates
(Mupsert
). This is required for merging entries during compaction and also
for doing lookups, resolving multiple entries of the same key on the fly.
The class has some laws, which should be tested (e.g. with QuickCheck).
It is okay to assume that the input bytes can be deserialised using
deserialiseValue
, as they are produced by either serialiseValue
or
resolveValue
itself, which are required to produce deserialisable output.
Prerequisites:
- [Valid Output] The result of resolution should always be deserialisable.
See
resolveValueValidOutput
. - [Associativity] Resolving values should be associative.
See
resolveValueAssociativity
.
Future opportunities for optimisations:
- Include a function that determines whether it is safe to remove an
Update
from the last level of an LSM tree. - Include a function
v -> RawBytes -> RawBytes
, which can then be used when inserting into the write buffer. Currently, usingresolveDeserialised
means that the inserted value is serialised and (if there is another value with the same key in the write buffer) immediately deserialised again.
TODO: The laws depend on SerialiseValue
, should we make it a superclass?
TODO: should we additionally require Totality (for any input RawBytes
,
resolution should successfully provide a result)? This could reduce the
risk of encountering errors during a run merge.
Instances
(Num a, SerialiseValue a) => ResolveValue (Sum a :: Type) Source # | Mostly to give an example instance (plus the property tests for it).
Additionally, this instance for |
Defined in Database.LSMTree.Monoidal | |
ResolveValue (ResolveAsFirst v :: Type) Source # | |
Defined in Database.LSMTree Methods resolveValue :: Proxy (ResolveAsFirst v) -> RawBytes -> RawBytes -> RawBytes Source # |
resolveDeserialised :: forall v. SerialiseValue v => (v -> v -> v) -> Proxy v -> RawBytes -> RawBytes -> RawBytes Source #
A helper function to implement resolveValue
by operating on the
deserialised representation. Note that especially for simple types it
should be possible to provide a more efficient implementation by directly
operating on the RawBytes
.
This function could potentially be used to provide a default implementation
for resolveValue
, but it's probably best to be explicit about instances.
To satisfy the prerequisites of ResolveValue
, the function provided to
resolveDeserialised
should itself satisfy some properties:
- [Associativity] The provided function should be associative.
- [Totality] The provided function should be total.
Properties
resolveValueValidOutput :: forall v. (SerialiseValue v, ResolveValue v, NFData v) => v -> v -> Bool Source #
Test the Valid Output law for the ResolveValue
class
resolveValueAssociativity :: forall v. (SerialiseValue v, ResolveValue v) => v -> v -> v -> Bool Source #
Test the Associativity law for the ResolveValue
class
Utility types
type IOLike m = (MonadAsync m, MonadMVar m, MonadThrow (STM m), MonadThrow m, MonadCatch m, MonadMask m, PrimMonad m, MonadST m) Source #
Utility class for grouping io-classes
constraints.