Oberon || Library || Module Index || Search Engine || Definition || Module

Ulm's Oberon Library:


TransStreams - transactions on streams


CONST last = 0; prior = 1; current = 2;
TYPE State = SHORTINT; (* last..current *)
CONST standard = 0; auto = 4; read = 8;
   (* additive combination of standard, auto, read, last and prior *)

TYPE Stream = POINTER TO StreamRec; TYPE StreamRec = RECORD (Streams.StreamRec); END;

(* errors at opening time *) CONST illegalParam = 0; CONST bufferedStream = 1; CONST badMagic = 2; CONST noLegalState = 3; CONST corruptedFile = 4; CONST cannotAccessFile = 5; (* invalid usage *) CONST illegalPos = 6; CONST nestedCall = 7; CONST noPriorState = 8; CONST noTransactionRunning = 9; CONST readOnly = 10; CONST transactionInProgress = 11; CONST alreadyClosed = 12; (* troubles with the underlying stream *) CONST cannotAccessSysPages = 13; CONST cannotUpdateSysPages = 14; CONST cannotAccessContents = 15; CONST cannotUpdateContents = 16; CONST recoveringDueToFailure = 17; CONST closeFailed = 18; CONST errorcodes = 19; TYPE ErrorCode = SHORTINT; TYPE Event = POINTER TO EventRec; TYPE EventRec = RECORD (Events.EventRec); errcode: ErrorCode; END; VAR error: Events.EventType; VAR errormsg: ARRAY errorcodes OF Events.Message;

PROCEDURE Open(VAR s: Streams.Stream; base: Streams.Stream; mode: Mode; errors: RelatedEvents.Object) : BOOLEAN;

(* transaction primitives *) PROCEDURE Begin(s: Streams.Stream) : BOOLEAN; PROCEDURE Abort(s: Streams.Stream) : BOOLEAN; PROCEDURE Commit(s: Streams.Stream) : BOOLEAN; (* transaction shorthands *) PROCEDURE Touch(s: Streams.Stream) : BOOLEAN; (* Commit & Begin *) PROCEDURE Forget(s: Streams.Stream) : BOOLEAN; (* Abort & Begin *)

PROCEDURE Switch(s: Streams.Stream) : BOOLEAN; PROCEDURE Toggle(s: Streams.Stream) : BOOLEAN; PROCEDURE Available(s: Streams.Stream; state: State) : BOOLEAN;

PROCEDURE GetInfo(s: Streams.Stream; state: State; VAR info: ARRAY OF BYTE) : BOOLEAN; PROCEDURE SetInfo(s: Streams.Stream; info: ARRAY OF BYTE) : BOOLEAN;



TransStreams (transaction streams) offers a local transaction concept (see ObjectTransactions) on stream level. Objects of type Stream are extensions of Streams.Stream with read, write, seek, tell and trunc capabilities but support transactions as well. A transaction in the sense of this module represents a frame for an arbitrary number of write operation executed on the stream. These operations do not alter the stream contents until the transaction is successfully committed. In any other cases, namely if the transaction is explicitely aborted or if the program terminates before a transaction was committed, the contents of a transaction stream remains unaffected. This holds true even if a program terminates for any reason while a commit operation itself is in progress. Since either all or none of the contents changes applied to the stream during a transaction become valid, committing a transaction can be seen as an atomar operation which transfers the stream from one consistent state into another.

A transaction stream can hold up to three states:

refers to the transaction currently in progress and is not available if no transaction is active.
reflects the contents of the stream at the time of the last successful commit. This state is always available.
stores the last but one successfully committed transaction. Only available if no error occured during the last two commit operations.

A transaction stream behaves like any other regular stream except that write operations must be executed within the scope of a transaction. After a transaction is aborted or when the stream is reopened, a consistent state is restored from the contents of the stream base given as an argument to Open. Base streams must be unbuffered and support read, write, seek and tell operations, and holes. They are used by TransStreams to store data permanently and will therefore typically be of type UnixFiles.File. Note that the termination of the base stream is propagated to the transaction stream (see Resources).

The parameter mode provided to Open is a combination (sum) of a state and an operation mode. Any senseful sum of the following constants may be used:

open a stream with standard capabilities, i.e. the application is responsible for beginning any transaction.
open a transaction stream for read only access. Any attempt to begin a transaction will be rejected. No write operation at all will be performed on base.
implicitely starts a transaction during the opening process. The transaction will be committed automatically when Streams.Close is called.
The next transaction will start from the state associated with the last successful transaction. This is the default behaviour.
If available, the last and the prior state are toggled (see below). The next transaction will start from the state associated with last but one successful transaction. If used in combination with standard or auto this switch becomes permanent, even if no transaction is executed later on. Combined with read any read operation will return data from the prior rather than the last state, but this effect is temporary.

On a read-only stream, read, tell or seek operations are always possible. In any other case any attempt to operate on a stream with no transaction in progress will fail. Thus, if not opened in auto mode, a transaction has to be started explicitly before the stream is accessible through the interface of Streams. Transactions may be controlled by Transactions on base of ObjectTransactions, or by means of the following procedures, which are available for all streams regardless of whether they have been opened in auto mode or not.

Start a transaction on stream s using the contents associated with the state last as origin.
Commit a previously started transaction and store any contents changes permanently in the underlaying base stream of s and associate it with the state last. The former last state will become the new prior one, while the former prior state is discarded.
Abort the current transaction and reset s to the state valid before the transaction was begun, i.e. to the last consistent state.
Toggle the states last and prior permanently. This operation is implicitely executed when the stream is opened with mode set accordingly. The procedure will fail, if a transaction is in progress, a stream is opened readonly or no prior state is available.
Temporarily switch the states last and prior. The next transaction will use the contents of the last but one successfully committed transaction as its starting point. The procedure will fail, if a transaction is in progress or a prior state is not available. For streams opened with mode = read + prior this operation is performed implicitely during the opening process. It will fail, if no prior state exists.
is equivalent to Commit + Begin.
is equivalent to Abort + Begin.

Toggle and Switch can be utilized to implement an undo command for transaction streams (see section examples), which discards the effect of the last successful transaction.

Since TransStreams can guarantee only the existence of one consistent state, Available should be used to check if a certain state exists.

Other than an internal enumeration TransStreams does not store any information about transactions. Instead, it offers a SetInfo procedure which associates an array of bytes with the current transaction. While SetInfo requires a transaction to be in progress, previously stored information can be obtained by GetInfo even if no transaction is running. According to state, GetInfo returns the information associated with the current transaction (if in progress), the last successfully commited transaction (which is always available) or a prior transaction (presumed the corresponding state is still accessible).

The size of info is restricted to an implementation-dependent value (about 8K in the current version).

Read and write operation on a transaction stream are buffered. To prevent programs from consuming to much memory and to reduce swapping or/and paging activity of the associated processes applications might want to control the size of the internal buffer pools. For this reason, the following procedures are provided:

Make no the maximum number of internal buffers to be used by s.
Limit the total number of internal buffers used by all transaction streams to no.

However, TransStreams will ignore the limits if more space is required to buffer write operations. In these cases, reduction of the internal pool size is delayed until the next commit or abort operation takes place. GetEffPoolSize and GetEffNoBufs return the effective number of buffers currently in use, while GetPoolSize and GetNoBufs return the default settings as defined by means of SetPoolSize or SetNoBufs.


All procedures return FALSE in case of an error and will raise an event of the type error to the affected stream. During the opening process error events are related to the parameter errors. Note that the error events of the underlying stream are forwarded to the associated transaction stream. Following error codes may be returned by TransStreams:
An invalid mode was given to Open.
The base stream passed to Open must not be buffered.
TransStreams did not find its magic number at the beginning of the underlying stream. Probably, it is not a file which has been created earlier by (this version of) TransStreams.
Neither of the two possible states in the underlying stream was found to be consistent. Probably, the file has been corrupted by external sources.
The system pages were not available at opening time.
This error code is returned by Open if some basic stream operations on the underlying stream fail.
An invalid position was given to a seek or trunc operation of Streams.
There may be only one operation running on a transaction stream concurrently.
This error code may be returned by Toggle or Switch when there is no other consistent state available.
Stream operations (read, write, seek, tell and trunc) are valid only during a transaction (the only exception are read-only opened transaction streams). Further, Abort, Commit, Forget, SetInfo, and Touch may be called only while a transaction is in progress.
This error code is returned by all updating operations if the stream has been opened in read-only mode.
Begin, Switch, and Toggle return this error code if there is an already running transaction.
An operation was tried on an already closed transaction stream.
Accesses to the system pages on the underlying stream failed.
Updates of the system pages on the underlying stream failed.
Accesses to the visible pages on the underlying stream failed.
Updates of the visible pages on the underlying stream failed.
A commit operation failed due to some reason (see additional error events) which caused the current transaction to be aborted.
The final close operation failed. This shouldn't be a fatal error, however, since the underlying stream is unbuffered, i.e. all changes are already done.

TransStreams has several assertions, some of them may fail in case of invalid usage:


Open a transaction stream stream in auto mode and store the data in file name:

Open a transaction stream in non-auto mode and execute two transactions on it:

Implement an undo command, which resets the stream to a consistent state prior to the last successful transaction:


transactions which involve one object only
error handling
stream operations
general abstraction for transactions
stream implementation of UNIX files


Werner Stanglow (stanglow@mathematik.uni-ulm.de),
minor revisions due to Andreas Borchert
Edited by: borchert, last change: 1996/11/28, revision: 1.6, converted to HTML: 1997/04/28

Oberon || Library || Module Index || Search Engine || Definition || Module