Compare commits
10 Commits
01c1de5003
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 714662d212 | |||
| 7a17c65712 | |||
| 2012610615 | |||
| f2ae46c427 | |||
| 97d9f27800 | |||
| a1eb6aa0ab | |||
| 362468b895 | |||
| 24976f172d | |||
| c21d9367b3 | |||
| d80972d19f |
@@ -0,0 +1,591 @@
|
|||||||
|
Die RPG-Quellen und Include-Dateien liegen derzeit bewusst in einem
|
||||||
|
gemeinsamen Verzeichnis.
|
||||||
|
|
||||||
|
Serviceprogramm
|
||||||
|
|
||||||
|
Das Serviceprogramm heißt:
|
||||||
|
|
||||||
|
MEDDFNSRV
|
||||||
|
|
||||||
|
Es besteht derzeit aus den Modulen:
|
||||||
|
|
||||||
|
MEDDFNSRV
|
||||||
|
MEDDFNBLD
|
||||||
|
|
||||||
|
Die öffentlichen Exporte werden über die Binder-Source
|
||||||
|
|
||||||
|
MEDDFNSRVB
|
||||||
|
|
||||||
|
definiert.
|
||||||
|
|
||||||
|
Die öffentlichen Prozeduren sind:
|
||||||
|
|
||||||
|
MD_CreateMediaDefinition
|
||||||
|
MD_DeleteMediaDefinition
|
||||||
|
MD_RetrieveMediaDefinition
|
||||||
|
Builder
|
||||||
|
|
||||||
|
Der Builder erzeugt die Daten für eine Media Definition.
|
||||||
|
|
||||||
|
Aktuell wird das Format
|
||||||
|
|
||||||
|
TAPE0200
|
||||||
|
|
||||||
|
unterstützt.
|
||||||
|
|
||||||
|
Der Builder kann bereits Media Definitions mit:
|
||||||
|
|
||||||
|
mehreren Devices
|
||||||
|
mehreren Media Files
|
||||||
|
mehreren Volume Identifiers
|
||||||
|
|
||||||
|
erzeugen.
|
||||||
|
|
||||||
|
Parser
|
||||||
|
|
||||||
|
Der Parser befindet sich in:
|
||||||
|
|
||||||
|
meddfnprs.rpgle
|
||||||
|
|
||||||
|
Ziel des Parsers ist es, die von QSRRTVMD gelieferten
|
||||||
|
TAPE0200-Daten wieder in eine
|
||||||
|
|
||||||
|
MD_MediaDefinition_T
|
||||||
|
|
||||||
|
zu überführen.
|
||||||
|
|
||||||
|
Die Parserentwicklung erfolgt schrittweise.
|
||||||
|
|
||||||
|
Testprogramm
|
||||||
|
|
||||||
|
Das Testprogramm heißt:
|
||||||
|
|
||||||
|
MEDDFNTSTP
|
||||||
|
|
||||||
|
Das Testprogramm wird verwendet, um Media Definitions zu erzeugen
|
||||||
|
und anschließend deren Inhalt wieder auszulesen.
|
||||||
|
|
||||||
|
Die bevorzugte Teststrategie ist ein Roundtrip:
|
||||||
|
|
||||||
|
MD_MediaDefinition_T
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
MD_CreateMediaDefinition
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
*MEDDFN
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
MD_RetrieveMediaDefinition
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Parser
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
MD_MediaDefinition_T
|
||||||
|
|
||||||
|
Damit können die vom Parser gelieferten Werte mit den ursprünglich
|
||||||
|
erzeugten Werten verglichen werden.
|
||||||
|
|
||||||
|
Status
|
||||||
|
|
||||||
|
Der Builder für TAPE0200 ist funktionsfähig.
|
||||||
|
|
||||||
|
Das Erzeugen einer Media Definition mit mehreren Devices und
|
||||||
|
mehreren Volumes wurde erfolgreich getestet.
|
||||||
|
|
||||||
|
Ein realer paralleler Save auf eine Tape Library mit zwei Drives
|
||||||
|
wurde ebenfalls erfolgreich getestet.
|
||||||
|
|
||||||
|
Die Parser-Implementierung befindet sich derzeit in Entwicklung.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
# 2. `DESIGN.md`
|
||||||
|
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# MEDDFN – Design
|
||||||
|
|
||||||
|
|
||||||
|
## 1. Zweck
|
||||||
|
|
||||||
|
|
||||||
|
MEDDFN soll eine wiederverwendbare RPGLE-Schnittstelle für die
|
||||||
|
Arbeit mit IBM i Media Definitions (`*MEDDFN`) bereitstellen.
|
||||||
|
|
||||||
|
|
||||||
|
Der aktuelle Schwerpunkt liegt auf dem Format:
|
||||||
|
|
||||||
|
|
||||||
|
```text
|
||||||
|
TAPE0200
|
||||||
|
|
||||||
|
Das Projekt besteht aus einem Builder, einem Parser und einem
|
||||||
|
Serviceprogramm.
|
||||||
|
|
||||||
|
2. Architektur
|
||||||
|
MEDDFN
|
||||||
|
│
|
||||||
|
├── meddfn_h.rpgle
|
||||||
|
│ └── Allgemeine Datenstrukturen und Konstanten
|
||||||
|
│
|
||||||
|
├── meddfnap_h.rpgle
|
||||||
|
│ └── Datenstrukturen und Prototypen für IBM i API-Aufrufe
|
||||||
|
│
|
||||||
|
├── meddfnbld.rpgle
|
||||||
|
│ └── Builder
|
||||||
|
│
|
||||||
|
├── meddfnprs.rpgle
|
||||||
|
│ └── Parser
|
||||||
|
│
|
||||||
|
├── meddfnsrv.rpgle
|
||||||
|
│ └── Öffentliche Serviceprogramm-Prozeduren
|
||||||
|
│
|
||||||
|
├── meddfnsrvb.rpgle
|
||||||
|
│ └── Binder-Source
|
||||||
|
│
|
||||||
|
└── meddfntstp.rpgle
|
||||||
|
└── Testprogramm
|
||||||
|
3. Öffentliche Schnittstelle
|
||||||
|
|
||||||
|
Das Serviceprogramm MEDDFNSRV stellt drei öffentliche Prozeduren
|
||||||
|
bereit.
|
||||||
|
|
||||||
|
MD_CreateMediaDefinition
|
||||||
|
|
||||||
|
Erzeugt eine *MEDDFN-Media-Definition aus einer
|
||||||
|
MD_MediaDefinition_T.
|
||||||
|
|
||||||
|
MD_DeleteMediaDefinition
|
||||||
|
|
||||||
|
Löscht eine vorhandene Media Definition.
|
||||||
|
|
||||||
|
MD_RetrieveMediaDefinition
|
||||||
|
|
||||||
|
Liest eine vorhandene Media Definition über die IBM i API und
|
||||||
|
wandelt die zurückgegebenen Daten wieder in eine
|
||||||
|
MD_MediaDefinition_T um.
|
||||||
|
|
||||||
|
4. IBM i APIs
|
||||||
|
|
||||||
|
Für das Projekt werden unter anderem folgende IBM i APIs verwendet:
|
||||||
|
|
||||||
|
QSRCRTMD
|
||||||
|
QSRRTVMD
|
||||||
|
QSRRSLMD
|
||||||
|
QMHSNDPM
|
||||||
|
|
||||||
|
Die API-spezifischen Strukturen und Prototypen befinden sich in:
|
||||||
|
|
||||||
|
meddfnap_h.rpgle
|
||||||
|
|
||||||
|
Allgemeine MEDDFN-Datenstrukturen und Konstanten befinden sich in:
|
||||||
|
|
||||||
|
meddfn_h.rpgle
|
||||||
|
5. TAPE0200
|
||||||
|
|
||||||
|
Der aktuelle Builder erzeugt das Format:
|
||||||
|
|
||||||
|
TAPE0200
|
||||||
|
|
||||||
|
Der grundsätzliche Aufbau ist:
|
||||||
|
|
||||||
|
TAPE0200 Header
|
||||||
|
│
|
||||||
|
├── Device Definition
|
||||||
|
│ │
|
||||||
|
│ ├── Media File Definition
|
||||||
|
│ │ │
|
||||||
|
│ │ └── Volume Identifier Array
|
||||||
|
│ │
|
||||||
|
│ └── weitere Media Files
|
||||||
|
│
|
||||||
|
└── weitere Device Definitions
|
||||||
|
6. TAPE0200 Header
|
||||||
|
|
||||||
|
Die RPG-Struktur ist:
|
||||||
|
|
||||||
|
MD_Tape0200Header_T
|
||||||
|
|
||||||
|
Sie enthält unter anderem:
|
||||||
|
|
||||||
|
Maximum parallel device resources
|
||||||
|
Minimum parallel device resources
|
||||||
|
Offset zur ersten Device Definition
|
||||||
|
Anzahl der Device Definitions
|
||||||
|
Länge des Headers
|
||||||
|
Device Allocation
|
||||||
|
Save Format
|
||||||
|
7. Device Definition
|
||||||
|
|
||||||
|
Die RPG-Struktur ist:
|
||||||
|
|
||||||
|
MD_Tape0200DeviceDefinition_T
|
||||||
|
|
||||||
|
Eine Device Definition beschreibt ein Gerät bzw. eine Ressource,
|
||||||
|
beispielsweise:
|
||||||
|
|
||||||
|
TAPMLB01
|
||||||
|
TAPMLB02
|
||||||
|
|
||||||
|
Sie enthält unter anderem:
|
||||||
|
|
||||||
|
Offset zur nächsten Device Definition
|
||||||
|
Device Name
|
||||||
|
Offset zur ersten Media File Definition
|
||||||
|
Anzahl der Media File Definitions
|
||||||
|
Länge der Device Definition
|
||||||
|
8. Media File Definition
|
||||||
|
|
||||||
|
Die RPG-Struktur ist:
|
||||||
|
|
||||||
|
MD_Tape0200MediaFileDefinition_T
|
||||||
|
|
||||||
|
Sie enthält unter anderem:
|
||||||
|
|
||||||
|
Offset zur nächsten Media File Definition
|
||||||
|
Sequence Number
|
||||||
|
Offset zum Volume Identifier Array
|
||||||
|
Anzahl der Volume Identifier
|
||||||
|
Länge eines Volume Identifiers
|
||||||
|
Starting Volume Array Element
|
||||||
|
Länge der Media File Definition
|
||||||
|
Starting Position in File
|
||||||
|
9. Volume Identifier
|
||||||
|
|
||||||
|
Volume Identifier haben derzeit eine feste Länge von:
|
||||||
|
|
||||||
|
6 Bytes
|
||||||
|
|
||||||
|
Die Konstante dafür ist:
|
||||||
|
|
||||||
|
MD_VOLUME_ID_LENGTH
|
||||||
|
|
||||||
|
Beispiele:
|
||||||
|
|
||||||
|
VOL001
|
||||||
|
VOL002
|
||||||
|
VOL003
|
||||||
|
|
||||||
|
Die Volume Identifier werden nach der zugehörigen Media File
|
||||||
|
Definition im Builder-Buffer abgelegt.
|
||||||
|
|
||||||
|
10. Alignment
|
||||||
|
|
||||||
|
Daten werden auf 4-Byte-Grenzen ausgerichtet.
|
||||||
|
|
||||||
|
Dafür wird verwendet:
|
||||||
|
|
||||||
|
MD_AlignLength()
|
||||||
|
|
||||||
|
Beispiele:
|
||||||
|
|
||||||
|
6 -> 8
|
||||||
|
12 -> 12
|
||||||
|
13 -> 16
|
||||||
|
11. Builder Context
|
||||||
|
|
||||||
|
Der Builder verwendet:
|
||||||
|
|
||||||
|
MD_BuilderContext_T
|
||||||
|
|
||||||
|
Der Builder schreibt die erzeugten Strukturen schrittweise in einen
|
||||||
|
gemeinsamen Buffer.
|
||||||
|
|
||||||
|
Aktuelle Builder-Prozeduren:
|
||||||
|
|
||||||
|
MD_BuildCreateBuffer
|
||||||
|
MD_BuildTape0200Header
|
||||||
|
MD_BuildTape0200Device
|
||||||
|
MD_BuildTape0200Media
|
||||||
|
MD_BuildTape0200VolumeArray
|
||||||
|
12. Builder-Reihenfolge
|
||||||
|
|
||||||
|
Der Aufbau eines TAPE0200 Buffers erfolgt in dieser Reihenfolge:
|
||||||
|
|
||||||
|
MD_BuildCreateBuffer
|
||||||
|
│
|
||||||
|
├── MD_BuildTape0200Header
|
||||||
|
│
|
||||||
|
└── für jedes Device
|
||||||
|
│
|
||||||
|
└── MD_BuildTape0200Device
|
||||||
|
│
|
||||||
|
├── MD_BuildTape0200Media
|
||||||
|
│
|
||||||
|
├── MD_BuildTape0200VolumeArray
|
||||||
|
│
|
||||||
|
└── weitere Media Files
|
||||||
|
13. Offset-Berechnung
|
||||||
|
|
||||||
|
Die TAPE0200-Strukturen enthalten relative Offsets.
|
||||||
|
|
||||||
|
Die Offsets werden beim Aufbau des Buffers anhand der aktuellen
|
||||||
|
Bufferposition und der Größe der jeweiligen Strukturen berechnet.
|
||||||
|
|
||||||
|
Besonders wichtig ist die korrekte Behandlung von:
|
||||||
|
|
||||||
|
Device Definitions
|
||||||
|
Media File Definitions
|
||||||
|
Volume Identifier Arrays
|
||||||
|
4-Byte-Alignment
|
||||||
|
14. StartingPositionInFile
|
||||||
|
|
||||||
|
Derzeit wird:
|
||||||
|
|
||||||
|
*ALL'0'
|
||||||
|
|
||||||
|
verwendet.
|
||||||
|
|
||||||
|
Beispiel:
|
||||||
|
|
||||||
|
Media0200.StartingPositionInFile = *ALL'0';
|
||||||
|
|
||||||
|
Die Business-Datenstruktur stellt derzeit noch nicht alle möglichen
|
||||||
|
API-Optionen für dieses Feld zur Verfügung.
|
||||||
|
|
||||||
|
15. Device Allocation
|
||||||
|
|
||||||
|
Die Konstanten befinden sich in:
|
||||||
|
|
||||||
|
meddfn_h.rpgle
|
||||||
|
|
||||||
|
Aktuell:
|
||||||
|
|
||||||
|
MD_DeviceAllocateAll
|
||||||
|
MD_DeviceAllocateOne
|
||||||
|
MD_DeviceAllocateMinimum
|
||||||
|
16. Save Format
|
||||||
|
|
||||||
|
Die Konstanten befinden sich ebenfalls in:
|
||||||
|
|
||||||
|
meddfn_h.rpgle
|
||||||
|
|
||||||
|
Aktuell:
|
||||||
|
|
||||||
|
MD_SaveFormatAuto
|
||||||
|
MD_SaveFormatSerial
|
||||||
|
MD_SaveFormatParallel
|
||||||
|
|
||||||
|
Für einen parallelen Save wird verwendet:
|
||||||
|
|
||||||
|
MediaDefinition.SaveFormat =
|
||||||
|
MD_SaveFormatParallel;
|
||||||
|
17. Fehlerbehandlung
|
||||||
|
|
||||||
|
API-Fehler werden über:
|
||||||
|
|
||||||
|
MD_APIError_T
|
||||||
|
|
||||||
|
behandelt.
|
||||||
|
|
||||||
|
Die zentrale Prüfung erfolgt über:
|
||||||
|
|
||||||
|
MD_CheckApiError()
|
||||||
|
|
||||||
|
Nachrichten werden über:
|
||||||
|
|
||||||
|
MD_SendMessage()
|
||||||
|
MD_SendEscape()
|
||||||
|
|
||||||
|
an den Aufrufer weitergegeben.
|
||||||
|
|
||||||
|
MD_SendEscape() verwendet intern MD_SendMessage() mit dem
|
||||||
|
Message Type Escape.
|
||||||
|
|
||||||
|
18. Parser
|
||||||
|
|
||||||
|
Der Parser befindet sich in:
|
||||||
|
|
||||||
|
meddfnprs.rpgle
|
||||||
|
|
||||||
|
Seine Aufgabe ist es, die von QSRRTVMD gelieferten Daten wieder
|
||||||
|
in die fachliche Struktur:
|
||||||
|
|
||||||
|
MD_MediaDefinition_T
|
||||||
|
|
||||||
|
zu überführen.
|
||||||
|
|
||||||
|
Der Parser soll die API-Daten anhand ihrer Header, Devices,
|
||||||
|
Media Files und Volume Arrays interpretieren.
|
||||||
|
|
||||||
|
Grundprinzip:
|
||||||
|
|
||||||
|
QSRRTVMD Receiver Buffer
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
TAPE0200 Header
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Device Definitions
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Media File Definitions
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Volume Identifier Arrays
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
MD_MediaDefinition_T
|
||||||
|
19. Parser-Teststrategie
|
||||||
|
|
||||||
|
Der Parser wird zunächst mit Media Definitions getestet, die durch
|
||||||
|
den eigenen Builder erzeugt wurden.
|
||||||
|
|
||||||
|
Teststufe 1
|
||||||
|
1 Device
|
||||||
|
└── 1 Media File
|
||||||
|
└── 1 Volume
|
||||||
|
Teststufe 2
|
||||||
|
1 Device
|
||||||
|
└── 1 Media File
|
||||||
|
├── VOL001
|
||||||
|
└── VOL002
|
||||||
|
Teststufe 3
|
||||||
|
1 Device
|
||||||
|
├── Media File 1
|
||||||
|
│ ├── VOL001
|
||||||
|
│ └── VOL002
|
||||||
|
│
|
||||||
|
└── Media File 2
|
||||||
|
├── VOL003
|
||||||
|
└── VOL004
|
||||||
|
Teststufe 4
|
||||||
|
2 Devices
|
||||||
|
|
||||||
|
|
||||||
|
TAPMLB01
|
||||||
|
└── Media File 1
|
||||||
|
├── VOL001
|
||||||
|
└── VOL002
|
||||||
|
|
||||||
|
|
||||||
|
TAPMLB02
|
||||||
|
└── Media File 1
|
||||||
|
├── VOL003
|
||||||
|
└── VOL004
|
||||||
|
Teststufe 5
|
||||||
|
|
||||||
|
Test mit einer realen Tape Library und mehreren Drives.
|
||||||
|
|
||||||
|
Ein paralleler Save auf zwei Tapes wurde erfolgreich getestet.
|
||||||
|
|
||||||
|
Dabei wurde festgestellt, dass ein installierter BRMS Exit Point
|
||||||
|
|
||||||
|
QIBM_QTA_TAPE_TMS
|
||||||
|
|
||||||
|
mit dem Exit-Programm
|
||||||
|
|
||||||
|
Q1ARTMS
|
||||||
|
|
||||||
|
das Verhalten beeinflussen kann.
|
||||||
|
|
||||||
|
Nach temporärem Entfernen des Exit Points konnte der parallele Save
|
||||||
|
auf zwei Tapes erfolgreich durchgeführt werden.
|
||||||
|
|
||||||
|
20. Serviceprogramm
|
||||||
|
|
||||||
|
Das Serviceprogramm heißt:
|
||||||
|
|
||||||
|
MEDDFNSRV
|
||||||
|
|
||||||
|
Aktuell werden folgende Module eingebunden:
|
||||||
|
|
||||||
|
MEDDFNSRV
|
||||||
|
MEDDFNBLD
|
||||||
|
|
||||||
|
Die Binder-Source heißt:
|
||||||
|
|
||||||
|
MEDDFNSRVB
|
||||||
|
|
||||||
|
Die Binder-Source exportiert:
|
||||||
|
|
||||||
|
MD_CreateMediaDefinition
|
||||||
|
MD_DeleteMediaDefinition
|
||||||
|
MD_RetrieveMediaDefinition
|
||||||
|
|
||||||
|
Beim Erstellen des Serviceprogramms wird:
|
||||||
|
|
||||||
|
TGTRLS(*CURRENT)
|
||||||
|
|
||||||
|
verwendet.
|
||||||
|
|
||||||
|
21. Entwicklungsumgebung
|
||||||
|
|
||||||
|
Das Projekt wird aktuell auf PUB400.com entwickelt.
|
||||||
|
|
||||||
|
Verwendet werden:
|
||||||
|
|
||||||
|
VS Code
|
||||||
|
Code for IBM i
|
||||||
|
IFS
|
||||||
|
Git
|
||||||
|
Gitea
|
||||||
|
|
||||||
|
Die Quellen liegen im IFS als UTF-8-Dateien vor.
|
||||||
|
|
||||||
|
Die RPG-Compile-Actions verwenden:
|
||||||
|
|
||||||
|
TGTCCSID(*JOB)
|
||||||
|
|
||||||
|
und:
|
||||||
|
|
||||||
|
TGTRLS(*CURRENT)
|
||||||
|
|
||||||
|
Die Include-Dateien liegen derzeit im selben Verzeichnis wie die
|
||||||
|
RPG-Quellen.
|
||||||
|
|
||||||
|
Sie werden beispielsweise über:
|
||||||
|
|
||||||
|
/COPY './meddfn_h.rpgle'
|
||||||
|
/COPY './meddfnap_h.rpgle'
|
||||||
|
|
||||||
|
eingebunden.
|
||||||
|
|
||||||
|
22. Entwicklungsgrundsätze
|
||||||
|
Bestehende Strukturen wiederverwenden
|
||||||
|
|
||||||
|
Neue Funktionen sollen nach Möglichkeit die vorhandenen
|
||||||
|
Datenstrukturen und Prozeduren verwenden.
|
||||||
|
|
||||||
|
Keine parallelen Varianten derselben Datenstruktur ohne
|
||||||
|
Notwendigkeit.
|
||||||
|
|
||||||
|
Öffentliche Schnittstelle klein halten
|
||||||
|
|
||||||
|
Das Serviceprogramm stellt nur die benötigten öffentlichen
|
||||||
|
Prozeduren bereit.
|
||||||
|
|
||||||
|
Interne Builder- und Parser-Prozeduren werden nicht unnötig
|
||||||
|
exportiert.
|
||||||
|
|
||||||
|
Builder und Parser getrennt halten
|
||||||
|
|
||||||
|
Der Builder erzeugt API-Daten.
|
||||||
|
|
||||||
|
Der Parser interpretiert API-Daten.
|
||||||
|
|
||||||
|
Beide Komponenten sollen unabhängig voneinander bleiben.
|
||||||
|
|
||||||
|
API-Strukturen und Business-Strukturen trennen
|
||||||
|
|
||||||
|
Die API-Strukturen in meddfnap_h.rpgle beschreiben die
|
||||||
|
IBM-i-API.
|
||||||
|
|
||||||
|
Die fachlichen Strukturen in meddfn_h.rpgle beschreiben das
|
||||||
|
interne Datenmodell.
|
||||||
|
|
||||||
|
Diese Trennung soll erhalten bleiben.
|
||||||
|
|
||||||
|
Git als gemeinsame Quelle
|
||||||
|
|
||||||
|
Der aktuelle Code im Git-Repository ist die technische Quelle der
|
||||||
|
Wahrheit.
|
||||||
|
|
||||||
|
Architekturentscheidungen und wichtige Besonderheiten werden in
|
||||||
|
dieser Datei dokumentiert, damit sie auch bei der Verwendung von
|
||||||
|
Codex in VS Code verfügbar sind.
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# MEDDFN
|
||||||
|
|
||||||
|
MEDDFN ist ein IBM i RPGLE-Projekt zur Erstellung, Löschung und
|
||||||
|
Abfrage von IBM i Media Definitionen (`*MEDDFN`).
|
||||||
|
|
||||||
|
Das Projekt verwendet die IBM i APIs für Media Definitions und
|
||||||
|
implementiert einen Builder sowie einen Parser für das
|
||||||
|
`TAPE0200`-Format.
|
||||||
|
|
||||||
|
## Ziel
|
||||||
|
|
||||||
|
Das Projekt soll die Arbeit mit `*MEDDFN`-Objekten über ein
|
||||||
|
wiederverwendbares Serviceprogramm ermöglichen.
|
||||||
|
|
||||||
|
Das Serviceprogramm stellt aktuell drei öffentliche Prozeduren bereit:
|
||||||
|
|
||||||
|
- `MD_CreateMediaDefinition`
|
||||||
|
- `MD_DeleteMediaDefinition`
|
||||||
|
- `MD_RetrieveMediaDefinition`
|
||||||
|
|
||||||
|
## Projektstruktur
|
||||||
|
|
||||||
|
Das Projekt wird als IFS-Projekt mit VS Code und Code for IBM i
|
||||||
|
entwickelt.
|
||||||
|
|
||||||
|
```text
|
||||||
|
MEDDFN/
|
||||||
|
├── .vscode/
|
||||||
|
├── meddfn_h.rpgle
|
||||||
|
├── meddfnap_h.rpgle
|
||||||
|
├── meddfnbld.rpgle
|
||||||
|
├── meddfnprs.rpgle
|
||||||
|
├── meddfnsrv.rpgle
|
||||||
|
├── meddfntstp.rpgle
|
||||||
|
├── meddfnsrvb.rpgle
|
||||||
|
├── README.md
|
||||||
|
└── DESIGN.md
|
||||||
|
|
||||||
+11
-8
@@ -36,8 +36,11 @@
|
|||||||
ctl-opt
|
ctl-opt
|
||||||
option(*srcstmt:*nodebugio) nomain ;
|
option(*srcstmt:*nodebugio) nomain ;
|
||||||
|
|
||||||
/COPY GOSCH1/MEDDFN,MEDDFN_H
|
/COPY './meddfn_h.rpgle'
|
||||||
/COPY GOSCH1/MEDDFN,MEDDFNAP_H
|
/COPY './meddfnap_h.rpgle'
|
||||||
|
|
||||||
|
// /COPY GOSCH1/MEDDFN,MEDDFN_H
|
||||||
|
// /COPY GOSCH1/MEDDFN,MEDDFNAP_H
|
||||||
|
|
||||||
|
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
@@ -148,7 +151,7 @@ dcl-proc MD_BuildCreateBuffer export;
|
|||||||
MediaDefinition);
|
MediaDefinition);
|
||||||
|
|
||||||
|
|
||||||
for DeviceIndex = 1 to MediaDefinition.NumberOfDevices;
|
for DeviceIndex = 1 to MediaDefinition.NumberOfDevices;
|
||||||
|
|
||||||
|
|
||||||
MD_BuildTape0200Device(
|
MD_BuildTape0200Device(
|
||||||
@@ -517,20 +520,20 @@ dcl-proc MD_BuildTape0200Media;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if MediaIndex < MediaDevice.NumberOfMediaFiles;
|
if MediaIndex < MediaDevice.NumberOfMediaFiles;
|
||||||
|
|
||||||
Media0200.OffsetToNextMediaFileDefinition =
|
Media0200.OffsetToNextMediaFileDefinition =
|
||||||
BuilderContext.BufferLength
|
BuilderContext.BufferLength
|
||||||
+ %size(MD_Tape0200MediaFileDefinition_T)
|
+ %size(MD_Tape0200MediaFileDefinition_T)
|
||||||
+ (MD_AlignLength(
|
+ (MD_AlignLength(
|
||||||
MediaFile.NumberOfVolumeIdentifiers
|
MediaFile.NumberOfVolumeIdentifiers
|
||||||
* MD_VOLUME_ID_LENGTH));
|
* MD_VOLUME_ID_LENGTH));
|
||||||
|
|
||||||
else;
|
else;
|
||||||
|
|
||||||
Media0200.OffsetToNextMediaFileDefinition = 0;
|
Media0200.OffsetToNextMediaFileDefinition = 0;
|
||||||
|
|
||||||
endif;
|
endif;
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
**FREE
|
||||||
|
//=====================================================================
|
||||||
|
//
|
||||||
|
// Project.....: MEDDFN
|
||||||
|
//
|
||||||
|
// Member......: MEDDFNPR
|
||||||
|
//
|
||||||
|
// Description.: Public prototypes for MEDDFN service procedures.
|
||||||
|
//
|
||||||
|
//=====================================================================
|
||||||
|
|
||||||
|
dcl-pr MD_CreateMediaDefinition;
|
||||||
|
|
||||||
|
MediaDefinition
|
||||||
|
likeds(MD_MediaDefinition_T) const;
|
||||||
|
|
||||||
|
end-pr;
|
||||||
|
|
||||||
|
dcl-pr MD_DeleteMediaDefinition;
|
||||||
|
|
||||||
|
MediaDefinition
|
||||||
|
likeds(MD_MediaDefinition_T) const;
|
||||||
|
|
||||||
|
end-pr;
|
||||||
|
|
||||||
|
dcl-pr MD_RetrieveMediaDefinition;
|
||||||
|
|
||||||
|
MediaDefinition
|
||||||
|
likeds(MD_MediaDefinition_T);
|
||||||
|
|
||||||
|
end-pr;
|
||||||
+244
-93
@@ -1,95 +1,246 @@
|
|||||||
**FREE
|
**free
|
||||||
//========================================================================
|
//========================================================================
|
||||||
//
|
//
|
||||||
// Media Definition Parser
|
// Media Definition Parser
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
ctl-opt
|
ctl-opt
|
||||||
option(*srcstmt:*nodebugio) nomain ;
|
option(*srcstmt:*nodebugio) nomain;
|
||||||
|
|
||||||
/COPY GOSCH1/MEDDFN,MEDDFN_H
|
/COPY './meddfn_h.rpgle'
|
||||||
/COPY GOSCH1/MEDDFN,MEDDFNAP_H
|
/COPY './meddfnap_h.rpgle'
|
||||||
|
|
||||||
|
// /COPY GOSCH1/MEDDFN,MEDDFN_H
|
||||||
|
// /COPY GOSCH1/MEDDFN,MEDDFNAP_H
|
||||||
//=====================================================================
|
|
||||||
//
|
dcl-pr MD_ParseRetrieveBuffer;
|
||||||
// MD_RetrieveMediaDefinition
|
|
||||||
//
|
ReceiverBuffer
|
||||||
// Retrieves a TAPE0200 media definition from IBM i.
|
char(32767) const
|
||||||
//
|
options(*varsize);
|
||||||
//=====================================================================
|
|
||||||
|
MediaDefinition
|
||||||
dcl-proc MD_RetrieveMediaDefinition export;
|
likeds(MD_MediaDefinition_T);
|
||||||
|
end-pr;
|
||||||
dcl-pi *n;
|
|
||||||
|
//=====================================================================
|
||||||
MediaDefinition
|
//
|
||||||
likeds(MD_MediaDefinition_T);
|
// MD_ParseRetrieveBuffer
|
||||||
|
//
|
||||||
end-pi;
|
// Parses a retrieved TAPE0200 buffer.
|
||||||
|
//
|
||||||
|
// Currently supported:
|
||||||
dcl-ds QualifiedObject
|
// - TAPE0200 header
|
||||||
likeds(MD_QualifiedObjectName_T);
|
// - TAPE0200 device definitions
|
||||||
|
//
|
||||||
dcl-ds Receiver
|
//=====================================================================
|
||||||
likeds(MD_ApiReceiverBuffer_T);
|
|
||||||
|
dcl-proc MD_ParseRetrieveBuffer;
|
||||||
dcl-ds ApiError
|
|
||||||
likeds(MD_APIError_T);
|
dcl-pi *n;
|
||||||
|
|
||||||
dcl-s ReceiverLength int(10);
|
ReceiverBuffer
|
||||||
|
char(32767) const
|
||||||
//---------------------------------------------------------------
|
options(*varsize);
|
||||||
// Qualified media definition name
|
|
||||||
//---------------------------------------------------------------
|
MediaDefinition
|
||||||
|
likeds(MD_MediaDefinition_T);
|
||||||
QualifiedObject.ObjectName =
|
end-pi;
|
||||||
MediaDefinition.MediaDefinitionName;
|
|
||||||
|
dcl-ds Header
|
||||||
QualifiedObject.LibraryName =
|
likeds(MD_Tape0200Header_T);
|
||||||
MediaDefinition.LibraryName;
|
|
||||||
|
dcl-ds Device
|
||||||
|
likeds(MD_Tape0200DeviceDefinition_T);
|
||||||
//---------------------------------------------------------------
|
|
||||||
// Initialize receiver buffer and error structure
|
dcl-ds MediaFile
|
||||||
//---------------------------------------------------------------
|
likeds(MD_Tape0200MediaFileDefinition_T);
|
||||||
|
|
||||||
clear Receiver;
|
dcl-s MediaOffset int(10);
|
||||||
clear ApiError;
|
|
||||||
|
dcl-s DeviceOffset int(10);
|
||||||
ApiError.BytesProvided =
|
dcl-s DeviceIndex int(10);
|
||||||
%size(ApiError);
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
ReceiverLength = %size(Receiver.Data);
|
// Initialize result
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// Retrieve TAPE0200 definition
|
|
||||||
//---------------------------------------------------------------
|
clear MediaDefinition;
|
||||||
|
|
||||||
QSRRTVMD(
|
//---------------------------------------------------------------
|
||||||
QualifiedObject :
|
// TAPE0200 Header
|
||||||
Receiver.Data :
|
//---------------------------------------------------------------
|
||||||
ReceiverLength :
|
|
||||||
'TAPE0200' :
|
Header =
|
||||||
ApiError);
|
%subst(
|
||||||
|
ReceiverBuffer :
|
||||||
//---------------------------------------------------------------
|
1 :
|
||||||
// Check API error
|
%size(Header));
|
||||||
//---------------------------------------------------------------
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
if ApiError.BytesAvailable > 0;
|
// Header -> Media Definition
|
||||||
|
//---------------------------------------------------------------
|
||||||
// zun�chst nur Fehler zur�ckgeben/anzeigen
|
|
||||||
|
MediaDefinition.MaximumParallelResources =
|
||||||
endif;
|
Header.MaximumParallelDeviceResources;
|
||||||
|
|
||||||
// MD_CheckApiError(ApiError);
|
MediaDefinition.MinimumParallelResources =
|
||||||
|
Header.MinimumParallelDeviceResources;
|
||||||
|
|
||||||
|
MediaDefinition.NumberOfDevices =
|
||||||
|
Header.NumberOfDeviceDefinitions;
|
||||||
|
|
||||||
|
MediaDefinition.DeviceAllocation =
|
||||||
|
Header.DeviceAllocation;
|
||||||
|
|
||||||
|
MediaDefinition.SaveFormat =
|
||||||
|
Header.SaveFormat;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Device Definitions
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
|
DeviceOffset =
|
||||||
|
Header.OffsetToFirstDeviceDefinition;
|
||||||
|
|
||||||
|
for DeviceIndex = 1
|
||||||
|
to Header.NumberOfDeviceDefinitions;
|
||||||
|
|
||||||
|
Device =
|
||||||
|
%subst(
|
||||||
|
ReceiverBuffer :
|
||||||
|
DeviceOffset + 1 :
|
||||||
|
%size(Device));
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
// Device -> Media Definition
|
||||||
|
//------------------------------------------------------------
|
||||||
|
|
||||||
|
MediaDefinition.Device(DeviceIndex).DeviceName =
|
||||||
|
Device.DeviceName;
|
||||||
|
|
||||||
|
MediaDefinition.Device(DeviceIndex).NumberOfMediaFiles =
|
||||||
|
Device.NumberOfMediaFileDefinitions;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// First Media File
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
|
if Device.NumberOfMediaFileDefinitions > 0;
|
||||||
|
|
||||||
|
MediaOffset =
|
||||||
|
Device.OffsetToFirstMediaFileDefinition;
|
||||||
|
|
||||||
|
MediaFile =
|
||||||
|
%subst(
|
||||||
|
ReceiverBuffer :
|
||||||
|
MediaOffset + 1 :
|
||||||
|
%size(MediaFile));
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
// Media File -> Media Definition
|
||||||
|
//------------------------------------------------------------
|
||||||
|
|
||||||
|
MediaDefinition.Device(DeviceIndex)
|
||||||
|
.MediaFile(1)
|
||||||
|
.SequenceNumber =
|
||||||
|
MediaFile.SequenceNumber;
|
||||||
|
|
||||||
|
MediaDefinition.Device(DeviceIndex)
|
||||||
|
.MediaFile(1)
|
||||||
|
.StartingPositionInFile =
|
||||||
|
MediaFile.StartingPositionInFile;
|
||||||
|
|
||||||
|
MediaDefinition.Device(DeviceIndex)
|
||||||
|
.MediaFile(1)
|
||||||
|
.NumberOfVolumeIdentifiers =
|
||||||
|
MediaFile.NumberOfVolumeIdentifiers;
|
||||||
|
endif;
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
// Next device
|
||||||
|
//------------------------------------------------------------
|
||||||
|
|
||||||
|
if Device.OffsetToNextDeviceDefinition > 0;
|
||||||
|
|
||||||
|
DeviceOffset +=
|
||||||
|
Device.OffsetToNextDeviceDefinition;
|
||||||
|
endif;
|
||||||
|
endfor;
|
||||||
end-proc;
|
end-proc;
|
||||||
|
|
||||||
|
//=====================================================================
|
||||||
|
//
|
||||||
|
// MD_RetrieveMediaDefinition
|
||||||
|
//
|
||||||
|
// Retrieves a TAPE0200 media definition from IBM i.
|
||||||
|
//
|
||||||
|
//=====================================================================
|
||||||
|
|
||||||
|
dcl-proc MD_RetrieveMediaDefinition export;
|
||||||
|
|
||||||
|
dcl-pi *n;
|
||||||
|
|
||||||
|
MediaDefinition
|
||||||
|
likeds(MD_MediaDefinition_T);
|
||||||
|
end-pi;
|
||||||
|
|
||||||
|
dcl-ds QualifiedObject
|
||||||
|
likeds(MD_QualifiedObjectName_T);
|
||||||
|
|
||||||
|
dcl-ds Receiver
|
||||||
|
likeds(MD_ApiReceiverBuffer_T);
|
||||||
|
|
||||||
|
dcl-ds ApiError
|
||||||
|
likeds(MD_APIError_T);
|
||||||
|
|
||||||
|
dcl-s ReceiverLength int(10);
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Qualified media definition name
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
|
QualifiedObject.ObjectName =
|
||||||
|
MediaDefinition.MediaDefinitionName;
|
||||||
|
|
||||||
|
QualifiedObject.LibraryName =
|
||||||
|
MediaDefinition.LibraryName;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Initialize receiver buffer and error structure
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
|
clear Receiver;
|
||||||
|
clear ApiError;
|
||||||
|
|
||||||
|
ApiError.BytesProvided =
|
||||||
|
%size(ApiError);
|
||||||
|
|
||||||
|
ReceiverLength = %size(Receiver.Data);
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Retrieve TAPE0200 definition
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
|
QSRRTVMD(
|
||||||
|
QualifiedObject :
|
||||||
|
Receiver.Data :
|
||||||
|
ReceiverLength :
|
||||||
|
'TAPE0200' :
|
||||||
|
ApiError);
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Check API error
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
|
if ApiError.BytesAvailable > 0;
|
||||||
|
|
||||||
|
// zun�chst nur Fehler zur�ckgeben/anzeigen
|
||||||
|
endif;
|
||||||
|
|
||||||
|
// MD_CheckApiError(ApiError);
|
||||||
|
end-proc;
|
||||||
+5
-2
@@ -28,8 +28,11 @@ ctl-opt
|
|||||||
//
|
//
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
|
|
||||||
/copy GOSCH1/MEDDFN,MEDDFN_H
|
/COPY './meddfn_h.rpgle'
|
||||||
/copy GOSCH1/MEDDFN,MEDDFNAP_H
|
/COPY './meddfnap_h.rpgle'
|
||||||
|
|
||||||
|
// /copy GOSCH1/MEDDFN,MEDDFN_H
|
||||||
|
// /copy GOSCH1/MEDDFN,MEDDFNAP_H
|
||||||
|
|
||||||
|
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
STRPGMEXP PGMLVL(*CURRENT)
|
||||||
|
|
||||||
|
EXPORT SYMBOL('MD_CREATEMEDIADEFINITION')
|
||||||
|
EXPORT SYMBOL('MD_DELETEMEDIADEFINITION')
|
||||||
|
EXPORT SYMBOL('MD_RETRIEVEMEDIADEFINITION')
|
||||||
|
|
||||||
|
ENDPGMEXP
|
||||||
+22
-18
@@ -21,8 +21,12 @@ ctl-opt
|
|||||||
// actgrp(*new)
|
// actgrp(*new)
|
||||||
option(*srcstmt:*nodebugio);
|
option(*srcstmt:*nodebugio);
|
||||||
|
|
||||||
/copy GOSCH1/MEDDFN,MEDDFN_H
|
|
||||||
/copy GOSCH1/MEDDFN,MEDDFNPR
|
/COPY './meddfn_h.rpgle'
|
||||||
|
/COPY './meddfnap_h.rpgle'
|
||||||
|
|
||||||
|
// /copy GOSCH1/MEDDFN,MEDDFN_H
|
||||||
|
// /copy GOSCH1/MEDDFN,MEDDFNPR
|
||||||
|
|
||||||
dcl-ds MediaDefinition
|
dcl-ds MediaDefinition
|
||||||
likeds(MD_MediaDefinition_T);
|
likeds(MD_MediaDefinition_T);
|
||||||
@@ -82,35 +86,35 @@ dcl-proc BuildTestDefinition;
|
|||||||
MediaDefinition.TextDescription = 'Test MEDDFN';
|
MediaDefinition.TextDescription = 'Test MEDDFN';
|
||||||
|
|
||||||
MediaDefinition.MaximumParallelResources = 2;
|
MediaDefinition.MaximumParallelResources = 2;
|
||||||
MediaDefinition.MinimumParallelResources = 2;
|
MediaDefinition.MinimumParallelResources = 2;
|
||||||
|
|
||||||
MediaDefinition.DeviceAllocation = MD_DeviceAllocateAll;
|
MediaDefinition.DeviceAllocation = MD_DeviceAllocateAll;
|
||||||
MediaDefinition.SaveFormat = MD_SaveFormatParallel;
|
MediaDefinition.SaveFormat = MD_SaveFormatParallel;
|
||||||
|
|
||||||
MediaDefinition.NumberOfDevices = 2;
|
MediaDefinition.NumberOfDevices = 2;
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// Device 1 / Resource 1
|
// Device 1 / Resource 1
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
MediaDefinition.Device(1).DeviceName = 'TAPMLBBRMS';
|
MediaDefinition.Device(1).DeviceName = 'TAPMLBBRMS';
|
||||||
|
|
||||||
MediaDefinition.Device(1).NumberOfMediaFiles = 1;
|
MediaDefinition.Device(1).NumberOfMediaFiles = 1;
|
||||||
|
|
||||||
MediaDefinition.Device(1)
|
MediaDefinition.Device(1)
|
||||||
.MediaFile(1)
|
.MediaFile(1)
|
||||||
.SequenceNumber = 0;
|
.SequenceNumber = 0;
|
||||||
|
|
||||||
MediaDefinition.Device(1)
|
MediaDefinition.Device(1)
|
||||||
.MediaFile(1)
|
.MediaFile(1)
|
||||||
.StartingPositionInFile = *ALL'0';
|
.StartingPositionInFile = *ALL'0';
|
||||||
|
|
||||||
MediaDefinition.Device(1)
|
MediaDefinition.Device(1)
|
||||||
.MediaFile(1)
|
.MediaFile(1)
|
||||||
.NumberOfVolumeIdentifiers = 1;
|
.NumberOfVolumeIdentifiers = 1;
|
||||||
|
|
||||||
MediaDefinition.Device(1)
|
MediaDefinition.Device(1)
|
||||||
.MediaFile(1)
|
.MediaFile(1)
|
||||||
.VolumeIdentifier(1)
|
.VolumeIdentifier(1)
|
||||||
.VolumeIdentifier = 'DAK066';
|
.VolumeIdentifier = 'DAK066';
|
||||||
@@ -120,23 +124,23 @@ MediaDefinition.Device(1)
|
|||||||
// Device 2 / Resource 2
|
// Device 2 / Resource 2
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
MediaDefinition.Device(2).DeviceName = 'TAPMLBBRMS';
|
MediaDefinition.Device(2).DeviceName = 'TAPMLBBRMS';
|
||||||
|
|
||||||
MediaDefinition.Device(2).NumberOfMediaFiles = 1;
|
MediaDefinition.Device(2).NumberOfMediaFiles = 1;
|
||||||
|
|
||||||
MediaDefinition.Device(2)
|
MediaDefinition.Device(2)
|
||||||
.MediaFile(1)
|
.MediaFile(1)
|
||||||
.SequenceNumber = 0;
|
.SequenceNumber = 0;
|
||||||
|
|
||||||
MediaDefinition.Device(2)
|
MediaDefinition.Device(2)
|
||||||
.MediaFile(1)
|
.MediaFile(1)
|
||||||
.StartingPositionInFile = *ALL'0';
|
.StartingPositionInFile = *ALL'0';
|
||||||
|
|
||||||
MediaDefinition.Device(2)
|
MediaDefinition.Device(2)
|
||||||
.MediaFile(1)
|
.MediaFile(1)
|
||||||
.NumberOfVolumeIdentifiers = 1;
|
.NumberOfVolumeIdentifiers = 1;
|
||||||
|
|
||||||
MediaDefinition.Device(2)
|
MediaDefinition.Device(2)
|
||||||
.MediaFile(1)
|
.MediaFile(1)
|
||||||
.VolumeIdentifier(1)
|
.VolumeIdentifier(1)
|
||||||
.VolumeIdentifier = 'DAK079';
|
.VolumeIdentifier = 'DAK079';
|
||||||
|
|||||||
Reference in New Issue
Block a user