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

Ulm's Oberon Library:


StandardContainers - standard implementation of Containers


CONST usecurrent = 0; usestripped = 1; usefree = 2; useothercurrent = 3;
CONST useotherstripped = 4; useotherfree = 5; usenew = 6; usedefault = 7;
TYPE AllocStrat = SHORTINT; (* usecurrent..usedefault *)

CONST usestrippedslot = 0; usefreeslot = 1; CONST usenewslot = 2; usedefaultslot = 3; TYPE SlotStrat = SHORTINT; (* usestrippedslot..usedefaultslot *)

CONST unsupportedStream = 0; CONST invalidContainer = 1; CONST containerInAutoMode = 2; CONST invalidTransaction = 3; CONST fatalIOError = 4; CONST transStreamOpFailed = 5; CONST persFailure = 6; CONST objectTooLarge = 7; CONST outOfSpace = 8; CONST tooManyObjects = 9; CONST objectIsNIL = 10; CONST noSuchIdent = 11; CONST noAnchorDefined = 12; CONST errors = 13; TYPE ErrorCode = SHORTINT; TYPE ErrorEvent = POINTER TO ErrorEventRec; TYPE ErrorEventRec = RECORD (Events.EventRec); errcode: ErrorCode; END; VAR error: Events.EventType; VAR errormsg: ARRAY errors OF Events.Message;

PROCEDURE Open(VAR container: Containers.Container; data: Streams.Stream; auto: BOOLEAN; errors: RelatedEvents.Object) : BOOLEAN;

PROCEDURE SetTries(cont: Containers.Container; tries: SHORTINT); PROCEDURE SetAllocStrat(cont: Containers.Container; insertpos, mode: AllocStrat); PROCEDURE SetSlotStrat(cont: Containers.Container; insertpos, mode: SlotStrat);


StandardContainers offers a standard implementation of Containers which uses transaction streams that support ObjectTransactions as persistent storage.

Open opens or creates (if data has zero length) a container on top of data which serves as persistent storage. The underlying stream needs to be supported by ObjectTransactions and must not have been attached to a transaction yet. Note that the termination of the underlying stream will be propagated to the container (see Resources). In auto mode, there is only one transaction running from the beginning up to the invocation of Containers.Close. Alternatively, the container supports ObjectTransactions and all operations of Transactions may be applied. All container operations of Containers are permitted, provided the transaction parameter matches the transaction container is attached to (NIL is to be given in auto mode).

StandardContainers allows some tuning of the allocation strategies. Allocation is done for new objects (tunable by SetAllocStrat) and for new entries of the index table (tunable by SetSlotStrat). Each of these strategies consists of a small vector (indexed from 0 to usedefault, and from 0 to usedefaultslot, respectively) with values which select one of the possible allocation variants. The last entry of these vectors is always usedefault (or usedefaultslot, respectively) which works as a wildcard of all possible variants. The other entries of the vectors are initialized to their associated indices. By calling SetAllocStrat or SetSlotStrat, it is possible to insert a strategy into the vector at the given position, i.e. the former strategy at this index and all following will be shifted towards the end of the vector with the last but one strategy entry being lost. On allocation, the associated variants will be considered exactly in the order as found in the associated vector. Note that neither usedefault nor usedefaultslot must be inserted because they will fire anyway as last strategy.

SetTries sets a tuning parameter which controls the number of free lists which are considered when allocating an object. The larger the value of tries, the more StandardContainers is willing to split larger free areas for small objects instead of allocating new areas. The default value of this parameter is 3.


All error events which are raised in the context of a container will be forwarded to it (or to errors at opening time). This includes the underlying data stream, an internal in-memory stream, the transaction (of ObjectTransactions) on the data stream, and the transaction on the container itself. All failures which are seen by StandardContainers will result in an error event which is related to the container:
The stream which was passed to Open does not support ObjectTransactions. TransStreams, for example, offers streams which provide the necessary support.
The container was non-empty and found to be not a valid container (at least of the same platform).
Transaction operations of Transactions are not valid if the container is in auto mode.
A transaction parameter was passed to one of the Container operations where the container is not attached to. If the container is in auto mode, any transaction not equal to NIL will be considered as invalid.
An operation on the underlying stream failed. In this case it is best to abort the transaction.
A transaction operation on the underlying stream failed. Note that transaction streams of TransStreams must not be opened in auto mode to be usable for StandardContainers.
Either PersistentObjects.Write or PersistentObjects.Read failed -- this may be due to a failure of one of the associated interface procedures. On reading, problems may occur if one of the referenced modules cannot be loaded (see Loader).
The given object is architecturally to large to fit into a container of StandardContainers (independent on how much space is left).
There is no virtual space left for the given object. Note that this is not a problem on your local disk but one of the virtual address space. If your local disk fills up, underlying stream operations will fail on committing and result in an abortion of the transaction.
There are no entries left in the index table, i.e. the container has already the maximal number of objects possible.
Objects passed to Containers.Insert or Containers.Replace must not be NIL.
An invalid ident was given to Containers.Delete, Containers.Obtain, Containers.Replace, Containers.Find, or Containers.SetAnchor.
Containers.GetAnchor was called but no anchor was previously defined, or the anchor became invalid due to a delete operation.

StandardContainers has a large number of assertions. Most of them check the internal consistency but some are used to check parameters:


Following procedure shows how to open a container of StandardContainers that bases on TransStreams and UnixFiles:
PROCEDURE OpenContainer(containerFile: ARRAY OF CHAR;
                        auto: BOOLEAN;
                        VAR trans: Transactions.Transaction;
                        VAR container: Containers.Container;
                        errors: RelatedEvents.Object) : BOOLEAN;
   (* open a standard container which is represented
      by the UNIX file with the name ``containerFile'';
      in auto mode, ``trans'' will be set to NIL, otherwise
      an associated transaction will be created;
      all errors at opening time and in future
      will be related to ``errors''
      file, ts: Streams.Stream;
   IF ~UnixFiles.Open(file, containerFile,
            UnixFiles.rdwr + UnixFiles.condcreate, Streams.nobuf,
            errors) OR
         ~TransStreams.Open(ts, file, TransStreams.standard, errors) OR
         ~StandardContainers.Open(container, ts, auto, errors) THEN
   RelatedEvents.Forward(container, errors);
   IF auto THEN
      trans := NIL;
      IF ~ObjectTransactions.Create(trans, container, NIL, errors) THEN
      RelatedEvents.Forward(trans, errors);
END OpenContainer;
It is later sufficient to close the container only. This will cause the transaction (if any) to be released and all underlying streams to be closed (because there are no other references on file and ts). This works because there is an implicit chain of dependencies of Resources starting from file and ending at trans.


general abstraction of object containers
transactions with one object only (supported by StandardContainers)
stream implementation which supports ObjectTransactions


The original implementation is due to Werner Stanglow, the revisions and this manual page have been contributed by Andreas Borchert.


Note that the format of the container is not portable across platforms. It depends on byte ordering and the page size of the memory system. Cross-platform access is still possible, though, by setting up distributed systems (RemoteObjects for Containers is supported by RemoteContainers). In this way, a container may be accessed by a process on the associated platform, converted implicitely by transferring it over the network, and dumped into a new container for a different platform.
Edited by: borchert, last change: 2005/02/09, revision: 1.4, converted to HTML: 2005/02/09

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