home *** CD-ROM | disk | FTP | other *** search
- ─────────────────────────────────────────────────────────────────────────────
- Dokumentation zur Datei: RECORDIO.INC
-
- ─────────────────────────────────────────────────────────────────────────────
-
- RECORDIO.INC - Routinen zur gepufferten Bearbeitung von Record-Dateien
- (für den Assembler A86)
-
- (c) Bernd Schemmer 1992
- Letzter Update: 22.02.1992
-
-
- ■ Beschreibung:
- ---------------
- RECORDIO.INC stellt Routinen zur gepufferten Bearbeitung von
- Record-Dateien (d.h. satzorientierten Dateien mit wahlfreien,
- direkten Lese- und Schreibzugriffen) zur Verfügung. Die Routinen
- können beliebig viele Dateien gleichzeitig und bis zu 250 Puffer
- pro Datei verwalten. Die Puffer werden nach einer LRU-Strategie
- verwaltet. LRU (= Last Reasently Used) bedeutet, daß, falls ein
- Puffer überschrieben werden muß, immer der Puffer, der am
- längsten nicht mehr genutzt wurde, überschrieben wird. Hierbei
- wird nicht unterschieden, ob ein Puffer zum Lesen oder Schreiben
- benutzt wurde.
- Die Routinen berücksichtigen auch einen eventuell vorhandenen
- Datei-Header vor den Sätzen in der Datei.
- Jeder Puffer muß mindestens einen kompletten Satz (= Record)
- aufnehmen können. Jeder Puffer wird nur soweit genutzt, daß genau
- n Sätze rein passen, d.h. die Länge eines Puffers sollte
- möglichst ein Vielfaches der Satzlänge sein. Zur Erhöhung der
- Performance der Lese- und Schreibvorgänge sollte die Länge
- eines Puffers und des Headers (falls vorhanden) auch ein
- Vielfaches von 512 (= Sektorlänge) sein (muß aber nicht!).
- Es ist auch möglich, die Verwendung der Puffer auf das Lesen
- von Sätzen einzuschränken (d.h. die Puffer können auch im Modus
- 'Write Through' betrieben werden).
-
- Für die Routinen gelten folgende Limits:
-
- max. Dateigröße: 2.147.483.647
- max. Headergröße: 2.147.483.647
- max. Satzgröße: 65.535
- min. Satzgröße: 2
- max. Anzahl Sätze: 2.147.483.647
- max. Anzahl Puffer: 250
- max. Größe eines Puffers: 65.535
-
- Folgende Bedingungen müssen ebenfalls eingehalten werden:
-
- Größe eines Puffer >= Satzgröße
- Dateitgröße + Headergröße <= 2.147.483.647
-
- Falls der Header länger als 65.535 Byte ist, kann er mit dem
- Routinen aus dieser Datei weder gelesen noch geschrieben werden.
-
- ■ Aufbau der Datei-Tabelle
-
- Für jede Datei muß eine Tabelle mit folgendem Aufbau vom Programm
- zur Verfügung gestellt werden:
-
- Offset | Länge | Inhalt
- -------+----------+-------------------------------------------
- * 00h | 1 Wort | Handle der Datei
- 02h | 2 Wörter | Offset des letzten Satzes
- * 06h | 2 Wörter | Länge des Headers der Datei
- | | oder 0 falls die Datei keinen Header hat
- * 0Ah | 1 Wort | Länge eines Satzes der Datei (Länge >= 2)
- 0Ch | 2 Wörter | Datei-Zeiger oder 0FFFFh:0FFFFh
- * 10h | 1 Wort | Anzahl der Puffer (Anzahl >= 1)
- * 12h | 1 Wort | Größe eines Puffers ( >= Länge eines Satzes)
- | | Der Inhalt dieses Feldes wird vor der ersten
- | | Benutzung auf ein Vielfaches der Satzlänge
- | | abgerundet.
- * 14h | 1 Byte | Flags, Aufbau: siehe unten
- 15h | 1 Byte | Indikator für eine leere Datei
-
- DIREKT HINTER dieser Tabelle muß für jeden Puffer eine Tabelle mit
- folgenden Aufbau deklariert werden:
-
- Offset | Länge | Inhalt
- -------+----------+-------------------------------------------
- 00h | 1 Byte | LRU-Inex
- 01h | 1 Byte | Flags des Puffers
- * 02h | 2 Wörter | Zeiger auf den Puffer (Offset, Segment)
- 06h | 2 Wörter | Datei-Offset des ersten Satzes im Puffer
-
- Die Puffer müssen alle gleich groß sein, sie können aber in
- beliebigen Speicherbereichen angelegt werden. Der Speicher
- für die Puffer muß von der aufrufenden Routine zur Verfügung
- gestellt werden. Die Adressen der Puffer werden vor der ersten
- Benutzung in das Format ssss:000o gebracht (d.h. normalisiert).
-
- ■ Aufbau des Flagbytes beim Offset 14h:
-
- Bit | Bedeutung
- --------+------------------------------------------------------------
- 0 | Writethrough-Bit, falls dieses Bit auf 1 steht, werden
- | die Puffer nur zum Lesen benutzt und jeder veränderte
- | Satz wird sofort in die Datei übertragen.
- | Da das Schreiben in die Datei nur Pufferweise vorgenommen
- | wird, sollte zur Verbesserung der Performance in diesem
- | Fall jeder Puffer nur 1 bis 4 Sätze aufnehmen können.
- |
- 1 | Ignore-LRU-Bit, falls dieses Bit auf 1 steht, werden
- | die akt. Werte der Puffer für die LRU-Verwaltung NICHT
- | mehr verändert. D.h. falls ein Puffer überschrieben
- | werden muß, wird immer der gleiche Puffer benutzt
- | und die anderen Puffer behalten ihren Inhalt.
- | Dies ist z.B. sinnvoll, falls die Datei mit leeren
- | Sätzen aufgefüllt werden soll.
- |
- 2..7 | reserviert
-
- ALLE mit einem Asterix (*) gekennzeichneten Felder in den Tabellen
- müssen von der aufrufenden Routine VOR dem ersten Benutzen der
- Tabelle durch die aufrufende Routine gefüllt werden.
- Nach dem Eröffnen oder Erstellen einer Datei darf, außer dem Feld
- mit dem Flags, kein Feld mehr verändert werden!
-
- Hinweis:
- Eine Änderung des WriteThrough-Bits bezieht sich nur auf
- zukünftige Schreibvoränge. Es sollte daher nach oder vor dem
- Setzen des WriteThrough-Bits die Routine 'FlushRecordFile'
- zum Sichern der geänderten Puffer aufgerufen werden.
-
- Das Feld für das Handle muß mit -1 initialisiert werden.
- Alle Wörter, Doppelwörter und Adressen müssen im INTEL-Format
- eingetragen werden.
-
- Die Routinen benutzen das Register AX als Arbeitsregister und
- verändern das Directionflag.
-
-
- ■ Variablen:
- ------------
- RFOpenMode
-
- Byte, diese Variable enthält den Modus, der zum Öffnen einer
- Datei verwendet wird. Voreinstellung für den Modus ist 02h;
- der Inhalt der Variable ist nur bei der Eröffnung einer
- bestehenden Datei von Bedeutung. (Aufbau: siehe unten)
-
- CreateRFileAttr
-
- Wort, Attribute für eine neu zu erstellende Datei
- (nur für die Routinen CREATE... von Bedeutung)
- Voreinstellung für das Attribut ist 0, folgende Bits werden
- ignoriert: Bit 3 (08h, Volume-Bit)
- Bit 4 (10h, Directory-Bit)
- und
- Bit 6 und 7 (40h und 80h, reservierte Bits)
- (Aufbau: siehe unten)
-
-
- ■ Routinen:
- -----------
- ResetRecordFile - Öffnet eine bestehende Record-Datei
- CreateRecordFile - Erstellt eine Record-Datei
- CreateNewRecordFile - Erstellt eine neue Record-Datei
- CloseRecordFile - Schließt eine Record-Datei
- FlushRecordFile - Schreibt alle veränderten Puffer einer
- Record-Datei
- WriteRecord - Schreibt einen Satz der Datei
- ReadRecord - Liest einen Satz der Datei
- TestRecord - Überprüft, ob ein Satz vorhanden ist
- ReadRecordFileHeader - Liest den Header einer Record-Datei
- WriteRecordFileHeader - Schreibt den Header einer Record-Datei
- GetRecordFileSize - Ermittelt die Größe und die Anzahl der
- Sätze einer Record-Datei
- SetRecordFileSize - Vergrößert oder verkleinert eine
- Record-Datei
-
- und falls nötig (d.h. die .LIB-Dateien mit den entsprechenden
- Routinen werden nicht benutzt):
-
- MulLongInt - Multipliziert zwei LongInt-Werte
- DivLongInt - Dividiert zwei LongInt-Werte
- Make20BitValue - Rechnet eine 32-Bit-Adresse in eine
- 20-Bit-Zahl um
- Make32BitAdress - Rechnet eine 20-Bit-Zahl in eine
- 32-Bit-Adresse um
-
-
- ■ Aufbau des Modus-Bytes für die Eröffnung einer bestehenden
- Datei (= Variable RFOpenMode):
-
- Bit | Bedeutung | Aufschlüsselung der Bits
- -------+---------------+-------------------------------------------
- 0..3 | Zugriffscode | 0000 nur Lesen
- | | 0001 nur Schreiben
- | | 0010 Lesen + Schreiben
- | |
- 4..6 | Sharing-Code | 000 Kompatibilitätsmodus
- | | 001 ablehnender Schreib/Lese-Modus
- | | 010 ablehnender Schreibmodus
- | | 011 ablehnender Lesemodus
- | | 100 nicht-ablehnender Modus
- | |
- 7 | Inherit-Bit | 0 Zugriff für Unterprozesse erlaubt
- | | 1 Zugriff für Unterprozesse verboten
-
- RFOpenMode DB 002h ; Modus für die Eröffnung von Dateien
-
-
- ■ Aufbau des Attributes für die Erstellung einer neuen Datei
- (= Variable CreateRFileAttr)
-
- Bit | Bedeutung
- -------+---------------
- 0 | Read-Only-Bit
- 1 | Hidden-Bit
- 2 | System-Bit
- 3 | Volume-Bit
- 4 | SubDir-Bit
- 5 | Archive-Bit
- 6 | reserviert
- 7 | reserviert
- 8..15 | reserviert
-
- CreateRFileAttr DW 0h ; Attribut für neu zu erstellende Dateien
-
-
- ; EQUs für das Flag-Byte
- ; -----------------------------
- RF_WriteThrough EQU 01h ; Write-Through-Bit einschalten
- RF_IgnoreLRU EQU 02h ; Ingore-LRU-Bit einschalten
-
- RF_DontWriteThrough EQU NOT RF_WriteThrough
- RF_DontIgnoreLRU EQU NOT RF_IgnoreLRU
-
-
- Fehlernummern der Routinen
- --------------------------
-
- Alle Fehlernummern der Routinen haben das Format 86xx, wobei xx die
- Nummer des eigentlichen Fehlers ist. Neben diesen werden auch die
- DOS-Fehlernummern im Format 00xx zurück geliefert.
-
- Name Nummer Bedeutung
- ----------------------------------------------------------------------
- 000xxh ; DOS-Fehlernummer
-
- RFileTableError EQU 08601h ; Die Datei-Tabelle ist fehlerhaft
-
- RFileNotOpen EQU 08602h ; Die Datei ist geschlossen
-
- RFileAlreadyOpen EQU 08603h ; Die Datei ist noch offen
-
- RFileReadError EQU 08604h ; Lesefehler, unerwartetes Dateiende
-
- RFileWriteError EQU 08605h ; Schreibfehler, Disk ist voll
-
- RFileRecordError EQU 08606h ; Falsche Satznummer angegeben
- ; beim Lesen: Satz nicht vorhanden
- ; beim Verlängern: Datei kann nicht
- ; auf die angegebene Länge verlängert
- ; werden.
- RFileLengthError EQU 08607h ; Die Länge der Datei stimmt nicht
- ; mit den Werten in der Datei-Tabelle
- ; überein.
-
- RFileDeviceError EQU 08608h ; Die Verwaltung der Ein- und Ausgaben
- ; von Geräten ist über diese Routinen
- ; nicht möglich
-
- RFileHeaderError EQU 08609h ; Der Datei-Header kann nur geschrieben
- ; oder gelesen werden, falls die Länge
- ; des Datei-Headers ungleich 0 und
- ; kleiner als 65.536 ist.
-
-
- ■ Hinweis: Da nicht alle Bezeichner aus dieser Datei dokumentiert
- sind, sollten in eigenen Routinen keine Bezeichner mit
- der Zeichenfolge 'RF_' verwendet werden.
-
-
- ----------------------------
- ResetRecordFile
-
- Funktion: Eröffnet eine bestehende Datei
-
- Eingabe: DS:BX -> Datei-Tabelle
- ES:DI -> Dateiname als String mit Längenzähler
-
- Ausgabe: CF = 0 ->> okay
- CF = 1 ->> Fehler
- AX = Fehlernummer
-
- Bes.: Die Datei muß mindestens den Header (falls in der Datei-
- Tabelle angegeben) enthalten, die Größe der Datei muß
- ein Vielfaches der Satzlänge plus der Länge des Datei-
- headers sein.
- Der Modus der Datei (Lesen, Schreiben oder Lesen und
- Schreiben) wird durch die Variable RFOpenMode bestimmt.
- Geräte können über diese Routine nicht eröffnet werden.
-
- ----------------------------
- CreateRecordFile
-
- Funktion: Erstellt eine neue Datei.
-
- Eingabe: DS:BX -> Datei-Tabelle
- ES:DI -> Dateiname als String mit Längenzähler
-
- Ausgabe: CF = 0 ->> okay
- CF = 1 ->> Fehler
- AX = Fehlernummer
-
- Bes.: Eine bestehende Datei wird überschrieben!
- Die Attribute der Datei werden durch die Variable
- CreateRFileAttr bestimmt.
- Geräte können über diese Routine nicht erstellt werden.
-
- ----------------------------
- CreateNewRecordFile
-
- Funktion: Erstellt eine Datei
-
- Eingabe: DS:BX -> Datei-Tabelle
- ES:DI -> Dateiname als String mit Längenzähler
-
- Ausgabe: CF = 0 ->> okay
- CF = 1 ->> Fehler
- AX = Fehlernummer
-
- Bes.: Eine bestehende Datei führt zu einem Fehler!
- Die Attribute der Datei werden durch die Variable
- CreateRFileAttr bestimmt.
- Geräte können über diese Routine nicht erstellt werden.
-
- ----------------------------
- CloseRecordFile
-
- Funktion: Schreibt alle Puffer mit veränderten Daten in die Datei
- und schließt die Datei
-
- Eingabe: DS:BX -> Datei-Tabele
-
- Ausgabe: CF = 0 ->> okay
- CF = 1 ->> Fehler
- AX = Fehlernummer
-
- ----------------------------
- FlushRecordFile
-
- Funktion: Schreibt alle Puffer mit veränderten Daten in die Datei
-
- Eingabe: DS:BX -> Datei-Tabelle
-
- Ausgabe: CF = 0 ->> okay
- CF = 1 ->> Fehler
- AX = Fehlernummer
-
- Bes.: Ab DOS-Version 3.30 werden auch die DOS-internen Puffer
- über die Funktion 68h des Interrupts 21h geschrieben.
-
- ----------------------------
- ReadRecord
-
- Funktion: Liest einen Satz
-
- Eingabe: DS:BX -> Datei-Tabelle
- DX:AX = Nummer des Satzes (0..n)
- ES:DI -> Puffer für den Satz
-
- Ausgabe: CF = 0 ->> okay
- CF = 1 ->> Fehler
- AX = Fehlernummer
-
- Bes.: Die Satzlänge wird der Datei-Tabelle entommen.
- Es können nur schon existierende Sätze gelesen werden.
-
- ----------------------------
- TestRecord
-
- Funktion: Überprüft, ob ein Satz in der Datei vorhanden ist
-
- Eingabe: DS:BX -> Datei-Tabelle
- DX:AX = Nummer des Satzes (0..n)
-
- Ausgabe: CF = 0 ->> okay
- ZF = 0 ->> Satz vorhanden
- ZF = 1 ->> Satz nicht vorhanden
- CF = 1 ->> Fehler
- AX = Fehlernummer
-
- ----------------------------
- WriteRecord
-
- Funktion: Schreibt einen Satz
-
- Eingabe: DS:BX -> Datei-Tabelle
- DX:AX = Nummer des Satzes (0..n)
- ES:DI -> zu schreibender Satz
-
- Ausgabe: CF = 0 ->> okay
- CF = 1 ->> Fehler
- AX = Fehlernummer
-
- Bes.: Die Satzlänge wird der Datei-Tabelle entommen.
- Falls der Satz noch nicht existiert, wird die
- Datei verlängert. Nach einer Verlängerung existieren
- alle Sätze bis zum neuen Satz inclusive, wobei alle
- Sätze zwischen den letzten Satz und dem neuen Satz
- nur 'Datenmüll' enthalten.
-
- ----------------------------
- GetRecordFileSize
-
- Funktion: Ermittelt die Größe einer Datei und die Anzahl
- der Sätze in der Datei
-
- Eingabe: DS:BX -> Datei-Tabelle
-
- Ausgabe: CF = 0 ->> okay
- DX:AX = Größe der Datei (incl. Header)
- CX:BX = Anzahl der Sätze
- CF = 1 ->> Fehler
- AX = Fehlernummer
-
- ----------------------------
- SetRecordFileSize
-
- Funktion: Setzt die Größe einer Datei
-
- Eingabe: DS:BX -> Datei-Tabelle
- DX:AX = Anzahl der Sätze für die Datei
-
- Ausgabe: CF = 0 ->> okay
- CF = 1 ->> Fehler
- AX = Fehlernummer
-
- Bes.: Falls die Datei verkleinert wird, sind alle Sätze,
- die hinter dem neuen letzten Satz liegen verloren!
- Falls die Datei vergrößert wird, enthalten alle neuen
- Sätze nur 'Datenmüll'.
- Nach der Veränderung der Größe der Datei werden die
- Inhalte aller Puffer mit gültigen veränderten Daten
- in die Datei geschrieben.
-
- ----------------------------
- ReadRecordFileHeader
-
- Funktion: Liest den Header einer Datei
-
- Eingabe: DS:BX -> Datei-Tabelle
- ES:DI -> Puffer für den Header
-
- Ausgabe: CF = 0 ->> okay
- CF = 1 ->> Fehler
- AX = Fehlernummer
-
- Hinweis: Die Länge des Headers wird aus der Datei-Tabelle entnommen,
- für das Lesen des Headers wird kein Puffer benutzt.
- Der Header kann nur gelesen werden falls gilt:
- 0 < HeaderLength <= 65.535
-
-
- ----------------------------
- WriteRecordFileHeader
-
- Funktion: Schreibt den Header einer Datei
-
- Eingabe: DS:BX -> Datei-Tabelle
- ES:DI -> Header für die Datei
-
- Ausgabe: CF = 0 ->> okay
- CF = 1 ->> Fehler
- AX = Fehlernummer
-
- Hinweis: Die Länge des Headers wird aus der Datei-Tabelle entnommen,
- für das Schreiben des Headers wird kein Puffer benutzt.
- Der Header kann nur geschrieben werden falls gilt:
- 0 < HeaderLength <= 65.535
-
- ----------------------------
- MulLongInt
-
- Funktion: Multipliziert zwei Longint-Werte
-
- Eingabe: DX:AX = 1. Operand
- CX:BX = 2. Operand
-
- Ausgabe: DX:AX = (DX:AX * CX:BX) = Ergebnis
- Keine Überprüfung auf Überlauf!
-
- ----------------------------
- DivLongInt
-
- Funktion: Dividiert zwei Longint-Werte
-
- Eingabe: DX:AX = 1. Operand
- CX:BX = 2. Operand
-
- Ausgabe: CF = 0 ->> okay
- DX:AX = (DX:AX DIV CX:BX) = Ergebnis
- CX:BX = (DX:AX MOD CX:BX) = Rest
- CF = 1 ->> Fehler
- 2. Operand ist 0
-
- ----------------------------
- Make32BitAdress
-
- Funktion: Konvertiert eine 20-Bit-Zahl in eine normalisierte
- Adresse aus Segment und Offset
-
- Eingabe: DX:AX = 20-Bit-Zahl (Aufbau: 000n:nnnn)
-
- Ausgabe: DX:AX = 32-Bit-Adresse (Aufbau: ssss:000o)
-
- ----------------------------
- Make20BitValue
-
- Funktion: Konvertiert eine Adresse aus Segment und Offset in
- eine 20-Bit-Zahl
-
- Eingabe: DX:AX = Adresse (ssss:oooo)
-
- Ausgabe: DX:AX = 20-Bit-Zahl (000n:nnnn)
-
- Bes.: Die Adresse muß nicht normalisiert sein.
-
-