muesli-0.1.1.0: A simple document-oriented database

Copyright(c) 2015 Călin Ardelean
LicenseMIT
MaintainerCălin Ardelean <calinucs@gmail.com>
Stabilityexperimental
Portabilityportable
Safe HaskellNone
LanguageHaskell2010
Extensions
  • GeneralizedNewtypeDeriving
  • MultiWayIf

Database.Muesli.Commit

Description

Transaction evaluation inside MonadIO.

Synopsis

Documentation

newtype Transaction l m a Source

Abstract monad for writing and evaluating queries under ACID semantics.

The l parameter stands for a LogState backend, m is a MonadIO that gets lifted, so users can run arbitrary IO inside queries, and a is the result.

Constructors

Transaction 

data TransactionState l Source

State held inside a Transaction.

Constructors

TransactionState 

Fields

transHandle :: !(Handle l)
 
transId :: !TransactionId

Allocated by runQuery with mkNewTransactionId (auto-incremental)

transReadList :: ![DocumentKey]

Accumulates all documents' keys that have been read as part of the transaction. It is considered that all updates in the transaction may depend of these, so the transaction is aborted if concurrent transactions update any of them.

transUpdateList :: ![(LogRecord, ByteString)]

Accumulates all updated or deleted documents' keys together with the serialized data.

runQuery :: (MonadIO m, LogState l) => Handle l -> Transaction l m a -> m (Either TransactionAbort a) Source

Transaction evaluation inside a MonadIO.

Lookups are executed directly, targeting a specific version (TransactionId) , while the keys of both read and written documents are collected in the TransactionState.

At the end various consistency checks are performed, and the transaction is aborted in case any fails. See TransactionAbort for details.

Otherwise, under master lock, space in the data (abstract) file is allocated with alloc, and the transaction records are written in the logPend, and also in the log file, with logAppend.

Writing the serialized data to the data file, updating indexes and completing the transaction is then left for the commitThread. Note that transactions are only durable after commitThread finishes. In the future we may add a blocking version of runQuery.

data TransactionAbort Source

Error returned by runQuery for aborted transactions.

It is an instance of Exception solely for user convenience, as the database never throws it.

Constructors

AbortUnique String

Returned when trying to update an Unique field with a preexisting value.

AbortConflict String

Returned when there is a conflict with concurrent transactions. This happenes when the transUpdateList of transactions in logPend or logComp with transId > then our own transId has any keys that we also have in either transReadList, or transUpdateList.

The second part could be relaxed in the future based on a user policy, since overwriting updates are sometimes acceptable.

AbortDelete String

Returned when trying to delete a document that is still referenced by other documents.

TODO: Current implementation is not completely safe in this regard, as updates should also be checked. The reason is that the check is performed on indexes and on the pending log. So there is a small window in which it is possible for a concurrent transaction to update a record deleted by the current one, before adding it to the pending log, without any error.

commitThread :: LogState l => Handle l -> Bool -> IO () Source

Code for the commit thread forked by open.

It periodically checks for new records in the logPend, and processes them, by adding a Completed record to the log file with logAppend, and updating indexes with updateMainIndex, updateFilterIndex, updateSortIndex and updateUniqueIndex, after writing (without master lock) the serialized documents in the data file with writeDocument. It also moves the records from logPend to logComp.