Version 6.8 (Geändert)
Im Beispiel aus dem vorigen Abschnitt Import mit Serverprozeduren (Beispiel) startet oder endet eine Serverprozedur immer, wenn ein Datenimport angefordert wird. In diesem Beispiel startet eine Serverprozedur automatisch beim Starten der Serverdatenbank und kann von jedem Client, der sich an die Datenbank anmeldet, beliebig beendet oder wieder gestartet werden. Sobald die Serverprozedur läuft, kann sie asynchron auf die verschiedenen Anfragen antworten, welche die an die Datenbank angeschlossenen Clients senden.
Der vorige Abschnitt zeigt, wie Sie einen in 4D Server bestehenden Service zur Optimierung von Operationen integrieren können. Dieser Abschnitt erläutert, wie Sie neue Services integrieren können, die für alle 4D Clients verfügbar sind. Sie können das Beispiel auch als Vorlage zum Einrichten eigener Services verwenden.
Automatisches Starten der Serverprozedur
Die Serverprozedur wird automatisch gestartet mit der Datenbankmethode On Server Startup:
` Datenbankmethode On Server Startup START SP SERVICES
Da die Datenbankmethode On Server Startup die Projektmethode SP SERVICES als Serverprozedur startet, läuft SP SERVICES, sobald die Datenbank mit 4D Server gestartet wird, unabhängig davon, ob derzeit Clients an die Server-Datenbank angemeldet sind. Das hier abgebildete Verwaltungsfenster von
4D Server zeigt die aktive Serverprozedur, ohne dass ein Client angemeldet ist.
Hinweis: Alle Serverprozeduren gelten als ein Benutzer von 4D Server. Von daher wird unter angemeldete Anwender "1" angezeigt.
Serverprozeduren individuell starten und beenden
Die Projektmethode START SP SERVICES sieht folgendermaßen aus:
` Projektmethode START SP SERVICES <>vlSPServices:=Execute on server("SP SERVICES";32*1024;"SP SERVICES";*)
Da die Funktion Execute on server wie New process arbeitet, wenn sie auf dem Server-Rechner aufgerufen wird, kann auf dem Server-Rechner bzw. jedem Client-Rechner dieselbe Methode (START SP SERVICES) verwendet werden, um die Methode SP SERVICES als Serverprozedur auf dem Server-Rechner aufzurufen.
Die Projektmethode STOP SP SERVICES stoppt die Projektmethode SP SERVICES
` Projektmethode STOP SP SERVICES SET PROCESS VARIABLE(<>vlSPServices;vbStopSPServices;True)
Startet die Projektmethode SP SERVICES, setzt sie die Prozessvariable vbStopSPServices auf Falsch und durchläuft die Schleife, bis diese Variable vom Typ Boolean den Wert Wahr annimmt. Mit dem Befehl SET PROCESS VARIABLE lässt sich in jedem Benutzerprozess auf dem Server-Rechner bzw. jedem Client-Rechner der Wert der Variablen vbStopSPServices verändern und so die Serverprozedur nach eigenen Wünschen stoppen.
Mit Serverprozeduren kommunizieren
Die Serverprozedur muss Anfragen des Clients jederzeit und in beliebiger Reihenfolge asynchron empfangen und beantworten können. Das lässt sich am einfachsten mit einer Tabelle bewerkstelligen.
Die Tabelle [SP Anfragen] enthält folgende Datenfelder:
[SP Anfragen]Anf_Nr arbeitet mit der Funktion Sequence number. Es dient nur zum Identifizieren der Anfragen.
[SP Anfragen]Anf_Typ beschreibt die Art der Anfrage.
[SP Anfragen]Anf_Status kann folgende Werte annehmen:
Wert | Beschreibung | |
1 | Die Anfrage wurde gesendet, jedoch noch nicht bearbeitet | |
0 | Die Anfrage wurde erfolgreich bearbeitet. | |
< 0 | Die Anfrage wurde bearbeitet, es ist jedoch ein Fehler aufgetreten. |
Hinweis: Die Werte wurden willkürlich für dieses Beispiel gewählt, sie sind nicht von 4D vorgegeben.
[SP Anfragen]Anf_Daten ist ein BLOB mit den Daten der Anfrage. Sie kann sowohl Daten enthalten, die der Anfrager sendet als auch Daten, die die Serverprozedur an den Anfrager zurückgibt.
[SP Anfragen]Anf_Parameter enthält optional Parameterwerte, die der Anfrager an die Serverprozedur sendet.
Warum eine Tabelle verwenden?
Die Kommunikation zwischen einem Client-Rechner und einer Serverprozedur lässt sich mit den Befehlen GET PROCESS VARIABLE, SET PROCESS VARIABLE und VARIABLE TO VARIABLE herstellen. Diese Befehle werden z. B. im Abschnitt Import mit Serverprozeduren (Beispiel) und in der Projektmethode STOP SP SERVICES verwendet.
Hier muss das System jedoch zulassen, dass die Serverprozedur variable Datenmengen empfängt und zurücksendet. Sie könnten zwar auch Arrays, einschließlich Arrays vom Typ Text und Bild verwenden, zwei Gründe sprechen jedoch für die Verwendung einer Tabelle:
Der Algorithmus zum Bearbeiten von Anfragen via Datensätzen lässt sich einfacher einrichten. Wollen Sie eine Anfrage von einem Client-Rechner aus senden, müssen Sie in der Tabelle lediglich eine Anfrage hinzufügen. Wird die Anfrage von der Serverprozedur aus beantwortet, muss diese Anfrage lediglich geändert werden.
Anfragen in einer Tabelle werden auch auf der Festplatte gespeichert. Von daher ist die Größe einer umfangreichen Anfrage kein Problem, da sie aus dem Speicher entfernt werden kann (im Gegensatz zu Daten, die in Arrays gespeichert sind)
Eine Anfrage vom Client-Rechner senden
Die Projektmethode Client post request ist eine generische Methode zum Senden einer Anfrage:
` Projektmethode Client post request ` Client post request ( String { ; Text } ) -> Long ` Client post request (Anfrage_Typ { ; Parameter } ) -> Anfrage_Nr CREATE RECORD([SP Anfragen]) [SP Anfragen]Anf_Nr:=Sequence number([SP Anfragen]) [SP Anfragen]Anf_Typ:=$1 [SP Anfragen]Anf_Status:=1 If (Count parameters>=2) [SP Anfragen]Anf_Parameter:=$2 End if SAVE RECORD([SP Anfragen]) $0:=[SP Anfragen]Anf_Nr
Die Methode gibt die Nummer der Anfrage zurück. Die Funktion Sequence number stellt ihre Einzigartigkeit sicher. Wurde der Datensatz in der Datenbank [SP Anfragen] hinzugefügt, kann der Client das Datenfeld [SP Anfragen]Anf_Status befragen und abwarten, bis die Serverprozedur die Anfragen vollständig bearbeitet hat.
Den Status der Anfrage abfragen und das Ergebnis auf dem Client-Rechner erhalten
Die Projektmethode Client get result ist eine generische Methode zum Abfragen des Status der Anfrage. Wie bereits erwähnt, weiss der Client, sobald das Datenfeld [SP Anfragen]Anf_Status einen anderen Wert als 1 hat, dass die Serverprozedur die Anfrage bearbeitet hat (erfolgreich oder nicht erfolgreich).
` Projektmethode Client get result ` Client get result ( Long ; ->BLOB {; Long } ) -> Long ` Client get result ( Anfrage-Nr; ->Daten {; Delay } ) -> Error Code C_LONGINT($0;$1;$vlDelay) $0:=1 $vlDelay:=0 If (Count parameters>=3) $vlDelay:=$3 End if READ ONLY([SP Anfragen]) Repeat QUERY([SP Anfragen];[SP Anfragen]AnfID=$1) If (Records in selection([SP Anfragen])>0) If ([SP Anfragen]Anf_Status # 1) $2->:=[SP Anfragen]Anf_Daten READ WRITE([SP Anfragen]) While (Locked([SP Anfragen])) WAITING LOOP ($vlDelay) LOAD RECORD([SP Anfragen]) End while DELETE RECORD([SP Anfragen]) $0:=[SP Anfragen]Anf_Status End if Else ` Datensatz für die Anfrage ging verloren! ` Das sollte zwar nicht passieren. Setze trotzdem den Fehler auf -2 (willkürlicher Wert) $0:=-2 End if ` Die Anfrage wurde noch nicht bearbeitet If ($0=1) WAITING LOOP ($vlDelay) End if Until ($0 # 1) READ ONLY([SP Anfragen])
Hat die Serverprozedur die Anfrage erfolgreich bearbeitet, kopiert die Methode das Ergebnis (falls vorhanden) aus dem Datensatz in das BLOB, dessen Zeiger als Parameter übergeben wurde. Die aufrufende Methode analysiert und verwendet dann die BLOB Daten je nach Art der Anfrage. Beachten Sie, dass der Client für das Löschen des Datensatzes [SP Anfragen] zuständig ist, sobald die Anfrage vollständig bearbeitet ist.
Die kleine Projektmethode WAITING LOOP durchläuft die Schleife, bis eine Anzahl Ticks vergangen ist:
`Projektmethode WAITING LOOP ` WAITING LOOP ( Long ) ` WAITING LOOP ( Delay in ticks ) C_LONGINT($1) $vlStartTicks:=Tickcount Repeat IDLE Until ((Tickcount-$vlStartTicks)>=$1)
Zu Erinnerung: Der Befehl DELAY PROCESS hat im Benutzerprozess keine Auswirkung. Mit der Projektmethode WAITING LOOP wartet der Prozess die erforderliche Zeitspanne ab, selbst wenn die Anfrage von einem Benutzerprozess auf einem Client-Rechner ausging.
Serverprozeduren und dazugehörige Unterroutinen
Die Projektmethode SP SERVICES läuft als Serverprozedur auf dem Server-Rechner. Der gesamte Aufbau dieser Methode, hier gezeigt in Pseudocode, ist denkbar einfach:
Initialisiere eine Variable "stop" Wiederhole Suche nach Anfragen mit dem Wert des Datenfeldes [SP Anfragen]Anf_Status ist gleich 1 Für jede Anfrage Rufe je nach Art der Anfrage eine Unterroutine auf die das Ergebnis im Datenfeld [SP Anfragen]Anf_Daten speichert Ändere den Status der Anfrage, so dass der Client weiß, was passiert ist Ende für "Schlafe" ein wenig vor erneutem Starten Bis die Variable "stop" den Wert wahr hat.
Hier ist der echte Source Code:
` Projektmethode SP SERVICES ` Die Serverprozedur startet vbStopSPServices:=False ` Die Serverprozedur benötigt auf Tabellen etc. keinen Zugriff im Lese/Schreibmodus READ ONLY(*) ` ...außer der Tabelle [SP Anfragen] READ WRITE([SP Anfragen]) Repeat ` Suche nach noch nicht bearbeiteten Anfragen QUERY([SP Anfragen];[SP Anfragen]Anf_Status=1) ` Bearbeite diese Anfragen eine nach der anderen For ($vlRecord;1;Records in selection([SP Anfragen])) ` Ist der Datensatz Anfrage gesperrt, warte bis er freigegeben wird While (Locked([SP Anfragen])) ` Warte eine Sekunde vor erneutem Versuch DELAY PROCESS(Current process;60) ` Versuche, Zugriff im Lese/Schreibmodus zu erhalten LOAD RECORD([SP Anfragen]) End while ` Nimm an, dass die Anfrage erfolgreich bearbeitet wird [SP Anfragen]Anf_Status:=0 Case of : ([SP Anfragen]Anf_Typ="Server Information") SP DO SERVER INFORMATION : ([SP Anfragen]Anf_Typ="Volume List") SP DO VOLUME LIST : ([SP Anfragen]Anf_Typ="Browse Directory") SP DO BROWSE DIRECTORY ([SP Anfragen]Anf_Parameter) ` ... ` HIER KÖNNEN ANDERE ANFRAGETYPEN HINZUGEFÜGT WERDEN! ` ... Else ` Der Anfragetyp ist unbekannt, gibt Fehler -1 zurück (willkürlicher Wert) [SP Anfragen]Anf_Status:=-1 End case ` Sorge dafür,dass der Anfragestatus ungleich 1 ist ` (falls eine Unterroutine ihn auf 1 setzt) If ([SP Anfragen]Anf_Status=1) [SP Anfragen]Anf_Status:=-3 End if ` Aktualisiere den Datensatz Anfrage SAVE RECORD([SP Anfragen]) ` Gehe zur nächsten unbearbeiteten Anfrage NEXT RECORD([SP Anfragen]) End for ` Gib den zuletzt bearbeiteten Datensatz Anfrage frei UNLOAD RECORD([SP Anfragen]) ` Warte eine Sekunde vor erneutem Starten der Antwort auf die Anfrage DELAY PROCESS(Current process;60) ` Bleibe in der Schleife, bis die SP angewiesen wird, die Ausführung zu stoppen Until (vbStopSPServices)
Die Projektmethode SP SERVICES kann als Vorlage zur Integration neuer Services in einer Datenbank dienen. In diesem Abschnitt betrachten wir näher die Unterroutinen SP DO SERVER INFORMATION und SP DO VOLUME LIST. Die Unterroutine SP DO BROWSE DIRECTORY, die den Parameter übernimmt, den der Client im Datenfeld [SP Anfragen]Anf_Parameter übersendet, wird hier nicht behandelt.
Die Projektmethode SP SERVICES ruft je nach Anfragetyp eine Unterrroutine auf, welche die resultierenden Daten im Datenfeld [SP Anfragen]Anf_Daten speichert. SP SERVICES sichert den Datensatz und ändert den Status der Anfrage.
Hier folgt die Unterroutine SP DO SERVER INFORMATION. Sie speichert die server-bezogene Information im BLOB. Eine andere Projektmethode entnimmt die BLOB Daten entsprechend auf dem Client-Rechner.
` Projektmethode SP DO SERVER INFORMATION TEXT TO BLOB(Application version(*);[SP Anfragen]Anf_Daten;Pascal string) TEXT TO BLOB(Structure file;[SP Anfragen]Anf_Daten;Pascal string;*) TEXT TO BLOB(Data file;[SP Anfragen]Anf_Daten;Pascal string;*) PLATFORM PROPERTIES($vlPlatform;$vlSystem;$vlMachine) VARIABLE TO BLOB($vlPlatform;[SP Anfragen]Anf_Daten;*) VARIABLE TO BLOB($vlSystem;[SP Anfragen]Anf_Daten;*) VARIABLE TO BLOB($vlMachine;[SP Anfragen]Anf_Daten;*)
Hier folgt die Unterroutine SP DO VOLUME LIST. Sie speichert die volume-bezogene Information im BLOB. Eine andere Projektmethode entnimmt die BLOB Daten entsprechend auf dem Client Rechner.
` Projektmethode SP DO VOLUME LIST VOLUME LIST($asVName) $vlSize:=Size of array($asVName) ARRAY REAL($arVSize;$vlSize) ARRAY REAL($arVUsedSpace;$vlSize) ARRAY REAL($arVFreeSpace;$vlSize) For ($vlElem;1;$vlSize) VOLUME ATTRIBUTES($asVName{$vlElem};$arVSize{$vlElem};$arVUsedSpace{$vlElem} ;$arVFreeSpace{$vlELem}) End for VARIABLE TO BLOB($asVName;[SP Anfragen]Anf_Daten) VARIABLE TO BLOB($arVSize;[SP Anfragen]Anf_Daten;*) VARIABLE TO BLOB($arVUsedSpace;[SP Anfragen]Anf_Daten;*) VARIABLE TO BLOB($arVFreeSpace;[SP Anfragen]Anf_Daten;*)
Die Server Information auf einem Client-Rechner zeigen
Mit den generischen Projektmethoden Client post request und Client get result zeigt die Projektmethode M_SERVER_INFORMATION die Serverinformation an, die die Serverprozedur auf dem Client-Rechner zurückgibt. Diese Methode kann einem Menübefehl zugeordnet werden oder z.B. über eine Objektmethode für eine Schaltfläche aufgerufen werden:
` M_SERVER_INFORMATION C_BLOB(vxData) C_LONGINT($vlAnf_Nr;$vlErrCode;$vlOffset) ` Stelle die Anfrage $vlAnfID:=Client post request ("Server Information") ` Frage den Anfragestatus ab und erhalte das Ergebnis $vlErrCode:=Client get result ($vlAnfID;->vxDaten;60) ` Ist die Anfrage erfolgreich abgeschlossen, zeige das Ergebnis an If ($vlErrCode=0) ` Entnehme die Information aus dem BLOB $vlOffset:=0 vsServerVersion:=BLOB to text(vxDaten;Pascal string;$vlOffset) vsStructureFile:=BLOB to text(vxDaten;Pascal string;$vlOffset) vsDataFile:=BLOB to text(vxDaten;Pascal string;$vlOffset) BLOB TO VARIABLE(vxDaten;$vlPlatform;$vlOffset) BLOB TO VARIABLE(vxDaten;$vlSystem;$vlOffset) BLOB TO VARIABLE(vxDaten;$vlMachine;$vlOffset) ` Analysiere die Plattform Eigenschaften vs4DPlatform:="Unbekannte 4D Server Version" vsSystem:="Unbekannte System Version" vsMachine:="Unbekannter Rechner" `... ` Hier ist der Code (nicht aufgelistet) der $vlSystem und $vlMachine analysiert ` (siehe Beispiel für den Befehl PLATFORM PROPERTIES) ` ... ` Zeige das Ergebnis DIALOG([SP Anfragen];"SERVER INFORMATION") Else ALERT("Anfrage error "+String($vlErrCode)) End if ` BLOB wird nicht länger benötigt CLEAR VARIABLE(vxDaten)
Hier ist das Formular [SP Anfragen];"SERVER INFORMATION" in der Benutzer- oder Runtime-Umgebung:
In diesem Fenster wird die Information von einem 4D Server-Rechner für Windows NT auf einem Client-Rechner für MacOS angezeigt.
Laufwerke des Server-Rechners auf einem Client-Rechner anzeigen
Mit den generischen Projektmethoden Client post request und Client get result zeigt die Projektmethode M_SERVER_VOLUMES auf dem Client-Rechner die Laufwerke des Server-Rechners an, die die Serverprozedur zurückgibt. Diese Methode kann einem Menübefehl zugeordnet werden oder z.B. über eine Objektmethode für eine Schaltfläche aufgerufen werden:
` M_SERVER_VOLUMES C_BLOB(vxDaten) ` Stelle die Anfrage $vlReqID:=Client post request ("LAUFWERK") ` Frage den Anfragestatus ab und erhalte das Ergebnis $vlErrCode:=Client get result ($vlAnf_Nr;->vxDaten;120) ` Ist die Anfrage erfolgreich abgeschlossen, zeige das Ergebnis an If ($vlErrCode=0) ` Entnehme die Information aus dem BLOB $vlOffset:=0 BLOB TO VARIABLE(vxDaten;asVName;$vlOffset) BLOB TO VARIABLE(vxDaten;arVSize;$vlOffset) BLOB TO VARIABLE(vxDaten;arVUsedSpace;$vlOffset) BLOB TO VARIABLE(vxDaten;arVFreeSpace;$vlOffset) For ($vlElem;1;Size of array(arVSize)) ` Konvertiere von bytes in MB arVSize{$vlElem}:=arVSize{$vlElem}/1048576 arVUsedSpace{$vlElem}:=arVUsedSpace{$vlElem}/1048576 arVFreeSpace{$vlElem}:=arVFreeSpace{$vlElem}/1048576 End for ` Zeige das Ergebnis DIALOG([SP Anfragen];"LAUFWERK") Else ALERT("Anfrage error "+String($vlErrCode)) End if ` BLOB wird nicht länger benötigt CLEAR VARIABLE(vxDaten)
Hier ist das Formular [SP Anfragen];"LAUFWERK" in der Benutzer- oder Runtime-Umgebung:
In diesem Fenster wird die Information von einem 4D Server-Rechner für Windows auf einem Client-Rechner für Macintosh angezeigt.
Referenz
BLOB Befehle, Execute on server, Import mit Serverprozeduren (Beispiel), Serverprozeduren.