その他の機能
前の章では、Caché Direct を使用するクライアント・アプリケーションの基本要件について説明しました。この章では、カスタム・プロセスを指定して、多様な場合に全体的なクライアントとサーバの相互作用を実行する方法について説明します。これらの機能の多くは、典型的なクライアントとサーバの相互作用の特定の部分に含まれるフックで、その大半はサーバ固有の機能です。クライアントにも追加されている機能があります。
この章には、以下のセクションが含まれます。
概要
このセクションでは、クライアントとサーバの相互作用の概要と、一般的なサーバ動作について説明します。まず、典型的なクライアントとサーバの相互作用は、次のステップから構成されています。
-
クライアントはサーバに接続し、サーバ宛に NewTask メッセージを送信します。
-
次に、クライアントは BeginTask メッセージを送信します。
ライセンス・スロットが使用できない場合、サーバは <No License> エラーを返して切断します。
-
サーバは BeginTaskHook をチェックします。ここには、サーバで独自に実行する処理を追加することができます。
-
次に、クライアントは通常、必要な数の ExecuteCode メッセージを送信します。クライアントが個々のメッセージを送信する直前に、クライアント側書き込みフックがあります。ここに、独自の処理を追加することができます。
-
サーバはメッセージを受信すると、サーバの読み取りフック (ReadHook) で指定された処理をすべて実行し、メッセージを読み取ります。
-
サーバは、要求されたとおりコードを実行します。
-
サーバは、サーバ書き込みフック (WriteHook) で指定された処理をすべて実行し、メッセージを送信します。
-
クライアントはメッセージを受信すると、クライアント側の読み取りフックで指定された処理をすべて実行し、メッセージを読み取ります。
-
やり取りの最後に、クライアントは EndTask メッセージを送信します。これにより、接続が切断されます。
-
サーバは EndTask メッセージを受信して、EndTaskHook をチェックします。ここには、サーバで独自に実行する処理を追加できます。
-
サーバは ShutDownHook をチェックします。これには、独自の処理を追加できます。その後、サーバはシャットダウンします。
Note:カスタム EndTask 処理とは対照的に、ここで説明するクライアントとサーバの相互作用以外に、カスタム・シャットダウン処理も行われます。タイムアウト・エラーなど、何らかの理由でサーバがシャットダウンした場合、シャットダウン処理が行われます。
この説明からわかるとおり、Caché Direct により、メッセージを送信する直前 (書き込みフック)、およびメッセージの受信直後 (読み取りフック) に処理を挿入するためのフックが用意されています。これらのフックは、カスタム・ログ、圧縮、暗号化など、アプリケーションにより選択された目的で使用することができます。クライアントの書き込みフックは、サーバの読み取りフックと、またクライアントの読み取りフックはサーバの書き込みフックと対になっています。書き込みフックによりメッセージが変換された場合、対応する読み取りフックで、このメッセージが Caché Direct で予期される形式になっていることを確認する必要があります。
エラー・トラップ
サーバは致命的ではないエラーをすべてトラップし、次の手順を通じて、クライアントにレポートします。
-
サーバのローカル変数、error と errorcode に値を設定します。
-
ローカル・エラー・フック (%cdEHOOK) で指定された関数を呼び出します。
-
クライアントにメッセージを送信し、サーバのローカル変数 error と errorcode に現在の値を渡します。
%cdEHOOK ローカル変数
%cdEHOOK エラー・フックは、サーバの (つまり、個々のジョブ内の) ローカル変数です。このフックを使用するには、ルーチン名を含む文字列を $$label^rtn の形式で設定します。エラーが発生したときに、サーバはこの変数を評価します。変数が空ではない場合、サーバはこのルーチンを呼び出します。変数が空の場合、サーバは次の手順に進みます。
このフックは、エラー処理を追加で指定する場合に使用します。例えば、エラー・メッセージを拡張することができます。関数では、ローカル変数 error および errorcode を自由に使用できます。ただし、残りのエラー処理ルーチンでこれらを使用不可能にしないことが前提です(つまり、変数は依然として定義されており、それぞれ 2 バイト以内のテキストまたは数値である必要があります)。例えば、クライアントのアプリケーション・コードで活用できるように、エラー番号やテキストを変更または拡張できます。
キープ・アライブ機能
クライアント/サーバ・アプリケーションでは、クライアントやサーバが相互に接続できなくなる原因は多数あります。Caché Direct には、クライアントとサーバに対して、定期的に接続を確認し、接続が失われた場合には適切に対応するための手段が用意されています。サーバの場合、適切にシャットダウンすることが唯一の意義ある対応です。しかし、クライアントでは、例えば、新しいサーバ接続を確立したり、ユーザにメッセージを表示したりすることができます。
この機能には以下の要素が含まれます。
-
キープ・アライブ間隔の初期設定。詳細は、次のセクションで説明します。
-
キープ・アライブ間隔とタイムアウトを表すクライアントのプロパティ。詳細は、次のセクションで説明します。
-
クライアントでの ShutDown イベント。詳細は次のセクションで説明します。
-
独自の処理を追加するためのサーバのフック。ShutDownHook は、サーバがシャットダウンしたときに必ず使用されます。詳細は、この章後半の "その他のサーバ側フック (グローバル変数)" のセクションを参照してください。
初期のキープ・アライブ間隔
キープ・アライブ間隔 5 回分のうちに、クライアントからのメッセージを受信できなかった場合、サーバはシャットダウンします。サーバの起動時、KeepAliveInterval の初期値は 17,280 秒 (1 日の 1/5) です。したがって、既定の設定では、17,280 秒のキープ・アライブ間隔が 5 回 (合計 86,400 秒 (24 時間)) 経過するまでにクライアントから何の連絡もないと、サーバはシャットダウンします。通常は、300 (5 分間) のような低めの値に設定するのが適当です。
キープ・アライブ設定 (クライアント)
クライアントはキープ・アライブ間隔を制御し、サーバにキープ・アライブ・メッセージを送信するたびに、この値を再送信します。VisM には、キープ・アライブの動作を制御するためのプロパティが 2 種類あります。
-
KeepAliveInterval プロパティは、キープ・アライブ・メカニズムのために、通信のアイドル時間を秒単位で指定します。ここで指定された秒数、クライアント/サーバ通信が行われなかった場合、クライアントからサーバにキープ・アライブ・メッセージが送信されます。KeepAliveTimeOut プロパティで指定された期間、クライアントに応答が届かなければ、クライアントは ShutDown イベントを起動します。応答が届いた場合は、もう一度待機し、もう 1 つのキープ・アライブ・メッセージを送信します。
-
KeepAliveTimeOut プロパティは、キープ・アライブ・ラウンド・トリップのタイムアウトを表します。この値は通常のタイムアウト時間、TimeOut よりも短くなければいけません。
キープ・アライブ・エラーのシャットダウン・イベント (クライアント)
前述のように、クライアントは、キープ・アライブ・メッセージに対する応答を受信しなかった場合、次の操作を行います。
-
ConnectionState プロパティの値を変更します。
このプロパティは、常に、接続の状態を表しています。ConnectionState が 0 の場合、接続には問題がないか、切断が正常に行われています。このプロパティの値が 0 以外の場合、サーバから切断された時刻 (午前 0 時からの経過秒数) を表しています (これは $Horolog の秒部分と同じです。日付は示されませんが、最新であると見なされます)。
-
その後、ShutDown イベントが起動され、このイベントに 1 つの引数、つまり、ConnectionState プロパティの現在の値が渡されます。
接続が失われた後に、クライアントがメッセージを送信しようとすると、<ServerLost> エラーが発生します。
このイベントは、前述のとおり、クライアントがキープ・アライブ・メッセージに対する応答を受け取らなかった場合にのみ、トリガされます。
サーバの読み取りループと終了確認
Caché Direct サーバ・プロセスの設定後、このプロセスは、制限時間付きの読み取りで始まるポーリング・ループ内で、クライアントからの通信を待ち受けます。読み取りのタイムアウトは 10 秒間です。タイムアウトする前に読み取りが完了すると、サーバはクライアントとの通信を処理し、応答メッセージをクライアントに送信して、ポーリング・ループの先頭に戻ります。しかし、先にタイムアウトすると、サーバは指定された手順に従って、このサーバ・プロセスをシャットダウンするかどうかを判断します。詳細は、次のセクションで説明します。
サーバの終了確認手順
読み取りループがタイムアウトした場合、サーバは指定された手順に従って、このサーバ・プロセスをシャットダウンするかどうかを判断します。シャットダウンする必要があると判断した場合、サーバは ShutDownHook を呼び出し、そこで指定された処理を実行してからシャットダウンします。それ以外の場合、終了確認手順で指定された次の手順に進みます。
この手順では、次のように、複数のサーバ側フックが使用されています。
-
ローカルのアイドル時間フック (%cdPULSE) に指定された関数を呼び出し、要求された場合は、アイドル時間処理を実行します。関数から 0 が返された場合は、サーバは、サーバの終了確認手順を継続します。関数から 1 が返された場合は、サーバはシャットダウンします。
-
グローバルのアイドル時間フック (IdleHook) に指定された関数を呼び出し、要求された場合は、アイドル時間処理を実行します。関数から 0 が返された場合は、サーバは、サーバの終了確認手順を継続します。関数から 1 が返された場合は、サーバはシャットダウンします。詳細は、この章後半の "その他のサーバ側フック (グローバル変数)" のセクションを確認してください。
-
クライアントとの最後の通信から経過した時間を計算します。クライアントからの通信なしに、キープ・アライブ間隔 5 回分を超える時間が経過している場合、サーバはシャットダウンします。
-
システムがシャットダウン信号を受信したかどうかを確認します。受信している場合、サーバはシャットダウンします。
-
サーバが Stop^%CDSrv コマンドを受信したかどうかを確認します。受信している場合、サーバは Caché Direct サーバ・ジョブをすべてシャットダウンします。
-
サーバが StopJob^%CDSrv コマンドを受信したかどうかを確認します。受信している場合、サーバは指定されたサーバ・ジョブをシャットダウンします。
-
スレーブ・サーバを終了する必要があるかどうかを確認します。終了する必要がある場合、サーバはシャットダウンします。
どの手順でも、サーバをシャットダウンする必要があることが確認されると、シャットダウン・フック (ShutDownHook) が呼び出され、そこで指定された処理がすべて実行され、その後シャットダウンされます。
%cdPULSE ローカル変数
この %cdPULSE フックは、ローカル変数としてのみ (つまり、個々のサーバ・ジョブ内にのみ) 存在します。このフックを使用するには、関数呼び出しを含む文字列を $$label^rtn の形式で設定します。前のセクションで説明したとおり、サーバは、指定されたタイミングで、この変数を評価します。変数が空ではない場合、サーバは指定された関数呼び出しを実行し、その結果が 0 または "" でない場合は終了します。変数が空の場合、サーバは次の手順に進みます。
フックの読み取りと書き込み
前述のとおり、Caché Direct により、メッセージを送信する直前 (書き込みフック)、およびメッセージの受信直後 (読み取りフック) に処理を挿入するためのフックが用意されています。これらのフックは、カスタム・ログ、圧縮、暗号化など、アプリケーションにより選択された目的で使用することができます。クライアントの書き込みフックは、サーバの読み取りフックと、またクライアントの読み取りフックはサーバの書き込みフックと対になっています。書き込みフックによりメッセージが変換された場合、対応する読み取りフックで、このメッセージが Caché Direct で予期される形式になっていることを確認する必要があります。
メッセージの先頭 4 バイトは、メッセージの長さを表す 32 ビットの整数です。メッセージの長さを変更した場合は、必ず、この値を変更してください。
サーバ・ルーチンとクライアント・ルーチンが適切に対応していることを確認するのは、プログラマの責任です。
サーバ側の読み取りフックと書き込みフック
サーバ側のフックは、その他のサーバ側フックと同じ一般的なメカニズムを使用します。詳細は、"その他のサーバ側フック (グローバル変数)" のセクションを参照してください。
ReadHook
ExecuteCode メッセージの受信後、直ちにサーバで実行する必要がある処理を指定するには、このフックを使用します。サーバはクライアントから ExecuteCode メッセージを受信した直後、ミラーリングされたプロパティに値を割り当てる前に、このフックを呼び出します。
関数では、ローカル変数 %cdMSG が使用されます。この変数には受信メッセージが入っています。関数は、そのアクションを実行し、変換後のメッセージを返します。メッセージが変更されなかった場合は、単に終了 (Quit ^%cdMSG) します。
WriteHook
クライアントに応答を送信する前に、サーバが実行する必要がある処理を指定するには、このフックを使用します。サーバは、クライアントにメッセージを送信する直前に、このフックを呼び出します。
関数では、ローカル変数 %cdMSG が使用されます。この変数には送信メッセージが入っています。関数は、そのアクションを実行し、変換後のメッセージを返します。メッセージが変更されなかった場合は、単に終了 (Quit ^%cdMSG) します。
クライアント側の読み取りフックと書き込みフック
クライアント側でフックをインストールするには、VisM.ocx または VisM64.ocx ファイルと同じディレクトリに、それぞれ CDHooks.dll (32 ビット・システム用) または CDHooks64.dll (64 ビット・システム用) という DLL を作成します。フックは、次のように特定の名前と署名を持つエントリ・ポイントです。
unsigned char* ReadHook(unsigned char* pInMsg);
unsigned char* WriteHook(unsigned char* pInMsg);
void FreeHookMem(unsigned char* pMem);
ReadHook および WriteHook ルーチンは、次のように動作すると見なされています。
-
入力引数として、バイトのブロック、つまり受信メッセージへのポインタを取ります。
-
データのブロックへのポインタを返します。
-
新たに割り当てられたデータへのポインタを返します (この場合、クライアントは新しいデータ・ブロックをコピーし、FreeHookMem ルーチンを使用して、返り値を解放します)。
返り値と引数が同じである場合、メモリは解放されません。これは、データが変更されていないか、元のメッセージと同じ領域を占めている場合に起こる状況です。サーバ側のルーチンに適切に対応するクライアント・ルーチンを記述するのはユーザの責任です。
FreeHookMem ルーチンは、別のルーチンにより割り当てられたメモリを解放します。
その他のサーバ側フック (グローバル変数)
このセクションでは、グローバル変数に保存されているその他のサーバ側フックに関する参考情報について説明します。
このセクションで説明するフックはすべて、同じ一般的なメカニズムを使用します。グローバル ^%CDSwitch("HookName") に対して値を指定します。この値は、$$label^rtn の形式で記述された関数呼び出しを含む文字列です。このグローバルは、指定されたタイミングで、サーバにより評価されます。詳細は、この章の概要のセクションを参照してください。グローバルが空ではない場合、サーバは、指定された関数呼び出しを実行します。グローバルが空の場合、サーバは次の手順に進みます。
これらすべてについて、実行は次のように、間接指定により行われます。
Set @("r="_^%CDSwitch("HookName"))
ここで、r は返り値です。
BeginTaskHook
このフックは、保護パラメータの調整や、プロセスのネームスペースの変更などの作業に使用します。サーバは、サーバ・ジョブの作成後、コードの実行前に、このフックを呼び出します。詳細は、この章の 概要 のセクションを参照してください。
関数は、次のローカル・サーバ変数を引数として使用できます。
-
username – Caché Direct ユーザ名
-
taskname – myapp.exe など、クライアントで実行されている実行可能ファイルの名前
-
clientIP – クライアントの IP アドレスで、127.0.0.1 のように文字列の形式で表されています。これは、クライアントの接続方法に応じて、便利な場合とそうでない場合があります。例えば、非 TCP Citrix 接続は、形式的な IP アドレスを受け取ることにより、Caché ライセンス・システムの要求を満たします。
関数は次のいずれかの値を返します。
-
成功 (値 0)
-
エラー (^errornumber^errorname" という形式の文字列。ここで、errornumber は 0 ではありません)。Caché Direct エラー番号の 20900 ~ 20999 は、アプリケーション・エラーのために予約されています。エラーが発生した場合、エラー番号とテキストが VisM プロパティ、Error および ErrorName に表示され、エラー・イベントの信号が送られます。
IdleHook
ポーリングの読み取り間隔がタイムアウトした場合など、サーバがアイドル状態のときに、サーバ側で処理が行われるように指定するには、このフックを使用します。サーバは、終了確認手順の一環として、このフックを呼び出します。詳細は、この章の概要にある "サーバの終了確認手順" のセクションを参照してください。
EndTaskHook
サーバが、クライアントから EndTask メッセージを受信したときに実行する必要がある追加処理を指定するには、このフックを使用します。このフックは、任意のアプリケーションのクリーンアップで実行できます。
ShutDownHook
何らかの理由でサーバがシャットダウンされたときに実行する必要がある追加処理を指定するには、このフックを使用します。このフックは、サーバがシャットダウンされるたびに、サーバにより呼び出されます。
この関数は 0 (サーバをシャットダウンするべきではない場合) または 1 (サーバをシャットダウンする必要がある場合) のどちらかを返します。
ユーザ・キャンセル・オプション
VisM から Caché にメッセージを送信する場合、サーバによるメッセージ要求の処理に時間がかかり、ユーザが応答を待たなければならないことがあります。この待機時間が長い場合に、要求をキャンセルするオプションをユーザに提供することができます。これを設定するには、PromptInterval プロパティを使用します。このプロパティは、サーバが応答しない場合に、クライアント・アプリケーションが待機する時間 (秒) を表します。この時間が経過すると、ユーザに対してプロンプトが表示されます。このプロンプトは、さらに応答を待つか、操作をキャンセルするかを選択するためのオプションをユーザに提供します。MsgText プロパティは、この場合に使用されるメッセージを表す 4 部分で構成される文字列です。詳細は、"VisM.ocx コントロールの詳細" の章にある "その他の VisM プロパティ" のセクションを参照してください。