アプリケーションによるマップ更新の追跡

アプリケーションがトランザクション中にマップに変更を加えた場合、 LogSequence オブジェクトはこれらの変更を追跡します。アプリケーションがマップ内のエントリーを変更する場合には、対応する LogElement オブジェクトがその変更の詳細を提供します。

アプリケーションがフラッシュを必要とするか、トランザクションにコミットすると必ず、特定のマップのための LogSequence オブジェクトにローダーが提供されます。ローダーは LogSequence オブジェクト内の LogElement オブジェクトで繰り返されて、各 LogElement オブジェクトをバックエンドに適用します。

ObjectGrid に登録されている ObjectGridEventListener リスナーも LogSequence オブジェクトを使用します。 これらのリスナーには、コミット済みトランザクションの各マップに LogSequence オブジェクトが提供されます。 アプリケーションはこれらのリスナーを使用して、従来のデータベースでのトリガーのような、 変更に対する特定のエントリーを待機できます。

以下のログ関連インターフェースまたはクラスは、eXtreme Scale フレームワークによって提供されます。

LogElement インターフェース

LogElement は、トランザクション中のエントリーに関する操作を示します。 LogElement オブジェクトには、その各種の属性を取得するためのいくつかのメソッドがあります。最も一般的に使用される属性は、getType() でフェッチされる type 属性と getCurrentValue() でフェッチされる current value 属性です。

type は、LogElement インターフェース内で定義される定数 INSERT、UPDATE、 DELETE、EVICT、FETCH、または TOUCH のうちの 1 つで表わされます。

current value は、INSERT、UPDATE、または FETCH 操作の場合にその新規の値を表します。操作が TOUCH、DELETE、または EVICT の場合は、current value は NULL になります。ValueInterface が使用中である場合、この値を ValueProxyInfo へキャストできます。

LogElement インターフェースについて詳しくは、API 資料を参照してください。

LogSequence インターフェース

ほとんどのトランザクションで、 マップ内の複数エントリーに対する操作が行われるため、複数の LogElement オブジェクトが作成されます。複数の LogElement オブジェクトのコンポジットとして動作するオブジェクトを作成する必要があります。LogSequence インターフェースは、LogElement オブジェクトのリストを含むことによって この目的に対応します。

LogSequence インターフェースについて詳しくは、API 資料を参照してください。

LogElement および LogSequence の使用

LogElement と LogSequence は、eXtreme Scale や、操作が 1 つのコンポーネントまたはサーバーから別のコンポーネントまたはサーバーに伝搬されるときにユーザーによって作成された ObjectGrid プラグインによって、幅広く使用されています。例えば、LogSequence オブジェクトは、分散 ObjectGrid トランザクション伝搬機能によって 変更を他のサーバーに伝えるために使用できます。 あるいは、ローダーによってパーシスタンス・ストアに適用することもできます。 LogSequence は主に以下のインターフェースによって使用されます。

  • com.ibm.websphere.objectgrid.plugins.ObjectGridEventListener
  • com.ibm.websphere.objectgrid.plugins.Loader
  • com.ibm.websphere.objectgrid.plugins.Evictor
  • com.ibm.websphere.objectgrid.Session

ローダーの例

このセクションでは、LogSequence および LogElement オブジェクトが ローダーで使用される方法について説明します。ローダーは、永続ストアからデータをロードし、永続ストアにデータを保管するために使用されます。 ローダー・インターフェースの batchUpdate メソッドは、以下のように LogSequence オブジェクトを使用します。

void batchUpdate(TxID txid, LogSequence sequence) throws
			LoaderException, OptimisticCollisionException;

ObjectGrid が現在のすべての変更をローダーに適用する必要がある場合に、batchUpdate メソッドが呼び出されます。 ローダーには、マップのための LogElement オブジェクトのリストが、カプセル化されて LogSequence オブジェクトに与えられています。batchUpdate メソッドの実装は変更を繰り返し、それらの変更をバックエンドに適用する必要があります。 以下のコード・スニペットは、ローダーが LogSequence オブジェクトを使用する方法を示しています。 このスニペットは、一連の変更を繰り返し、INSERT、UPDATE、および DELETE という 3 つのバッチ Java Database Connectivity (JDBC) ステートメントをビルドします。

public void batchUpdate(TxID tx, LogSequence sequence) throws LoaderException
{
    // Get a SQL connection to use.
    Connection conn = getConnection(tx);
    try
    {
    // Process the list of changes and build a set of prepared
    // statements for executing a batch update, insert, or delete
    // SQL operations. The statements are cached in stmtCache.
    Iterator iter = sequence.getPendingChanges();
    while ( iter.hasNext() )
    {
        LogElement logElement = (LogElement)iter.next();
        Object key = logElement.getCacheEntry().getKey();
        Object value = logElement.getCurrentValue();
        switch ( logElement.getType().getCode() )
        {
            case LogElement.CODE_INSERT:
                buildBatchSQLInsert( key, value, conn );
                break;
            case LogElement.CODE_UPDATE:
                buildBatchSQLUpdate( key, value, conn );
                break;
            case LogElement.CODE_DELETE:
                buildBatchSQLDelete( key, conn );
                break;
        }
    }
    // Run the batch statements that were built by above loop.
    Collection statements = getPreparedStatementCollection( tx, conn );
    iter = statements.iterator();
    while ( iter.hasNext() )
    {
        PreparedStatement pstmt = (PreparedStatement) iter.next();
        pstmt.executeBatch();
    }
} catch (SQLException e)
{
    LoaderException ex = new LoaderException(e);
    throw ex;
}
}

前のサンプルは、LogSequence 引数処理の高水準ロジックを示していますが、SQL の INSERT、UPDATE、または DELETE ステートメントのビルド方法の詳細は示していません。getPendingChanges メソッドが LogSequence 引数で呼び出され、ローダーが処理する必要のある LogElement オブジェクトのイテレーターを取得します。また、LogElement.getType().getCode() メソッドを使用して、LogElement が SQL の挿入、更新、または削除操作に使用されるかどうかを判別します。

Evictor の例

Evictor で LogSequence および LogElement オブジェクトを使用することもできます。Evictor は、特定の基準に基づいてバッキング・マップからマップ・エントリーを除去するために使用します。 Evictor インターフェースの apply メソッドは、LogSequence を使用します。

/**
* This is called during cache commit to allow the evictor to track object usage
* in a backing map. This will also report any entries that have been successfully
* evicted.
*
* @param sequence LogSequence of changes to the map
*/
void apply(LogSequence sequence);

apply メソッドが LogSequence を使用する方法について詳しくは、カスタム Evictor の作成 トピックのコード・サンプルを参照してください。

LogSequenceFilter および LogSequenceTransformer インターフェース

場合によっては、特定の基準の LogElement オブジェクトのみを受け入れ、その他のオブジェクトを拒否するように、 LogElement オブジェクトをフィルターに掛ける必要があります。例えば、何らかの基準に基づいて、特定の LogElement を直列化する場合があります。

LogSequenceFilter は、以下のメソッドでこの問題を解決します。

public boolean accept (LogElement logElement);

このメソッドは、操作で特定の LogElement を 使用する必要がある場合は true を、その必要がない場合は false を返します。

LogSequenceTransformer は、LogSequenceFilter 関数を使用するクラスです。LogSequenceFilter を使用して一部の LogElement オブジェクトにフィルターを掛け、 次に、その受け入れた LogElement オブジェクトを直列化します。このクラスには、2 つのメソッドがあります。最初のメソッドは以下のとおりです。

public static void serialize(Collection logSequences, ObjectOutputStream stream,
			LogSequenceFilter filter, DistributionMode mode) throws IOException

このメソッドにより、呼び出し元は、直列化プロセスに 組み込む LogElements を判定するためのフィルターを提供できます。呼び出し元は、DistributionMode パラメーターを使用して直列化プロセスを制御します。 例えば、分散モードが無効化のみである場合、値を直列化する必要はありません。 このクラスの 2 番目のメソッドは、以下のような inflate メソッドです。

public static Collection inflate(ObjectInputStream stream, ObjectGrid
			objectGrid) throws IOException, ClassNotFoundException

inflate メソッドは、serialize メソッドによって作成されたログ・シーケンスの直列化済みフォームを、提供されたオブジェクト入力ストリームから読み取ります。