オプティミスティック・ロック・ストラテジーを使用しているときは、TransactionCallback プラグインによってキャッシュ・オブジェクトのバージョン管理および比較操作をカスタマイズすることができます。
com.ibm.websphere.objectgrid.plugins.OptimisticCallback インターフェースを実装するプラグ可能オプティミスティック・コールバック・オブジェクトを用意できます。エンティティー・マップの場合、ハイパフォーマンス OptimisticCallback プラグインが自動的に構成されます。
OptimisticCallback インターフェースを使用して、マップの値としてオプティミスティック比較演算を提供します。 オプティミスティック・ロック・ストラテジーを使用するときは、OptimisticCallback の実装が必要です。 WebSphere® eXtreme Scale はデフォルトの OptimisticCallback 実装を提供します。 ただし、通常、アプリケーションは独自の OptimisticCallback インターフェースの実装をプラグインする必要があります。 詳しくは、ロック・ストラテジーを 参照してください。
public interface Employee
{
// Sequential sequence number used for optimistic versioning.
public long getSequenceNumber();
public void setSequenceNumber(long newSequenceNumber);
// Other get/set methods for other fields of Employee object.
}
この場合、ローダーは、getSequenceNumber メソッドを使用して、Employee 値オブジェクトの現行バージョン情報を取得できることを認識しています。 ローダーは、戻り値を増分して、新規 Employee 値で永続ストレージを更新する前に、新規バージョン番号を生成します。 Java Database Connectivity (JDBC) ローダーの場合、過剰 SQL UPDATE ステートメントの WHERE 文節内の現行シーケンス番号が使用され、新規生成シーケンス番号を使用して、シーケンス番号列が新規シーケンス番号の値に設定されます。
このほかにも、オプティミスティック・バージョン管理に使用できる非表示の列を自動的に 更新するなんらかのバックエンド提供の関数をローダーが利用する可能性があります。場合によっては、ストアード・プロシージャーまたはトリガーを使用して、バージョン情報が入っている列を保守できるようにすることもあります。ローダーが、オプティミスティック・バージョン情報を保守するためにこれらの技法のいずれかを使用している場合は、アプリケーションが OptimisticCallback 実装を提供する必要はありません。ローダーは OptimisticCallback オブジェクトからの支援なしにオプティミスティック・バージョン管理を処理できるため、デフォルトの OptimisticCallback 実装を使用することができます。
エンティティーは、タプル・オブジェクトを使用して、ObjectGrid に保管されます。 デフォルトの OptimisticCallback 実装は、非エンティティー・マップに対する振る舞いと同様の振る舞いをします。 ただし、エンティティー内のバージョン・フィールドは、エンティティー記述子 XML ファイルの @Version アノテーションまたはバージョン属性を使用して識別されます。
バージョン属性の型は、int、Integer、short、Short、long、Long、java.sql.Timestamp のいずれかになります。エンティティーには、1 つだけのバージョン属性が定義される必要があります。バージョン属性は、構成時にのみ設定される必要があります。エンティティーが永続化されると、バージョン属性の値は変更してはなりません。
バージョン属性が構成されず、オプティミスティック・ロック・ストラテジーが使用される場合、タプルの全体の状態を使用して、タプル全体が暗黙的にバージョン設定されます。
@Entity
public class Employee
{
private long sequence;
// Sequential sequence number used for optimistic versioning.
@Version
public long getSequenceNumber() {
return sequence;
}
public void setSequenceNumber(long newSequenceNumber) {
this.sequence = newSequenceNumber;
}
// Other get/set methods for other fields of Employee object.
}
OptimisticCallback 実装は、OptimisticCallback インターフェースを実装し、共通 ObjectGrid プラグイン規則に準拠する必要があります。
次のリストには、OptimisticCallback インターフェース内の各メソッドについての説明または考慮事項があります。
この特殊値は、アプリケーション提供の OptimisticCallback 実装の代わりにデフォルトの OptimisticCallback 実装が使用される場合に、getVersionedObjectForValue メソッドによって戻されます。
getVersionedObjectForValue メソッドは、値のコピーを戻します。 あるいはバージョン管理のために使用できる値の属性を戻すことがあります。 このメソッドは、オブジェクトがトランザクションに関連付けられるたびに呼び出されます。 ローダーがバックアップ・マップ内に設定されていない場合、 バックアップ・マップは、コミット時刻にこの値を使用してオプティミスティック・バージョン管理比較を行います。 オプティミスティック・バージョン管理比較は、 このトランザクションが、このトランザクションによって変更されたマップ・エントリーに最初にアクセスしてから、 バージョンが変更されていないことを確認するために、バックアップ・マップによって使用されます。 別のトランザクションが既にこのマップ・エントリーのバージョンを変更している場合、 バージョン比較は失敗し、バックアップ・マップは OptimisticCollisionException 例外を表示して、 トランザクションを強制的にロールバックします。 ローダーがプラグインされている場合、 バックアップ・マップはオプティミスティック・バージョン管理情報を使用しません。 代わりに、ローダーは、オプティミスティック・バージョン管理比較を行い、 必要に応じてバージョン管理情報を更新する責任があります。 ローダーは通常、ローダーの batchUpdate メソッドに渡される LogElement から、初期バージョン管理オブジェクトを取得します。このオブジェクトは、フラッシュ操作が発生するか、トランザクションがコミットされたときに呼び出されます。
public Object getVersionedObjectForValue(Object value)
{
if (value == null)
{
return null;
}
else
{
Employee emp = (Employee) value;
return new Long( emp.getSequenceNumber() );
}
}
前の例に示すように、sequenceNumber 属性は、ローダーが予期するように、java.lang.Long オブジェクト内に戻されます。これは、ローダーの作成者と同一人物が EmployeeOptimisticCallbackImpl を作成したか、 EmployeeOptimisticCallbackImpl を実装した人物と協力して作業を行ったかのいずれかであることを示しています。 例えば、これらの人物は getVersionedObjectForValue メソッドによって戻された値に合意しました。 前に示したように、デフォルトの OptimisticCallback 実装は、バージョン・オブジェクトとして特殊値 NULL_OPTIMISTIC_VERSION を戻します。
public void updateVersionedObjectForValue(Object value)
{
if ( value != null )
{
Employee emp = (Employee) value;
long next = emp.getSequenceNumber() + 1;
emp.updateSequenceNumber( next );
}
}
前の例で示すように、sequenceNumber 属性は、次に getVersionedObjectForValue メソッドが呼び出されたときに、戻される java.lang.Long 値が元のシーケンス番号である長整数値を持つように、1 ずつ増分されます。 例えば、1 を加えたものは、この従業員インスタンスの次のバージョン値です。 この場合も、この例は、ローダーを作成者が EmployeeOptimisticCallbackImpl 実装の作成者と同一人物であるか、EmployeeOptimisticCallbackImpl 実装を実装した人物と協力して作業を行ったかのいずれかであることを示しています。
このメソッドは、指定されたストリームにバージョン値を書き込みます。 実装によっては、バージョン値を使用して、オプティミスティック更新の衝突を識別することができます。 一部の実装では、バージョン値は元の値のコピーです。 それ以外の実装では、値のバージョンを示すシーケンス番号またはその他のいくつかのオブジェクトがあります。 実際の実装が不明であるため、このメソッドは適切なシリアライゼーションを実行するために提供されます。 デフォルト実装は writeObject メソッドを呼び出します。
このメソッドは、バージョン値のシリアライズ・バージョンを取り、実際のバージョン値オブジェクトを戻します。 実装によっては、バージョン値を使用して、オプティミスティック更新の衝突を識別することができます。 一部の実装では、バージョン値は元の値のコピーです。 それ以外の実装では、 値のバージョンを示すシーケンス番号またはその他のいくつかのオブジェクトがあります。 実際の実装が不明であるため、このメソッドは適切なデシリアライゼーションを行うために提供されます。 デフォルト実装は readObject メソッドを呼び出します。
アプリケーション提供の OptimisticCallback を BackingMap 構成に追加する場合、プログラマチック構成と XML 構成の 2 つの方法があります。
import com.ibm.websphere.objectgrid.ObjectGridManagerFactory;
import com.ibm.websphere.objectgrid.ObjectGridManager;
import com.ibm.websphere.objectgrid.ObjectGrid;
import com.ibm.websphere.objectgrid.BackingMap;
ObjectGridManager ogManager = ObjectGridManagerFactory.getObjectGridManager();
ObjectGrid og = ogManager.createObjectGrid( "grid1" );
BackingMap bm = dg.defineMap("employees");
EmployeeOptimisticCallbackImpl cb = new EmployeeOptimisticCallbackImpl();
bm.setOptimisticCallback( cb );
<?xml version="1.0" encoding="UTF-8"?>
<objectGridConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ibm.com/ws/objectgrid/config ../objectGrid.xsd"
xmlns="http://ibm.com/ws/objectgrid/config">
<objectGrids>
<objectGrid name="grid1">
<backingMap name="employees" pluginCollectionRef="employees" lockStrategy="OPTIMISTIC" />
</objectGrid>
</objectGrids>
<backingMapPluginCollections>
<backingMapPluginCollection id="employees">
<bean id="OptimisticCallback" className="com.xyz.EmployeeOptimisticCallbackImpl" />
</backingMapPluginCollection>
</backingMapPluginCollections>
</objectGridConfig>