![]() |
![]() |
![]() |
![]() |
![]() |
• Basic Universityサンプル・アプリケーションのしくみ。このトピックでは、設計と実装の考慮事項について説明します
• Universityサーバー・アプリケーションの設計上の考慮事項。このトピックでは、次のトピックについて包括的に説明します。
•
•
•
•
•
•
図3-1に、Basic Universityサンプル・アプリケーションを示します。
• アプリケーションの起動 - サーバー・アプリケーションが起動し、クライアント・アプリケーションがRegistrarオブジェクトのオブジェクト参照を取得するとき次に、Basicクライアント・アプリケーションおよびサーバー・アプリケーションが起動し、クライアント・アプリケーションがRegistrarオブジェクトのオブジェクト参照を取得するときに行われる一般的な一連のイベントを示します。
1. Basicクライアント・アプリケーションおよびサーバー・アプリケーションが起動し、クライアント・アプリケーションはFactoryFinderからRegistrarFactoryオブジェクトのオブジェクト参照を取得します。
3.
4. インスタンス化が済んだら、RegistrarFactoryオブジェクトのfind_registrar()操作が呼び出されます。RegistrarFactoryオブジェクトは、Registrarのオブジェクト参照を作成してクライアント・アプリケーションに戻します。
• 変数number_to_getで表され、返される概要リストのサイズを指定する整数。
2.
3.
b.
d.
4. 前のステップで作成したオブジェクト参照を使用して、RegistrarオブジェクトはCourseSynopsisEnumeratorオブジェクトに対するget_next_n()操作を呼び出して、リスト・サイズを渡します。ステップ1で説明したように、このリスト・サイズはパラメータnumber_to_getによって表されます。
5.
6. TPフレームワークは、CourseSynopsisEnumeratorオブジェクトのactivate_object()操作を呼び出します。この操作は、次の2つのことを行います。
•
• 検索基準に一致するが、まだ返されていないコース概要の数。これは、number_remainingパラメータによって指定されます。
8. (number_remaining変数が0の場合、RegistrarオブジェクトはCourseSynopsisEnumeratorオブジェクトのdestroy()操作を呼び出し、クライアント・アプリケーションにnil参照を返します。)
9. クライアント・アプリケーションは、一致する次の概要リストを取得するためのリクエストを直接CourseSynopsisEnumeratorオブジェクトに送信します。
11. クライアント・アプリケーションは、CourseSynopsisEnumeratorオブジェクトとのやり取りを終了すると、CourseSynopsisEnumeratorオブジェクトに対してdestroy()操作を呼び出します。この結果、CourseSynopsisEnumeratorオブジェクトはTP::deactivateEnable()操作を呼び出します。
12. TPフレームワークは、CourseSynopsisEnumeratorオブジェクトのdeactivate_object()操作を呼び出します。この結果、CourseSynopsisEnumeratorオブジェクトが保持しているコース概要のリストがサーバー・コンピュータのメモリーから削除されるため、CourseSynopsisEnumeratorオブジェクトのサーバントを別のクライアント・リクエストのために再利用できるようになります。
2. クライアント・アプリケーションは、Registrarオブジェクトのget_course_details()操作を呼び出し、コース番号のリストを受け渡します。
3.
RegistrarFactoryオブジェクトのオブジェクト参照は、RegistrarFactoryオブジェクトをFactoryFinderに登録するサーバー・オブジェクトで生成されます。クライアント・アプリケーションは、RegistrarFactoryオブジェクトへの参照をFactoryFinderから取得します。Basic Universityサーバー・アプリケーション・プロセスには、RegistrarFactoryオブジェクトは1つしか存在しません。 Registrarオブジェクトのオブジェクト参照は、RegistrarFactoryオブジェクトによって作成され、クライアント・アプリケーションがfind_registrar()操作を呼び出したときに返されます。Registrarオブジェクト用に作成されたオブジェクト参照は常に同一です。このオブジェクト参照には一意のOIDが含まれません。Basic Universityサーバー・アプリケーション・プロセスには、Registrarオブジェクトは1つしか存在しません。 CourseSynopsisEnumeratorオブジェクトのオブジェクト参照は、クライアント・アプリケーションがget_courses_synopsis()操作を呼び出したときにRegistrarオブジェクトによって作成されます。つまり、RegistrarオブジェクトはCourseSynopsisEnumeratorオブジェクトのファクトリです。CourseSynopsisEnumeratorオブジェクトの設計と使い方については、この章で後述します。Basic Universityサーバー・アプリケーション・プロセスには、任意の数のCourseSynopsisEnumeratorオブジェクトが存在できます。
• サーバー・オブジェクトは、RegistrarFactoryオブジェクトをFactoryFinderに登録します。この方法により、クライアント・アプリケーションはサーバー・アプリケーション内の基本オブジェクトのオブジェクト参照を取得するために必要なファクトリを検索できます。
•
•
• RegistrarFactoryオブジェクトは、特定のクライアント・リクエストに対して一意である必要はありません。また、このオブジェクトをメモリーに保持しておき、クライアント呼出しごとにこのオブジェクトをアクティブ化および非アクティブ化する負担を回避することは合理的です。したがって、RegistrarFactoryオブジェクトにはprocessアクティブ化ポリシーが割り当てられます。Basicサンプル・アプリケーションは、小規模環境でのデプロイを目的としています。Registrarオブジェクトは、RegistrarFactoryオブジェクトに似た特性を多数備えています。つまり、このオブジェクトは特定のクライアント・リクエストに一意である必要はありません。また、呼出しのたびにオブジェクトのアクティブ化/非アクティブ化を継続して行う必要をなくすためにも合理的です。そのため、Basicサンプル・アプリケーションでは、Registrarオブジェクトはprocessアクティブ化ポリシーを持ちます。Universityサーバー・アプリケーションは、このソリューションを実装するCourseSynopsisEnumeratorオブジェクトを備えています。このオブジェクトは最初に呼び出されたときに最初の概要リストを返しますが、その後もインメモリー・コンテキストに保持されるので、クライアント・アプリケーションは後続のリクエストで概要の残りを取得できます。インメモリー・コンテキストを保持するには、CourseSynopsisEnumeratorオブジェクトはステートフルでなければなりません。つまり、このオブジェクトは複数のクライアント呼出しにわたってメモリー内に常駐します。クライアントがCourseSynopsisEnumeratorオブジェクトとの会話を終了するときに、このオブジェクトにはメモリーからフラッシュされるための手段が必要です。このため、CourseSynopsisEnumeratorオブジェクトの適切な状態管理の方法は、processアクティブ化ポリシーを割り当て、CORBAアプリケーション制御の非アクティブ化機能を実装することです。アプリケーション制御の非アクティブ化は、そのオブジェクトのdestroy()操作によって実装されます。次のサンプル・コードに、CourseSynopsisEnumeratorオブジェクトのdestroy()操作を示します。Registrarオブジェクトの操作の1つによって、クライアント・アプリケーションにコース情報の詳細が返されます。一般的なシナリオでは、数多くのコース概要を参照した学生は、通常2つか3つのコースに関する詳細情報を一度に参照しようとします。この使用シナリオを効率的に実装するために、Registrarオブジェクトにはget_course_details()操作が定義されています。この操作は、コース番号のリストを指定するパラメータを入力として受け付けます。次にこの操作は、データベースからコースの詳細を検索し、その詳細をクライアント・アプリケーションに返します。この操作が実装されるオブジェクトはプロセス・バウンドなので、この操作はその呼出しの完了後に状態データをメモリーに保持するのを避ける必要があります。Registrarオブジェクトは、永続状態をメモリーに保持しません。クライアント・アプリケーションがget_course_details()操作を呼び出すと、このオブジェクトは関連するコース情報をUniversityデータベースからフェッチしてクライアントに送信します。このオブジェクトは、コース・データをメモリー内に保持しません。このオブジェクトに対するactivate_object()操作またはdeactivate_object()操作では永続状態は処理されません。CourseSynopsisEnumeratorオブジェクトは、自身がUniversityデータベースから検索するコース概要を処理します。状態処理に関する設計上の考慮事項は、ディスクから状態を読み取る方法です。このオブジェクトは、状態をディスクに書き込みません。
• アクティブ化時に、そのオブジェクトのactivate_object()操作を介してその永続状態情報を読み取ります。
• 非アクティブ化時に、deactivate_object()操作を介してメモリーからコース概要をフラッシュします。
注意: オブジェクトに対するTobj_ServantBase::activate_object()操作またはTobj_ServantBase::deactivate_object()操作を実装する場合は、実装ヘッダー・ファイル(つまり、application_i.hファイル)を編集し、これらの操作の定義をそのオブジェクトのインタフェースのクラス定義テンプレートに追加してください。
• すべてのUniversityサンプル・アプリケーションは、Universityデータベースにアクセスしてコース情報と学生情報を操作します。通常、これが、実装ファイルで記述するコードの大部分を占めます。Universityサンプルの実装ファイルをより簡素化して、データベース・コードではなくCORBAの機能に集中できるようにするために、サンプルでは、データベースを読み書きするすべてのコードが一連のクラスにラッピングされています。utilsディレクトリのsamplesdb.hファイルには、これらのクラスの定義が含まれています。これらのクラスは、Universityデータベース内のコース・レコードと学生レコードを読み書きするために必要なすべてのSQL呼出しを行います。
注意: Basicサーバー・アプリケーションに組み込むファイルの詳細は、『CORBA Universityサンプル・アプリケーション・ガイド』を参照してください。
• CourseSynopsisEnumeratorオブジェクトは、データベース・カーソルを使用してUniversityデータベースから一致するコース概要を検索します。データベース・カーソルは複数のトランザクションにまたがることができないため、CourseSynopsisEnumeratorオブジェクトに対するactivate_object()操作は一致するすべてのコース概要をメモリーに読み込みます。カーソルはイテレータ・クラスによって管理されているため、CourseSynopsisEnumeratorオブジェクトからは見えないことに注意してください。Universityサンプル・アプリケーションがトランザクションを使用する方法の詳細は、第6章「トランザクションのCORBAサーバー・アプリケーションへの統合」を参照してください。1-22ページの「Process-Entityデザイン・パターン」という項で説明したように、このデザイン・パターンは、クライアント・アプリケーションによって必要とされるデータ・エンティティを処理する1つのプロセス・オブジェクトが存在する場合に適しています。データ・エンティティは、クライアント・アプリケーションではなくこのプロセス・オブジェクトによって操作されるCORBA structとしてカプセル化されます。Process-Entityデザイン・パターンをBasicサンプル・アプリケーションに適用すると、Basicサンプル・アプリケーションは細粒度オブジェクトの実装を回避できます。たとえば、Registrarオブジェクトは、同様に数の多い一連のコース・オブジェクトのかわりに使用できる効率的なオブジェクトです。単一の粗粒度Registrarオブジェクトを管理する負荷は、何百、何千もの細粒度のコース・オブジェクトを管理するオーバーヘッドに比べれば、それほど大きくはありません。List-Enumeratorデザイン・パターンは、CourseSynopsisEnumeratorオブジェクトに最適です。このデザイン・パターンを実装すると、次のメリットが得られます。
• 各CourseSynopsisEnumeratorオブジェクトは一意で、その内容はこのオブジェクトが作成される原因となったリクエストによって決まります。(また、各CourseSynopsisEnumeratorのオブジェクトIDも一意です。)クライアントがRegistrarオブジェクトに対してget_courses_synopsis()操作を呼び出すと、Registrarオブジェクトは次のものを戻します。
•
• 残りの概要を返すことができるCourseSynopsisEnumeratorオブジェクトのオブジェクト参照。このため、後続のすべての呼出しは適切なCourseSynopsisEnumeratorオブジェクトに対して行われます。これは、サーバー・プロセスにCourseSynopsisEnumeratorクラスのアクティブ・インスタンスが複数存在する場合に重要です。get_courses_synopsis()操作は一意のCourseSynopsisEnumeratorオブジェクト参照を返すので、クライアント・リクエストどうしが衝突することはありません。つまり、クライアント・リクエストが間違ったCourseSynopsisEnumeratorオブジェクトに誤って送られることはありません。Registrarオブジェクトはget_courses_synopsis()操作を備えていますが、データベース問合せと概要リストの知識はすべてCourseSynopsisEnumeratorオブジェクトに埋め込まれます。この場合、Registrarオブジェクトは単にクライアントが次のデータを取得するための手段として機能します。
•
• 残りの概要を返すことができるCourseSynopsisEnumeratorオブジェクトの参照。この例には、RegistrarオブジェクトがCourseSynopsisEnumeratorオブジェクトのオブジェクト参照を作成し、それによってそのオブジェクトがインスタンス化された場合などがあります。この2つのオブジェクト間のリクエストとレスポンスでは、データ・マーシャリングは行われません。状態を持つオブジェクトの事前アクティブ化機能を使用すると、クライアント・アプリケーションがオブジェクトを呼び出す前にそのオブジェクトをアクティブ化できます。この機能は、UniversityサンプルのCourseSynopsisEnumeratorオブジェクトなどのイテレータ・オブジェクトを作成するときに特に役立ちます。状態を持つオブジェクトの事前アクティブ化では、TP::create_active_object_reference()操作を使用します。通常、クライアントがあるオブジェクトに対する呼出しを発行するまで、CORBAサーバー・アプリケーションでそのオブジェクトは作成されません。ただし、オブジェクトを事前アクティブ化し、TP::create_active_object_reference()操作を使用してそのオブジェクトへの参照をクライアントに渡すことによって、クライアント・アプリケーションは、すでにアクティブ化され、状態を持っているオブジェクトを呼び出すことができます。
1. オブジェクトを作成するためのC++ new文の呼出しを含めます。
3. このように、事前アクティブ化オブジェクトは、TPフレームワークがそのオブジェクトのServer::create_servant()とTobj_ServantBase::activate_object()操作を呼び出さずに作成されます。
• 事前アクティブ化オブジェクトには、processアクティブ化ポリシーが割り当てられている必要があります。このため、これらのオブジェクトは、プロセスの終了時か、それらのオブジェクトに対するTP::deactivateEnable()操作の呼出しによってのみ非アクティブ化できます。
• サーバーがクラッシュし、そのときに削除されたオブジェクトをクライアント・アプリケーションが呼び出そうとする状況を回避するには、事前アクティブ化されるオブジェクトに対するTobj_ServantBase::activate_object()操作の実装にTobjS::ActivateObjectFailed例外を追加します。クライアントがサーバー・クラッシュ後にこのようなオブジェクトを呼び出そうとし、TPフレームワークがそのオブジェクトに対してTobj_ServantBase::activate_object()操作を呼び出した場合、TPフレームワークはクライアント・アプリケーションに次の例外を戻します。