SPベースのサービス (例題)

4D - Documentation   French   English   German   日本語   4D Serverテーマリスト   4D Serverインデックス   戻る   前   次

version 6.8 (Modified)


SPベースの読み込み (例題)で説明している例では、ストアドプロシージャは、データ読み込み処理が要求されるたびに開始され、終了されています。次の例では、ストアドプロシージャはサーバデータベースが起動されると自動的に開始され、サーバデータベースに接続している任意の4Dから随時に終了する、または再開することができます。ストアドプロシージャは実行されるとすぐに、データベースに接続しているクライアントから送られる複数の要求に対して、非同期的に応答することができるようになります。

SPベースの読み込み (例題)の節では、4D Server で提供される既存のサービスを飛躍的に最適化する方法について説明していますが、この例ではすべての4Dクライアントマシンで使用できる、新しいサービスやカスタムサービスを実現する方法について説明します。さらにこの例は、独自のサービスを実現するためのテンプレートとしても使用することができます。

ストアドプロシージャを自動起動する


ストアドプロシージャは、On Server Startup データベースメソッドによって自動的に開始されます:

??      ` On Server Startup Database Method
   START SP SERVICES 

On Server Startup データベースメソッドが、SP SERVICESプロジェクトメソッドをストアドプロシージャとして開始するため、実際にクライアントがサーバデータベースに接続しているかどうかに関わらず、4D Server でデータベースが開かれるとすぐにSP SERVICESが実行されます。次の図では、クライアントがまだ接続していない状態で、ストアドプロシージャが実行されている様子が4D Server の管理ウィンドウに表示されています。

Note: ユーザプロセスの“(1)” はストアドプロシージャのユーザスロットに対応します。

ストアドプロシージャの開始と終了


START SP SERVICES プロジェクトメソッドは以下のとおりです。:

      ` START SP SERVICES プロジェクトメソッド
   ?vlSPServices:=Execute on server("SP SERVICES";32*1024;"SP SERVICES";*)

Execute on serverコマンドはサーバマシンから呼ばれたときはNew processと同様に動作するので、同じメソッド (START SP SERVICES) をサーバマシンおよびクライアントマシンから使用して、ストアドプロシージャとしてSP SERVICESメソッドをサーバマシン上で実行できます。

STOP SP SERVICESプロジェクトメソッドはSP SERVICESプロジェクトメソッドに停止するよう通知します。

      ` STOP SP SERVICES Project Method
   SET PROCESS VARIABLE(?vlSPServices;vbStopSPServices;True)

SP SERVICESプロジェクトメソッドが開始されると、vbStopSPServicesプロセス変数がFalseに設定され、このブール変数がTrueになるまでループします。コマンドSET PROCESS VARIABLEを使用して、サーバあるいはクライアント上で実行されているユーザプロセスからvbStopSPServices変数の値を変更し、ストアドプロシージャを停止させられます。

ストアドプロシージャとの通信


ストアドプロシージャは、任意の時間に任意の順序で非同期的にクライアントのリクエストを受信し、応答できる必要があります。この通信を保証する簡単な方法はテーブルを使用することです。

[SP Requests] テーブルには、次のフィールドが含まれています:

[SP Requests]reqIDは、Sequence numberコマンドを使用して設定されます。このフィールドによって各リクエストを識別します。

[SP Requests]reqTypeはリクエストのタイプを示します。

[SP Requests]reqStatusは次の値のうちいずれかになります:

説明
1リクエストは送られたが、まだ処理されていない。
0リクエストは正常に処理された。
< 0リクエストは処理されたが、エラーが発生した。

Note: これらの値は、この例題のため任意に選ばれたものであり、4D から与えられた値ではありません。

[SP Requests]reqDataは、リクエストデータを格納しているBLOB です。リクエスト元から送られたデータやストアドプロシージャからリクエスト元に返されるデータが含まれています。

[SP Requests]reqParamsには、オプションとしてリクエスト元がストアドプロシージャに送った引数の値が含まれています。

なぜテーブルを使用するのか?

クライアントプロセスとストアドプロシージャの間の通信はGET PROCESS VARIABLESET PROCESS VARIABLEVARIABLE TO VARIABLEコマンドを使用して実現できます。SPベースの読み込み (例題)の節や、前述のSTOP SP SERVICESプロジェクトメソッドで使用したソリューションがこの例です。

今回の場合は、ストアドプロシージャがさまざまな量のデータを送受信できるようにシステムが設定されていなければなりません。テキスト配列やピクチャ配列等の配列を使用することもできますが、次の2つの理由からテーブルを使用します:

・レコードを使用してリクエストを処理するアルゴリズムの方が、より容易に実装できます。クライアントマシンからリクエストを送る処理は、テーブルにリクエストを追加する処理だけで構成されています。ストアドプロシージャ内からリクエストに応答する処理は、このリクエストレコードを修正する処理だけで構成されています。

・リクエストはテーブルに格納されるため、ディスク上に保存されます。したがって、リクエストは (配列に格納されるデータの場合とは異なり) メモリには保持されず、リクエストのサイズが大きい場合でも問題にはなりません。

クライアントマシンからリクエストを送る


Client post request プロジェクトメソッドは、リクエストを送るための汎用的なメソッドです:

      ` Client post request プロジェクトメソッド
      ` Client post request ( String { ; Text } ) -> Long
      ` Client post request ( Request type { ; Parameters } ) -> Request ID
   CREATE RECORD([SP Requests])
   [SP Requests]reqID:=Sequence number([SP Requests])
   [SP Requests]reqType:=$1
   [SP Requests]reqStatus:=1
   If (Count parameters>=2)
      [SP Requests]reqParams:=$2
   End if 
   SAVE RECORD([SP Requests])
   $0:=[SP Requests]reqID

このメソッドからリクエストID 番号が返されますが、Sequence numberコマンドを使用することにより、この番号は必ずユニークになります。レコードが[SP Requests]テーブルに追加された後、クライアントはフィールド[SP Requests]reqStatus を調べ、ストアドプロシージャが完全にリクエストを処理するまで待機します。

リクエストステータスの検査とクライアントマシンでの結果の取得


Client get resultプロジェクトメソッドは、リクエストステータスを調べるための汎用的なメソッドです。前述したように、[SP Requets]redStatusフィールドが1以外の値になるとすぐに、クライアントはストアドプロシージャがリクエストを処理したことが (成功しても失敗しても) 分かります。

      ` Client get result プロジェクトメソッド
      ` Client get result ( Long ; ->BLOB {; Long } ) -> Long
      ` Client get result ( Request ID ; ->Data {; Delay } ) -> Error Code
   C_LONGINT($0;$1;$vlDelay)
   $0:=1
   $vlDelay:=0
   If (Count parameters>=3)
      $vlDelay:=$3
   End if 
   READ ONLY([SP Requests])
   Repeat 
      QUERY([SP Requests];[SP Requests]reqID=$1)
      If (Records in selection([SP Requests])>0)
         If ([SP Requests]reqStatus?#?1)
            $2->:=[SP Requests]reqData
            READ WRITE([SP Requests])
            While (Locked([SP Requests]))
               DELAY PROCESS(Current process;$vlDelay)
               LOAD RECORD([SP Requests])
            End while 
            DELETE RECORD([SP Requests])
            $0:=[SP Requests]reqStatus
         End if 
      Else 
            ` リクエストレコードが失われた!
            ` これは発生すべきではないが、とにかくerrorを-2に設定 (任意の値)
         $0:=-2
      End if 
         ` リクエストはまだ処理されいない 
      If ($0=1)
         WAITING LOOP ($vlDelay)
      End if 
   Until ($0?#?1)
   READ ONLY([SP Requests])

リクエストがストアドプロシージャにより正常に処理された場合、このメソッドはレコードからBLOB へ結果 (ある場合) をコピーします。BLOB へのポインタは引数として渡されます。次に、呼び出し元であるメソッドでリクエストタイプに応じ、BLOB データが解析されます。リクエストの処理が終了したら、[SP Requests]レコードの削除を行うのはクライアントである点に注意してください。



ストアドプロシージャとサブルーチン


SP SERVICESプロジェクトメソッドは、サーバマシン上でストアドプロシージャとして実行されるメソッドです。疑似コードを次に示しますが、総体的なアーキテクチャは簡単です:

   “stop” 変数の初期化
   以下繰り返す
      [SP Requests]reqStatus フィールドが1であるリクエストを検索
      リクエストごとに
         リクエストのタイプに応じ、サブルーチンを呼び出し、
            [SP Requests]reqData フィールドに結果を格納する
         リクエストのスータスを変更し、処理の終了をクライアントに通知
      リクエストごとの繰り返しここまで
      再開始するまで少々の時間停止する
   “stop” 変数がTrueになるまで

以下は実際のコードです:

      ` SP SERVICES プロジェクトメソッド
      ` ストアドプロシージャの開始
   vbStopSPServices:=False
      ` ストアドプロシージャはーブルに対し読み書きアクセスを必要としない
   READ ONLY(*)
      ` ただし[SP Requests] ーブルを除く
   READ WRITE([SP Requests])
   Repeat 
         ` まだ処理しいないリクエストを検索
      QUERY([SP Requests];[SP Requests]reqStatus=1)
         ` これらのリクエストをひとつづつ処理
      For ($vlRecord;1;Records in selection([SP Requests]))
            ` リクエストレコードがロックされいれば、ロック解除まで待つ
         While (Locked([SP Requests]))
               ` 再試行まで1秒待つ
            DELAY PROCESS(Current process;60)
               ` 読み書きアクセスを試行
            LOAD RECORD([SP Requests])
         End while 
            ` 処理が成功したと仮定する  
         [SP Requests]reqStatus:=0
         Case of 
            : ([SP Requests]reqType="Server Information")
               SP DO SERVER INFORMATION 
            : ([SP Requests]reqType="Volume List")
               SP DO VOLUME LIST 
            : ([SP Requests]reqType="Browse Directory")
               SP DO BROWSE DIRECTORY ([SP Requests]reqParams)
               ` ...
               ` 他のリクエストタイプをここに追加可能!
               ` ...
            Else 
                  ` 未知のリクエストタイプ, エラー -1を返す (任意の値)        
               [SP Requests]reqStatus:=-1
         End case 
            ` リクエストスータスが1でないようにする
            ` (サブルーチンが1にししまった場合)
         If ([SP Requests]reqStatus=1)
            [SP Requests]reqStatus:=-3
         End if 
            ` リクエストレコードを更新 
         SAVE RECORD([SP Requests])
            ` 次の未処理レコードに移動
         NEXT RECORD([SP Requests])
      End for 
         ` 最後に処理したレコードをアンロード
      UNLOAD RECORD([SP Requests])
         ` 再び処理を開始する前に1秒待つ
      DELAY PROCESS(Current process;60)
         ` 停止を指示されるまでループする
   Until (vbStopSPServices)

SP SERVICESプロジェクトメソッドは、データベースに新しいサービスを実現するためのテンプレートとして使用することができます。この節では、SP DO SERVER INFORMATIONサブルーチンおよびSP DO VOLUME LISTサブルーチンの詳細について説明します。SP DO BROWSE DIRECTORY ([SP Requests]reqParamsフィールドに納めて送られた引数を引数として取得するサブルーチン) の詳細については、このドキュメントでは説明されていません。

リクエストのタイプによってSP SERVICESプロジェクトメソッドは、結果データを[SP Requests]reqDataフィールドに保存する処理を行うサブルーチンを呼び出します。レコードの保存やリクエストステータスの変更は、SP SERVICESプロジェクトメソッドによって実行されます。

次に示すのはSP DO SERVER INFORMATIONサブルーチンです。このサブルーチンはサーバ関連の情報をBLOB に保存します。別のプロジェクトメソッドを使用して、クライアントマシン上でBLOB データを取り出します。

      ` SP DO SERVER INFORMATION プロジェクトメソッド
   TEXT TO BLOB(Application version(*);[SP Requests]reqData;UTF8 C String)
   TEXT TO BLOB(Structure file;[SP Requests]reqData;UTF8 C String;*)
   TEXT TO BLOB(Data file;[SP Requests]reqData;UTF8 C String;*)
   PLATFORM PROPERTIES($vlPlatform;$vlSystem;$vlMachine)
   VARIABLE TO BLOB($vlPlatform;[SP Requests]reqData;*)
   VARIABLE TO BLOB($vlSystem;[SP Requests]reqData;*)
   VARIABLE TO BLOB($vlMachine;[SP Requests]reqData;*)

次に示すのはSP DO VOLUME LISTサブルーチンです。このサブルーチンは、ボリューム関連の情報をBLOB に保存します。別のプロジェクトメソッドを使用して、クライアントマシン上でBLOB データを取り出します。

      ` SP DO VOLUME LIST プロジェクトメソッド
   VOLUME LIST($asVName)
   $vlSize:=Size of array($asVName)
   配列 REAL($arVSize;$vlSize)
   配列 REAL($arVUsedSpace;$vlSize)
   配列 REAL($arVFreeSpace;$vlSize)
   For ($vlElem;1;$vlSize)
      VOLUME ATTRIBUTES($asVName{$vlElem};$arVSize{$vlElem};$arVUsedSpace{$vlElem}
                        ;$arVFreeSpace{$vlELem})
   End for 
   VARIABLE TO BLOB($asVName;[SP Requests]reqData)
   VARIABLE TO BLOB($arVSize;[SP Requests]reqData;*)
   VARIABLE TO BLOB($arVUsedSpace;[SP Requests]reqData;*)
   VARIABLE TO BLOB($arVFreeSpace;[SP Requests]reqData;*)

サーバ情報をクライアントマシン上に表示する


汎用的なClient post requestClient get resultプロジェクトメソッドを使用して、M_SERVER_INFORMATIONプロジェクトメソッドはストアドプロシージャより返されたサーバ情報をクライアントマシン上に表示します。このメソッドは、メニューに割り当てる、あるいはボタンのオブジェクトメソッドで呼び出してもいいでしょう。

      ` M_SERVER_INFORMATION
   C_BLOB(vxData)
   C_LONGINT($vlReqID;$vlErrCode;$vlOffset)
      ` リクエストを送信
   $vlReqID:=Client post request ("Server Information")
      ` リクエストスータスを見、結果を取得
   $vlErrCode:=Client get result ($vlReqID;->vxData;60)
      ` リクエストが正しく処理されいれば、結果を表示
   If ($vlErrCode=0)
         ` BLOBから情報を取り出し  
      $vlOffset:=0
      vsServerVersion:=BLOB to text(vxData;UTF8 C String;$vlOffset)
      vsStructureFile:=BLOB to text(vxData;UTF8 C String;$vlOffset)
      vsDataFile:=BLOB to text(vxData;UTF8 C String;$vlOffset)
      BLOB TO VARIABLE(vxData;$vlPlatform;$vlOffset)
      BLOB TO VARIABLE(vxData;$vlSystem;$vlOffset)
      BLOB TO VARIABLE(vxData;$vlMachine;$vlOffset)
         ` プラットフォームプロパィを解析
      vs4DPlatform:="Unknown 4D Server Version"
      vsSystem:="Unknown System Version"
      vsMachine:="Unknown Machine"
         `...
         ` $vlSystem と $vlMachineを取得するコードをここに記述
         ` (PLATFORM PROPERTIES コマンドの例題参照)
         ` ...
         ` 結果を表示
      DIALOG([SP Requests];"SERVER INFORMATION")
   Else 
      ALERT("Request error "+String($vlErrCode))
   End if 
      ` BLOBは必要ない
   CLEAR VARIABLE(vxData)

以下は実行された[SP Requests];"SERVER INFORMATION"フォームです:

サーバマシンのボリューム一覧をクライアントマシン上に表示する


汎用的なClient post requestClient get resultプロジェクトメソッドを使用して、M_SERVER_INFORMATIONプロジェクトメソッドはストアドプロシージャより返されたボリューム一覧をクライアントマシン上に表示します。このメソッドをメニューに割り当てたり、あるいはボタンのオブジェクトメソッドで呼び出してもいいでしょう:

      ` M_SERVER_VOLUMES
   C_BLOB(vxData)
      ` リクエストを送信
   $vlReqID:=Client post request ("Volume List")
      ` リクエストスータスを見、結果を取得
   $vlErrCode:=Client get result ($vlReqID;->vxData;120)
      ` リクエストが正しく処理されいれば、結果を表示
   If ($vlErrCode=0)
         ` BLOBから情報を取り出し  
      $vlOffset:=0
      BLOB TO VARIABLE(vxData;asVName;$vlOffset)
      BLOB TO VARIABLE(vxData;arVSize;$vlOffset)
      BLOB TO VARIABLE(vxData;arVUsedSpace;$vlOffset)
      BLOB TO VARIABLE(vxData;arVFreeSpace;$vlOffset)
      For ($vlElem;1;Size of array(arVSize))
            ` バイトをMBに変換
         arVSize{$vlElem}:=arVSize{$vlElem}/1048576
         arVUsedSpace{$vlElem}:=arVUsedSpace{$vlElem}/1048576
         arVFreeSpace{$vlElem}:=arVFreeSpace{$vlElem}/1048576
      End for 
            ` 結果を表示 
      DIALOG([SP Requests];"VOLUME LIST")
   Else 
      ALERT("Request error "+String($vlErrCode))
   End if 
      ` BLOBは必要ない
   CLEAR VARIABLE(vxData)

以下は実行された[SP Requests];"VOLUME LIST"フォームです:

参照

BLOB コマンド, Execute on server, SPベースの読み込み (例題), ストアドプロシージャ.


4D - Documentation   French   English   German   日本語   4D Serverテーマリスト   4D Serverインデックス   戻る   前   次