リソース マネージャーの作成
リソース マネージャーは、各トランザクションのデータを管理し、トランザクションの操作をログに記録します。 トランザクション処理システム (TPS) に複数のリソース マネージャーが存在する場合、各リソース マネージャーは各トランザクションのコミット、ロールバック、および回復操作に参加できます。
各リソース マネージャーは、トランザクション クライアントがリソース マネージャーの保持するデータベースその他のリソースへのアクセスに使用できるインターフェイスをエクスポートする必要があります。
通常、カーネルモードのリソース マネージャーは、以下のタスクを一覧に示されている順序で実行する必要があります。
ログストリームを作成します。
リソース マネージャーは、共通ログ ファイル システム (CLFS) またはその他のログ機能を使用して、ログ ストリームを管理できます。 ClfsCreateLogFile を呼び出すと、CLFS ログ ストリームが作成されます。 リソース マネージャーは、ログ ストリームを使用して、トランザクションのコミット、ロールバック、または回復に必要な情報を記録する必要があります。 また、KTM はログ ストリームを使用して、トランザクショントランザクションの回復に必要な内部状態の変更を記録します。
トランザクション マネージャー オブジェクトを作成します。
ZwCreateTransactionManager を呼び出すと、トランザクション マネージャー オブジェクトが作成され、リソース マネージャーが指定する追加の CLFS ログ ストリームにリソース マネージャーが接続されます。
トランザクション マネージャーの状態を回復します。
ZwRecoverTransactionManager の呼び出しによって、トランザクション マネージャー オブジェクトのログ ストリーム (KTM が管理) が読み取られ、すべてのトランザクションが完了する前に TPS がシャットダウンされたかどうかを判断します (たとえば、システムがクラッシュしたため)。 KTM は、ログ ストリーム内の情報に基づいて内部状態を復元します。
リソース マネージャー オブジェクトを作成します。
ZwCreateResourceManager を呼び出すと、リソース マネージャー オブジェクトが作成され、以前に作成されたトランザクション マネージャー オブジェクトに関連付けられます。
リソース マネージャーの状態を回復します。
ZwRecoverResourceManager を呼び出すと、リソース マネージャーが最後にシャットダウンした時点で進行中であったトランザクションに対して、JTM がリソース マネージャー TRANSACTION_NOTIFY_RECOVER 通知を送信します。 リソース マネージャーがこれらの通知に応答する方法については、「回復操作の処理」を参照してください。
クライアントからトランザクションを受信します。
通常、クライアントはトランザクション オブジェクトを作成し、リソース マネージャーのクライアント インターフェイスを使用して、トランザクション オブジェクトの GUID をリソース マネージャーに渡します。 たとえば、リソース マネージャーは、TPS コンポーネントの理解に関するトピックで説明されているルーチンに似た CreateDataObject ルーチンを提供できます。
各トランザクションにエンリストします。
ZwOpenTransaction を呼び出すと、トランザクション オブジェクトへのハンドルが開きます。次に、ZwCreateEnlistment を呼び出すと、トランザクションへのエンリストが作成されます。 エンリストにより、リソース マネージャーは、指定したトランザクション通知のセットを受信できるようになります。
トランザクション通知の受信を有効にします。
リソース マネージャーは、ZwGetNotificationResourceManager を呼び出して通知を同期的に取得するか、TmEnableCallbacks を呼び出して、通知が発生した場合に KTM から呼び出せるように ResourceManagerNotification コールバック ルーチンを登録できます。
クライアントからのリソース アクセス要求を処理しますが、変更を永続化しないでください。
クライアントはトランザクション オブジェクトを作成した後、通常、リソース マネージャーのインターフェイスを呼び出してリソース マネージャーのリソースにアクセスします。 データベースのリソース マネージャーは、たとえば、データベースの読み取りと書き込みの要求を受け取ります。
リソース マネージャーは、トランザクションの操作がコミット、ロールバック、または回復されるという通知を受け取るまで、CLFS ログ ストリーム やその他のログ記録機能に読み取りおよび書き込み操作の結果を記録する必要があります。
クライアント操作をコミットまたはロールバックします。
最後に、リソース マネージャーは、クライアントが実行した操作のコミット開始またはロールバック開始の通知を受け取ります。 これに対して、リソース マネージャーは、クライアント操作を永続化するか、破棄する必要があります。 コミット通知とロールバック通知を処理する方法の詳細については、「トランザクション操作の処理」を参照してください。
リソース マネージャーが、デバイスが突然削除されたと判断した場合など、状況によっては、リソース マネージャーが KTM からの迅速なコミットまたはロールバックの通知を要求することがあります。 このような場合、リソース マネージャーは TmRequestOutcomeEnlistment を呼び出すことができます。
エンリスト オブジェクト ハンドルを閉じます。
リソース マネージャーは、トランザクションの処理を完了した後、ZwClose を呼び出して、参加オブジェクトのハンドルを閉じる必要があります
リソース マネージャー オブジェクト ハンドルとトランザクション マネージャー オブジェクト ハンドルを閉じます。
リソース マネージャーはアンロードする前に、ZwClose を呼び出して、リソース マネージャー オブジェクトのハンドルとトランザクション マネージャー オブジェクトのハンドルを閉じる必要があります。
手順 1 から 5 は、リソース マネージャーの初期化コードで実行する必要があります。 たとえば、リソース マネージャーがカーネルモード ドライバーの場合、初期化コードはドライバーの DriverEntry ルーチンです。
手順 6 から 11 は、通常、トランザクション クライアントからの要求に応答するコードで実行されます。
手順 12 は、カーネルモード ドライバーの Unload ルーチンなど、リソース マネージャーの最終的なクリーンアップ コードで実行する必要があります。
読み取り専用エンリストの作成
読み取り専用のエンリストは、KTM から通知を受け取らないエンリストです。 リソース マネージャーは、ZwReadOnlyEnlistment を呼び出して、任意のエンリストを読み取り専用に設定することができます。 これを呼び出すと、KTM はリソース マネージャーへの通知配信を停止します。
リソース マネージャーは、ZwCreateEnlistment の呼び出し後、通常、ZwPrepareComplete を呼び出すまで、いつでも ZwReadOnlyEnlistment を呼び出すことができます。
リソース マネージャーで ZwReadOnlyEnlistment を呼び出す理由は 2 つあります。
リソース マネージャーがトランザクションに参加していて、TRANSACTION_NOTIFY_COMMIT 通知を受け取る前に、トランザクションのコミット操作に参加する必要がなくなったと判断した場合。
たとえば、リソース マネージャーは、TRANSACTION_NOTIFY_PREPARE 通知を受け取ったときに、トランザクションのいずれも操作もリソース マネージャーのデータベースを変更していないと判断する場合があります。 リソース マネージャーは、ZwPrepareComplete の代わりに ZwReadOnlyEnlistment を呼び出して、トランザクションから自身を削除できます。
このリソース マネージャーがトランザクションのコミット操作に参加することはありません。
たとえば、リソース マネージャーは、格納されているデータベースを変更せずに、クライアントが送信するデータを監視できます。 この場合、リソース マネージャーは、ZwCreateEnlistment を呼び出した直後に ZwReadOnlyEnlistment を呼び出す可能性があります。 さらに、このトピックの次のセクションで説明するように、このようなリソース マネージャーを揮発化することもできます。
リソース マネージャーは、ZwReadOnlyEnlistment を呼び出した後、ZwClose を呼び出して参加ハンドルを閉じることができます。
揮発性リソース マネージャーの作成
揮発性リソース マネージャーは、永続的なデータを保持しないリソース マネージャーです。 たとえば、リソース マネージャーが永続的に保存されたデータベースを変更しない場合、揮発性リソース マネージャーを作成してクライアントの送信するデータを監視することが考えられます。 揮発性リソース マネージャーは通常、トランザクション アクティビティをログに記録しないため、回復操作やロールバック操作は実行できません。
揮発性リソース マネージャーは、ZwCreateResourceManager を呼び出す際、RESOURCE_MANAGER_VOLATILE フラグを設定する必要があります。 このフラグが設定されている場合、KTM は、関連するトランザクション マネージャー オブジェクトのログ ストリームに、リソース マネージャーに関する情報を記録しません。
リソース マネージャーは、ZwCreateTransactionManager を呼び出すときに TRANSACTION_MANAGER_VOLATILE フラグを設定することもできます。 このフラグが設定されている場合、KTM はトランザクション マネージャー オブジェクトのログ ストリームを作成しません。 さらに、トランザクション マネージャー オブジェクトに接続されているその他のリソース マネージャーも揮発性でなければならず、RESOURCE_MANAGER_VOLATILE フラグを設定する必要があります。
既存の TPS への Resource Manager の追加
既存の TPS にリソース マネージャーを追加する必要がある場合は、次の 2 つの選択肢があります。
新しいリソース マネージャーは、ZwCreateTransactionManager を呼び出して、独自のトランザクション マネージャー オブジェクトを作成します。
リソース マネージャーが TPS 内の他のリソース マネージャーと通信しない場合は、この選択を使用します。
新しいリソース マネージャーが ZwOpenTransactionManager を呼び出して、既存のトランザクション マネージャー オブジェクトに接続します。
リソース マネージャーが TPS 内の他のリソース マネージャーと通信する必要がある場合は、この選択を使用します。 ZwCreateTransactionManager を呼び出すリソース マネージャーは、他のリソース マネージャーが ZwOpenTransactionManager を呼び出すことができるように、トランザクション マネージャー オブジェクトの GUID、ログ ストリーム名、またはオブジェクト名を共有する必要があります。 これらの他のリソース マネージャーは、ZwQueryInformationTransactionManager を呼び出して、トランザクション マネージャー オブジェクトに関する追加情報を取得できます。
リソース マネージャーを TPS に追加した後、リソース マネージャーを認識しているクライアントは、リソース マネージャーのクライアント インターフェイスを呼び出すことができます。