4D v14

Service mit Serverprozeduren (Beispiel)

Home

 
4D v14
Service mit Serverprozeduren (Beispiel)

Service mit Serverprozeduren (Beispiel)  


 

 

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 remote 4D, 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 angemeldeten Client-Rechner verfügbar sind. Sie können das Beispiel auch als Vorlage zum Einrichten eigener Services verwenden.

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 sie, 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.

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. auf 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. auf jedem Client-Rechner der Wert der Variablen vbStopSPServices verändern und so die Serverprozedur nach eigenen Wünschen stoppen.

Die Serverprozedur muss Anfragen des Clients jederzeit und in beliebiger Reihenfolge asynchron empfangen und beantworten können. Das ist am einfachsten mit einer Tabelle möglich.

Die Tabelle [SP Anfragen] enthält folgende Datenfelder:

  • [SP Anfragen]Anf_Nr arbeitet mit der Funktion Sequence number. Sie 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.

Die Kommunikation zwischen einem Client-Prozess 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).

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.

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&NBSP;#&NBSP;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)|Process aborted)

Zu Erinnerung: Der Befehl DELAY PROCESS hat im Anwendungsprozess 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.

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 erläutert.

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;UTF8 C string)
 TEXT TO BLOB(Structure file;[SP Anfragen]Anf_Daten;UTF8 C string;*)
 TEXT TO BLOB(Data file;[SP Anfragen]Anf_Daten;UTF8 C 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;*)

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;UTF8 C string;$vlOffset)
    vsStructureFile:=BLOB to text(vxDaten;UTF8 C string;$vlOffset)
    vsDataFile:=BLOB to text(vxDaten;UTF8 C 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 Ausführung:

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 Ausführung:

 
EIGENSCHAFTEN 

Produkt: 4D
Thema: 4D Server und Programmiersprache

 
SIEHE AUCH 

Import mit Serverprozeduren (Beispiel)
Serverprozeduren

 
ARTIKELVERWENDUNG

4D Server Handbuch ( 4D v13)
4D Server Handbuch ( 4D Server v12)
4D Server Handbuch ( 4D Server v11 SQL Release 6)
4D Server Handbuch ( 4D v14 R2)
4D Server Handbuch ( 4D v14)
4D Server Handbuch ( 4D v14 R3)
4D Server Handbuch ( 4D Server v14 R4)