verbs インターフェースのプログラミング・ヒント (Linux のみ)
jVerbs verbs インターフェースを使用するアプリケーションを開発するプロセスは複雑です。 開発者を支援するために、ヒントおよびベスト・プラクティスについていくつか説明します。


ステートフル verbs メソッド (SVM) オブジェクトの作成
ステートフル操作は、 postSend() や postReceive()などのファスト・パス・データ操作のために Java Native Interface (JNI) を介して複雑な構造を渡すことによるパフォーマンスへの影響を回避します。 ステートフル・メソッド・オブジェクトは、一度だけ作成すれば、複数回使用できます。 例えば、同じバッファーで同じデータを再送信したり、受信したりできます。 SVM オブジェクトは、JNI を介して渡さなければならないパラメーターを保持するために、ダイレクト・バイト・バッファーを割り振ります。 SVM オブジェクトが不要になったら、free() メソッドを使用して SVM オブジェクトを解放し、ガーベッジ・コレクションの対象としてそのバッファーにマークを付けることができるようにする必要があります。 最後の操作が正常に終了したかどうかを調べるには、IsSuccess() メソッドを使用します。
完了キューの共有
複数の接続 ID 間で完了キューを共有する場合は、完了キュー・エントリーが、すべての送受信操作を行うのに十分な大きさであることを確認します。 制限の設定は、createCompletionQueue() メソッドを使用してキューを作成するときに、引数を渡すことによって行います。 完了エントリーが多すぎる場合にデバイス制限に達すると、IOException 例外が発生し、残りの完了エントリーは失われます。
WorkCompletion.getQueuePairNum() メソッドは、作業完了エントリーが属しているキュー・ペア番号を一意的に識別します。 したがって、作業完了イベントを、対応する接続 ID にディスパッチして、操作を続けることができます。
通知の要求
完了キューが CompletionChannel.getCQEvent() 呼び出しを待っているときに、CompletionQueue.requestNotifyCQ() メソッドを呼び出してアプリケーション・スレッドに通知する必要があります。 CompletionQueue.requestNotifyCQ() メソッドを使用して通知を要求しない場合は、完了キューで完了イベントを受信したときに通知が送信されません。 ただし、完了イベントは完了キューに入れられます。この完了キューを、pollCQ() メソッドを使用してポーリングすることができます。
通知を getCQEvent() メソッドから受信すると、次の getCQEvent() メソッドのために、requestNotifyCQ() メソッドを再度呼び出す必要があります。 要求をキューに入れるために CompletionQueue.requestNotifyCQ() メソッドを複数回呼び出すことはできません。次の getCQEvent() メソッドに登録される通知要求は 1 つのみです。
CompletionQueue.requestNotifyCQ() メソッドは、送信請求イベント、またはすべてのイベントについて、完了キューでの完了時に通知が必要かどうかを判別するブール・データ型を受け入れます。 イベントに送信請求のマークを付ける場合は、作業請求にIBV_SEND_SOLICITED
フラグを設定できます。
キュー・ペアの作成
キュー・ペアは、送信要求および受信要求をポストするために必要です。 新しいキュー・ペアを作成する場合は、システムに存在するその他のアクティブなキュー・ペアを考慮する必要があります。 任意の時点で送信または受信用にポストされる作業要求の数に合った、キュー・ペアのサイズを選択します。 キュー・ペアのデバイス制限を超えると、IOException 例外が発生します。 キュー・ペアの作成時にキュー・ペア・サイズを設定できますが、既存のキュー・ペアと使用可能なリソースに基づいて、より適切なサイズをシステムによって選択することができます。 作成後にキュー・ペアの実際のサイズを確認するには、QueuePair.getQueuePairLimit() メソッドを使用します。
送信バッファーまたは受信バッファーのポスト
RDMA 操作は非同期です。 送信バッファーまたは受信バッファーをポストすることは、作業が実際に送信されたり、受信されたりすることを表すわけではありません。 送信バッファーまたは受信バッファーをポストしたクライアントやサーバーは、作業完了まで待機して、送信または受信の操作が正常に終了したかどうかを判別する必要があります。 作業完了状況は、成功または失敗を判別する WorkCompletion.getStatus() メソッドを使用して照会することができます。 WorkCompletion.getOpcode() メソッドを使用して、送信または受信の操作が完了したかどうかを確認することもできます。 作業が完了していれば、送信バッファーまたは受信バッファーを再使用できます。 ポストした操作が完了していない場合に、登録された同じバッファーを再使用すると、異常終了またはメモリー破損につながるおそれがあります。
接続が確立したときにデータ転送の欠落を防止するために、クライアント・サイドから接続する前、かつサーバー・サイドで受け入れる前に、バッファーを所定の位置に配置する必要があります。 データを受信するときに、バッファーの位置は変わりません。これは、RDMA 操作ではバッファーを pin して内容をコピーするためです。 アプリケーションは、書き込まれたバイト数を特定することによって、バッファー位置の変更に対処する必要があります。 正常に送信または受信されたバイト数に関する情報を取得するには、WorkCompletion.getByteLength() メソッドを使用します。 このデータを使用できるのは、完了状況が正常である場合に限られます。
PollCQEvent() メソッドおよび getCQEvent() メソッドの使用
getCQEvent() メソッドは、メソッドが呼び出されるチャネルでイベントを受信したときに、呼び出しコードに通知します。 チャネルからイベントを取り出すには、PollCQEvent() メソッドを呼び出す必要があります。 getCQEvent() メソッドを pollCQEvent() メソッドと組み合わせることにより、イベントを受信したことを確認してから、そのイベントを取り出すことができます。 または、取り出すイベントがない場合はゼロのポーリング数が返されるので、pollCQEvent() メソッドを単独で使用することもできます。 ただし、getCQEvent() メソッドとは異なり、pollCQEvent() メソッドは、プロセッサーを占有し、プロセッサー・サイクルを使用します。 アプリケーションは、getCQEvent() メソッドと pollCQEvent() メソッドを一緒に使用すること、または pollCQEvent() メソッドのみを使用することを選択できます。
リソースの削除
- 通信を終了する準備ができたら、サーバーまたはクライアントから切断を開始する必要があります。 切断により、未解決のイベントまたは要求が削除されてから、リソースが削除されます。 切断により、RDMA_CM_EVENT_DISCONNECTED タイプのイベントが生成されます。このイベントは、接続の他方のサイドに送信されます。 他方のサイドでは、そのサイドにあるリソースの削除を開始する必要があります。 disconnect() メソッドを再度呼び出す必要はありません。
- 接続 ID を削除する前に、destroyQueuePair() メソッドを使用して、関連付けられたキュー・ペアを削除する必要があります。
- 完了キューは、完了チャネルより前に削除する必要があります。
- 完了チャネルは、すべての完了キュー通知要求に対して確認応答を行わないと削除できません。 したがって、成功した各 getCQEvent() 呼び出しを ackCQEvent() 呼び出しと組み合わせる必要があります。
- イベント・チャネルは、すべての接続要求に対して確認応答を行わないと削除できません。 したがって、成功した各 getConnectionEvent() 呼び出しを ackConnectionEvent() 呼び出しと組み合わせる必要があります。