Service mit Serverprozeduren (Beispiel)

4D - Documentation   Français   English   German   4D Server, Inhalt   Index   Back   Previous   Next

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:

WertBeschreibung
1Die Anfrage wurde gesendet, jedoch noch nicht bearbeitet
0Die Anfrage wurde erfolgreich bearbeitet.
< 0Die 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.


4D - Documentation   Français   English   German   4D Server, Inhalt   Index   Back   Previous   Next