CLOVER🍀

That was when it all began.

InfinispanのListener機能を使ってみる - 2

前回の続きです。InfinispanのListener自体とか、ソースコードや設定ファイルについては前回のエントリを参照してくださいね。

InfinispanのListener機能を使ってみる - 1
http://d.hatena.ne.jp/Kazuhira/20130626/1372258778

では、簡単そうなものから行ってみましょう。基本的にはinfinispan.xmlの設定変更で、挙動を変更します。どこを変えるのかは、とりあえず端折ります。

また、クラスタリングが登場するまでは、実行しているのは

> run-main InfinispanListeners

という感じです。

クラスタリング、CacheStore、トランザクション全部なし

1番単純そうなやつです。

Cacheにエントリを登録する

[info] [InfinispanListeners$]# エントリ (key1,value1) を登録します
[info] [CacheLevelListener]# [Pre ] 作成イベント => key1:null
[info] [CacheLevelListener]# [Pre ] 変更イベント => key1:null, isCreated? => true
[info] [CacheLevelListener]# [Post] 変更イベント => key1:value1, isCreated? => true
[info] [CacheLevelListener]# [Post] 作成イベント => key1:value1

作成と変更のイベントが、順次発生します。

ここでのコンソールの見方ですが、[CacheLevelListener]と言っているのは、ログを出力しているクラスです。また、Pre/Postと言っているのはEvent#isPreの判定結果を表しています。まあ、イベント発生前後ということですね。

Cache中のエントリを参照します。

[info] [InfinispanListeners$]# エントリ (key1,value1) を参照します
[info] [CacheLevelListener]# [Pre ] 参照イベント => key1:value1
[info] [CacheLevelListener]# [Post] 参照イベント => key1:value1

まあ、普通に…

ただ、存在しないエントリを参照しても、イベントは発生しません。

更新。

[info] [InfinispanListeners$]# エントリ (key1,value1-replace) をreplaceで更新します
[info] [CacheLevelListener]# [Pre ] 変更イベント => key1:value1, isCreated? => false
[info] [CacheLevelListener]# [Post] 変更イベント => key1:value1-replace, isCreated? => false
[info] [InfinispanListeners$]# エントリ (key1,value1-put) をputで更新します
[info] [CacheLevelListener]# [Pre ] 変更イベント => key1:value1-replace, isCreated? => false
[info] [CacheLevelListener]# [Post] 変更イベント => key1:value1-put, isCreated? => false

replaceでもputでも存在するエントリに対して、変更イベントが発生します。

削除。

[info] [InfinispanListeners$]# エントリ (key1,value1) を削除します
[info] [CacheLevelListener]# [Pre ] 削除イベント => key1:value1-put, 古い値 => value1-put
[info] [CacheLevelListener]# [Post] 削除イベント => key1:null, 古い値 => value1-put

Cacheの起動・停止

Cache#stop時

[info] [CacheManagerLevelListener]# キャッシュ停止イベント => listenersCache

Cache#start時

[info] [CacheManagerLevelListener]# キャッシュ開始イベント => listenersCache

と普通に発生しますが、最初のCacheManagerからgetCacheした時には、すでに開始した状態で取得するでしょうけど、何も起こりません。開始イベントを見ることができるのは、あえて停止、開始をした時なんでしょうね。

なお、こちらは[CacheManagerLevelListener]なのでCacheManagerレベルのイベントになります。

CacheStoreを付ける

単にCacheStoreを使用しただけだと、先の単純なケースと動きが変わりません。

細工として、preloadをfalseにすると起動時にエントリをロードしなくなるため、

    <loaders passivation="false" shared="false" preload="false">

エントリの参照などにCacheStoreからロードするため、イベントが発生するようになります。こちらは、参照した時の動きです。

[info] [CacheLevelListener]# [Pre ] ロード完了イベント => key100:value100
[info] [CacheLevelListener]# [Post] ロード完了イベント => key100:value100
[info] [CacheLevelListener]# [Pre ] 参照イベント => key100:value100
[info] [CacheLevelListener]# [Post] 参照イベント => key100:value100
[info] [CacheLevelListener]# [Post] 変更イベント => key100:value100, isCreated? => false

ロード完了後に、参照イベントが発生しています…が、最後に変更イベントが入ってますね…。

今回のサンプルプログラムだと2回起動しないと、CacheStoreからエントリをロードしません。まあ、ロードしちゃうとメモリに載ったままですしね。

Evictionを有効に

では、Evictするようにしてみます。

    <eviction strategy="LIRS" maxEntries="2" />
    <loaders passivation="false" shared="false" preload="false">

あ、確認のテーマが変わる都度、CacheStoreのデータは消していますからね。

EvictのmaxEntriesをすごい絞っているので、ちょっと追加すると普通に追い出されます。

[info] [CacheLevelListener]# [Pre ] 作成イベント => key102:null
[info] [CacheLevelListener]# [Pre ] 変更イベント => key102:null, isCreated? => true
[info] [CacheLevelListener]# [Post] エビクトイベント => {key100=value100}
[info] [CacheLevelListener]# [Post] 変更イベント => key102:value102, isCreated? => true
[info] [CacheLevelListener]# [Post] 作成イベント => key102:value102

ここでは、キーがkey102のエントリを登録する時に、キーkey100のエントリがEvictされてます。

2回目以降の起動では、参照時にロードが発生しつつ、その時にEvictされたり

[info] [CacheLevelListener]# [Pre ] ロード完了イベント => key102:value102
[info] [CacheLevelListener]# [Post] ロード完了イベント => key102:value102
[info] [CacheLevelListener]# [Pre ] 参照イベント => key102:value102
[info] [CacheLevelListener]# [Post] 参照イベント => key102:value102
[info] [CacheLevelListener]# [Post] エビクトイベント => {key100=value100}
[info] [CacheLevelListener]# [Post] 変更イベント => key102:value102, isCreated? => false

変更時には変更と作成イベントが発生したりもします。

[info] [CacheLevelListener]# [Pre ] ロード完了イベント => key102:value102
[info] [CacheLevelListener]# [Post] ロード完了イベント => key102:value102
[info] [CacheLevelListener]# [Pre ] 変更イベント => key102:value102, isCreated? => false
[info] [CacheLevelListener]# [Post] エビクトイベント => {key109=value109}
[info] [CacheLevelListener]# [Post] 変更イベント => key102:value102, isCreated? => true
[info] [CacheLevelListener]# [Post] 作成イベント => key102:value102

もちろん、この時にEvictされるエントリもあるわけですが。

Passivationも有効に

さらに、Passivationも有効にしてみましょう。

    <eviction strategy="LIRS" maxEntries="2" />
    <loaders passivation="true" shared="false" preload="false">

今度は、エントリの追加時にPassivateとEvictイベントが発生するようになります。

[info] [CacheLevelListener]# [Pre ] 作成イベント => key102:null
[info] [CacheLevelListener]# [Pre ] 変更イベント => key102:null, isCreated? => true
[info] [CacheLevelListener]# [Pre ] 非活性化イベント => key100:value100
[info] [CacheLevelListener]# [Post] 非活性化イベント => key100:null
[info] [CacheLevelListener]# [Post] エビクトイベント => {key100=value100}
[info] [CacheLevelListener]# [Post] 変更イベント => key102:value102, isCreated? => true
[info] [CacheLevelListener]# [Post] 作成イベント => key102:value102

あと、ここだけちょっとコードを変えたのですが、Evictされたエントリを参照しようとすると

[info] [CacheLevelListener]# [Pre ] ロード完了イベント => key100:value100
[info] [CacheLevelListener]# [Pre ] 活性化イベント => key100:value100
[info] [CacheLevelListener]# [Post] ロード完了イベント => key100:value100
[info] [CacheLevelListener]# [Post] 活性化イベント => key100:value100
[info] [CacheLevelListener]# [Pre ] 参照イベント => key100:value100
[info] [CacheLevelListener]# [Post] 参照イベント => key100:value100
[info] [CacheLevelListener]# [Pre ] 非活性化イベント => key110:value110
[info] [CacheLevelListener]# [Post] 非活性化イベント => key110:null
[info] [CacheLevelListener]# [Post] エビクトイベント => {key110=value110}
[info] [CacheLevelListener]# [Post] 変更イベント => key100:value100, isCreated? => false

ロード、Activate、参照、他のエントリのPassivateとEvict、最後にロードしたエントリの変更イベントと盛りだくさんなイベントが発生します。

では、ここまででPassivationは無効にして、Evictionだけ有効にしておきます。

こんな感じ。

    <eviction strategy="LIRS" maxEntries="2" />
    <loaders passivation="false" shared="false" preload="true">

トランザクションを使う

トランザクションは、前回載せたinfinispan.xmlのトランザクション設定をそのまま使用しています。

オートコミットも有効にしてあるので、普通にCache#putするのにもトランザクションがかかるようになります。

[info] [InfinispanListeners$]# エントリ (key1,value1) を登録します
[info] [CacheLevelListener]# [Post] トランザクション登録 => GlobalTransaction:<ubuntu-39315>:1:local, isOriginLocal? => true
[info] [CacheLevelListener]# [Pre ] 作成イベント => key1:null
[info] [CacheLevelListener]# [Pre ] 変更イベント => key1:null, isCreated? => true
[info] [CacheLevelListener]# [Post] 変更イベント => key1:value1, isCreated? => true
[info] [CacheLevelListener]# [Post] 作成イベント => key1:value1
[info] [CacheLevelListener]# [Post] トランザクション完了 => GlobalTransaction:<ubuntu-39315>:1:local, isTransactionSuccessful? => true, isOriginLocal? => true

実際にJTAを利用したトランザクション管理を行うと、コミットできた場合は

[info] [InfinispanListeners$]# トランザクションを開始します
[info] [InfinispanListeners$]# データ (transactional-key1,transactional-value1) を登録します
[info] [CacheLevelListener]# [Post] トランザクション登録 => GlobalTransaction:<ubuntu-39315>:5:local, isOriginLocal? => true
[info] [CacheLevelListener]# [Pre ] 作成イベント => transactional-key1:null
[info] [CacheLevelListener]# [Pre ] 変更イベント => transactional-key1:null, isCreated? => true
[info] [InfinispanListeners$]# データ (transactional-key1,transactional-value1-update) を更新します
[info] [CacheLevelListener]# [Pre ] 変更イベント => transactional-key1:transactional-value1, isCreated? => false
[info] [InfinispanListeners$]# トランザクションをコミットします
[info] [CacheLevelListener]# [Post] 変更イベント => transactional-key1:transactional-value1-update, isCreated? => true
[info] [CacheLevelListener]# [Post] 作成イベント => transactional-key1:transactional-value1-update
[info] [CacheLevelListener]# [Post] トランザクション完了 => GlobalTransaction:<ubuntu-39315>:5:local, isTransactionSuccessful? => true, isOriginLocal? => true

という感じになります。TransactionManager#commit時に、変更・作成の後半のイベントが発生するところがポイントです。

ロールバックした場合は

[info] [InfinispanListeners$]# トランザクションを開始します
[info] [InfinispanListeners$]# データ (transactional-key1,transactional-value1) を削除します
[info] [CacheLevelListener]# [Post] トランザクション登録 => GlobalTransaction:<ubuntu-39315>:6:local, isOriginLocal? => true
[info] [CacheLevelListener]# [Pre ] 削除イベント => transactional-key1:transactional-value1-update, 古い値 => transactional-value1-update
[info] [InfinispanListeners$]# データ (transactional-key2,transactional-value2) を登録します
[info] [CacheLevelListener]# [Pre ] 作成イベント => transactional-key2:null
[info] [CacheLevelListener]# [Pre ] 変更イベント => transactional-key2:null, isCreated? => true
[info] [InfinispanListeners$]# トランザクションをロールバックします
[info] [CacheLevelListener]# [Post] トランザクション完了 => GlobalTransaction:<ubuntu-39315>:6:local, isTransactionSuccessful? => false, isOriginLocal? => true

更新系のイベントの、後半部分がなくなります。Preしか出ていませんね。

長くなってきたので、クラスタリングは次回に。