Antwort schreiben...
 
Themen-Optionen Thema durchsuchen
Alt 05.01.2014, 13:55   #1
Hans Jürgen
Registrierter Benutzer
Maximale Datenbankgrößen in OAIII

Hallo zusammen,

jetzt habe ich lange gesucht und doch nichts gefunden: wo finde ich die Limitierungen für Datenbanken unter OAIII/OA4 ?
Es muss wohl eine maximale Dateigröße bei 32768 kB geben. Läßt sich das umgehen?
Gibt es auch Einschränkungen bezüglich der Anzahl von Datensätzen?

Gruß
Hans Jürgen
Hans Jürgen ist offline   Mit Zitat antworten
Alt 07.01.2014, 08:42   #2
waldbauer.com
Entwickler
EDIT: Lt. Handbuch hast du bei OA4 2048 Byte pro Datensatz bei max. 2.2.Milliarden Datensätzen = 4.0 TB für eine Datei wenn ich mich nicht verrechnet habe.

Über OA3 habe ich leider keine Angaben.
waldbauer.com ist offline   Mit Zitat antworten
Alt 07.01.2014, 09:23   #3
leecher
Moderator
Da stößt Du vorher aber auf das FAT-Limit von 2GB pro file
leecher ist offline   Mit Zitat antworten
Alt 07.01.2014, 12:44   #4
Hans Jürgen
Registrierter Benutzer
In welchem Handbuch und unter welchem Kapitel steht das? Ich habe ja die OA3 Unterlagen hier, finde aber nichts.
Hans Jürgen ist offline   Mit Zitat antworten
Alt 07.01.2014, 12:45   #5
waldbauer.com
Entwickler
Im Datenbankhandbuch ganz hinten (vor dem Inhaltsverzeichnis).
waldbauer.com ist offline   Mit Zitat antworten
Alt 07.01.2014, 13:15   #6
Hans Jürgen
Registrierter Benutzer
Ich habe das OAIII Datenbank-Handbuch, da steht dummerweise nichts. Und auch alle anderen Handbücher habe ich durchsucht.

Gibt es eigentlich außer dem OA4-Programmierer-Handbuch noch weitere Handbücher als PDF irgendwo?
Hans Jürgen ist offline   Mit Zitat antworten
Alt 07.01.2014, 13:25   #7
waldbauer.com
Entwickler
Ich hab nur die OA4 Handbücher ...
Miniaturansicht angehängter Grafiken
Klicken Sie auf die Grafik für eine größere Ansicht

Name:	unterschied1.jpg‎
Hits:	9
Größe:	115.4 KB
ID:	581   Klicken Sie auf die Grafik für eine größere Ansicht

Name:	unterschied2.jpg‎
Hits:	9
Größe:	83.7 KB
ID:	582  
waldbauer.com ist offline   Mit Zitat antworten
Alt 12.01.2014, 12:32   #8
leecher
Moderator
Hallo zusammen,

Ich hab das jetzt mal verifiziert, OA3 hat tatsächlich ein 32MB Limit, es dürfte sich hierbei wohl um einen Design/Programmierfehler handeln.
Ich würde es als Bug klassifizieren, nachdem keinerlei Sicherheitsüberprüfungen zu diesem Limit implementiert sind und der Fehler somit für die Datenintegrität gefährlich ist (u.A. zerschießt man sich bei der Reparatur das .IF file).

Bevor wir zur weiteren Analyse schreiten gleich vorweg: Dieser Fehler wurde in OA4 behoben, dort kann man also ungestört mit großen Dateien operieren (bei der Netzwerkversion aber meinen Heap-Patch nicht vergessen, dort ist nämlich wiederum ein Speicherüberschreiber bug drinnen, aber das haben wir eh schon in einem anderen Thread abgehandelt).

Aufgrund der Natur des Fehlers, ist es leider nicht möglich, das so einfach zu patchen, da hierfür umfangreiche Änderungen des Programmablaufs notwendig wären (Aufruf anderer Funktionen mit anderen Parametern, etc.).

Nun zur Fehleranalyse:
Schreibt man ein kleines Programm, welches in einer Schleife einfach versucht, die Datenbank zu befüllen und mit dem uns wohl bekannten TRACE-Utility mitprotokolliert, so erhält man kurz vor Abbruch Folgendes:
8 = Filehandle der .DF Datei

Code:
42 3A3B:135D lseek(8, 0, 2) = 33551361          ; Länge der Datei?
42 3A3B:135D lseek(8, 33551360, 0) = 33551360   ; Gehen wir zur letzen Seite
3f 3A3B:1310 read(8, 29C0:675A, 4096) = 1       ; Seite Lesen -> Ups, die ist nicht da, nur 1 Byte gelesen
42 3A3B:135D lseek(8, 0, 1) = 33551361          ; Wo sind wir? -> Am Ende der Datei
Offensichtlich konnte also die letzte Seite im File nicht geschrieben werden.
Hier kann man noch nicht ganz verstehen, was los ist, aber beim Reparieren der Datei offenbart sich das Ganze dann etwas detaillierter. Merken wir uns vorerst nur einmal die Adresse der hier zur Anwendung kommenden Funktion, welche lseek aufruft -> 3A3B:135D

Repariert man die .DF Datei also mit dem Reparaturtool, so kann man schön sehen, wie die .IF Datei sich kurz vor Abbruch der Reparatur mit einem Fehler selbst zerstört. Auch hier können wir wieder den Trace betrachten (7 ist hier das handle zur .DF Datei, 8 ist das zur .IF Datei):

Code:
26C4:24E7 lseek(8, 33550336, 0) = 33550336
26C4:251D read(8, 904A:0010, 2048) = 2048
3A3B:135D lseek(7, 0, 2) = 33551361
3A3B:135D lseek(7, 21398528, 0) = 21398528
3A3B:1310 read(7, 29C0:414A, 4096) = 4096
3A3B:135D lseek(7, 0, 1) = 21402624
26C4:24E7 lseek(8, 33550336, 0) = 33550336
26C4:251D write(8, 904A:0010, 2020) = 2020
3A3B:135D lseek(8, 2048, 0) = 2048
3A3B:1310 write(8, 29C0:FDB4, 0) = 0
3A3B:135D lseek(8, 0, 2) = 2048
Das ganze Log ist leider zu lang, aber würde man es druchforsten kann man anhand der Funktionsadresse des lseek-Aufrufs feststellen, dass die Funktion zum Seeken an 3A3B:135D normalerweise nur für Filehandle 7 (.DF Datei) genutzt wird, hier bei Überschreitung der 32MB-Grenze jedoch auch für Handle 8 (.IF Datei).
Der Seek auf Position 2048 sieht wie ein 16bit Integer Überlauf aus, denn unter 16bit Systemen wie DOS ist ein INT nunmal so lang. Die Bestätigung dieser Theorie findet sich, wenn man die Seek-Funktion an der angegebenen Adresse zerlegt, ich habe sie hier dokumentiert und erläutert.
Nachdem ich den Debugger in einer anderen Umgebung ausgeführt habe, als den Trace, bitte nicht darüber wundern, dass hier im Dump ein anderes Segment steht als im TRACE:

Code:
2393:133A  8BEC                mov  bp,sp
2393:133C  8B5E08              mov  bx,[bp+08]             ss:[FE86]=0006   ; File handle 6
2393:133F  8B460A              mov  ax,[bp+0A]             ss:[FE88]=0042   ; 42h = lseek
2393:1342  8AE0                mov  ah,al
2393:1344  3C3E                cmp  al,3E                                   ; Close file?
2393:1346  7415                je   0000135D ($+15)        (no jmp)         ;  \_ Then do it
2393:1348  8B4E04              mov  cx,[bp+04]             ss:[FE82]=0000   ; Origin of move (0,1,2)
2393:134B  8AC1                mov  al,cl                                   
2393:134D  8B5606              mov  dx,[bp+06]             ss:[FE84]=13AA   ; Block in file (0-32MB)!
2393:1350  33C9                xor  cx,cx
2393:1352  8ACE                mov  cl,dh
2393:1354  8AF2                mov  dh,dl
2393:1356  32D2                xor  dl,dl
2393:1358  F8                  clc
2393:1359  D1D2                rcl  dx,1
2393:135B  D1D1                rcl  cx,1                                    ; Offset = 512*Sector no
2393:135D  CD21                int  21

Stack:
------
0-4  Return address
4-6  Origin of move (0,1,2)
6-8  Block to write
8-A  File handle
A-C  DOS INT21h Function (42h=lseek, 3E=close file)
Wie wir eindeutig erkennen können, wird dieser Funktion nur eine 16bit Blocknummer übergeben, und die läuft nach 65535 nunmal über, das entspricht auch ungefähr der von uns festgestellten Limitierung von 65535 * 512 = 33553920 Bytes = 32MB.
Jetzt stellt sich noch die Frage, wo diese Funktion aufgerufen wird. Sieht man sich die Returnadresse am Stack an und folgt dieser, landet man nach Ausführen der Funktion wieder im UCSD-Pascal PCODE-Interpreter. Anhand der gelesenen Bytes lässt sich feststellen, wo im PCODE wir uns befinden.
Es handelt sich um eine Stelle im PASCAL.IMAGE der OA3.SPI, also im PASCAL-Teil der Runtime. Sieht man sich die PCODE Opcodes dort an, so hat man zumindest eine Vermutung, was hier getan wird. Leider sind die PCODE Opcodes der Pascal Runtime für die hier verwendete DOS-Version scheinbar nirgends dokumentiert, sie dürften sich rein von der Logik her auch von der klassischen PCode-Machine für Apple II unterscheiden, leider ist es mir bis heute nicht gelungen heruaszufinden, welches UCSD Development-System hier verwendet wird. Eventuell ist das von SPI selbst gestrickt, oder sie haben es irgendwo zugekauft, es finden sich jedoch keine Spuren davon im Netz, man findet meist nur die alten Runtime-Systeme aus Ende der 70er Jahre.
Hier mein "Interpretationsversuch" der Opcodes (alles Hex):

Code:
-------------------------------------------------------
PASCAL.IMAGE
-------------------------------------------------------
6B 00   - ?
80 42   - Push 42h (Dos function code number for lseek)
27      - Push file handle
7C      - Push block number
25 00   - Push 0 (Origin of move)
91 2A   - Execute Function 2A (our block lseek funct)
-------------------------------------------------------
68 00   - ?
80 3F   - Push 3Fh (Dos function code number for read)
27      - Push Buffer of data
7C      - Push file handle
24      - Push number of bytes to read
91 29   - Execute Function 29 (Do INT21h with params)
-------------------------------------------------------
68 23   - ?
D4      - ?
09      - Return
-------------------------------------------------------
SS.IMG
-------------------------------------------------------
20 00 B3 F1 05 01 ...
Sieht man sich den Aufbau und Position der der Funktion innerhalb
von PASCAL.IMAGE an, so handelt es sich vermutlich um die UCSD Pascal
BlockRead-Funktion:

Code:
FUNCTION BLOCKREAD(FILEID: FILE, ARRAY, BLOCKS: INTEGER, [ RELBLOCK: INTEGER] ): INTEGER;
Wie man sehen kann, wird hier für die Blocknummer ein INTEGER gegeben. DOS ist ein 16bit System, damit ist auch die Größe eines INTs mit 16bit limitiert, wobei wir wieder bei unserem 32MB-Limit wären. Dieses Problem wird u.A. auch hier beschrieben, und schon damals suchte man nach Lösungsansätzen.

Sieht man sich die Adresse der Schreiboperationen beim Datenfile über die 32MB-Grenze hinaus an, so wird man feststellen, dass beim .DF dort dieselbe BlockWrite-Funktion verwendet wird, womit man dort eben genauso in das Limit hineinläuft.

Sieht man sich nun einen Trace von OpenAccess IV an derselben Stelle an und überprüft mit einem Debugger auch noch die aufgerufenen Funktionen, so sieht man, dass die BlockRead / BlockWrite Funktionen hier scheinbar nicht mehr verwendet werden, sondern welche, die diese Limitierung nicht mehr haben:

Code:
26C4:23AE lseek(8, 33547588, 0) = 33547588
26C4:2257 lseek(8, 33550336, 0) = 33550336
26C4:239D read(8, 935F:0000, 2048) = 2048
26C4:23AE lseek(8, 33552384, 0) = 33552384
4656:148A lseek(7, 21398528, 0) = 21398528
4656:10B2 read(7, 29E6:3F82, 4096) = 4096
4656:148A lseek(7, 0, 1) = 21402624
26C4:2257 lseek(8, 33550336, 0) = 33550336
26C4:239D write(8, 935F:0000, 2020) = 2020
26C4:23AE lseek(8, 33552356, 0) = 33552356
4656:148A lseek(8, 33556480, 0) = 33556480
4656:10B2 write(8, 29E6:FCBA, 0) = 0
4656:148A lseek(8, 0, 2) = 33556480
Es sieht also so aus, als ob die Autoren von OA das Problem erkannt und in der Version 4 behoben hätten. Nachdem die PCode-Opcodes des UCSD-Systems nirgendwo dokumentiert sind und es sich auch nicht um einen einfachen Bug sondern um falsch verwendete Funktionen handelt, hilft also voraussichtlich nur ein Update auf OA4.

Lg.
leecher ist offline   Mit Zitat antworten
Alt 12.01.2014, 12:56   #9
Hans Jürgen
Registrierter Benutzer
Du bist wirklich ein absoluter Profi - danke für die Klärung! Bleibt wirklich nur OA4.
Gruß und schönen Sonntag
Hans Jürgen
Hans Jürgen ist offline   Mit Zitat antworten


Antwort schreiben...

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche


Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Nützliche Tips (Ergänzungen zum Handbuch von Heinz Richartz) waldbauer.com SPI OA4 Open Access II/III/IV (2,3,4) Anwender Forum 204 08.11.2012 14:11