Oberon ||
Library ||
Module Index ||
Search Engine ||
Definition ||
Module
Ulm's Oberon Library:
TransStreams
NAME
TransStreams - transactions on streams
SYNOPSIS
CONST last = 0; prior = 1; current = 2;
TYPE State = SHORTINT; (* last..current *)
CONST standard = 0; auto = 4; read = 8;
TYPE Mode = SHORTINT;
(* 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;
PROCEDURE SetPoolSize(s: Streams.Stream; no: INTEGER) : BOOLEAN;
PROCEDURE GetPoolSize(s: Streams.Stream; VAR no: INTEGER) : BOOLEAN;
PROCEDURE GetEffPoolSize(s: Streams.Stream; VAR no: INTEGER) : BOOLEAN;
PROCEDURE SetNoBufs(no: INTEGER) : BOOLEAN;
PROCEDURE GetNoBufs(VAR no: INTEGER) : BOOLEAN;
PROCEDURE GetEffNoBufs(VAR no: INTEGER) : BOOLEAN;
DESCRIPTION
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:
- current
-
refers to the transaction currently in progress and is not available
if no transaction is active.
- last
-
reflects the contents of the stream at the time of the
last successful commit. This state is always available.
- prior
-
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:
- standard
-
open a stream with standard capabilities, i.e. the application
is responsible for beginning any transaction.
- read
-
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.
- auto
-
implicitely starts a transaction during the opening process.
The transaction will be committed automatically when
Streams.Close
is called.
- last
-
The next transaction will start from the
state associated with the last successful transaction.
This is the default behaviour.
- prior
-
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.
- Begin
-
Start a transaction on stream
s
using the contents associated
with the state
last
as origin.
- Commit
-
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
-
Abort the current transaction and reset
s
to the state valid
before the transaction was begun, i.e. to the
last
consistent state.
- Toggle
-
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.
- Switch
-
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.
- Touch
-
is equivalent to
Commit
+
Begin.
- Forget
-
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:
- SetPoolSize
-
Make
no
the maximum number of internal buffers to be used by
s.
- SetNoBufs
-
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.
DIAGNOSTICS
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:
- illegalParam
-
An invalid mode was given to Open.
- bufferedStream
-
The base stream passed to Open must not be buffered.
- badMagic
-
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.
- noLegalState
-
Neither of the two possible states in the underlying stream
was found to be consistent. Probably, the file has been
corrupted by external sources.
- corruptedFile
-
The system pages were not available at opening time.
- cannotAccessFile
-
This error code is returned by Open if some
basic stream operations on the underlying stream fail.
- illegalPos
-
An invalid position was given to a seek or trunc operation
of Streams.
- nestedCall
-
There may be only one operation running on
a transaction stream concurrently.
- noPriorState
-
This error code may be returned by Toggle or Switch
when there is no other consistent state available.
- noTransactionRunning
-
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.
- readOnly
-
This error code is returned by all updating operations
if the stream has been opened in read-only mode.
- transactionInProgress
-
Begin, Switch, and Toggle
return this error code if there is an already running transaction.
- alreadyClosed
-
An operation was tried on an already closed transaction stream.
- cannotAccessSysPages
-
Accesses to the system pages on the underlying stream failed.
- cannotUpdateSysPages
-
Updates of the system pages on the underlying stream failed.
- cannotAccessContents
-
Accesses to the visible pages on the underlying stream failed.
- cannotUpdateContents
-
Updates of the visible pages on the underlying stream failed.
- recoveringDueToFailure
-
A commit operation failed due to some reason (see
additional error events) which caused the current transaction
to be aborted.
- closeFailed
-
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:
- SetPoolSize expects no to be non-negative.
- SetNoBufs asserts that no is positive.
EXAMPLES
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:
IF UnixFiles.Open(file, name, UnixFiles.condcreate + UnixFiles.rdwr,
Streams.nobuf, err) &
TransStreams.Open(stream, file, TransStreams.standard, err) &
ObjectTransactions.Create(trans, stream, NIL, err) THEN
IF ~Transactions.Begin(trans, NIL) THEN (* T1 *)
(* error handling *)
END;
Streams.Procedure(trans, .....); (* apply to 1st trans. *)
IF ~Transactions.Commit(trans, NIL) THEN (* T1 *)
(* error handling *)
END;
IF ~Transactions.Begin(trans, NIL) THEN (* T2 *)
(* error handling *)
END;
Streams.Procedure(stream,.....); (* apply to 2nd trans. *)
IF ~Transactions.Commit(trans, NIL) THEN (* T2 *)
(* error handling *)
END;
IF ~Transactions.Release(stream, NIL) THEN
(* error handling *)
END;
END;
- The stream now stores two states. The last one, which discribes its contents
after the second transaction (T2) was committed,
and a prior one, which holds
the data stored during the first transaction (T1).
- Applying
Toggle
to the stream will toggle the states,
i.e. the last one becomes the prior
one and vice versa.
Implement an undo command, which resets the stream to a consistent state
prior to the last successful transaction:
IF UnixFiles.Open(file, name, UnixFiles.condcreate + UnixFiles.rdwr,
Streams.nobuf, err) &
TransStreams.Open(stream, file, TransStrems.standard, err) &
TransStreams.Available(stream, TransStreams.prior) &
TransStreams.Toggle(stream) & TransStreams.Close(stream) THEN
(* .... *)
ELSE
(* error *)
END;
- If a prior state is available, the effects of the last transaction are discarded.
- If there is no prior state, one of the last two must have failed
due to program termination. In this case there is no use to undo
the last successful transaction, since it is the only one we have.
- Operations during the next transaction will now apply to the last but one
consistent state (T1 in the above example).
SEE ALSO
- ObjectTransactions
-
transactions which involve one object only
- RelatedEvents
-
error handling
- Streams
-
stream operations
- Transactions
-
general abstraction for transactions
- UnixFiles
-
stream implementation of UNIX files
AUTHOR
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