ELMのメカニズムはいくつかの簡単な例を用いると理解が容易です。以下に、2つ以上のノードで構成されるクラスタ (ノードA、ノードB、ノードC等) を例に説明します。
各ノードのロック名はRMS<nnnnnn>の形式で命名されています。<nnnnnn>は6桁のCFノードIDです。このため、各ノード名とノードIDおよびロック名との対応が簡単に分かります。ロックはCFによってクラスタごとに管理され、どのノードからどのロックに対してもアクセスを要求することができます。
あるノードがロックに対してはじめてのアクセス要求を行った場合、要求は直ちに許可されます。これは、ノードが最初はNULL状態で要求を受信するためです。これは特別な中立の状態であり、他のいかなるノードにおけるそのロックの状態とも競合しません。ローカルノードはここでELMに対し、ロックを別の状態に変更するよう要求できます。いったん要求が許可されると、ノードはその状態を維持することも、別の状態に変更することもできます。ただし、可能な処理はこの2つのみです。
ELMがサポートする状態はNULL状態以外には以下の2つだけです。
concurrent read (CR)
複数のノードがロックをこの状態で保持できます。これは他のノードがロックをexclusive状態に変更することを防止します。
exclusive (EX)
クラスタ内で1つのノードのみがロックをこの状態で保持できます。これは他のノードがロックをconcurrent状態またはexclusive状態に変更することを防止します。
変更の処理はELMの中心的な制御メカニズムです。他ノードとの競合が発生する変更を要求してもエラー状態は発生しません。その要求はELMが要求を許可できるようになるまで、キューに入れられます。要求しているプロセスはWait状態に置かれ、再活性化されることにより、その時点で、要求が許可されたことが分かります。
ノードがロックをNULL状態に戻すと、そのロックは解放されます。これにより、他のノードがロックを目的の状態に変更できるようになります。要求はキューに入れられた順序で許可されます。
たとえば、AがロックをEX状態に変更したとします。BはAのロックにアクセスを要求することが可能です。Bは直ちにNULL状態のロックを受信します。BがここでそのロックをCR状態に変更するように要求を発行すると、その要求はA (もしくはELM自身) がロックをNULLまたはCR状態に変更するまで待ち状態になります。これは、どちらもBの要求と競合しないためです。このようにしてBがAのロックの変更を完了すると、その時点で、BにはAがロックをEX状態に保っていないことが分かります。
他のノードのロックへのアクセス要求が直ちに許可され、ELMのロックメカニズムに影響を与えないため、このステップは以下の説明では省略します。
RMSを起動する最初のノードをAとします。以下の処理が行われます。
Aは自らのロックをEXモードに変更します。他のノードはこの時点ですでに起動処理を完了しているため、これは直ちに実行されます。
AはUDPハートビートを起動し、他ノードからの応答を待ちます。この時点ではまだ他ノードのロックの変更要求を出しません。
RMSを起動する2番目のノードをBとします。以下の処理が行われます。
Bは自らのロックをEXモードに変更します。Aはこの時点ではまだBのロックに対するアクセス要求をしていないため、モードの変更は直ちに実行されます。
BはUDPハートビートを起動し、他ノードからの応答を待ちます。この時点ではまだ他ノードのロックの変更要求を出しません。
Aは最初のハートビートをBから受信します。AはBのロックをCR状態に変更するように要求を発行します。BはロックをEX状態に維持しているため、Aの要求はELMキューに入って休眠します。
Aの要求が休眠状態にあるため、Bは自らのロックを保持しなければなりません。このため、BはOnline状態であることが必要で、AはBにその状態のマークを付けます。Aは自らの要求が休眠状態を続ける限り、BのOnline状態のマークを維持します。
BはAからのハートビートを検出し、同じ処理を実行します。BはAのロックをCRモードに変更しようとします。しかしAはロックをEX状態に維持しているため、Bの要求はELMキューに入って休眠します。
Bの要求が休眠状態を続ける限り、BはAのOnline状態のマークを維持します。
この時点で、2つのノードとも自身のロックをEX状態に保ち、それぞれ相手方のロックをCR状態に変更するように要求を発行しています。両者の要求とも休眠状態にありますが、このことは、両ノードが実行している処理以外に対しては何の影響も与えません。しかし、各ノードで要求の処理が完了していないといういうことは、他方のベースモニタがOnlineであるということを示しています。
RMSを起動する3番目のノードをCとします。AおよびBとの間で行われる処理は、上記2番目のノードの起動時と同様です。
Cは自らのロックをEX状態に変更し、ハートビートを開始し、他のノードからのハートビートを待ちます。
Cは、他ノードの1つから最初のハートビートを受け取った時点で、そのノードのロックをCR状態に変更しようとしますが、要求は休眠状態に入ります。
要求が休眠状態を続ける限り、Cは、他ノードのOnline状態のマークを維持します。
Cはあるノードから最初のハートビートを受け取ると、必ずステップ2と3を実行します。
同時に、Online状態にある他のノードはCの最初のハートビートを受信し、Cのロックについてステップ2と3を実行します。
クラスタ全体がOnline状態になった時点で、各ノードのロックは次の状態になっています。
ノードは自らのロックをEX状態に保っている。
ノードは、他のノードのロックをCR状態に変更する要求を発行済みであり、これらの要求はすべて休眠状態にある。
CFがリモートノードのLEFTCLUSTERイベントを発行した場合、または、リモートノードのベースモニタが停止した場合、ELMは、そのノードのロックをクラスタ内のすべてのノードでNULL状態に変更します。
たとえば、ノードBが停止したと仮定します。ノードA上では以下の処理が行われます。これは他のオンラインノードでも同様です。
BのロックをCR状態に変更するというAの要求が待機状態を脱します。その結果、AはそのロックをCR状態で維持します。
AはロックをNULL状態に変更し、BのマークをOffline状態にします。
AはBからハートビートを受信するまで、BのマークをOffline状態で維持します。ハートビートを受信した時点で、AはBのロックをCR状態に変更する要求を発行してロックサイクルを再始動します。
ノードBのベースモニタが最初に停止した場合も、同様の処理が行われます。大きな違いは、ノードが停止した場合は、LEFTCLUSTERイベントがELMロックのリリースに先行し、ベースモニタが停止した場合は、ELMロックのリリースがLEFTCLUSTERイベントに先行する点です。いずれの場合にも、RMSはノードの強制停止を開始します。
クラスタ内で何らかの故障が発生した場合に、ELMは他のベースモニタに対して能動的に警告を発します。ハートビートのタイムアウト時間が経過するのを待つ必要はありません。
ただし、通常終了の場合でも、ELMはほぼ同じような動作をしますが、その場合はノード自身がロックを解放します。また、RMSのレベルでは、ノードの強制停止は必要ありません。
リモートノードがビジー状態にある場合、そのベースモニタの反応は非常に遅くなります。ELMは状態ベースの監視方法であり、この状態を検出できません。このため、リモートノードの反応遅延が許容範囲を超えた場合は、RMSは時間ベースのUDPハートビートを使用します。
たとえば、ノードBは停止してはいませんが、ベースモニタの反応が非常に遅いとします。クラスタ内のあるノード (この例ではノードA) で次の処理が行われます。
BのロックをCR状態に変更するよう求めるAの要求は、sleep状態を続けます。これはBが引き続き動作中のためです。
Bのハートビート期間 (デフォルトは30秒) が経過し、さらに、ハートビートリカバリ期間 (デフォルトは600秒) が経過します。
ハートビートが失われたため、AはSFにBを強制停止するよう指示します (ただし、ELMは依然として問題を検出していません)。
Bの強制停止が完了すると、ELMはすべてのノードでロックを解放します。
Aが発行したBのロックの変更要求は許可されます。Aは直ちにロックを解放し、BのマークをOffline状態にします。
AはBのハートビートを待機し、ロックサイクルが再開します。
他のノードは、自らのロック要求が休眠状態を脱する前に、Bのハートビート喪失を検出する可能性があります。この場合にも、Bの強制停止を開始します。
これが、ELMがUDPハートビートをバックアップとして必要とする理由です。UDPが稼動していない場合、ELMロック要求は、リモートノードのサービス停止後もかなりの時間キューに残ることになります。