A Transaction Processing Monitor
Basic Model

Transactions
The most basic unit of work managed by the system is the transaction - an atomic grouping of operations performed by one process. A transaction is just a procedure that is given some number (possibly zero) of input parameters, does some sequence of operations and returns an outcome that consists of:
  • A result of commit if it was successful or abort if it was not.
  • A return code. If a transaction results in abort, the return code will carry some information about why the transaction aborted. If the result is commit, the return code can be used to flag warnings.
  • Output data. If the result is commit, the transaction is also allowed to return an arbitrary amount of data. This data is typically records retrieved from a database query or some information describing the result of the event in some way.
Operations done by transactions are usually database operations but are frequently device control operations as well. Typical examples of devices being controlled would be display screens or machines that move cargo from one place to another.

Applications that execute transactions are referred to as server processes; those that request transactions from other processes are called requestor processes. In general, a server manages a set of objects such as databases or machines and implements all transactions that operate on these objects.

Any application running in the system can, at any time, request a transaction or offer to execute one. Thus, the terms "server" and "requestor" should always be interpreted as being relative to a particular transaction.

Events
A requestor does not request a transaction directly, it requests a more general entity known as an event. An event is an atomic collection of one or more transactions. The transactions in an event can all execute at once and will either all commit or all abort. The transactions in an event are called its related transactions. The bindings between events and their related transactions are kept in an internal event table. Events are requested using a unique event code.

In order to guarantee atomicity of events, a two-phase commit protocol is used. Once the system finds one server per related transaction, the first (prepare) phase begins: the system sends each one a transaction request. Each server determines if the part of the event that its transaction performs can be done correctly. If so, the server is expected to set up an intermediate state from which either the original state or the new state can be obtained even if the system crashes. It then sends a commit outcome of the transaction to the system; otherwise, it sends an abort. The second (complete) phase then begins. If all of the other transactions in the event also {commit}ed, the event commits and the system will send a FinalCommit message, telling the server to make the transaction permanent. Otherwise, the event aborts and the system will send a FinalAbort message telling the server to discard any effects of the transaction. In either case, the second phase message is sent to the requestor at the same time as the servers.

When an event commits its return code and output data buffer is that of one of its one transactions known as the selected transaction. Otherwise, the return code is that of the first transaction in the event to abort.

The event mechanism allows atomically-executing entities (events) to be made up of independent entities (transactions) and this buys a fair amount of flexibility, especially for incremental modification of events. For example, if the programmer wanted to add some functionality to an event e{1}, she could do so by writing a new transaction, tx{i}, that performed the new actions and then add tx{i} to the definition of e{1} in the event table. The alternative to this would be to write an entirely new transaction that contained the code that implements the functionality of e{1} plus the code that would have been in tx{i}. The advantage of the event-based solution is that it doesn't require any rewriting of (presumably) working code.

Passing Data Between Requestors and Servers
Information is passed between requestors and servers through an object known as a data buffer. A data buffer holds a set of bindings between symbol names and values. When an event is requested, a data buffer that contains the input parameters expected by the events transactions is passed. Each transaction that accesses the parameters passed by the requestor through the symbol name. A transaction's output data also takes the form of a data buffer.

Like the event mechanism itself, this method of passing parameters provides flexibility. If it is determined that one of the transactions included in an event requires more information, a new symbol can be added to the message and be passed with the data buffer. Since each transaction explicitly asks for the data by symbol name, other transactions in the same event are not affected by this change.