ORBの実行
CORBA_ORB_run関数を実行して、CORBAのイベントループを起動させる。
【CORBA_ORB_run関数】
この関数では、POA_main_loop( The_RootPOA ); を呼んでいるのみである。
【POA_main_loop関数】
この関数では、server_loop(10000.0, PortableServer_execute_request, rootPOA); を呼んでいるのみである。
【server_loop関数】
この関数は、RtORBのもっとも低レベルの通信レイアである。この関数の処理の流れは、下記の通り。
- init_socket_servers(); GIOPで使用するfd_set 構造体を初期化する。
- selectシステムコールで使用するtime_out構造体に引数で与えられたmsecの時間をセット
- 以下の処理をループする
- select_socket_servers(time_out); time_outの時間、またはGIOPリクエストの到達まで待ち、リクエストに対する処理を実行。
- (*idle)(arg); 第2引数の関数ポインタがNULLでなければ、第2引数の関数を第3引数のポインタを引数にして関数を実行。すなわち、PortableServer_execute_request(The_RootPOA) が実行される。
【init_socket_servers関数】
この関数は、GIOPで使用するfd_set構造体を初期化する。この関数の処理の流れは、下記の通り。
- get_Servers_from_SockProfile(sockServers, &nSock, 0); sockport_profileのtypeがSOCK_SERVERまたはSOCK_SERVICEのものを抽出
- FD_ZERO(&main_socket_bits); selectシステムコールで使用するfd_set構造体を初期化
- sockport_profileのtypeがSOCK_SERVERのものをfd_set構造体にセット
【get_Servers_from_SockProfile関数】(要 修正)
この関数は、sockport_profileのtypeがSOCK_SERVERまたはSOCK_SERVICEのものを抽出する。
SockProfileは、予め大域変数として定義されたsockport_profile構造体である。また、FD_SETSIZEは、OSごとに定義されている最大のfd_setの数である。
【select_socket_servers関数】
この関数は、select_socket_ports関数を呼び出しているのみである。
select_socket_ports( &main_socket_bits, time_out);
【select_socket_ports関数】
この関数は、selectシステムコールで、外部からのGIOPリクエストを待ち、接続要求の場合には、GIOP用のsocketを生成し、そうでなければ、予めSockProfileに設定されているcommand_procを実行する。command_procがNULLまたは、実行時にエラーが発生すれば、その接続を閉じる。この関数の処理の流れは、下記のとおり。
- selectシステムコールで使うfd_set socksをFD_ZERO関数で初期化
- 引数で与えられたselectシステムコールで入力待ちになるfd_set sockbitsを、先ほど初期化したsocksにコピーする。
- 引数で与えられたtime_out構造体をコピー
- selectシステムコールで、GIOPイベントの到着を待つ。
- selectシステムコールで、イベントが来たsocket記述子すべてに対して以下の処理を行う。
- active_portに0をセットし、イベントが来たsocket記述子を取得。
- SockProfile配列から、active_portに対応するcommand_procの関数ポインタを取得しておく。これは、RtORBでは、SOCK_SERVERでは、POAの活性化時に、PortableServer_enqueue_request関数がセットされているはずである。SockProfile配列から、active_portに対応するtypeを取得し、それに応じて、次の処理を行う。
- typeがSOCK_SERVERの時:
- これは、新規の接続要求である。そのためaccept_connection関数でGIOP通信用のsocketを生成する。この時active_portに対応するconnection_procがセットされていれば、active_portとargを引数として関数を実行。acceptが成功すれば、新規に生成されたsocket記述子に対応するSockProfileに対して、copy_sockport_profile関数でコールバック関数等をコピーし、typeをSOCK_SERVICEにする。さらに、そのsocket記述子をFD_SET関数でsockbitsにセットする。
- FD_CLRで、socksからactive_portを除去し、イベント待ちのsocket記述子の数を1つ減じる。
- typeがSOCK_CLIENTまたは、SOCK_SERVICEの時:
- active_portに対応するcommand_procの関数をGIOP_ConnectionHandler h={CONNECTION_TYPE_SOCKET,active_port} を引数として実行する。この時、処理が失敗すれば、コネクションが切れているので、active_portに対応するdisconnect_procがセットされていれば、それを実行し、active_portをクローズし、sockbitsからactive_portをクリアするとともに、typeをSOCK_CLOSEDにする。
- FD_CLRで、socksからactive_portを除去し、イベント待ちのsocket記述子の数を1つ減じる。
- それ以外の時:
- エラーメッセージを表示し、イベント待ちのsocket記述子の数を1つ減じる。
【PortableServer_execute_request関数】
この関数は、GIOPメセージを処理する。CORBAのリモートメソッドコールのメインの関数である。引数であたえられたポインタは、POAであるはず。また、GIOPのリクエストは、一時的に、poa->requests にストックされ、そのリクエストキューに対して
GIOP_execute_request(poa, poa->requests);
を実行する。
【GIOP_execute_request関数】
この関数は、GIOPメセージをすべて処理する。この処理が、CORBAのメインの処理となる。この関数の処理の流れは、下記のとおり。
- 引数であたえられたPtrList *lstの各要素に対して以下の処理をする。
- request = (GIOP_Request_Item)current_request->item; 要素の中身を取る。
- header = (GIOP_MessageHeader *)request->buf; 要素の中のGIOPメッセージをGIOPヘッダーheadにキャスト
- buf = request->buf; 要素の中のGIOPメッセージをbufにセット
- h = request->connh; コネクションハンドラをセット
- version = header->minor; GIOPバージョンをセット
- header->flags & 0x01 をチェックしてbyte_orderをセットし、必要であれば、メッセージサイズを変換。
- header->message_typeに応じて下記の処理をする
- header->message_typeがGIOP_Requestの時:
- スレッドをサポートしている場合には、該当リクエストのコピーを作って RunThread(&thr, GIOP_Request_perform_thread, (void *)arg, 1); で新規スレッドに処理を渡す。
- スレッドをサポートしていない場合には、GIOP_Request_perform(h, (octet *)buf, poa, header, body, &env);を実行
- header->message_typeがGIOP_Replyの時:GIOP_Reply_perform(h, (octet *)buf, poa, header, body, &env);を実行
- header->message_typeがGIOP_CancelRequestの時:GIOP_CancelRequest_perform(h, (octet *)buf, poa, header, body, &env);を実行
- header->message_typeがGIOP_LocateRequestの時:GIOP_LocationRequest_perform(h, (octet *)buf, poa, header, body, &env);を実行
- header->message_typeがGIOP_LocateReplyの時:GIOP_LocationRequest_perform(h, (octet *)buf, poa, header, body, &env);を実行
- header->message_typeがGIOP_CloseConnectionの時:何もしない
- header->message_typeがGIOP_MessageErrorの時: "Message Error occured\n"のメッセージを表示
- header->message_typeがGIOP_Fragmentの時:"FragmentMessage have not implemented.....\n"のメッセージを表示
- その他: "Invalid message type ([header->message_type])\n"メッセージを表示
- header->message_typeがGIOP_Requestの時:
- current_request->released = 1; 処理が終わったのでreleaseに1をセット
- current_request = current_request->next; 次の要素に移動。
- すべてのリクエストに対する処理が終了したら、PtrList_remove_released_items関数で、処理が終わったリクエストを削除。