Oracle Tuxedoシステムでは、次のアプリケーションがサポートされています。
お使いのオペレーティング・システムでPOSIXスレッド関数と共にほかのスレッド関数がサポートされている場合は、POSIXスレッド関数を使用することをお薦めします。この関数を使用すると、後でコードをほかのプラットフォームに簡単に移植できます。
お使いのプラットフォームでカーネル・レベルのスレッド・パッケージ、C言語の関数、またはPOSIX関数がサポートされているかどうかを確認するには、『Oracle Tuxedoシステムのインストール』で、使用しているオペレーティング・システムのデータ・シートを参照してください。
多くのプラットフォームには、マルチスレッドおよびマルチコンテキスト・アプリケーション固有の要件があります。 プラットフォーム固有の要件については、『Oracle Tuxedoシステムのインストール』に説明があります。 お使いのプラットフォームの要件については、該当するデータ・シートを参照してください。
Oracle Tuxedoシステムでは、単一のプロセスで複数のタスクを同時に実行できます。このようなプロセスを実装するプログラミング手法はマルチスレッドおよびマルチコンテキストと呼ばれます。 この項では、これらの手法に関する基本事項について説明します。
マルチスレッドとは、1つのプロセスに複数の実行単位が含まれている処理方法です。 マルチスレッド・アプリケーションでは、同じプロセスから同時に複数の呼出しを行うことができます。 たとえば、個々のプロセスが1つの未終了のtpcall(3c)に制限されることはありません。
サーバーのマルチスレッドでは、アプリケーション生成のスレッドがシングル・コンテキスト・サーバーで使用される場合を除き、マルチコンテキストが必要です。 マルチスレッドのシングル・コンテキスト・アプリケーションを作成する唯一の方法は、アプリケーション生成のスレッドを使用することです。
Oracle Tuxedoシステムでは、C言語で記述されたマルチスレッド・アプリケーションがサポートされています。COBOL言語のマルチスレッド・アプリケーションはサポートされていません。
図10-1は、マルチスレッド・クライアントが3つのサーバーに対して同時に呼出しを行う方法を示しています。
マルチスレッド・アプリケーションでは、同じサーバーで複数のサービス・ディスパッチ・スレッドを使用できるので、アプリケーションに対して起動するサーバー数が少なくて済みます。
図10-2は、異なるクライアントに対して、サーバー・プロセスが同時に複数のスレッドをディスパッチする方法を示しています。
コンテキストはドメインへの対応付けです。 マルチコンテキストを使用すると、1つのプロセスで次のいずれかが可能になります。
マルチコンテキストは、クライアントとサーバーの両方で使用できます。 サーバーでマルチコンテキストを使用すると、マルチスレッドも使用することになります。
コンテキストの特徴の詳細は、次のいずれかの項で「コンテキストの属性」を参照してください。
Oracle Tuxedoシステムでは、C言語またはCOBOL言語のいずれかで記述されたマルチコンテキスト・アプリケーションがサポートされています。 ただし、サポートされるマルチスレッド・アプリケーションは、C言語で記述されたものだけです。
図10-3は、ドメイン内でのマルチコンテキスト・クライアント・プロセスの動作を示しています。各矢印はサーバーへの未終了の呼出しを表します。
ライセンスの関係で、各コンテキストは1人のユーザーとしてカウントされます。1つのコンテキストで複数のスレッドを使用するために、ライセンスを追加する必要はありません。例:
マルチスレッドとマルチコンテキストを適切な状況で使用すると、Oracle Tuxedoアプリケーションのパフォーマンスを向上できます。 ただし、これらの手法を取り入れる前に、潜在的な利点と問題点について理解しておくことが大切です。
マルチスレッドおよびマルチコンテキスト・アプリケーションには、以下の利点があります。
マルチスレッドとマルチコンテキストを併用すると、一部のアプリケーションではパフォーマンスと並列性が向上します。 また、一部のアプリケーションでは、パフォーマンスが変わらないか、逆に低下する場合があります。 パフォーマンスへの影響は、使用しているアプリケーションによって異なります。
アプリケーションによっては、異なるリモート・プロシージャ・コールと会話を別々のスレッドでコーディングした方が、同じスレッドで管理するより簡単な場合があります。
Oracle Tuxedoクライアントを同時に複数のアプリケーションに接続できます。
1つのサーバーで複数のサービス・スレッドをディスパッチできるので、アプリケーションに対して起動するサーバーの数を減らすことができます。 このように複数のスレッドをディスパッチできる機能は、特に会話型サーバーの場合に有用です。会話型サーバーにこの機能がない場合、会話が終了するまで1つのクライアントしか使用できなくなります。
アプリケーションで、クライアント・スレッドがMicrosoft Internet Information Server APIまたはNetscape Enterprise Serverインタフェース(NSAPI)によって生成される場合、これらのツールの機能を最大限に利用するにはマルチスレッドが不可欠です。 ほかのツールについても同じことが言えます。
マルチスレッドおよびマルチコンテキスト・アプリケーションには、以下の問題点があります。
マルチスレッドおよびマルチコンテキスト・アプリケーションのコーディングは簡単ではありません。 このようなアプリケーションのコーディングは、十分な経験を持つプログラマだけが行うことができます。
マルチスレッド・アプリケーションまたはマルチコンテキスト・アプリケーションで発生したエラーを再現することは、シングル・スレッドおよびシングル・コンテキスト・アプリケーションで再現するより難しい作業です。 そのため、エラー発生時にその根本的な原因を特定して検証することがさらに難しくなります。
スレッド間の並列性の管理は難しい作業であり、アプリケーションで新たに問題を引き起こす可能性があります。
マルチスレッド・アプリケーションのテストは、シングル・スレッド・アプリケーションのテストより難しい作業です。問題がタイミングに関連していることが多く、再現が困難だからです。
既存のコードでマルチスレッドとマルチコンテキストを使用するには、大部分のコードを再構築しなければなりません。 プログラマは、以下の作業を行う必要があります。
マルチスレッドおよびマルチコンテキスト・アプリケーションがアクティブの場合、クライアントのライフサイクルは次の3つのフェーズから構成されます。
注意: | Oracle Tuxedoシステムから独立して動作するスレッドが存在する場合もあります。 ここでは、そのようなスレッドについては説明していません。 |
Oracle Tuxedoマルチコンテキスト・アプリケーションのクライアントは、次の規則に従うかぎり、複数のアプリケーションに対応付けることができます。
クライアントが複数のコンテキストに参加するには、TPINFO
データ型のflags
にTPMULTICONTEXTS
フラグを設定して、tpinit(3c)関数を呼び出します。
TPMULTICONTEXTS
フラグを設定してtpinit()
関数が呼び出されると、アプリケーションとの新しい対応付けが生成され、スレッドに対するカレントの対応付けが指定されます。 新しい対応付けが生成されるOracle Tuxedoドメインは、TUXCONFIG
またはWSENVFILE/WSNADDR
環境変数の値で決定されます。
多くのATMI関数はコンテキスト単位で動作します。 このようなATMI関数のリストについては、「マルチスレッド・クライアントでのコンテキスト単位の関数とデータ構造体」を参照してください。 コンテキスト単位で動作するには、ターゲット・コンテキストが現在のコンテキストであることが必要です。 クライアントは複数のコンテキストに参加できますが、状況とスレッドにかかわらず現在のコンテキストになることができるコンテキストは1つだけです。
アプリケーション内でタスクの優先順位が移り、ほかのOracle Tuxedoドメインと通信する必要が発生した場合、あるコンテキストから別のコンテキストにスレッドを再割り当てした方がよい場合があります。
そのような場合、あるクライアント・スレッドがtpgetctxt(3c)を呼び出し、返された現在のコンテキストを値として持つハンドルを別のクライアント・スレッドに渡します。 2番目のスレッドはtpsetctxt(3c)を呼び出し、最初のスレッドでtpgetctxt(3c)から受け取ったハンドルを指定して、現在のコンテキストとの対応付けを確立します。
目的のコンテキストとの対応付けが確立されると、2番目のスレッドはコンテキスト単位で動作するATMI関数を使用してタスクを実行できるようになります。詳細は、「マルチスレッド・クライアントでのコンテキスト単位の関数とデータ構造体」を参照してください。
このフェーズでは、各スレッドによって処理が行われます。 次は、行われる処理の例です。
スレッドは、同期リクエストの場合はtpcall(3c)、非同期リクエストの場合はtpacall(3c)を呼び出して、サーバーにリクエストを送ります。tpcall()
でリクエストを送った場合、以降操作を行わなくても応答を受け取ることができます。
tpcall(3c)でサービスの非同期リクエストを送った場合、同じコンテキスト内のスレッドはtpgetrply(3c)を呼び出して応答を受け取ります。このスレッドは、リクエストを送ったスレッドと同じスレッドではない場合もあります。
あるスレッドがトランザクションを開始すると、そのスレッドのコンテキストを共有するすべてのスレッドでそのトランザクションが共有されます。
コンテキスト内の多くのスレッドでトランザクションに関する処理が行われますが、トランザクションをコミットまたは停止できるのは1つのスレッドだけです。トランザクションをコミットまたは停止するスレッドは、トランザクションを開始したスレッドである必要はなく、トランザクションを処理しているどのスレッドでもかまいません。スレッド・アプリケーションでは、通常のトランザクション規則に従うために、適切に同期を行う必要があります。たとえば、未終了のRPC呼び出しや会話がある場合に、トランザクションをコミットすることはできません。また、トランザクションがコミットまたは停止された後で、そのトランザクションに対する呼出しを行うことはできません。プロセスは、アプリケーションの各対応付けに対して、1つのトランザクションの一部にだけなることができます。
アプリケーションの1つのスレッドがtpcommit(3c)を呼び出し、それと同時に別のスレッドがRPC呼び出しまたは会話型呼出しを行うと、これらの呼出しは特定の順序で呼び出されたものとして処理されます。 アプリケーション・コンテキストは、シングル・スレッド・プログラムとシングル・コンテキスト・プログラムに対する制約と同じ制約に従って、tpsuspend(3c)を呼び出してトランザクションを一時的に中断し、別のトランザクションを開始します。
マルチスレッド・アプリケーションまたはマルチコンテキスト・アプリケーションの各コンテキストでは、非請求メッセージを次の3種類のいずれかの方法で処理できます。
専用のスレッド通知の場合、非請求メッセージの受信と、非請求メッセージ・ハンドラのディスパッチに別々のスレッドが使用されます。 あるコンテキストで一度に実行できる非請求メッセージ・ハンドラは1つだけです。
スレッドがサポートされていないOracle Tuxedoシステム用プラットフォームでtpinit(3c)が呼び出された場合に、スレッドがサポートされていないプラットフォーム上でTPU_THREAD
通知がリクエストされたことを示すパラメータが指定されていると、tpinit()
は-1
を返してtperrno
にTPEINVAL
を設定します。UBBCONFIG(5)のデフォルトのNOTIFY
オプションがTHREAD
に設定されている場合に、特定のマシンでスレッドを利用できないと、そのマシンのデフォルトの機能はDIPIN
になります。このような動作の相違があるので、スレッドがサポートされているマシンとサポートされていないマシンが混在する環境では、管理者はすべてのマシンにデフォルトを指定できます。ただし、そのマシンで利用できない機能をクライアントが明示的にリクエストすることはできません。
tpsetunsol(3c)がコンテキストに対応付けされていないスレッドから呼び出されると、新しく生成されるすべてのtpinit(3c)コンテキストに対して、プロセス単位のデフォルトの非請求メッセージ・ハンドラが作成されます。 特定のコンテキストは、コンテキストがアクティブのときにtpsetunsol()
を再度呼び出して、そのコンテキストの非請求メッセージ・ハンドラを変更することができます。 プロセス単位のデフォルトの非請求メッセージ・ハンドラは、コンテキストに現在対応付けされていないスレッドでtpsetunsol()
を再度呼び出すと、変更できます。
プロセスが同じアプリケーションと複数の対応付けを持つ場合、各対応付けに異なるCLIENTID
を割り当てられ、非請求メッセージを特定のアプリケーションとの対応付けに送信できるようになります。 プロセスが同じアプリケーションと複数の対応付けを持つ場合、ブロードキャスト基準を満たすアプリケーションの各対応付けに任意のtpbroadcast(3c)が別々に送信されます。 非請求メッセージを受信する場合のディップ・イン・チェックでは、カレントのアプリケーションとの対応付けに送信されるメッセージだけが対象となります。
非請求メッセージ・ハンドラではATMI関数を利用できるほか、非請求メッセージ・ハンドラ内でtpgetctxt(3c)を呼び出すことができます。 そのため、非請求メッセージ・ハンドラは別のスレッドを生成して、同じコンテキスト内で必要となる実質的なATMI作業を行うことができるようになります。
userlog(3c)を使用すると、各アプリケーション内の各スレッドに対して次の識別情報が記録されます。
process_ID.thread_ID.context_ID
スレッドがサポートされていないプラットフォームやシングル・コンテキスト・アプリケーションに対しては、thread_ID
フィールドとcontext_ID
フィールドにプレースホルダーが出力されます。
TM_MIB(5)では、この機能はT_ULOG
クラスのTA_THREADID
フィールドとTA_CONTEXTID
フィールドでサポートされています。
このフェーズでは、クライアント・プロセスの終了時に、現在のコンテキストおよび対応付けられたすべてのスレッドにかわって1つのスレッドがtpterm(3c)を呼び出してそのアプリケーションとの対応付けを終了します。ほかのATMI関数と同じように、tpterm()
は現在のコンテキストに対して処理を行います。tpterm()は、終了するコンテキストに対応付けされたすべてのスレッドに影響し、これらのスレッドで共有されるすべてのコンテキストを終了します。
アプリケーションの設計が適切であれば、特定のコンテキスト内のすべての処理が完了してからtpterm()
が呼び出されます。 tpterm()
が呼び出される前に、すべてのスレッドが同期していなければなりません。
マルチスレッドおよびマルチコンテキスト・アプリケーションがアクティブの場合、サーバーで行われる処理は次の3つのフェーズに分類できます。
起動フェーズで行われる処理は、構成ファイルのMINDISPATCHTHREADS
とMAXDISPATCHTHREADS
パラメータの値によって異なります。
|
||
|
クライアントのサービス・リクエストへのレスポンスとして、サーバー・ディスパッチャは各種のクライアント・リクエストに同時に割り当てることができる1つのサーバーに、設定可能な最大数まで複数のスレッドを生成します。サーバーがtpinit(3c)を呼び出してクライアントになることはできません。
各ディスパッチ・スレッドは、別々のコンテキストと対応付けられています。 この機能は会話型サーバーとRPCサーバーで有用です。 特に、会話型サーバーではこの機能を利用できないと、ほかの会話接続がサービスを待っている間、クライアント側の会話をアイドル状態で待つことになります。
この機能は、UBBCONFIG(5)ファイルのSERVERS
セクションとTM_MIB(5)の次のパラメータで制御されます。
THREADSTACKSIZE
またはTA_THREADSTACKSIZE
で指定されるスタック・サイズで生成されます。 このパラメータが指定されていない場合、または0の場合、オペレーティング・システムのデフォルト値が使用されます。 オペレーティング・システムのデフォルト値が小さすぎてOracle Tuxedoシステムで使用できない場合、その値より大きなデフォルト値が使用されます。THREADSTACKSIZE
設定がサポートされていない場合は、オペレーティング・システムのデフォルト値が使用されます。MINDISPATCHTHREADS
またはTA_MINDISPATCHTHREADS
は、MAXDISPATCHTHREADS
またはTA_MAXDISPATCHTHREADS
以下でなければなりません。MAXDISPATCHTHREADS
またはTA_MAXDISPATCHTHREADS
が1の場合、ディスパッチャ・スレッドとサービス関数スレッドは同じスレッドです。MAXDISPATCHTHREADS
またはTA_MAXDISPATCHTHREADS
が1より大きい場合、ほかのスレッドのディスパッチに使用されるスレッドは、ディスパッチ・スレッドとしてカウントされません。MINDISPATCHTHREADS
またはTA_MINDISPATCHTHREADS
のサーバー・スレッドを起動します。 MAXDISPATCHTHREADS
またはTA_MAXDISPATCHTHREADS
を超えるサーバー・スレッドを起動することはありません。オペレーティング・システム関数を使用して、アプリケーション・サーバー内に新しいスレッドを追加できます。 アプリケーション生成のスレッドは、次のように動作します。
アプリケーション内にスレッドを生成する場合、次の制約があります。
tpreturn()
を呼び出す前に、TPNULLCONTEXT
に設定されたコンテキストでtpsetctxt(3c)を呼び出す必要があります。BBLは定期的にサーバーを検証します。特定のサービス・リクエストの実行に時間がかかりすぎている場合、BBLはそのサーバーを強制終了します。そして、指定されている場合は、そのサーバーを再起動します。BBLがマルチコンテキスト・サーバーを強制終了した場合、プロセスを強制終了した結果として、実行中のそのほかのサービス呼び出しも終了します。
また、BBLはタイムアウト値を超えてメッセージの受信を待機しているプロセスまたはスレッドにメッセージを送信します。 すると、ブロッキング・メッセージ受信への呼出しが、タイムアウトを示すエラーを返します。
Oracle Tuxedoシステムでは、各サーバーに対して次の統計情報が保持されます。
userlog(3c)を使用すると、各アプリケーション内の各スレッドに対して次の識別情報が記録されます。
process_ID.thread_ID.context_ID
スレッドがサポートされていないプラットフォームやシングル・コンテキスト・アプリケーションに対しては、thread_ID
フィールドとcontext_ID
フィールドにプレースホルダーが出力されます。
TM_MIB(5)では、この機能はT_ULOG
クラスのTA_THREADID
フィールドとTA_CONTEXTID
フィールドでサポートされています。
アプリケーションを停止すると、tpsvrthrdone(3c)とtpsvrdone(3c)が呼び出されて、リソース・マネージャのクローズなど、必要な終了処理が行われます。
マルチスレッドおよびマルチコンテキスト・アプリケーションは、一部のOracle Tuxedoドメインでは正しく動作しますが、すべてのドメインで正しく動作するとはかぎりません。そのようなアプリケーションを作成するかどうかは、次の基本事項を検討してから決定します。
マルチスレッド・アプリケーションまたはマルチコンテキスト・アプリケーションの開発では、開発環境と実行時環境に関して次の内容を検討します。
OPENINFO
文字列の一部としてTHREADS=true
パラメータを設定する必要があります。 この設定により、各スレッドがOracleとの別々の対応付けとして動作するようになります。すべてのRMで混在モードがサポートされているわけではありません。 プロセス内のすべてのスレッドが同じRMとの対応付けにマップされなければならない場合もあります。 アプリケーション生成のスレッド内でトランザクションに関与するRMアクセスを使用するアプリケーションを設計する場合は、RMで混在モードがサポートされていることを確認します。
マルチスレッド・アプリケーションやマルチコンテキスト・アプリケーションの設計では、次の内容を検討します。
次の表は、アプリケーションをマルチスレッドまたはマルチコンテキストにすべきかどうかを判断するための参考となる検討事項を示しています。 この表だけでは十分ではないので、個々の要件に基づいてほかの事項も検討してください。
そのほかの検討事項については、マルチスレッド・アプリケーションやマルチコンテキスト・アプリケーションのプログラミングに関する書籍を参照してください。
アクセスするアプリケーションの数と、確立する接続の数を決定します。
これは設計段階での重要な検討事項です。このドキュメントでは、この内容について取り上げていません。マルチスレッド・アプリケーションやマルチコンテキスト・アプリケーションのプログラミングに関する書籍を参照してください。
後でアプリケーションを移植する必要がある場合、オペレーティング・システムに応じて異なる関数が使用されていることに注目してください。 あるプラットフォームで作成した初期バージョンのアプリケーションを後で移植する場合、異なる関数でコードを書き直すためにどれだけのリソース時間が必要なのかを考慮する必要があります。
現在使用されているマルチスレッド・プログラムには、次のようなモデルがあります。
スレッド・モデルについては、このドキュメントでは取り上げていません。アプリケーションのプログラミング・モデルを選択する場合は、利用できるすべてのモデルを調べて、設計の要件を慎重に検討してください。
リリース7.1のWorkstationクライアントと7.1以前のOracle Tuxedoシステムに基づくアプリケーションとの相互運用性は、次のどの場合でもサポートされています。
Oracle Tuxedoリリース7.1のワークステーション・クライアントで、1つのコンテキストに複数のスレッドがある場合は、リリース7.1より前のOracle Tuxedoシステムとは相互運用しません。
コーディングを開始する前に、次の内容や条件を満たしていることを確認してください。
開発プロジェクトを開始する前に、開発環境が次の条件を満たしていることを確認します。
Oracle Tuxedoシステムには、スレッド生成用のツールは提供されていません。ただし、ほかのオペレーティング・システムで提供される各種のスレッド・パッケージがサポートされています。 スレッドを生成して同期するには、オペレーティング・システム固有の関数を使用する必要があります。 オペレーティング・システムでサポートされているスレッド・パッケージを確認するには、『Oracle Tuxedoシステムのインストール』を参照してください。
マルチスレッド・プログラムは、十分に経験を持つプログラマがコーディングします。 特に、次のようなマルチスレッド固有の設計に関する基本的な知識があることが必要です。
これらは検討事項の一部にすぎず、ここに記せないほど多くの検討事項があります。マルチスレッド・プログラムをコーディングするプログラマは、それらの検討事項を熟知していることが前提となります。 これらの検討事項については、マルチスレッド・アプリケーションのプログラミングに関する書籍を参照してください。
マルチスレッドを使用すると、1つのアプリケーションの異なるスレッドが同じ会話で並列処理を行うことができるようになります。この方法はお薦めしませんが、Oracle Tuxedoシステムで禁止されているわけではありません。異なるスレッドによって同じ会話で並列処理が行われると、システムは同時呼出しが任意の順序で行われたように動作します。
複数のスレッドを使ってプログラミングする場合、ミューテックスなどの同時実行制御関数を使用して、スレッド間の並列処理を管理する必要があります。 以下は、同時実行制御が必要になる3つの例です。
tpcommit()
が呼び出される場合、アプリケーションで何らかの同時実行制御が必要になります。 tpsend()
呼出しが任意の順序で行われたように動作します。アプリケーション・プログラマは、それを認識しておかなければなりません。 ほとんどのアプリケーションで最良の方法は、1つの会話のすべての処理を1つのスレッドにまとめてコーディングすることです。 また、同時実行制御を使用して、これらの処理を連続して行う方法もあります。
クライアントでマルチコンテキストを使用するには、次の内容をコーディングします。
アプリケーションでトランザクションを使用する場合、トランザクションのマルチコンテキストの結果についても注目します。詳細は、「マルチスレッドおよびマルチコンテキスト・アプリケーションにおけるトランザクションのコーディング規則」を参照してください。
注意: | この項で示す手順とサンプル・コードは、Oracle Tuxedoシステムで提供されるC言語のライブラリ関数を参照します。それらに相当するCOBOLライブラリ関数も利用できます。詳細は、『Tuxedo COBOLリファレンス』を参照してください。 |
コンテキストを使用する場合、コーディングで以下の事柄に注意してください。
TPNULLCONTEXT
に変更されることはありません。tpinit()
を呼び出すたびに、確立されているセキュリティ・メカニズムを調整する必要があります。 クライアントがアプリケーションに参加する準備ができたら、次のサンプル・コードに示すように、TPMULTICONTEXTS
フラグを設定してtpiit(3c)を指定します。
#include <stdio.h>
#include <atmi.h>
TPINIT * tpinitbuf;
main()
{
tpinitbuf = tpalloc(TPINIT, NULL, TPINITNEED(0));
tpinitbuf->flags = TPMULTICONTEXTS;
.
.
.
if (tpinit (tpinitbuf) == -1) {
ERROR_PROCESSING_CODE
}
.
.
.
}
新しいアプリケーションとの対応付けが生成され、TUXCONFIG
またはWSENVFILE/WSNADDR
環境変数で指定されたOracle Tuxedoドメインに割り当てられます。
注意: | 1つのプロセスでは、tpinit(3c)へのすべての呼出しにTPMULTICONTEXTS フラグを含めるか、または、tpinit() へのすべての呼出しにこのフラグを含めません。この規則には例外が1つあり、tpterm(3c)への呼出しが正常に終了して、クライアントのすべてのアプリケーション関連付けが終了した場合、次にtpinit() を呼び出すときに必ずしもTPMULTICONTEXTS フラグを含む必要のない状態にプロセスが復元されます。 |
同じプロセス内の各アプリケーションとの対応付けには、別個にセキュリティ検査を行う必要があります。 検査の内容は、アプリケーションで使用されているセキュリティ・メカニズムのタイプによって異なります。 たとえば、Oracle Tuxedoアプリケーションでは、システム・レベルのパスワードまたはアプリケーション・パスワードを使用します。
マルチコンテキスト・アプリケーションのプログラマは、アプリケーションで使用するセキュリティのタイプを決定し、そのセキュリティをプロセス内の各アプリケーションとの対応付けに実装します。
クライアントをアプリケーションから切断する準備ができたら、tpterm(3c)を呼び出します。 ただし、マルチコンテキスト・アプリケーションでは、tpterm()
を呼び出すと現在のコンテキストが破棄されることに注目してください。 その場合、現在のコンテキストで動作しているすべてのスレッドが影響を受けます。 アプリケーション・プログラマは、tpterm()
が不意に呼び出されることがないように、複数のスレッドを使用する場合は注意してください。
まだ処理を行っているスレッドがあるコンテキストでは、tpterm(3c)を呼び出さないようにします。 そのような状況でtpterm()
を呼び出すと、そのコンテキストと対応付けられていたほかのスレッドが特別な無効コンテキスト状態になります。 無効コンテキスト状態では、大部分のATMI関数を使用できなくなります。 無効コンテキスト状態からスレッドを解放するには、tpsetctxt(3c)またはtpterm()
を呼び出します。 良く設計されたアプリケーションでは、無効コンテキスト状態が生じることはありません。
注意: | Oracle Tuxedoシステムでは、COBOLアプリケーションのマルチスレッドはサポートされていません。 |
次は、2つのコンテキストからサービスを呼び出すクライアントで行われる処理の手順をまとめたものです。
TUXCONFIG
環境変数にfirstapp
で必要な値を設定します。TPMULTICONTEXTS
フラグを設定してtpinit(3c)を呼び出し、最初のアプリケーションに参加します。tuxputenv()
を呼び出して、TUXCONFIG
環境変数の値をsecondapp
コンテキストに必要な値に切り替えます。TPMULTICONTEXTS
フラグを設定してtpinit(3c)を呼び出して、2番目のアプリケーションに参加します。firstapp
コンテキストからコンテキストの切替えを開始します。firstapp
サービスを呼び出します。secondapp
コンテキストに切り替え、secondapp
サービスを呼び出します。firstapp
コンテキストに切り替え、firstapp
サービスを呼び出します。firstapp
コンテキストを終了します。secondapp
コンテキストに切り替え、secondapp
サービスを呼び出します。secondapp
コンテキストを終了します。注意: | コードを簡単にするために、エラー・チェックは省略してあります。 |
#include <stdio.h>
#include "atmi.h" /* BEA Tuxedo header file */
#if defined(__STDC__) || defined(__cplusplus)
main(int argc, char *argv[])
#else
main(argc, argv)
int argc;
char *argv[];
#endif
{
TPINIT * tpinitbuf;
TPCONTEXT_T firstapp_contextID, secondapp_contextID;
/* Assume that TUXCONFIG is initially set to /home/firstapp/TUXCONFIG*/
/*
* Attach to the BEA Tuxedo system in multicontext mode.
*/
tpinitbuf=tpalloc(TPINIT, NULL, TPINITNEED(0));
tpinitbuf->flags = TPMULTICONTEXTS;
if (tpinit((TPINIT *) tpinitbuf) == -1) {
(void) fprintf(stderr, "Tpinit failed\n");
exit(1);
}
/*
* Obtain a handle to the current context.
*/
tpgetctxt(&firstapp_contextID, 0);
/*
* Use tuxputenv to change the value of TUXCONFIG,
* so we now tpinit to another application.
*/
tuxputenv("TUXCONFIG=/home/second_app/TUXCONFIG");
/*
* tpinit to secondapp.
*/
if (tpinit((TPINIT *) tpinitbuf) == -1) {
(void) fprintf(stderr, "Tpinit failed\n");
exit(1);
}
/*
* Get a handle to the context of secondapp.
*/
tpgetctxt(&secondapp_contextID, 0);
/*
* Now you can alternate between the two contexts
* using tpsetctxt and the handles you obtained from
* tpgetctxt. You begin with firstapp.
*/
tpsetctxt(firstapp_contextID, 0);
/*
* You call services offered by firstapp and then switch
* to secondapp.
*/
tpsetctxt(secondapp_contextID, 0);
/*
* You call services offered by secondapp.
* Then you switch back to firstapp.
*/
tpsetctxt(firstapp_contextID, 0);
/*
* You call services offered by firstapp. When you have
* finished, you terminate the context for firstapp.
*/
tpterm();
/*
* Then you switch back to secondapp.
*/
tpsetctxt(secondapp_contextID, 0);
/*
* You call services offered by secondapp. When you have
finished, you terminate the context for secondapp and
end your program.
*/
tpterm();
return(0);
}
非請求メッセージを処理する各コンテキストでは、非請求メッセージ・ハンドラを設定するか、またはプロセス・ハンドラのデフォルトが設定されている場合はそれを使用する必要があります。
tpsetunsol(3c)がコンテキストに対応付けされていないスレッドから呼び出されると、新しく生成されるすべてのtpinit(3c)コンテキストに対して、プロセス単位のデフォルトの非請求メッセージ・ハンドラが作成されます。 特定のコンテキストは、コンテキストがアクティブのときにtpsetunsol()
を再度呼び出して、そのコンテキストの非請求メッセージ・ハンドラを変更することができます。 プロセス単位のデフォルトの非請求メッセージ・ハンドラは、コンテキストに現在対応付けされていないスレッドでtpsetunsol()
を再度呼び出すと、変更できます。
ハンドラの設定は、シングル・スレッド・アプリケーションまたはシングル・コンテキスト・アプリケーションのハンドラを設定する場合と同じように行います。詳細は、tpsetunsol(3c)を参照してください。
現在処理を行っているコンテキストを識別するには、非請求メッセージ・ハンドラ内でtpgetctxt(3c)を使用します。
トランザクションを使用する場合、コーディングで以下の事柄に注意してください。
注意: | この項で示す手順とサンプル・コードは、Oracle Tuxedoシステムで提供されるC言語のライブラリ関数を参照します。詳細は、『Oracle Tuxedo Cリファレンス』を参照してください。 COBOLアプリケーションではマルチコンテキスト・サーバーの生成に必要なマルチスレッドがサポートされていないので、C言語の関数に相当するCOBOLルーチンは利用できません。 |
コンテキストを使用する場合、コーディングで以下の事柄に注意してください。
TPNULLCONTEXT
に変更されることはありません。マルチコンテキスト・サーバー使用する場合、コーディングで以下の規則に注意してください。
tpinit()
が呼び出されると、tpinit()
は-1
を返してtperrno(5)にTPEPROTO
を設定します。 アプリケーション生成のサーバー・スレッドは、tpsetctxt(3c)を呼び出す前にATMIを呼び出すことはできません。tpreturn()
を呼び出す前に、そのコンテキストに対応するアプリケーション生成の各スレッドがコンテキストをTPNULLCONTEXT
または別の有効なコンテキストに設定してtpsetctxt(3c)を呼び出す必要があります。 この規則に違反すると、tpreturn(3c)またはtpforward(3c)はユーザー・ログにメッセージを書き込み、呼出し側にTPESVCERR
を示して、メイン・サーバーのディスパッチ・ループに制御を戻します。 無効tpreturn()
が実行されたコンテキスト内のスレッドは、無効コンテキスト状態になります。
tpreturn()
またはtpforward()
はユーザー・ログにメッセージを書き込み、呼出し側にTPESVCERR
を示して、メイン・サーバーのディスパッチ・ループに制御を戻します。サーバーとサーバー・スレッドの初期化と終了には、Oracle Tuxedoシステムで提供されるデフォルトの関数や独自の関数を使用できます。
マルチコンテキスト・サーバーを使用するほとんどのアプリケーションでは、システム生成のディスパッチ・サーバー・スレッドだけが使用されます。ただし、アプリケーション・サーバーに新しいスレッドを生成することもできます。この項では、その方法について説明します。
オペレーティング・システムのスレッド関数を使用して、アプリケーション・サーバーに新しいスレッドを生成できます。 これらの新しいスレッドは、Oracle Tuxedoシステムから独立して動作できます。また、いずれかのサーバー・ディスパッチ・スレッドと同じコンテキストで動作することもできます。
アプリケーション生成のサーバー・スレッドは、当初どのサーバー・ディスパッチ・コンテキストにも対応付けられていません。 ただし、初期化される前に呼び出された場合、ほとんどのATMI関数は暗黙的にtpinit(3c)を実行します。 サーバーでtpinit()
を呼び出すことは禁止されているので、そのような呼出しを行うと問題が発生します。 サーバー・プロセスがtpinit()
を呼び出すと、tpinit()
は -1を返してtperrno(5)にTPEPROTO
を設定します。
そのため、アプリケーション生成のサーバー・スレッドは、既存のコンテキストと対応付けを行ってからATMI関数を呼び出す必要があります。 アプリケーション生成のサーバー・スレッドを既存のコンテキストに対応付けるには、以下の手順をコーディングします。
tpreturn()
またはtpforward()
を呼び出す前に、そのコンテキストにあったすべてのアプリケーション生成のサーバー・スレッドはTPNULLCONTEXT
または別の有効なコンテキストに切り替える必要があります。この規則に違反すると、tpforward(3c)またはtpreturn(3c)が失敗し、呼出し側にサービス・エラーが示されます。
次のサンプル・コードは、サービスが別のスレッドを生成してそのサービスの作業を行うマルチコンテキスト・サーバーを示しています。このコードは、サーバーでアプリケーション・スレッドを生成する必要があるアプリケーションで使用します。 オペレーティング・システムのスレッド関数は、オペレーティング・システムによって異なります。 このサンプル・コードでは、POSIX関数とATMI関数が使用されています。
注意: | コードを簡単にするために、エラー・チェックは省略してあります。 また、Oracle Tuxedoシステムによってディスパッチされたスレッドだけを使用するマルチコンテキスト・サーバーも省略してあります。そのようなサーバーのコーディングは、スレッド・セーフのプログラミング方法が使用されている場合、シングル・コンテキスト・サーバーのコーディングとまったく同じです。 |
#include <pthread.h>
#include <atmi.h>
void *withdrawalthread(void *);
struct sdata {
TPCONTEXT_T ctxt;
TPSVCINFO *svcinfoptr;
};
void
TRANSFER(TPSVCINFO *svcinfo)
{
struct sdata transferdata;
pthread_t withdrawalthreadid;
tpgetctxt(&transferdata.ctxt, 0);
transferdata.svcinfoptr = svcinfo;
pthread_create(&withdrawalthreadid, NULL, withdrawalthread, &transferdata);
tpcall("DEPOSIT", ...);
pthread_join(withdrawalthreadid, NULL);
tpreturn(TPSUCCESS, ...);
}
void *
withdrawalthread(void *arg)
{
tpsetctxt(arg->ctxt, 0);
tpopen();
tpcall("WITHDRAWAL", ...);
tpclose();
return(NULL);
}
このコードでは、元のディスパッチ・スレッドでDEPOSIT
サービスを呼び出し、アプリケーション生成のスレッドでWITHDRAWAL
を呼び出して、口座振替えを行っています。 この例では、リソース・マネージャで混在モデルがサポートされていることを前提としています。つまり、サーバーのすべてのスレッドが特定のインスタンスと対応付けされていなくても、そのサーバーの複数のスレッドが特定のデータベース接続と対応付けられます。 ただし、そのようなモデルがサポートされたリソース・マネージャはほとんどありません。
アプリケーション生成のスレッドを使用しないようにすると、このコードはさらに簡単になります。 このサンプル・コードでtpcall(3c)を2回呼び出して行っている並列処理を実現するには、サーバー・ディスパッチ・スレッド内でtpacall(3c)とtpgetrply(3c)をそれぞれ2回呼び出します。
注意: | Oracle Tuxedoシステムでは、COBOLアプリケーションのマルチスレッドはサポートされていません。 |
マルチスレッド・クライアントを使用する場合、コーディングで以下の規則に注意してください。
tpacall()
の呼出し側かどうかに関係なく、tpgetrply(3c)を呼び出して以前のtpacall(3c)呼出しのレスポンスを受け取ることができます。tpcommit()
はトランザクションを停止し、-1
を返してtperrno(5)にTPEABORT
を設定します。TUXCONFIG
またはWSNADDR
の値を手動で変更してからtpinit(3c)を呼び出します。 このような処理が複数のスレッドで行われる場合、環境変数の設定とtpinit()
呼出しを同期する必要があります。 クライアントのすべてのアプリケーション対応付けは、以下の規則に従う必要があります。TPMULTICONTEXTS
フラグを設定してtpinit(3c)関数を呼び出す必要があります。 クライアントを複数のコンテキストに参加させるには、TPINIT
データ構造体のflags
要素にTPMULTICONTEXTS
フラグを設定してtpinit(3c)関数を呼び出します。
1つのプロセスでは、tpinit(3c)へのすべての呼出しにTPMULTICONTEXTS
フラグを含めるか、または、tpinit()
へのすべての呼出しにこのフラグを含めません。この規則には例外が1つあり、tpterm(3c)への呼出しが正常に終了して、クライアントのすべてのアプリケーション関連付けが終了した場合、次にtpinit()
を呼び出すときに必ずしもTPMULTICONTEXTS
フラグを含む必要のない状態にプロセスが復元されます。
TPMULTICONTEXTS
フラグを設定してtpinit(3c)関数が呼び出されると、アプリケーションとの新しい対応付けが生成され、スレッドに対するカレントの対応付けが設定されます。 新しい対応付けが生成されるOracle Tuxedoドメインは、TUXCONFIG
またはWSENVFILE/WSNADDR
環境変数の値で決定されます。
クライアント・スレッドがTPMULTICONTEXTS
フラグを設定せずにtpinit(3c)を正常に実行した場合、クライアントのすべてのスレッドがシングル・コンテキスト状態(TPSINGLECONTEXT
)になります。
tpinit(3c)が失敗した場合、呼出し側スレッドは元のコンテキスト、つまりtpinit()
呼出しの前に操作していたコンテキスト状態のままになります。
まだ動作中のスレッドがあるコンテキストからtpterm(3c)を呼び出すことはできません。 このような状況やそれ以外の状況でtpterm()
を呼び出した結果生じるコンテキスト状態については、「マルチコンテキスト状態の遷移」を参照してください。
マルチコンテキストのアプリケーションでは、様々な関数を呼び出すと、呼出し側スレッド、および呼出し側プロセスと同じコンテキストでアクティブなその他のスレッドのコンテキスト状態が変化します。図10-4は、tpinit()、tpsetctxt(3c)およびpterm()を呼び出した結果、変化したコンテキスト状態を示しています(tpgetctxt(3c)関数を呼び出しても、コンテキスト状態は変化しません)。
注意: | tpterm(3c)がマルチコンテキスト状態(TPMULTICONTEXTS )で実行しているスレッドによって呼び出されると、呼出し側スレッドはNULLコンテキスト状態(TPNULLCONTEXT )になります。 終了するコンテキストに関連するその他すべてのスレッドは、無効コンテキスト状態(TPINVALIDCONTEXT )に切り替わります。 |
表10-2は、tpinit(3c)、tpsetctxt(3c)およびtpterm(3c)を呼び出した場合のコンテキスト状態の変化を示しています。
コンテキスト0へのtpsetctxt(3c)
|
||||
コンテキスト> 0へのtpsetctxt(3c)
|
||||
暗黙のtpinit(3c)
|
||||
このスレッドでのtpterm(3c)
|
||||
このコンテキストの異なるスレッドでのtpterm(3c)
|
tpgetrply(3c)は、tpacall(3c)からのリクエストに対するレスポンスだけを受け取ります。tpcall(3c)からのリクエストは、マルチスレッドまたはマルチコンテキストのレベルに関係なく、tpgetrply()
で取得することはできません。
tpgetrply(3c)は、1つのコンテキスト、つまり呼出し側コンテキストだけで動作します。 そのため、TPGETANY
フラグを設定してtpgetrply()
を呼び出すと、同じコンテキストで生成されたハンドルだけが考慮されます。 同じように、あるコンテキストで生成されたハンドルを別のコンテキストで使用することはできません。ただし、同じコンテキストで動作するスレッドには、そのハンドルを使用できます。
tpgetrply(3c)をマルチスレッド環境で呼び出す場合、以下の制約があります。
tpgetrply()
を呼び出して同じハンドルの取得を試みると、tpgetrply()
は-1
を返し、tperrno
にTPEPROTO
を設定します。 TPGETANY
フラグを設定してtpgetrply(3c)の応答を待機しているときに、同じコンテキストの別のスレッドがtpgetrply()
を呼び出して特定のハンドルの取得を試みると、tpgetrply()は-1
を返し、tperrno(5)にTPEPROTO
を設定します。 これは、1つのスレッドがすでにtpgetrply(3c)で特定のハンドルを待機しているときに、同じコンテキストの別のスレッドがTPGETANY
フラグを設定してtpgetrply()
を呼び出した場合も同じです。これらの制約により、特定のハンドルを待機しているスレッドがある場合、その応答が別のスレッドに渡されることがなくなります。
TPGETANY
フラグを設定してtpgetrply(3c)の応答を待機できるのは、特定のコンテキスト内で1つのスレッドだけです。 TPGETANY
フラグを設定して呼び出したtpgetrply()
がまだ処理されていない場合に、同じコンテキストの別のスレッドが同じ呼出しを行うと、この2番目の呼出しは-1
を返し、tperrno(5)にTPEPROTO
を設定します。Oracle Tuxedoアプリケーションをマルチコンテキスト・マルチスレッド環境で実行する場合、環境変数に関して以下の事柄に注意してください。
注意: | オペレーティング・システム環境が認識されないオペレーティング・システムの場合、初期状態では空の環境になっています。 |
TUXCONFIG
、WSNADDR
、またはWSENVFILE
環境変数の値を適切な値に変更する必要があります。 そのようなアプリケーションがマルチスレッドの場合、以下の処理を確実に行うために、ミューテックスなどのアプリケーション定義の同時実行制御が必要になります。WSENVFILE
やマシン環境ファイルが読み取られ、そのコンテキストの環境だけが影響を受けます。 環境ファイルで上書きされないコンテキスト部分には、プロセス全体に対する以前の環境が適用されます。 以下に示すATMI関数は、呼出し側のアプリケーション・コンテキストだけに影響します。
注意: | tpbroadcast(3c)の場合、ブロードキャスト・メッセージは特定のアプリケーションとの対応付けから送られたものとして識別されます。tpnotify(3c)の場合、通知は特定のアプリケーションとの関連付けから送られたものとして識別されます。tpinit(3c)の注記については、「マルチスレッド・クライアントでのプロセス単位の関数とデータ構造体」を参照してください。 |
注意: | tpsetunsol(3c)がコンテキストに対応付けされていないスレッドから呼び出されると、新しく生成されるすべてのtpinit(3c)コンテキストに対して、プロセス単位のデフォルトの非請求メッセージ・ハンドラが作成されます。 特定のコンテキストは、コンテキストがアクティブのときにtpsetunsol() を再度呼び出して、そのコンテキストの非請求メッセージ・ハンドラを変更することができます。 プロセス単位のデフォルトの非請求メッセージ・ハンドラは、コンテキストに現在対応付けされていないスレッドでtpsetunsol() を再度呼び出すと、変更できます。 |
以下に示すOracle Tuxedo関数は、呼出し側のプロセス全体に影響します。
TPMULTICONTEXTS
モードまたはシングル・コンテキスト・モードに応じて適用されます。 「マルチスレッド・クライアントでのコンテキスト単位の関数とデータ構造体」も参照してください。シングル・コンテキスト・モード、マルチコンテキスト・モード、または非初期化モードのどれを使用するかは、プロセス全体に影響します。 また、バッファ・タイプ・スイッチ、ビュー・キャッシュ、および環境変数の値も、プロセス単位の関数です。
Ferror、Ferror32(5)、tperrno(5)、tpurcode(5)、およびUunix_err
変数は、各スレッドに固有です。
次のサンプル・コードは、ATMI呼出しを使用するマルチスレッド・クライアントを示しています。 スレッド関数は、オペレーティング・システムによって異なります。 この例では、POSIX関数が使用されています。
注意: | コードを簡単にするために、エラー・チェックは省略してあります。 |
#include <stdio.h>
#include <pthread.h>
#include <atmi.h>
TPINIT * tpinitbuf;
int timeout=60;
pthread_t withdrawalthreadid, stockthreadid;
TPCONTEXT_T ctxt;
void * stackthread(void *);
void * withdrawalthread(void *);
main()
{
tpinitbuf = tpalloc(TPINIT, NULL, TPINITNEED(0));
/*
* This code will perform a transfer, using separate threads for the
* withdrawal and deposit. It will also get the current
* price of BEA stock from a separate application, and calculate how
* many shares the transferred amount can buy.
*/
tpinitbuf->flags = TPMULTICONTEXTS;
/* Fill in the rest of tpinitbuf. */
tpinit(tpinitbuf);
tpgetctxt(&ctxt, 0);
tpbegin(timeout, 0);
pthread_create(&withdrawalthreadid, NULL, withdrawalthread, NULL);
tpcall("DEPOSIT", ...);
/* Wait for the withdrawal thread to complete. */
pthread_join(withdrawalthreadid, NULL);
tpcommit(0);
tpterm();
/* Wait for the stock thread to complete. */
pthread_join(stockthreadid, NULL);
/* Print the results. */
printf("$%9.2f has been transferred \
from your savings account to your checking account.\n", ...);
printf("At the current BEA stock price of $%8.3f, \
you could purchase %d shares.\n", ...);
exit(0);
}
void *
stockthread(void *arg)
{
/* The other threads have now called tpinit(), so resetting TUXCONFIG can
* no longer adversely affect them.
*/
tuxputenv("TUXCONFIG=/home/users/xyz/stockconf");
tpinitbuf->flags = TPMULTICONTEXTS;
/* Fill in the rest of tpinitbuf. */
tpinit(tpinitbuf);
tpcall("GETSTOCKPRICE", ...);
/* Save the stock price in a variable that can also be accessed in main(). */
tpterm();
return(NULL);
}
void *
withdrawalthread(void *arg)
{
/* Create a separate thread to get stock prices from a different
* application.
*/
pthread_create(&stockthreadid, NULL, stockthread, NULL);
tpsetctxt(ctxt, 0);
tpcall("WITHDRAWAL", ...);
return(NULL);
}
ほとんどの場合、マルチスレッド・サーバーはマルチコンテキストでもあります。 マルチスレッド・サーバーのコーディングについては、「サーバーでマルチコンテキストとマルチスレッドを使用するためのコーディング」を参照してください。
buildserver(1)やbuildclient(1)など、コンパイルまたはビルドの実行可能ファイル用にOracle Tuxedoシステムで提供されるプログラムには、必要なコンパイラ・フラグが自動的に設定されます。 これらのツールを使用すると、コンパイル時にフラグを設定する必要がありません。
ただし、最終的なコンパイルの前に.c
ファイルを.o
ファイルにコンパイルする場合は、プラットフォーム固有のコンパイラ・フラグを設定する必要があります。 そのようなフラグは、単一のプロセスにリンクするすべてのコードに一貫して設定しなければなりません。
マルチスレッド・サーバーを生成する場合、-t
オプションを指定してbuildserver(1)コマンドを実行する必要があります。 これはマルチスレッド・サーバーの場合に必須のオプションです。ビルド時にこのオプションが指定されておらず、その後、MAXDISPATCHTHREADS
の値が1を超える構成ファイルを使用して新しいサーバーを起動すると、警告メッセージがユーザー・ログに記録され、サーバーはシングル・スレッドの動作に戻ります。
マルチスレッド環境で.c
ファイルを.o
ファイルにコンパイルする場合に必要なオペレーティング・システム固有のコンパイラ・パラメータを識別するには、-v
オプションを指定してbuildclient(1)またはbuildserver(1)をテスト・ファイルで実行します。
マルチスレッドやマルチコンテキストのコードをテストする場合、以下を行うことをお薦めします。
エラーの原因を調べる場合、まずTPMULTICONTEXTS
フラグが設定されているかどうか、またその設定内容を確認します。 このフラグが設定されていないこと、または正しく設定されていないことが原因でよくエラーが起こります。
TPMULTICONTEXTS
フラグを使用できない場合にこのフラグがプロセスに設定されているとき、またはTPMULTICONTEXTS
を設定する必要がある場合に設定されていないとき、tpinit(3c)は-1
を返し、tperrno
にTPEPROTO
を設定します。
TPMULTICONTEXTS
が設定されていない場合にtpinit(3c)が呼び出されると、この関数はシングル・コンテキスト・アプリケーションで呼び出されたときと同じように動作します。tpinit()
がすでに1回呼び出されている場合、それ以降のtpinit()
呼出しでTPMULTICONTEXTS
フラグが設定されていなくても、この関数は正常に終了します。これは、アプリケーション内のTUXCONFIG
またはWSNADDR
環境変数の値が変更されている場合にも当てはまります。TPMULTICONTEXTS
フラグを設定せずにtpinit()
を呼び出すことは、マルチコンテキスト・モードではできません。
クライアントがアプリケーションに参加していない場合に、tpinit(3c)を呼び出す別の関数の呼出しの結果として、暗黙的にtpinit()
が呼び出されると、Oracle TuxedoシステムではTPMULTICONTEXTS
フラグが設定されずにtpinit()
が呼び出されたと解釈されます。これは、以降のtpinit()
呼出しでどのフラグが使用されるかを判断するためです。
ほとんどのATMI関数は、すでにマルチコンテキスト・モードで動作しているプロセスのコンテキストに対応付けされていないスレッドに呼び出された場合、tperrno(5)=TPEPROTO
が設定されて失敗します。
一部のオペレーティング・システムでは、オペレーティング・システムのデフォルトのスレッド・スタック・サイズがOracle Tuxedoシステムで使用するには十分ではありません。 Compaq Tru64 UNIXとUnixWareの2つのオペレーティング・システムは、サイズが小さいことが認識されています。 デフォルトのスレッド・スタック・サイズのパラメータが使用されている場合に、スタックを多用する関数がメイン・スレッド以外のスレッドで呼び出されると、これらのプラットフォーム上のアプリケーションはコア・ダンプします。 通常、生成されるコア・ファイルから、スタック・サイズの不足が問題の原因であることはわかりません。
サーバー・ディスパッチ・スレッドやクライアントの非請求メッセージ・スレッドなど、Oracle Tuxedoシステムで独自のスレッドが生成される場合、これらのプラットフォームのデフォルトのスタック・サイズのパラメータを適切な値に調整できます。 ただし、アプリケーションで独自のスレッドが生成される場合、アプリケーションで十分なスタック・サイズを指定する必要があります。 Oracle Tuxedoシステムにアクセスするスレッドには、最低128 Kを指定してください。
Compaq Tru64 UNIXおよびPOSIXスレッドが使用されるそのほかのシステムでは、スレッドのスタック・サイズは、pthread_create()
を呼び出す前にpthread_attr_setstacksize()
を呼び出して指定します。UnixWareでは、スレッドのスタック・サイズはthr_create()
の引数として指定されます。この問題の詳細は、お使いのオペレーティング・システムのドキュメントを参照してください。
エラーはユーザー・ログに記録されます。 シングル・コンテキスト・モードでもマルチコンテキスト・モードでも、各エラーに対して次の情報が記録されます。
process_ID.thread_ID.context_ID