Solaris DHCP サービス開発ガイド

更新における衝突の回避

アーキテクチャは、ファイルベースのモジュールがレコード更新における衝突を回避するのを助ける機能を提供します。サービスプロバイダ API では、レコード単位の更新シグニチャ (符号なしの 64 ビット整数) を使用することによって、データの整合性を維持します。この更新シグニチャは、/usr/include/dhcp_svc_public.h で定義された、d?_rec_t コンテナレコードデータ構造の d?_sig 要素です。アプリケーション/サービス層からフレームワーク構成層 API、およびサービスプロバイダ層 API に至るまで、このアーキテクチャのすべての層が d?_rec_t を使用します。サービスプロバイダ層より上では、更新シグニチャは、フレームワーク構成層 API のユーザーからは操作されない不透明なオブジェクトです。

モジュールは、サービスプロバイダ層 API 関数呼び出しを通して d?_rec_t レコードを受け取ったら、d?_rec_t のキーフィールドとマッチするレコードをデータサービス内で検索し、内部レコードのシグニチャと呼び出しから渡された d?_rec_t を比較する必要があります。内部レコードのシグニチャが、渡されたレコードのものとマッチしない場合、レコードは、その使用者がパブリックモジュールから取得した後で変更されていることを意味します。この場合には、モジュールは、レコードが前に取得されたときから変更されていることを呼び出し元に知らせる DSVC_COLLISION を返す必要があります。シグニチャがマッチする場合は、モジュールは、そのレコードを格納する前に引数レコードの更新シグニチャを増分する必要があります。

モジュールがサービスプロバイダ層 API を通して新しい d?_rec_t レコードを受け取ったら、そのモジュールはそれをコンテナに追加する前に、更新シグニチャに値を設定する必要があります。最もシンプルな方法は、値に 1 を設定する方法です。

ただし、まれなケースとはいえ、シグニチャが常に同じ初期値を持つと、更新における衝突を検出できないことがあります。たとえば、次のような場合です。まず、スレッド A がシグニチャ 1 のレコードを追加し、スレッド B がそのレコードを検索します。次に、スレッド A がそのレコードを削除し、同じキーフィールドでシグニチャ 1 の新しいレコードを作成します。その後スレッド B が、検索したレコードを変更しますが、それはすでに削除されています。モジュールは、スレッド B が検索したレコードのキーフィールドとシグニチャをデータ格納内のレコードと比較し、両者が同じなので変更を行います。しかし、これらのレコードは実際は同じものではないので、このような変更の試行は、本来は衝突とされるべきものです。

Solaris DHCP で提供される ds_SUNWfiles.sods_SUNWbinfiles.so モジュールは、こういった可能性を指摘します。これらのモジュールは、各レコードのシグニチャの一意性を確実にするために更新シグニチャを 2 つのフィールドに分割します。更新シグニチャの最初の 16 ビットフィールドに、ランダムに生成した数値を設定します。このフィールドは、設定後、レコード内で変更されません。シグニチャの下位 48 ビットフィールドには 1 が設定され、レコードが更新されるたびに 1 つずつ増分されます。


注 –

Solaris DHCP で提供されるモジュールは、レコードの更新における衝突を避けるためのアプローチの 1 つです。ユーザーは、これと似た方法を使用したり、独自の方法を考案することができます。