MAL-Homepage Inhaltsverzeichnis



MAL Dokumentation: Poolsystem




Inhalt:

1. EINFÜHRUNG
2. VERBINDUNG ZWISCHEN BETRIEBSSYSTEM UND MAL
3. POOLHANDLES
4. EINRICHTEN DER POOLDATEIEN
5. ÖFFNEN UND SCHLIESSEN
6. AUS DER SICHT DES MAL-ANWENDERS
6.1. Adressierung von Pooleinträgen
6.2. Physikalische Nutzung der Pufferung
6.3. Die Speicherverwaltung
6.4. Dereferenzierungsprinzip


1. EINFÜHRUNG

Das Poolsystem dient zum Speichern von Daten auf Externspeicher. Sämtliche im MAL-System dauerhaft gespeicherten Daten (auch MAL-Programme) sind in Pools untergebracht.

Verglichen mit der direkten Verwendung von Betriebsystemdateien hat das Poolsystem zwei entscheidende Vorteile:

  1. Im MAL-Code werden keine Dateinamen sondern Poolnamen (=interne Namen) verwendet. Daher kann die Portierung von Programmen, die Verlagerung von Dateien oder deren Umbenennung ohne Veränderung der MAL-Programme durchgeführt werden.
  2. Pools ermöglichen den Aufbau von sowohl einfachen als auch komplexen Datenstrukturen mit raschem Zugriff auf MAL-Ebene.
Das Lesen von Daten aus einem Pool unterscheidet sich auf MAL-Ebene nicht vom Lesen anderer Variable, was den Code sehr kurz und übersichtlich macht. Die Zugriffe sind auch erheblich schneller als bei üblichen Datenbanksystemen.

MAL-Homepage Inhaltsverzeichnis


2. VERBINDUNG ZWISCHEN BETRIEBSSYSTEM UND MAL

Auf Betriebsystemebene besteht ein Pool aus zwei Dateien: Der Pooldatei und der Indexdatei. Auf MAL-Ebene wird ein Pool durch einen 4 Zeichen langen Namen identifiziert. Die Zuordnung zwischen beiden Systemen erfolgt durch einen speziellen Dateneintrag im Vokabular, den sogenannten Poolhandle.

Wie obiges Bild zeigt, enthält der Poolhandle nicht nur die Verweise auf die Dateien, sondern auch einen Puffer für die Beschleunigung des Dateizugriffs.

Ein Poolverweis ist ein Dateneintrag am MAL-Stack, der mit Hilfe des Poolhandles auf einen Datensatz im Pool verweist.

MAL-Homepage Inhaltsverzeichnis


3. POOLHANDLES

Die MAL-interne Adressierung eines Pools erfolgt über eine eigene Variable (=Poolhandle), die den Namen 'pool_xxxx' hat, wobei 'xxxx' für den entsprechenden Poolnamen steht. Dieser Poolhandle enthält nebst dem physikalischen Dateinamen auch einen Puffer, in dem ein Teil oder alle Adressverweise gespeichert werden. Er wird beim Öffnen des Pools (siehe später) aktualisiert.

Das Erstellen eines Poolhandles geschieht mit dem Wort
create_pool_handle:

datname indname pufferl -> handle

Beispiel:

Einrichten eines Pools mit dem Namen "test" und 4000 Byte Puffer. Die Betriebssystemdateien heißen ´test.pl´ (Pooldatei) und ´test.ix´ (Indexdatei).
"test.pl" "test.ix" 500 
create_pool_handle >> pool_test

MAL-Homepage Inhaltsverzeichnis


4. EINRICHTEN DER POOLDATEIEN

Mit dem wort
reset_pool werden die Dateien für einen neuen Pool eingerichtet. Falls die Dateien bereits vorhanden sind werden sie (ohne Warnung!) gelöscht.

Syntax:

poolname ->

Beispiel:

"test" reset_pool

Der Poolhandle muß zuvor mit create_pool_handle eingerichtet worden sein (siehe oben).

MAL-Homepage Inhaltsverzeichnis


5. ÖFFNEN UND SCHLIESSEN

Bevor auf einen Pool zugegriffen werden kann muß er geöffnet werden. Beim Öffnen eines Pools werden die Dateien auf Betriebsystemebene geöffnet und die Adressverweise in den Poolhandle geladen.

Die drei Worte haben alle die gleiche Syntax:

poolname ->

In einem Multiusersystem wird der gleichzeitige schreibende Zugriff mehrerer Benutzer verhindert, indem ein Pool, der bereits mit wopen_pool geöffnet wurde, nur mehr zum Lesen geöffnet werden kann. Leider ist die dafür verwendete C-Routine 'lockfile()' unter Windows fehlerhaft. Das führt zwar nicht zu Datenverlust, aber zu merkwürdigen Effekten, wenn ein zweiter User auf eine Datei zugreift, die man gerade bearbeitet. Mit einem Neustart des MAL-Interpreters lässt sich die Sache bereinigen.

Beim Öffnen eines Pools wird eine Variable pool_open_status eingerichtet, in der der alte Öffnungszustand der Dateien gemerkt wird. Beim Austragen dieses Wortes aus dem Vokabular, also beim Verlassen der Doppelpunktdefinition oder bei bye, wird der alte Öffnungszustand hergestellt. Das Wort close_pool ist daher in der Regel nicht erforderlich.

Schreibzugriffe wie put, update oder delete erfordern ein Öffnen des Pools mit wopen_pool. Wurde dies nicht gemacht, so wird mit der Fehlermeldung "Pool nicht geöffnet" abgebrochen.

Beim Öffnen eines Pools werden die Verweise im Puffer des Poolhandles neu eingelesen, was in der Regel etwas Zeit benötigt. Beim Schreiben neuer Einträge mit put wird nur der letzte Eintrag aktualisiert. Das bedeutet, daß nach vielen 'put'-Zugriffen die Verteilung der Adressen im Puffer etwas aus dem Gleichgewicht geraten kann, wodurch weitere Poolzugriffe langsamer werden. Dann kann durch erneutes Öffnen des Pools wieder eine Beschleunigung erreicht werden.

MAL-Homepage Inhaltsverzeichnis


6. AUS DER SICHT DES MAL-ANWENDERS

Am besten stellt man sich unter einem Pool einen Behälter vor, in den die Stackeinträge eingeworfen werden. Damit man auf die eingeworfenen Einträge wieder zugreifen kann, wird jeder mit einem Bindfaden (=Poolverweis, Pooladresse oder Poolzeiger) versehen. Die Enden dieser Bindfäden werden am MAL-Stack als Stackeinträge zurückgelassen. Damit hat der Benutzer die Möglichkeit verschiedenste Adressierungsstrukturen selbst zu gestalten.

Der größte Teil der Behandlung von Poolzugriffen kann mit folgenden vier Worten bewerkstelligt werden:
Syntaxdiagramme: Ein Poolverweis ist ein MAL-Stackeintrag mit einem eigenen Datentyp. Aufgrund eines automatischen Dereferenzierens (siehe später) erscheinen Poolverweise aus der Sicht des MAL-Benutzers weitgehend wie normale Stackeinträge.

MAL-Homepage Inhaltsverzeichnis


6.1. Adressierung von Pooleinträgen

Ein Poolverweis besteht aus dem Poolnamen (vier Zeichen) und der Eintragsnummer. Mit dem Wort
poolentry> können diese Werte eines Poolverweises gelesen werden.

poolverweis -> eintragsnummer poolname

Umgekehrt kann mit dem Wort poolentry ein Poolverweis mit einem bestimmten Namen und einer bestimmten Eintragsummer erzeugt werden.

eintragsummer poolname -> poolverweis

Diese beiden Worte werden aber nur in Sonderfällen benötigt, da man beim Eintragen eines Datensatzes in einen Pool automatisch den entsprechenden Poolverweis am Stack übergeben bekommt.

Die Eintragsnummer ist eine Zahl >=0 und stellt für jeden Eintrag im Pool eine eindeutige Kennung dar. Sie wird beim Schreiben eines Eintrags in den Pool vergeben und bleibt auf Dauer gleich. Auch wenn der entsprechende Eintrag gelöscht wird, wird seine Nummer nicht wieder vergeben. Eine Adressierungsstruktur, die unter diesen Voraussetzungen arbeitet ist wesentlich leichter zu realisieren, als eine, die bei Veränderungen auch die Verweise korrigieren muß.

Beispiel:

Pool "test" einrichten und öffnen:

"xxx.pl" "xxx.ix" 500 create_pool_handle >> pool_test
"test" reset_pool
"test" wopen_pool


Eintrag schreiben

3 ramp "test" put


Probelesen get .

[ 0 1 2 ]


Eintrag schreiben, überschreiben und probelesen:

3 ramp "test" put dup
"hallo" swap update get .
hallo

MAL-Homepage Inhaltsverzeichnis


6.2. Physikalische Nutzung der Pufferung

Der RAM-residente Adresspuffer im Poolhandle enthält Einträge bestehend aus jeweils der Eintragsnummer und einer Adresse. Die Adresse kann entweder direkt die Adresse des Eintrags in der Pooldatei, oder die Adresse des Verweises in der Indexdatei sein.

Ersteres ist der Fall, wenn der Puffer mehr Einträge hat als Einträge im Pool sind. Dann kann mit einem einzigen Dateizugriff auf den Pooleintrag zugegriffen werden.

Andernfalls ist nur ein Teil der Eintragsnummern im Puffer vertreten. Wenn z.B. 10-mal so viele Einträge im Pool sind, wie im Puffer Platz haben, wird nur jede zehnte Indexadresse abgespeichert. Nachdem die Eintragsnummern sowohl im Puffer als auch in der Indexdatei geordnet sind, kann bei der Suche folgendermaße vorgegangen werden:

MAL-Homepage Inhaltsverzeichnis


6.3. Die Speicherverwaltung

Als MAL-Anwender braucht man sich über die Speicherverwaltung der Pools in der Regel keine Sorgen zu manchen. Die Platzreservierung erfolgt automatisch. Es können auch kleine Einträge mit
update ohne explizite Verlagerung vergrößert werden (physikalisch werden die Einträge dann gestückelt).

Zu beachten ist allerdings, daß beim Löschen von Einträgen kein Platz freigegeben wird, das heist, die Dateien nicht verkürzt werden (auch nicht beim Verkürzen der Einträge mit update). Wird in einem Pool öfter gelöscht, so sollte eine Garbadge-Collection (=Müll-Aufräumung) durchgeführt werden oder (wie das z.B. beim Work-Pool gemacht wird) der Pool von Zeit zu Zeit neu eingerichtet werden.

Eine Garbadge-Collection wird durchgeführt, indem der Pool zuerst auf Metaformat umgewandelt und anschließend zurückgewandelt wird (siehe Kapitel Metaformat).

MAL-Homepage Inhaltsverzeichnis


6.4. Dereferenzierungsprinzip

Es gibt in MAL drei verschiedene Typen von Stackeinträgen, die Referenzen im weitesten Sinn darstellen:

Die Auflösung (=Dereferenzierung) dieser Codes erfolgt entweder explizit (bei Poolverweisen mit
get, bei Codestrings oder Doppelpunktdefinitionen mit make) oder, was die Regel ist, automatisch beim Aufruf einer Variablen oder beim Indizieren aus einem Verbund.

Beispiel:

Pool "test" einrichten und öffnen:

"xxx.pl" "xxx.ix" 500 create_pool_handle >> pool_test
"test" reset_pool
"test" wopen_pool


Schreiben und Lesen:

17 "test" put >> alter
alter .
17


[ "hallo" "test" put
"zweiter Eintrag" "test" put
] 2 , .
zweiter Eintrag




Soll die automatische Dereferenzierung unterbunden werden, so muß für das Lesen von Variablen das Wort cool verwendet werden. Zu den verschiedensten Worten für das Indizieren aus Verbunden existieren jeweils auch Worte mit vorangestelltem Kennwort ´cool´.

Beispiele:

17 "test" put >> alter
cool alter .
alter=test:3


[ "hallo" "test" put
"zweiter Eintrag" "test" put
] 2 cool, .
test:5
Ist nun in einer Variablen oder Verbundkomponente ein Wert, der aus einer Kette von Poolverweisen und/oder Codestrings besteht, so gilt folgende Regel: So lange die Dereferenzierung eines Poolverweises wieder einen Poolverweis ergibt, wird weiter Dereferenziert. Anschlie end wird auf Code- oder Doppelpunktdefinition geprüft und eventuell ausgeführt, aber nicht weiter dereferenziert.

Bild: Beispiel der Dereferenzierung von Codes und Poolverweisen in Kombination.

Nachdem die Dereferenzierung der Variablen ´x´ wieder einen Poolverweis zum Ergebnis hat, nämlich ´test:4´, wird weiter dereferenziert. Durch die Dereferenzierung von ´test:4´ erscheint der Code ´cool y´ am Stack. Dieser wird exekutiert. Als Ergebnis erscheint zwar wieder ein Poolverweis, aber hier wird nicht weiter automatisch dereferenziert.

Würde im Codeeintrag allerdings ´y´ statt ´cool y´ stehen, so würde automatisch eine neue Dereferenzierung bei der Ausführung des Codes gestartet werden.

Code zu obigem Bild:

Pool "test" einrichten und öffnen und Einträge 0 bis 2 schreiben:

"xxx.pl" "xxx.ix" 500 create_pool_handle >> pool_test
"test" reset_pool
"test" wopen_pool
4711 "test" put 123 "test" put "zwei" "test" put


Eintrag test:3 schreiben:

"hallo" "test" put
>> y


Eintrag test:4 schreiben:

"cool y" >code "test" put
Eintrag test:5 schreiben:

"test" put
>> x


Start der Dereferenzierung

x .
y=test:3


MAL-Homepage Inhaltsverzeichnis