OpenSpec-Review dokumentieren und ISAM-Vertragsabweichungen beheben
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-09-05
|
||||
@@ -0,0 +1,33 @@
|
||||
## Context
|
||||
|
||||
oeffnen ruft direkt Database::begin_write auf, während schreiben/lesen laufende Transaktionen wiederverwenden. Undo enthält nur Eingefuegt/Vorher für Sätze. FREEFILE fragt ausschließlich Dateien ab. Siehe proposal.md und die Delta-Specs.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:** Die bestehende redb-Schicht und die vorhandenen Bindungen behalten; Transaktions- und Nummernlogik an ihren gemeinsamen Einstiegspunkten berichtigen.
|
||||
|
||||
**Non-Goals:** Kein neues Speichersystem, keine verteilte Atomarität über mehrere Datenbankdateien, keine Performance-Umschreibung der Indizes.
|
||||
|
||||
## Decisions
|
||||
|
||||
### D1 — Gemeinsame Transaktion verwenden
|
||||
|
||||
OPEN und Layoutprüfung benutzen bei aktiver Transaktion deren vorhandenen Schreibkontext; außerhalb bleiben sie einzelne Transaktionen. Das vermeidet die Selbstblockade. OPEN und DELETETABLE verwenden kanonische absolute Pfade als Schlüssel für Datenbanken, Transaktionen und Bindungen; bei neuen Dateien wird zunächst der vorhandene Elternpfad kanonisiert. Nach erfolgreicher Dateianlage wird der vollständige Pfad erneut kanonisiert und als endgültige Identität an alle Aufrufer zurückgegeben, damit neu auflösbare Symlinks keinen zweiten Cache-Schlüssel erzeugen. CHDIR ändert damit weder bestehende Bindungen noch die Bedeutung der Cache-Schlüssel. Eine zweite Verbindung oder ein impliziter Commit würde Isolation und ROLLBACK brechen. CLOSE ohne Nummer und RESET lösen wie CLOSE #n nur Bindungen; die Freigabe der Datenbankdateien bleibt vom Transaktionsende getrennt.
|
||||
|
||||
### D2 — Sicherungspunkte umfassen Struktur und Inhalt
|
||||
|
||||
Das vorhandene Undo-Protokoll um die tatsächlich unterstützten Index-/Tabellenstrukturänderungen und deren Metadaten erweitern; in umgekehrter Operationsreihenfolge zurücknehmen. Layoutinformationen für Rücknahme auch nach CLOSE behalten. ROLLBACK ALL bleibt der Abbruch der redb-Transaktion. Keine Kopie der gesamten Datenbank je Savepoint. Struktur-Undo speichert alte Metadaten sowie beim Löschen die betroffenen rohen Satz-/Indexeinträge; diese Nutzdaten zählen zum SETMEM-Puffer und werden vor der Mutation gegen die Grenze geprüft. Satz-Undo trägt sein Layout selbst. Nach Rücknahme werden ungültige aktive Indizes gelöscht und Bindungen an verschwundene Tabellen oder zurückgenommene Layouts gelöst; gültige Bindungen behalten einen unpositionierten Cursor. Erfolgreiches DELETETABLE löst alle Bindungen dieser Tabelle; die Rücknahme stellt den Bestand, aber keine geschlossenen Bindungen wieder her. DELETE prüft die alten Satzbytes vor der Mutation gegen den verfügbaren Puffer, auch außerhalb einer expliziten Transaktion.
|
||||
|
||||
### D3 — Dateinummern gemeinsam prüfen
|
||||
|
||||
FREEFILE fragt beide bestehenden Belegungsprüfungen ab. Kein dritter Nummernspeicher, der von den Bindungen abweichen kann. Beide OPEN-Einstiege prüfen auch die andere Verwaltung und weisen Doppelbelegung mit Fehler 55 zurück. Ist keine als INTEGER darstellbare freie Nummer übrig, meldet FREEFILE Fehler 67.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- Versehentlicher Commit durch OPEN → nach Öffnen/Schließen weiterer Bindungen ROLLBACK ALL und erneutes Öffnen zur Persistenzprüfung.
|
||||
- Fehlendes Undo für Strukturänderungen → CREATEINDEX, DELETEINDEX, DELETETABLE und Tabellenneuanlage vor/nach mehreren Savepoints prüfen.
|
||||
- Hängender Regressionstest → Der CLI-Unterprozess hat fünf Sekunden Frist. Jeder Runtime-Datenbanktest und jede Korpusausführung werden zusätzlich über einen unabhängigen Watchdog nach 30 Sekunden mit Prozessstatus 124 beendet. Der ganze Testprozess darf beim Timeout scheitern, damit blockierende Bibliotheksaufrufe keine unendlichen Testläufe hinterlassen. Ein absichtlich blockierter Kind-Test beweist den Abbruch; der Elternprozess hat eine separate Kill-Frist.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
Eigenständig. Gemeinsame Änderungen in builtins.rs mit laufzeit-eingabe-und-systemstatus sequenziell integrieren. Bestehende Spec-/Codeverträge erst nach erfolgreicher Umsetzung synchronisieren und archivieren. Die Tasks werden nach ihrer jeweiligen Abnahme abgeschlossen; Spec-Synchronisation und Archivierung folgen getrennt. Änderungen als zusammenhängenden Commit je Change integrieren; bei Fehlschlag auf den vorherigen Code zurückgehen und neue Datenformatversionen nicht mit alten Lesern öffnen.
|
||||
@@ -0,0 +1,28 @@
|
||||
## Why
|
||||
|
||||
ISAM kann beim Öffnen einer weiteren Tabelle innerhalb einer Transaktion blockieren, Sicherungspunkte lassen Indexänderungen stehen und FREEFILE liefert bereits belegte Nummern. F01–F03 des Reviews zeigen diese Fälle mit reproduzierbaren CLI-Programmen. Siehe [Review vom 05.09.2026](../../../../docs/reviews/2026-09-05-openspec-code-review.md).
|
||||
|
||||
## What Changes
|
||||
|
||||
- Zusätzliche ISAM-Bindungen innerhalb einer Transaktion ohne Selbstblockade und ohne impliziten Commit erlauben.
|
||||
- Sicherungspunkte auf Satz- und Indexänderungen einschließlich Metadaten anwenden.
|
||||
- FREEFILE über gewöhnliche und ISAM-Dateinummern gemeinsam bestimmen.
|
||||
- Datenbankpfade über Verzeichniswechsel und Aliase korrekt zuordnen, Bindungen bei DELETETABLE lösen und die Puffergrenze vor DELETE prüfen.
|
||||
- Blockierende Regressionen durch Prozessfristen für Runtime-Datenbanktests und Korpusausführungen absichern.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
Keine neuen Capability-Pfade.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `isam-datenbank`: Transaktionales Öffnen, Pfadidentität, vollständige Rücknahme über Sicherungspunkte, Bindungen nach Tabellenlöschung und Puffergrenzen präzisieren.
|
||||
- `datei-eio`: Freie Dateinummern ausdrücklich über alle Zugriffsarten bestimmen.
|
||||
|
||||
## Impact
|
||||
|
||||
crates/tb-runtime/src/isam.rs, builtins.rs und fileio.rs; ISAM-Unit-Tests, CLI-Korpus und docs/dateiformate.md. Keine neue Bibliothek und kein neues Datenbankformat.
|
||||
|
||||
Eigenständig. Gemeinsame Änderungen in builtins.rs mit laufzeit-eingabe-und-systemstatus sequenziell integrieren.
|
||||
@@ -0,0 +1,30 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Dateinummern und Öffnen in drei Zugriffsarten
|
||||
`OPEN` SHALL in beiden Syntaxen des Vorbilds (Klausel- und Kurzform) die
|
||||
Zugriffsarten sequenziell (`INPUT`, `OUTPUT`, `APPEND`), wahlfrei
|
||||
(`RANDOM`) und binär (`BINARY`) unterstützen und die Datei an eine
|
||||
Dateinummer binden. `FREEFILE` SHALL die kleinste freie Dateinummer
|
||||
liefern. `CLOSE` ohne Argument SHALL alle offenen Dateien schließen,
|
||||
`RESET` ebenso. Eine bereits belegte Dateinummer MUST Laufzeitfehler 55
|
||||
„File already open" auslösen, eine nicht geöffnete Nummer Fehler 52
|
||||
„Bad file name or number", eine fehlende Datei bei `INPUT` Fehler 53
|
||||
„File not found".
|
||||
|
||||
FREEFILE SHALL die gemeinsame Belegung durch sequenzielle, wahlfreie, binäre und ISAM-Bindungen berücksichtigen.
|
||||
|
||||
#### Scenario: Sequenzielles Schreiben und Lesen
|
||||
- **WHEN** eine Datei mit `OPEN "d.txt" FOR OUTPUT AS #1` beschrieben, geschlossen und mit `FOR INPUT` wieder geöffnet wird
|
||||
- **THEN** liefert das Lesen genau die geschriebenen Zeilen
|
||||
|
||||
#### Scenario: Doppeltes Öffnen derselben Nummer
|
||||
- **WHEN** `OPEN` eine bereits offene Dateinummer verwendet
|
||||
- **THEN** tritt Laufzeitfehler 55 auf
|
||||
|
||||
#### Scenario: Freie Dateinummer
|
||||
- **WHEN** `#1` offen ist und `FREEFILE` aufgerufen wird
|
||||
- **THEN** liefert `FREEFILE` eine Nummer, die noch nicht belegt ist
|
||||
|
||||
#### Scenario: ISAM belegt eine Dateinummer
|
||||
- **WHEN** eine ISAM-Tabelle auf #1 und sonst keine Datei offen ist
|
||||
- **THEN** liefert FREEFILE den Wert 2
|
||||
@@ -0,0 +1,111 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Datenbank- und Tabellenbindung an eine Dateinummer
|
||||
`OPEN datenbank$ FOR ISAM typname tabellenname AS #n` SHALL eine Tabelle
|
||||
einer Datenbankdatei an eine Dateinummer binden. Das Satzlayout SHALL
|
||||
sich aus dem benannten benutzerdefinierten Typ ergeben; dessen Felder
|
||||
sind die Spalten der Tabelle. Existiert die Tabelle noch nicht, SHALL sie
|
||||
mit diesem Layout angelegt werden; existiert sie mit abweichendem Layout,
|
||||
MUST Laufzeitfehler 88 „ISAM - Database inconsistent" auftreten. Ein
|
||||
ungültiger Tabellen- oder Datenbankname MUST Fehler 81 „ISAM - Invalid
|
||||
name" auslösen. `CLOSE` SHALL die Bindung lösen; ausstehende Änderungen
|
||||
sind dabei bereits festgeschrieben, weil jede Operation außerhalb einer
|
||||
Transaktion für sich eine Transaktion ist. Eine laufende Transaktion MUST
|
||||
`CLOSE` unberührt lassen — über ihr Ende entscheiden allein `COMMITTRANS`
|
||||
und `ROLLBACK ALL`. `DELETETABLE` SHALL eine Tabelle samt ihren
|
||||
Indizes entfernen; eine nicht vorhandene Tabelle MUST Fehler 82 „ISAM -
|
||||
Table not found" auslösen.
|
||||
|
||||
Eine weitere Bindung derselben Datenbank innerhalb einer laufenden Transaktion SHALL deren bisherigen Zustand sehen und MUST ohne implizites Festschreiben oder Selbstblockade entstehen.
|
||||
|
||||
OPEN und DELETETABLE SHALL relative Datenbankpfade im aktuellen Arbeitsverzeichnis auflösen und kanonisch auflösbare Aliase derselben Datei gemeinsam verwalten. Bereits offene Bindungen MUST nach CHDIR weiterhin auf ihre ursprünglich geöffnete Datenbank zeigen. DELETETABLE SHALL bei Erfolg alle Bindungen der entfernten Tabelle lösen; weitere Zugriffe über diese Nummern MUST Fehler 52 melden. Eine Rücknahme SHALL die gelöschte Tabelle wiederherstellen, ohne geschlossene Bindungen erneut zu öffnen.
|
||||
|
||||
#### Scenario: Gleicher relativer Name nach Verzeichniswechsel
|
||||
- **WHEN** nach OPEN in Verzeichnis A alle Bindungen geschlossen werden und derselbe relative Name in Verzeichnis B geöffnet wird
|
||||
- **THEN** betreffen Lesen und Schreiben die Datei in B; die Datei in A bleibt unverändert
|
||||
|
||||
#### Scenario: Pfadalias in einer Transaktion
|
||||
- **WHEN** dieselbe vorhandene Datenbank nach BEGINTRANS und INSERT über einen relativen oder absoluten Pfadalias erneut geöffnet wird
|
||||
- **THEN** sieht die neue Bindung die bisherigen Änderungen ohne zweiten Writer; ROLLBACK ALL nimmt die Änderungen zurück
|
||||
|
||||
#### Scenario: Neuanlage über einen noch nicht auflösbaren Symlink
|
||||
- **WHEN** OPEN eine Datenbank über einen Symlink mit bislang fehlender Zieldatei anlegt und die Datenbank danach innerhalb einer Transaktion erneut über Alias oder Zielpfad geöffnet wird
|
||||
- **THEN** teilen alle Bindungen denselben Transaktionszustand; Sicherungspunkt-Rücknahme und ROLLBACK ALL funktionieren über beide Pfade
|
||||
|
||||
#### Scenario: Bindungen nach Tabellenlöschung und Rücknahme
|
||||
- **WHEN** eine mehrfach gebundene Tabelle nach SAVEPOINT mit DELETETABLE gelöscht und anschließend zurückgenommen wird
|
||||
- **THEN** sind die alten Bindungen geschlossen; ein erneutes OPEN sieht wieder die ursprünglichen Sätze und Indizes
|
||||
|
||||
#### Scenario: Tabelle wird beim ersten Öffnen angelegt
|
||||
- **WHEN** eine Datenbank ohne die Tabelle `Kunden` mit `OPEN "db" FOR ISAM KundeTyp "Kunden" AS #1` geöffnet wird
|
||||
- **THEN** entsteht die Tabelle mit den Feldern des Typs und die Dateinummer ist nutzbar
|
||||
|
||||
#### Scenario: Abweichendes Satzlayout
|
||||
- **WHEN** eine bestehende Tabelle mit einem Typ geöffnet wird, dessen Felder nicht zu ihren Spalten passen
|
||||
- **THEN** tritt Laufzeitfehler 88 auf
|
||||
|
||||
#### Scenario: CLOSE lässt eine laufende Transaktion stehen
|
||||
- **WHEN** innerhalb einer Transaktion eine andere Dateinummer mit `CLOSE` geschlossen wird
|
||||
- **THEN** läuft die Transaktion weiter und ein folgendes `ROLLBACK ALL` nimmt ihre Änderungen zurück
|
||||
|
||||
#### Scenario: Entfernte Tabelle
|
||||
- **WHEN** `DELETETABLE` für eine nicht vorhandene Tabelle aufgerufen wird
|
||||
- **THEN** tritt Laufzeitfehler 82 auf
|
||||
|
||||
#### Scenario: Weitere Tabelle während einer Transaktion
|
||||
- **WHEN** nach BEGINTRANS und INSERT eine zweite Tabelle derselben Datenbank geöffnet und danach ROLLBACK ALL ausgeführt wird
|
||||
- **THEN** kehrt OPEN zurück; die eingefügten Daten sind nach Wiederöffnung nicht festgeschrieben
|
||||
|
||||
### Requirement: Transaktionen mit Rücknahme
|
||||
`BEGINTRANS` SHALL eine Transaktion eröffnen, `COMMITTRANS` alle
|
||||
Änderungen seit ihrem Beginn festschreiben und `ROLLBACK` sie
|
||||
zurücknehmen. `SAVEPOINT` SHALL als **Funktion** einen Sicherungspunkt
|
||||
setzen und dessen Kennung liefern; `ROLLBACK` mit einer solchen Kennung
|
||||
SHALL auf diesen Punkt zurücksetzen, ohne die Transaktion aufzugeben.
|
||||
`ROLLBACK ALL` SHALL alle Änderungen seit `BEGINTRANS` zurücknehmen und
|
||||
die Transaktion beenden. Nach jeder Rücknahme MUST der Satzbestand
|
||||
einschließlich aller Indizes dem Zustand zum Bezugspunkt entsprechen und
|
||||
der Cursor als unpositioniert gelten. Eine beim Programmende nicht
|
||||
festgeschriebene Transaktion MUST wirkungslos bleiben.
|
||||
|
||||
Die Rücknahme auf einen Sicherungspunkt SHALL auch seitdem angelegte oder gelöschte Indizes und Tabellenstrukturen einschließlich ihrer Metadaten zurücknehmen. CLOSE einer Bindung MUST die spätere Rücknahme ihrer Änderungen weiterhin erlauben.
|
||||
|
||||
#### Scenario: Rücknahme stellt den Bestand wieder her
|
||||
- **WHEN** nach `BEGINTRANS` Sätze eingefügt und gelöscht werden und dann `ROLLBACK` folgt
|
||||
- **THEN** entspricht der Bestand beim erneuten Durchlauf dem Zustand vor `BEGINTRANS`
|
||||
|
||||
#### Scenario: Rücknahme auf einen Sicherungspunkt
|
||||
- **WHEN** innerhalb einer Transaktion `s = SAVEPOINT` ausgewertet, danach geändert und mit `ROLLBACK s` zurückgesetzt wird
|
||||
- **THEN** bleiben die Änderungen vor dem Sicherungspunkt erhalten und die danach sind zurückgenommen
|
||||
|
||||
#### Scenario: ROLLBACK ALL beendet die Transaktion
|
||||
- **WHEN** nach mehreren Sicherungspunkten `ROLLBACK ALL` ausgeführt wird
|
||||
- **THEN** entspricht der Bestand dem Zustand vor `BEGINTRANS` und die Transaktion ist beendet
|
||||
|
||||
#### Scenario: Indexanlage nach Sicherungspunkt
|
||||
- **WHEN** nach SAVEPOINT ein Index angelegt und auf den Sicherungspunkt zurückgesetzt wird
|
||||
- **THEN** ist der neue Index nicht vorhanden; SETINDEX mit seinem Namen löst Fehler 83 aus
|
||||
|
||||
#### Scenario: Geschlossene Tabelle rücknehmen
|
||||
- **WHEN** eine geänderte Tabellenbindung vor ROLLBACK auf einen Sicherungspunkt geschlossen wird
|
||||
- **THEN** gelingt die Rücknahme und der bei Wiederöffnung sichtbare Satz-/Indexbestand entspricht dem Sicherungspunkt
|
||||
|
||||
### Requirement: Pufferverwaltung mit benanntem Fehler
|
||||
`SETMEM` SHALL als **Funktion** die für ISAM verfügbare Puffergröße um
|
||||
den übergebenen Betrag ändern und die danach verfügbare Größe liefern.
|
||||
Reicht
|
||||
der verfügbare Puffer für eine Operation nicht aus, MUST Laufzeitfehler 89
|
||||
„ISAM - Insufficient ISAM buffers" auftreten statt eines generischen
|
||||
Fehlers oder eines stillen Abbruchs. Weicht die Bedeutung von `SETMEM`
|
||||
mangels DOS-Speichermodell vom Vorbild ab, MUST die Abweichung in
|
||||
docs/sprachreferenz.md dokumentiert sein.
|
||||
|
||||
DELETE SHALL den benötigten Satz-/Undo-Puffer vor der Änderung prüfen. Bei Fehler 89 MUST Satzbestand, Indexbestand und Cursor unverändert bleiben.
|
||||
|
||||
#### Scenario: Pufferfehler wird benannt
|
||||
- **WHEN** eine Operation den verfügbaren ISAM-Puffer überschreitet
|
||||
- **THEN** tritt Laufzeitfehler 89 auf
|
||||
|
||||
#### Scenario: DELETE bei ausgeschöpftem Puffer
|
||||
- **WHEN** DELETE auf einem gültigen aktuellen Satz bei unzureichendem ISAM-Puffer ausgeführt wird
|
||||
- **THEN** meldet es Fehler 89 ohne den Satz zu löschen, den Cursor zu verschieben oder Undo hinzuzufügen; eine spätere Rücknahme bleibt möglich
|
||||
@@ -0,0 +1,46 @@
|
||||
## 1. Transaktionspfade
|
||||
|
||||
- [x] 1.1 OPEN/Layoutanlage auf den bestehenden Transaktionskontext führen; verifizieren mit OPEN → BEGINTRANS → INSERT → zweites OPEN derselben Datenbank unter harter Prozessfrist und anschließendem ROLLBACK ALL.
|
||||
- [x] 1.2 Strukturänderungen am bestehenden Undo-Protokoll rücknehmbar machen und benötigte Layouts über CLOSE erhalten; verifizieren mit verschachtelten Savepoints, CREATEINDEX/DELETEINDEX/DELETETABLE, geschlossenen Bindungen und unverändertem Bestand nach Wiederöffnung.
|
||||
|
||||
## 2. Dateinummern und Abnahme
|
||||
|
||||
- [x] 2.1 FREEFILE gegen beide Dateiverwaltungen prüfen; verifizieren mit gemischten OPEN-Modi, ISAM #1, Lücken nach CLOSE und wiederverwendeten Nummern.
|
||||
- [x] 2.2 ISAM-Korpus um die regressiven Ablaufkombinationen erweitern; verifizieren mit cargo test -p tb-runtime und cargo test -p tb-cli --test compat.
|
||||
- [x] 2.3 Transaktions-/Sicherungspunktgrenzen dokumentieren und Delta-Specs prüfen; verifizieren mit git diff --check und openspec validate isam-transaktionen-und-dateinummern --strict.
|
||||
|
||||
## Abnahme am 05.09.2026
|
||||
|
||||
- `cargo test -p tb-runtime --quiet`: 130 bestanden.
|
||||
- `cargo test -p tb-cli --test compat --quiet`: 15 bestanden; der Golden-Generator bleibt ignoriert. Drei neue Korpusprogramme mit unabhängig festgelegten Sollausgaben.
|
||||
- `cargo test --workspace --quiet`: 385 bestanden, 0 fehlgeschlagen, 1 bewusst ignoriert.
|
||||
- Der CLI-Test für OPEN innerhalb einer Transaktion läuft mit einer harten Fünf-Sekunden-Frist und prüft Sichtbarkeit sowie ROLLBACK ALL nach CLOSE.
|
||||
- Formatprüfung der vier geänderten Rust-Dateien, `git diff --check` und `openspec validate isam-transaktionen-und-dateinummern --strict` bestanden.
|
||||
|
||||
## 3. Befunde der Verifikation
|
||||
|
||||
- [x] 3.1 V01: Datenbankpfade eindeutig auflösen; Verzeichniswechsel, relative/absolute Aliase und DELETETABLE über Aliase prüfen.
|
||||
- [x] 3.2 V02: Alle gefährdeten Runtime-/Korpusläufe mit einer wirksamen Prozessfrist schützen und einen absichtlich blockierten Testprozess nachweislich beenden.
|
||||
- [x] 3.3 V03: Bindungen gelöschter Tabellen lösen; Zugriffe danach, Wiederanlage und Rücknahme der Löschung prüfen.
|
||||
- [x] 3.4 V04: DELETE vor Mutation gegen die Puffergrenze prüfen; Bestand, Indizes und Cursor bei Fehler 89 unverändert erhalten.
|
||||
- [x] 3.5 Alle Befunde erneut verifizieren, Dokumentation und Delta-Specs abgleichen sowie Workspace-Tests und OpenSpec-Validierung abschließen.
|
||||
|
||||
## Nachprüfung der Befunde am 05.09.2026
|
||||
|
||||
- Runtime: 134 Tests bestanden; CLI-Kompatibilität: 16 bestanden, Golden-Generator ignoriert.
|
||||
- Workspace: 390 bestanden, 0 fehlgeschlagen, 1 bewusst ignoriert.
|
||||
- V01: Neuer Korpusfall `isamidentitaet.bas`, Unit-Test für Pfad-/Symlinkaliase und separate CLI-Prozesse bestätigen getrennte Daten in a/db und b/db.
|
||||
- V02: Jeder Runtime-Datenbanktest und Korpuslauf hat eine harte Prozessfrist; der Selbsttest beendet einen absichtlich blockierten Kindprozess mit Status 124.
|
||||
- V03: Zwei alte Bindungen sind nach DELETETABLE unbenutzbar; Rücknahme und Wiederöffnung stellen Sätze und Eindeutigkeit wieder her.
|
||||
- V04: DELETE meldet bei vollem Puffer Fehler 89; Satzbestand, Indizes, Cursor und Undo bleiben unverändert. Genau passende Puffergröße und anschließende Rücknahme sind geprüft.
|
||||
|
||||
## 4. Letzter Aliasbefund
|
||||
|
||||
- [x] 4.1 V05: Nach Neuanlage die tatsächliche kanonische Dateiidentität an Cache und Bindungen weitergeben; Symlink-Neuanlage mit erneutem OPEN über Alias und Ziel, DELETETABLE, Sicherungspunkt und ROLLBACK ALL prüfen.
|
||||
|
||||
## Schlussabnahme V05
|
||||
|
||||
- `symlink_neuanlage_behaelt_die_dateiidentitaet`: bestanden für relative und absolute Symlinkziele, inklusive Alias-/Zielbindung, DELETETABLE, Sicherungspunkt, ROLLBACK ALL und erneutem Öffnen.
|
||||
- Ursprüngliche CLI-Reproduktion: Alias und Ziel liefern innerhalb der Transaktion je einen Satz; nach ROLLBACK ALL ist der Bestand leer.
|
||||
- `cargo test --workspace --quiet`: 391 bestanden, 0 fehlgeschlagen, 1 bewusst ignoriert.
|
||||
- Format-/Diffprüfung und strikte OpenSpec-Validierung bestanden; vier Anforderungen in zwei Hauptspecs synchronisiert und alle 15 Hauptspecs validiert.
|
||||
@@ -0,0 +1,162 @@
|
||||
# Verifikation: isam-transaktionen-und-dateinummern
|
||||
|
||||
Nachprüfung am 05.09.2026, aktueller uncommitteter Arbeitsbaum auf `19804e0`.
|
||||
Geprüft: Proposal, Design, Tasks, Delta-Specs, betroffene Hauptspec-Verträge,
|
||||
Implementierung, Regressionstests und ursprüngliche Fehlerreproduktionen.
|
||||
|
||||
**Schlussabnahme: V01–V05 behoben und nachgeprüft. Keine offenen Befunde.
|
||||
Die Hauptspecs sind synchronisiert; alle 11 Tasks sind abgeschlossen.**
|
||||
|
||||
| Dimension | Ergebnis |
|
||||
|---|---|
|
||||
| Vollständigkeit | 11/11 Tasks abgeschlossen |
|
||||
| Korrektheit | 4 Anforderungen, 20 Szenarien zugeordnet; Neuanlage über Symlink zusätzlich abgesichert |
|
||||
| Kohärenz | D1–D3 eingehalten; Dokumentation und Delta-Specs um die Korrekturen ergänzt |
|
||||
| Befunde | 0 offen; V01–V05 behoben |
|
||||
|
||||
## V05 — Neuanlage über einen Symlink: behoben
|
||||
|
||||
**Vorher:** Bei `alias.db → target.db` mit noch fehlender Zieldatei gelang
|
||||
das erste OPEN; das zweite OPEN derselben Datei meldete Fehler 88. Die erste
|
||||
Anlage speicherte den Alias als Cache-Schlüssel, die nächste Auflösung ergab
|
||||
den Zielpfad.
|
||||
|
||||
**Korrektur:** `db_oeffnen` bestimmt nach erfolgreicher Dateianlage die
|
||||
endgültige kanonische Identität, speichert den Datenbankhandle darunter und
|
||||
gibt diesen Pfad an OPEN beziehungsweise DELETETABLE zurück. Bindungen,
|
||||
Transaktionen und Undo verwenden damit von Anfang an den Zielpfad.
|
||||
|
||||
**Nachweise:**
|
||||
|
||||
- `symlink_neuanlage_behaelt_die_dateiidentitaet` in
|
||||
[isam/tests.rs](../../../../crates/tb-runtime/src/isam/tests.rs): relative und
|
||||
absolute Symlinkziele, erneutes OPEN über Alias und Ziel, gemeinsamer
|
||||
Transaktionsbestand, DELETETABLE über Alias, Sicherungspunkt-Rücknahme,
|
||||
ROLLBACK ALL und persistierter Ausgangsbestand nach erneutem Öffnen.
|
||||
- Ursprüngliche CLI-Reproduktion in einem frischen temporären Verzeichnis,
|
||||
mit fünf Sekunden Frist: beide zusätzlichen Bindungen sehen einen Satz;
|
||||
nach ROLLBACK ALL liefert LOF den Wert 0. Prozessstatus 0, keine Fehler 88/52.
|
||||
- Vollständige Workspace-Suite: **391 bestanden, 0 fehlgeschlagen,
|
||||
1 bewusst ignoriert**. Davon 135 Runtime-Tests und 16 aktive CLI-Korpus-/Harness-Tests.
|
||||
|
||||
## V01 — Datenbankidentität: behoben
|
||||
|
||||
**Vorher:** Nach CLOSE und CHDIR konnte OPEN mit demselben relativen Namen
|
||||
in die alte Datei schreiben. OPEN über `./db` erkannte eine bereits laufende
|
||||
Transaktion derselben Datei nicht und meldete Fehler 88.
|
||||
|
||||
**Korrektur:** [datenbank_pfad](../../../../crates/tb-runtime/src/isam.rs#L1560)
|
||||
löst vorhandene Dateien kanonisch auf. Bei neuen Dateien wird ihr vorhandener
|
||||
Elternpfad kanonisiert. OPEN und DELETETABLE verwenden diesen Schlüssel
|
||||
durchgängig für Datenbanken, Transaktionen, Bindungen und Rücknahme.
|
||||
|
||||
**Nachweise:**
|
||||
|
||||
- [isamidentitaet.bas](../../../../tests/compat/isamidentitaet.bas): Nach Wechsel
|
||||
von a nach b ist die zweite Datenbank leer; der Alias `./db` sieht innerhalb
|
||||
einer Transaktion den gleichen Bestand. DELETETABLE über `../a/db` und
|
||||
Rücknahme funktionieren ebenfalls.
|
||||
- [pfadaliase_teilen_transaktion_und_ruecknahme](../../../../crates/tb-runtime/src/isam/tests.rs#L696):
|
||||
absolute Pfade mit `..` und auf Unix auch ein Symlink teilen denselben Writer.
|
||||
- Separate CLI-Prozesse lesen anschließend genau einen Satz mit Nr=1 aus
|
||||
`a/db` und einen Satz mit Nr=2 aus `b/db`. Beide Dateien existieren.
|
||||
|
||||
## V02 — Prozessfristen: behoben
|
||||
|
||||
**Vorher:** Nur der besondere CLI-Unterprozess war geschützt; die direkten
|
||||
ISAM-Aufrufe im Korpustest und in Runtime-Tests konnten weiterhin hängen.
|
||||
|
||||
**Korrektur:** [Prozessfrist](../../../../tests/support/prozessfrist.rs) überwacht
|
||||
jeden Runtime-Datenbanktest über dessen TempDb sowie jeden Aufruf von
|
||||
[run_corpus_file](../../../../crates/tb-cli/tests/compat.rs#L359), einschließlich
|
||||
beider Korpusdurchläufe und des bewusst ignorierten Golden-Generators.
|
||||
Nach 30 Sekunden beendet ein unabhängiger Watchdog den gesamten betroffenen
|
||||
Testprozess mit Status 124. Beim regulären Abschluss wird die Frist aufgehoben.
|
||||
Der spezielle CLI-Unterprozess behält seine eigene Fünf-Sekunden-Frist.
|
||||
|
||||
**Nachweis:** `frist_beendet_blockierten_testprozess` startet einen Kind-Test,
|
||||
der absichtlich unbegrenzt blockiert. Dessen Watchdog beendet ihn mit Status 124
|
||||
und benannter Fehlermeldung; der Elternprozess prüft beides und besitzt zusätzlich
|
||||
eine unabhängige Fünf-Sekunden-Kill-Frist. Dieser Test besteht sowohl im Runtime-
|
||||
als auch im CLI-Testbinary. Keine Änderung am Produktcode zur Simulation nötig.
|
||||
|
||||
## V03 — Bindungen nach DELETETABLE: behoben
|
||||
|
||||
**Vorher:** Ein alter Handle konnte nach DELETETABLE unbemerkt eine interne
|
||||
Satztabelle ohne Layoutmetadaten wieder anlegen.
|
||||
|
||||
**Korrektur:** [tabelle_loeschen](../../../../crates/tb-runtime/src/isam.rs#L988)
|
||||
löst nach erfolgreicher Löschung alle Bindungen genau dieser Tabelle und
|
||||
Datenbank. Eine Rücknahme stellt den Bestand wieder her, öffnet aber keine
|
||||
zuvor geschlossenen Bindungen. Ein neues OPEN bindet den restaurierten Bestand.
|
||||
|
||||
**Nachweise:**
|
||||
|
||||
- [deletetable_loest_alle_betroffenen_bindungen](../../../../crates/tb-runtime/src/isam/tests.rs#L725):
|
||||
Beide alten Handles melden Fehler 52, eine andere Tabelle bleibt gebunden.
|
||||
Rücknahme und Wiederöffnung stellen Sätze und eindeutigen Index wieder her.
|
||||
Erneute Löschung und Neuanlage ergeben eine leere Tabelle ohne alten Index.
|
||||
- Die ursprüngliche CLI-Reproduktion meldet jetzt Fehler 52 beim INSERT über
|
||||
die alte Nummer und LOF=0 nach Neuanlage. RETRIEVE auf der leeren Tabelle
|
||||
meldet erwartungsgemäß Fehler 85; es gibt keinen Geistersatz.
|
||||
|
||||
## V04 — DELETE bei ausgeschöpftem Puffer: behoben
|
||||
|
||||
**Vorher:** DELETE speicherte Undo und entfernte den Satz trotz Puffergröße 0.
|
||||
|
||||
**Korrektur:** [satz_loeschen](../../../../crates/tb-runtime/src/isam.rs#L1123)
|
||||
prüft die alten Satzbytes gegen den noch verfügbaren Puffer, bevor Satz oder
|
||||
Indizes verändert beziehungsweise Undo hinzugefügt werden.
|
||||
|
||||
**Nachweise:**
|
||||
|
||||
- [delete_pufferfehler_erhaelt_saetze_indizes_und_cursor](../../../../crates/tb-runtime/src/isam/tests.rs#L760):
|
||||
Fehler 89 außerhalb und innerhalb einer Transaktion lässt Bestand, aktiven
|
||||
Index, Cursor und Undo unverändert. Bei exakt passender Größe gelingt ein
|
||||
DELETE; der nächste scheitert ohne Änderung. Rücknahme restauriert beide
|
||||
Sätze und gibt den Puffer wieder frei.
|
||||
- Ursprüngliche CLI-Reproduktion: `free=0`, `ERR=89`, `LOF=1`, `restored=1`.
|
||||
|
||||
## Szenarionachweise
|
||||
|
||||
| Delta-Szenario | Nachweis |
|
||||
|---|---|
|
||||
| Sequenzielles Schreiben und Lesen | `tests/compat/dateien.bas` |
|
||||
| Doppeltes Öffnen derselben Nummer | `isamdateinummern.bas`: Fehler 55 in beiden Richtungen |
|
||||
| Freie Dateinummer | `isamdateinummern.bas`: gemischte Modi und wiederbelegte Lücken |
|
||||
| ISAM belegt eine Dateinummer | `isamdateinummern.bas`: FREEFILE=2 |
|
||||
| Gleicher relativer Name nach Verzeichniswechsel | `isamidentitaet.bas` und separate Persistenzprüfung |
|
||||
| Neuanlage über einen noch nicht auflösbaren Symlink | `symlink_neuanlage_behaelt_die_dateiidentitaet` und CLI-Reproduktion |
|
||||
| Pfadalias in einer Transaktion | `isamidentitaet.bas`, Runtime-Pfadaliastest |
|
||||
| Bindungen nach Tabellenlöschung und Rücknahme | Runtime-DELETETABLE-Bindungstest |
|
||||
| Tabelle wird beim ersten Öffnen angelegt | `isamtabellen.bas` |
|
||||
| Abweichendes Satzlayout | `isamtabellen.bas`: Fehler 88 |
|
||||
| CLOSE lässt eine laufende Transaktion stehen | `close_beendet_keine_transaktion`, `isamopen.bas` |
|
||||
| Entfernte Tabelle | `isamtabellen.bas`, `isamopen.bas`: Fehler 82 |
|
||||
| Weitere Tabelle während einer Transaktion | `isamopen.bas` und CLI-Test mit Prozessfrist |
|
||||
| Rücknahme stellt den Bestand wieder her | CLI-Probe der Erstprüfung: INSERT/DELETE und bare ROLLBACK ergeben LOF=1 und LOC=0; Rücknahmepfad unverändert |
|
||||
| Rücknahme auf einen Sicherungspunkt | `isamtrans.bas`, `isamstruktur.bas`, Runtime-Strukturtests |
|
||||
| ROLLBACK ALL beendet die Transaktion | `isamtrans.bas`; CLI-Probe der Erstprüfung mit zwei Savepoints und anschließendem Fehler 5 |
|
||||
| Indexanlage nach Sicherungspunkt | `isamstruktur.bas`: Fehler 83; Runtime-Strukturtests |
|
||||
| Geschlossene Tabelle rücknehmen | `isamstruktur.bas`, Runtime-Tests für CLOSE und Struktur-Rücknahme |
|
||||
| Pufferfehler wird benannt | `isampuffer.bas`, `struktur_undo_prueft_puffer_vor_dem_loeschen` |
|
||||
| DELETE bei ausgeschöpftem Puffer | Neuer Runtime-DELETE-Puffertest und ursprüngliche CLI-Reproduktion |
|
||||
|
||||
## Prüfungen einschließlich erneuter Verifikation
|
||||
|
||||
- `cargo test -p tb-runtime --quiet`: 135 bestanden.
|
||||
- `cargo test -p tb-cli --test compat --quiet`: 16 bestanden, Golden-Generator ignoriert.
|
||||
- Erneut `cargo test --workspace --quiet`: **391 bestanden, 0 fehlgeschlagen,
|
||||
1 bewusst ignoriert**; einschließlich beider Watchdog-Selbsttests.
|
||||
- Formatprüfung aller geänderten Rust-Dateien und des neuen Testhelfers bestanden.
|
||||
- `git diff --check` und Whitespace-Prüfung der neuen Dateien bestanden.
|
||||
- `openspec validate isam-transaktionen-und-dateinummern --strict`: bestanden.
|
||||
- Ursprüngliche Reproduktionen und positive Zusatzproben erneut ausgeführt:
|
||||
Index-Neuanlage mit geändertem Aufbau und Rücknahme, RESET/COMMIT,
|
||||
Rücknahme über zwei Datenbankdateien, Programmende ohne COMMIT sowie
|
||||
Persistenz über neue CLI-Prozesse. Alle externen Proben mit fünf Sekunden Frist.
|
||||
|
||||
Keine GUI-, Windows-/Linux-Abnahme, Speichererschöpfung oder simulierten
|
||||
redb-I/O-Ausfälle ausgeführt. Keine neue Abhängigkeit, kein neues Datenbankformat.
|
||||
Die vier geänderten Anforderungen wurden in die Hauptspecs datei-eio und
|
||||
isam-datenbank synchronisiert; alle 15 Hauptspecs bestehen die strikte Validierung.
|
||||
Reference in New Issue
Block a user