home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
M.u.C.S. Disc 2000
/
MUCS2000.iso
/
anwend
/
gemar306
/
plugin
/
plugins.txt
< prev
next >
Wrap
Text File
|
1997-01-21
|
11KB
|
303 lines
PlugIns für GEMAR ╛ Steffen Engel 1992-94
25.05.94
ALLGEMEINES
In dieser Datei werden alle nötigen Informationen zu PlugIns gegeben, der
aktuelle Stand der von GEMAR installierten PlugIn-Calls, die Liste der aktuell
existierenden PlugIns und der aktuelle Stand der PlugIns und ihrer
Programmierung.
Die mit GEMAR gelieferten PlugIns sind grundsätzlich alle deaktiviert, indem
die Namen mit PLX enden.
Bitte beurteilen Sie selbst, welche PlugIns für Sie sinnvoll sind.
WAS SIND PLUGINS?
Um GEMAR mit weiteren Fähigkeiten auszustatten, wurde ein Konzept entworfen,
mit dem externe Programme als Erweiterung hinzugeladen werden können.
Dabei wird von GEMAR an bestimmten Stellen einfach kontrolliert, ob ein zu
diesem Zweck gehörendes PlugIn existiert, und ruft es gegebenenfalls auf.
Grundsätzlich wurde das Konzept relativ einfach gehalten, da es dadurch
einerseits einfach zu verstehen und programmieren ist und andererseits kein
vollständig modulares Programmierungssystem entworfen werden sollte.
Mit diesem Konzept sind nur kleine Erweiterungen oder Ersetzungen von Teilen
von GEMAR möglich.
PlugIns sind vor allem dann sinnvoll, wenn kleine Erweiterungen an GEMAR
gemacht werden sollen, die für bestimmte Probleme sinnvoll sind, aber zu
speziell sind, um allgemein in GEMAR eingebaut zu werden.
PlugIns werden von GEMAR grundsätzlich im Ordner PLUGIN im GEMAR-Pfad
gesucht.
AUFBAU UND PROGRAMMIERUNG VON PLUGINS
PlugIns werden grundsätzlich als Pozeduren aufgerufen. Als Methode wurde ein
ähnlicher Weg gewählt wie bei CPX-Modulen.
Zur Identifikation tragen PlugIns zur Zeit einen 512-Byte langen Kopf:
TYPE tPlugHead
= RECORD
Magic : lCARDINAL; (* 'Plug' *)
Identify : ARRAY[0..19] OF CHAR; (* Kontrolle für Programm *)
SlotIdent : ARRAY[0..19] OF CHAR; (* Identifikation für Verwendung *)
Info : ARRAY[0..467] OF CHAR; (* Beschreibung *)
END;
Identify dient dabei dazu, zu erkennen, ob dieses Plugin überhaupt für das
laufende Programm ist. Bei Gemar mu₧ Identify immer 'Gemar' sein.
SlotIdent dient zur Erkennung, ob das PlugIn für den Slot geeignet ist.
Dies dient als Schutz, da₧ zB ein Plugin für die Index-Bearbeitung nicht
für SCSI-Routinen eingeklinkt wird.
PlugIns werden geladen und danach wird der Rumpf des PlugIns mit einem Zeiger
auf folgende Struktur aufgerufen:
tPlugEnvironment
= RECORD
(* aktuelle Parameterversion = 1.00 = 0100H *)
Version : sINTEGER; (* Version zeigt Umfang der Parameter an *)
Private : ADDRESS; (* spezielle Parameter für den Rumpf *)
ApplId : sINTEGER; (* Applikationsid des rufenden Programmes *)
VDIHandle: sINTEGER; (* Workstation des Hauptprogrammes *)
PlugPath : POINTER TO ARRAY[0..512] OF CHAR; (* Name und Pfad des PlugIn, kann auch
relativ sein *)
Alert : PROCEDURE((* def *) sINTEGER, VAR (* msg *) STRING) : sINTEGER;
END;
In C sieht das entsprechend so aus:
typedef struct
{
int Version;
void *private;
int ApplId;
int VDIHandle;
char *PlugPath;
int (*Alert) (int defbutt, char *msg);
} PLUGPARMS;
Die Struktur wird grundsätzlich abwärtskompatibel sein, d.h. bei erweiterten
Versionen kommen zusätzliche Parameter hinzu und die Versionsnummer wird
erhöht.
Nach einer evtl. nötigen Initialisierung (zB Abfragen, ob das Modul überhaupt
aktiviert werden soll) mu₧ das PlugIn mit einem Zeiger auf eine Tabelle
von Funktionen antworten:
TYPE tpPlugProcs = POINTER TO tPlugProcs;
tPlugProc = PROCEDURE((* par : *) ADDRESS) : lINTEGER;
tPlugProcs = RECORD
num : SHORTINT; (* Anzahl der Funktionen *)
Procs : ARRAY[0..07FFFH] OF tPlugProc;
END;
Ein Null-Zeiger zeigt an, da₧ das PlugIn nicht aktiviert werden soll (oder
bereits fertig ist).
Diese Funktionen werden dann zur eigentlichen Verwendung ein- oder mehrmals
aufgerufen. Als Parameter wird ein Zeiger übergeben, der auf die zu
bearbeitenden Daten zeigt.
Bitte beachten Sie, da₧ UNBEDINGT aller Speicher bei der Deinitialisierung
des PlugIns freigegeben wird, da der Speicher nicht durch das Freigeben des
PlugIn freigeben wird!
Die Aufforderung zur Deinitialisierung erfolgt durch Aufruf der Funktion 0
mit -1 (0FFFFFFFFH) als Parameter.
Als Beispiel sollten Sie sich die beiliegenden PlugIns ansehen, insbesondere
PLUGPARM.D
PARAMETER IN GEMAR
Als Standardstruktur wird von GEMAR in private ein Zeiger auf die folgende
Struktur übergeben:
TYPE tPlugPrivate = RECORD
Version : SHORTCARD; (* = 0200H = 2.00 *)
special : ADDRESS; (* Spezielles für Art des PlugIn *)
StrHandle : SHORTCARD;
StrMaxLen : LONGCARD;
BlockLen: SHORTCARD; (* Blocklänge des Streamers *)
ScsiIn : PROCEDURE ((* ScsiCmd *) tpScsiCmd) : SHORTINT;
ScsiOut : PROCEDURE ((* ScsiCmd *) tpScsiCmd) : SHORTINT;
SuperOn : PROC;
SuperOff : PROC;
END;
In C sieht das so aus:
typedef struct
{
unsigned word version;
void *special;
word strhandle;
long strmaxlen;
word blocklen;
word (*ScsiIn) (SCSIPARMS *Parms);
word (*ScsiOut) (SCSIPARMS *Parms);
void (*SuperOn) ();
void (*SuperOff) ();
} tScsiCall;
tScsiCmd = RECORD
handle : SHORTCARD; (* das handle des Gerätes *)
Cmd : ADDRESS; (* Zeiger auf CmdBlock *)
CmdLen : SHORTCARD; (* Länge des Cmd-Block *)
Buffer : ADDRESS; (* Datenpuffer *)
TransferLen : LONGCARD; (* Übertragungslänge *)
SenseBuffer : ADDRESS; (* Puffer für ReqSense (18 Bytes) *)
Timeout : LONGCARD; (* Timeout in 1/200 sec *)
Flags : BITSET; (* Bitvektor für Ablaufwünsche *)
END;
tpScsiCmd = POINTER TO tScsiCmd;
Return-Werte für ScsiIn und ScsiOut sind:
NOSCSIERROR = 0; (* Kein Fehler *)
SELECTERROR = -1; (* Fehler beim Selektieren *)
STATUSERROR = -2; (* Default-Fehler *)
PHASEERROR = -3; (* ungültige Phase *)
BSYERROR = -4; (* BSY verloren *)
BUSERROR = -5; (* Busfehler bei DMA-Übertragung *)
TRANSERROR = -6; (* Fehler beim DMA-Transfer (nichts übertragen) *)
FREEERROR = -7; (* Bus wird nicht mehr freigegeben *)
TIMEOUTERROR = -8; (* Timeout *)
DATATOOLONG = -9; (* Daten für ACSI-Softtransfer zu lang *)
LINKERROR = -10; (* Fehler beim Senden des Linked-Command (ACSI) *)
TIMEOUTARBIT = -11; (* Timeout bei der Arbitrierung *)
PENDINGERR = -12;
Werte > 0 sind das Statusbyte des SCSI-Gerätes (siehe SCSI-Norm)
ACHTUNG!!!
BlockLen kann sich während des Betriebes von GEMAR ändern und ist nur gültig,
wenn ein Band geladen ist!!
special ist dabei ein Spezial-Parameter für das PlugIn, der von der Art des
PlugIn abhängt.
Dieser Parameter ist _NUR_ während der Initialisierung des PlugIn gültig und
mu₧ daher getrennt von der private-Struktur gesichert werden!!
Es reicht, den Zeiger zu sichern, da die Struktur auf die special zeigt,
nicht flüchtig ist.
EXISTIERENDE PLUGINS
Zur Zeit existieren fünf PlugIn-Slots:
-REQSENSE präzisiert die Fehlermeldungen des Streamers, die in den Request
Sense Daten übergeben werden.
-INDEX wird nach jedem Backup aufgerufen und kann entweder den Inhalt eines
Bandes ausdrucken, oder in eine Datei schreiben.
Darin können INDEX.PLG und SCANINDEX.PLG eingesetzt werden.
-SCANINDE wird beim Indexscanning aufgerufen. Damit kann eine Datei auf einem
Band gesucht werden.
Darin können INDEX.PLG und SCANINDEX.PLG eingesetzt werden.
-SCSI Wird bei allen SCSI-Befehlen gerufen und kann damit Anpassungen an
exotische Streamer durchführen.
Darin können die folgenden Plugins eingesetzt werden:
-SPACE.PLG wird bei Space-Operationen des Streamers gerufen, um
ein modifziertes Spacing durchzuführen
-QFA.PLG wird bei eingeschaltetem Quick File Access für die
Funktionen benutzt.
Dabei ist egal, welche Art eingeschaltet ist (Seek oder
Locate)
-Index-Import Wird bei unbekanntem Band-Header gerufen. Damit sind Restores
von GEMAR-fremden Bändern möglich.
SCANINDE und INDEX besitzen gleiche Aufrufe, da₧ hei₧t, Sie können INDEX.PLG
in SCANINDE.PLG umbenennen und damit per 'Scannen' nachträglich den Inhalt des
Bandes in eine Datei schreiben lassen.
EXISTIERENDE PLUGIN-AUFRUFE
1. Namentliche installierte PlugIns:
-INDEX.PLG:
Aufruf : Nach einem Backup
Name : INDEX.PLG
Anzahl : 1 (Laden nach Name)
SlotIdent : 'Index'
Prozeduren: 2 Prozeduren für Aufruf
1. Prozedur : Der Call bekommt Zeiger auf Index-Einträge,
jeweils einen Ordner alphabetisch durchlaufen,
danach den nächsttieferen Ordner.
Auf dieser Basis wäre zB ein Exporter in eine
Datenbank möglich.
übergebene Struktur: s. INDEX.M
2. Prozedur Zeiger auf den Index-Header.
Ein Aufruf zeigt an, da₧ ein neuer Index gelesen
wurde und der Header mit den Daten gefüllt ist.
-SCANINDEX.PLG:
Aufruf : bei Index-Scanning
Name : SCANINDE.PLG
Anzahl : 1 (Laden nach Name)
SlotIdent : 'Index'
Prozeduren: 2 Prozeduren für Aufruf, wie INDEX
retour = 1 bricht Scanning ab und wählt den aktuellen Index
2. Typbasiert installierte PlugIns:
-REQSENSE:
Aufruf : Nach einem Scsi-Fehler (Check Condition auf Streamerzugriff).
Anzahl : 1
SlotIdent : 'REQSENSE'
Prozeduren: 1 Prozedur für Aufruf
Parameter : Zeiger auf Request-Sense-Daten, die vorher vom SCSI-Gerät geholt
wurden.
Antwort : Zeiger auf einen (nullterminierten) String, der in die Alertbox
eingesetzt wird ('Check Condition(%s)')
-SCSI:
Aufruf : Wird bei allen SCSI-Kommandos gerufen
Anzahl : 1
SlotIdent : 'SCSI'
Prozeduren: 2 Prozeduren für Aufruf
1. Prozedur ist SCSIIn
2. Prozedur ist SCSIOut
Parameter : Zeiger auf die ScsiStruktur
Bemerkung : Aufruf im Supervisor-Modus!
-Index-Import:
Aufruf : Wird bei unbekanntem Band-Header gerufen
Anzahl : frei
SlotIdent : 'Index-Import'
Bemerkung : Dokumentation nur für Programmierer von Importern.
Weitere Aufrufe richte ich gerne ein, Ideen sind immer willkommen.
HISTORY
17.07.94
-Umstellung auf den Header vor dem PlugIn
-Umstellung der private-Parameter.
20.12.94
-Umstellung auf Slotbasierte PlugIns
Steffen Engel