ICrmLogControl
COM公式ドキュメント
CRM Worker および CRM Compensator が、ログにレコードを書き込み、それらを永続化するための手段です。
解説(Remarks)
CRM Compensator は、インスタンス化後に ICrmCompensator::SetLogControl メソッドまたは ICrmCompensatorVariants::SetLogControlVariants メソッドを使用して、このインターフェイスを受け取ります。
各メソッドについて記載された戻り値に加えて、これらのメソッドは Distributed Transaction Coordinator (DTC) からのエラーコードやその他の標準的な COM エラーコードを返す場合もあります。
メソッド 7
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
トランザクションの作業単位 (UOW) を、ログレコードに記録することなく取得します。
| pVal | LPWSTR* | out | トランザクションの UOW。 |
戻り値
このメソッドは次の値を返す場合があります。
| リターンコード | 説明 |
|---|---|
| メソッドは正常に完了しました。 | |
| 引数として NULL ポインターが指定されました。 | |
| このメソッドが誤った状態で呼び出されました。RegisterCompensator の前、またはトランザクションが完了しつつあるとき (CRM Worker) のいずれかです。 | |
| メモリ不足エラーが発生しました。 |
CRM Worker はこのメソッドを使用して、CRM Compensator を CRM インフラストラクチャに登録します。
| lpcwstrProgIdCompensator | LPWSTR | in | CRM Compensator の ProgId。CRM Compensator の CLSID を文字列形式で指定することもできます。 |
| lpcwstrDescription | LPWSTR | in | 監視インターフェイスで使用される説明文字列。 |
| lCrmRegFlags | INT | in | CRMREGFLAGS 列挙型のフラグで、トランザクション完了のどのフェーズを CRM Compensator が受け取るか、および回復を試みた後に不確定 (in-doubt) トランザクションが残っている場合に回復を失敗させるかどうかを制御します。 |
戻り値
このメソッドは次の値を返す場合があります。
| リターンコード | 説明 |
|---|---|
| メソッドは正常に完了しました。 | |
| 引数として NULL ポインターが指定されました。 | |
| 予期しないエラーが発生しました。 | |
| CRM clerk を作成しているコンポーネントにトランザクションがありません。 | |
| CRM ログファイルの回復がまだ進行中です。 | |
| 不確定 (in-doubt) トランザクションが残っているため、CRM ログファイルの回復に失敗しました。 | |
| このメソッドが誤った状態で呼び出されました。RegisterCompensator の前、またはトランザクションが完了しつつあるとき (CRM Worker) のいずれかです。 | |
| メモリ不足エラーが発生しました。 | |
| CRM Compensator が、必要なインターフェイス (ICrmCompensator または ICrmCompensatorVariants) の少なくとも 1 つをサポートしていません。 |
解説(Remarks)
lCrmRegFlags パラメーターにより、実装者は CRM Compensator が受け取りたいトランザクション完了のフェーズを決定できます。CRM Compensator の中には準備 (prepare) フェーズで何の処理も行わないものもあり、その場合は準備通知を受け取る必要がありません。このような場合、準備フェーズが不要であると指定するとパフォーマンスが向上する可能性があります。
CRM Worker および CRM Compensator は "Both" スレッドコンポーネント (Threading Model = Any Apartment) として開発することが推奨されます。ただし、言語上の制約 (たとえば Visual Basic で CRM を開発する場合) により、これが不可能な場合もあります。アパートメントスレッドの CRM Compensator (Threading Model = Single Thread Apartment) は、その同期プロパティが "not supported" に設定されていない限り、準備フェーズでデッドロックします。アパートメントスレッドの CRM Compensator のもう 1 つの代替策は、準備フェーズが不要な場合にはこれをスキップすることです。
複数の Distributed Transaction Coordinator (DTC) が存在するシナリオでは、DTC トランザクションが不確定 (in-doubt) 状態になることがあります。通常、これはトランザクションの途中で中断が発生し、トランザクションの発生元に連絡してその結果を確認できないことが原因です。この場合、CRM インフラストラクチャはトランザクションの結果を判断できません。CRM の実装者は、この場合に新しいトランザクションを許可するかどうかを決定できます。
"fail if in-doubts remain" フラグは次のように使用します。RegisterCompensator で "fail if in-doubts remain" フラグを指定すると、回復後に不確定 (in-doubt) トランザクションが残っている場合、RegisterCompensator の呼び出しは "recovery failed" エラーコードで失敗します。"fail if in-doubts remain" フラグを指定しない場合、回復は成功し、新しいトランザクションが許可され、不確定トランザクションは CRM ログファイルに残ります。CRM インフラストラクチャは、次回の回復時 (アプリケーションサーバープロセスが再起動されたとき) に、これらの不確定トランザクションの解決を再度試みます。
CRM Worker および CRM Compensator は、このメソッドを使用して構造化ログレコードをログに書き込みます。
| pLogRecord | VARIANT* | in | Variant の Variant 配列へのポインター。これは下限が 0 の 1 次元配列である必要があります。 |
戻り値
このメソッドは次の値を返す場合があります。
| リターンコード | 説明 |
|---|---|
| メソッドは正常に完了しました。 | |
| 引数の 1 つが正しくありません。 | |
| 引数として NULL ポインターが指定されました。 | |
| このメソッドが誤った状態で呼び出されました。RegisterCompensator の前、またはトランザクションが完了しつつあるとき (CRM Worker) のいずれかです。 | |
| トランザクションが中止されました。原因はトランザクションのタイムアウトである可能性が最も高いです。 |
すべてのログレコードをディスク上で永続化するよう強制します。
戻り値
このメソッドは次の値を返す場合があります。
| リターンコード | 説明 |
|---|---|
| メソッドは正常に完了しました。 | |
| このメソッドが誤った状態で呼び出されました。RegisterCompensator の前、またはトランザクションが完了しつつあるとき (CRM Worker) のいずれかです。 | |
| トランザクションが中止されました。原因はトランザクションのタイムアウトである可能性が最も高いです。 |
解説(Remarks)
CRM Worker および CRM Compensator は、このメソッドを使用してログレコードを遅延書き込み (lazily) でログに書き込みます。つまり、ログに強制的に書き込まれるまでは永続化されません。ForceLog を呼び出すと、書き込み済みのすべてのログレコードがディスク上で永続化されます。
このインターフェイスのインスタンスによって書き込まれた最後のログレコードを破棄 (forget) します。
戻り値
このメソッドは次の値を返す場合があります。
| リターンコード | 説明 |
|---|---|
| メソッドは正常に完了しました。 | |
| 破棄すべき有効なログレコードがありません。 | |
| このメソッドが誤った状態で呼び出されました。RegisterCompensator の前、またはトランザクションが完了しつつあるとき (CRM Worker) のいずれかです。 | |
| トランザクションが中止されました。原因はトランザクションのタイムアウトである可能性が最も高いです。 |
解説(Remarks)
ネストという概念がないため、このメソッドで破棄できるのは最後のレコードのみです。つまり、write、forget、write、forget は有効ですが、write、write、forget、forget は無効です。破棄されたログレコードは、トランザクション結果の通知時に CRM Compensator へ配信されません。
トランザクションに対して即時の中止 (abort) 呼び出しを実行します。
戻り値
このメソッドは次の値を返す場合があります。
| リターンコード | 説明 |
|---|---|
| メソッドは正常に完了しました。 | |
| このメソッドが誤った状態で呼び出されました。RegisterCompensator の前、またはトランザクションが完了しつつあるとき (CRM Worker) のいずれかです。 | |
| トランザクションが中止されました。原因はトランザクションのタイムアウトである可能性が最も高いです。 |
CRM Worker および CRM Compensator は、このメソッドを使用して非構造化ログレコードをログに書き込みます。
| rgBlob | BLOB* | in | ログレコードを構成する BLOB の配列。BLOB は、任意の量のバイナリデータを格納するために使用される Windows のデータ型です。 |
| cBlob | DWORD | in | 配列内の BLOB の数。 |
戻り値
このメソッドは次の値を返す場合があります。
| リターンコード | 説明 |
|---|---|
| メソッドは正常に完了しました。 | |
| BLOB の数のカウントが 0 です。 | |
| 引数として NULL ポインターが指定されました。 | |
| このメソッドが誤った状態で呼び出されました。RegisterCompensator の前、またはトランザクションが完了しつつあるとき (CRM Worker) のいずれかです。 | |
| トランザクションが中止されました。原因はトランザクションのタイムアウトである可能性が最も高いです。 |
解説(Remarks)
非構造化レコードは単なるバイトのバッファーです。このメソッドは、特定の CRM ログレコードの各部分を BLOB の配列から組み立てられるようにすることで、収集 (gather) 機能を実装します。BLOB は、データへのポインターとバイト数のカウントを含む構造体です。これによりデータのコピーが削減され、CRM のメモリ空間からログマネージャーのバッファーへ直接 1 回だけコピーされるようになります。
非構造化ログレコードと構造化ログレコードを混在させることはできません。WriteLogRecord または WriteLogRecordVariants のいずれかを呼び出すことができますが、同一の CRM Worker または CRM Compensator が両方を呼び出すことはできません。
ログレコードの BLOB に含まれるデータ構造の中にポインター型を含めるべきではありません。CRM Compensator は、ログレコードを書き込んだ CRM Worker とは別のプロセスで実行されるため、回復フェーズではオブジェクト参照はもはや有効ではありません。ログレコードの BLOB 内にポインター型を含めると、回復中にアプリケーションがクラッシュしたり、それ自体が破損したりする可能性があります。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_ICrmLogControl "{A0E174B3-D26E-11D2-8F84-00805FC7BCD9}" #usecom global ICrmLogControl IID_ICrmLogControl "{}" #comfunc global ICrmLogControl_get_TransactionUOW 3 var #comfunc global ICrmLogControl_RegisterCompensator 4 wstr,wstr,int #comfunc global ICrmLogControl_WriteLogRecordVariants 5 var #comfunc global ICrmLogControl_ForceLog 6 #comfunc global ICrmLogControl_ForgetLogRecord 7 #comfunc global ICrmLogControl_ForceTransactionToAbort 8 #comfunc global ICrmLogControl_WriteLogRecord 9 var,int ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。#define global IID_ICrmLogControl "{A0E174B3-D26E-11D2-8F84-00805FC7BCD9}" #usecom global ICrmLogControl IID_ICrmLogControl "{}" #comfunc global ICrmLogControl_get_TransactionUOW 3 sptr #comfunc global ICrmLogControl_RegisterCompensator 4 wstr,wstr,int #comfunc global ICrmLogControl_WriteLogRecordVariants 5 sptr #comfunc global ICrmLogControl_ForceLog 6 #comfunc global ICrmLogControl_ForgetLogRecord 7 #comfunc global ICrmLogControl_ForceTransactionToAbort 8 #comfunc global ICrmLogControl_WriteLogRecord 9 sptr,int ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。