00001 #!/usr/bin/env python 00002 # -*- coding: euc-jp -*- 00003 00004 ## 00005 # \file CorbaPort.py 00006 # \brief CorbaPort class 00007 # \date $Date: 2007/09/26 $ 00008 # \author Noriaki Ando <n-ando@aist.go.jp> and Shinji Kurihara 00009 # 00010 # Copyright (C) 2006-2008 00011 # Noriaki Ando 00012 # Task-intelligence Research Group, 00013 # Intelligent Systems Research Institute, 00014 # National Institute of 00015 # Advanced Industrial Science and Technology (AIST), Japan 00016 # All rights reserved. 00017 00018 from omniORB import CORBA 00019 from omniORB import any 00020 import traceback 00021 import sys 00022 00023 import OpenRTM_aist 00024 import RTC 00025 00026 00027 00028 ## 00029 # @if jp 00030 # @class CorbaPort 00031 # @brief RT コンポーネント CORBA provider/consumer 用 Port 00032 # 00033 # CorbaPort は RT コンポーネントにおいて、ユーザ定義の CORBA オブジェ 00034 # クトサービスおよびコンシューマを提供する Port 実装である。 00035 # 00036 # RT コンポーネントは、Port を介してユーザが定義した CORBA サービス 00037 # を提供することができ、これを RT Service (Provider) と呼ぶ。また、 00038 # 他の RT コンポーネントのサービスを利用するための CORBA オブジェク 00039 # トのプレースホルダを提供することができ、これを RT Service 00040 # Consumer と呼ぶ。 00041 # CorbaPort は任意の数の Provider および Consumer を管理することがで 00042 # き、Port 同士を接続する際に対応する Provider と Consumer を適切に 00043 # 関連付けることができる。 00044 # CorbaPort は通常以下のように利用される。 00045 # 00046 # <pre> 00047 # RTC::CorbaPort m_port0; // Port の宣言 00048 # 00049 # MyService_impl m_mysvc0; // この Port が提供する Serivce Provider 00050 # RTC::CorbaConsumer<YourService> m_cons0; // この Port の Consumer 00051 # 00052 # // Service Provider を Port に登録 00053 # m_port0.registerProvider("MyService0", "Generic", m_mysvc0); 00054 # // Service Consumer を Port に登録 00055 # m_port0.registerConsumer("YourService0", "Generic", m_cons0 ); 00056 # 00057 # // connect が行われた後 00058 # 00059 # m_cons0->your_service_function(); // YourService の関数をコール 00060 # 00061 # // connect された 別のコンポーネントにおいて 00062 # m_cons1->my_service_function(); // MyService の関数をコール 00063 # </pre> 00064 # 00065 # このように、提供したい Service Provider を registerProvider() で登 00066 # 録することにより、他のコンポーネントから利用可能にし、他方、利用し 00067 # たい Service Consumer を registerConsumer() で登録することにより他 00068 # のコンポーネントの Service をコンポーネント内で利用可能にすること 00069 # ができる。 00070 # 00071 # PortInterfaceProfile は Port に所属するプロバイダもしくはコンシュー 00072 # マインターフェースについての情報を記述するためのプロファイルである。 00073 # 接続を行うツール等は、これらの情報に基づき ConnectorProfile を適切 00074 # に生成し、接続を構成する Port のうち任意の一つに対して引数に 00075 # ConnectorProfile を与えて Port::connect() を呼び出す必要がある。 00076 # 00077 # なお、PortInterfaceProfile のインスタンス名 "#" は特殊なインスタン 00078 # スを表す。 00079 # 00080 # PROVIDEDすなわちプロバイダのインスタンス名が "#" の場合は、接続開 00081 # 始時点ではインスタンスが存在せず、コンシューマの要求に応じて動的に 00082 # インスタンスを生成するタイプのプロバイダであることを表す。したがっ 00083 # て、接続開始時点ではインスタンス名は存在しないが、接続シーケンス中 00084 # のインターフェースを公開するプロセスにおいて、プロバイダは生成した 00085 # インスタンスに対応した記述子を ConnectorProfile に適正に設定するも 00086 # のとする。(未実装) 00087 # 00088 # REQUIREDすなわちコンシューマのインスタンス名が "#" の場合は、一つ 00089 # のコンシューマが複数のプロバイダと接続可能なタイプのコンシューマで 00090 # あることを示す。(未実装) 00091 # 00092 # 以下は、Port間のインターフェースを接続するために ConnectorProfile に 00093 # マッピングを記述するためのルールを示す。 00094 # 00095 # Portに付属するインターフェースの指定子のフォーマットを以下のように 00096 # 定める。インターフェースに関するプロパティが以下の場合 00097 # 00098 # - RTCインスタンス名: rtc_iname 00099 # - ポート名: port_name 00100 # - インターフェース極性: if_polarity 00101 # - インターフェース型名: if_tname 00102 # - インターフェースインスタンス名: if_iname 00103 # 00104 # インターフェースの指定子を以下の文字列名称で指定するものとする。 00105 # 00106 # <rtc_iname>.port.<port_name>.<if_polarity>.<if_tname>.<if_iname> 00107 # 00108 # PROVIDED(提供)型すなわちプロバイダのインタフェースのプロパティが以 00109 # 下の場合、 00110 # 00111 # - rtc_iname = MyComp0 00112 # - port_name = myservice 00113 # - if_polarity = provided 00114 # - if_tname = echo_interface 00115 # - if_iname = echo_interface2 00116 # 00117 # インターフェース指定子は 00118 # 00119 # MyComp0.port.myservice.provided.echo_interface.echo_interface2 00120 # 00121 # のように記述される。また、同様にREQUIRED(要求)型すなわちコンシュー 00122 # マのインターフェースのプロパティが以下の場合、 00123 # 00124 # - rtc_iname = YourComp0 00125 # - port_name = yourservice 00126 # - if_polarity = required 00127 # - if_tname = hoge_interface 00128 # - if_iname = hoge_interface1 00129 # 00130 # インターフェース指定子は、 00131 # 00132 # YourComp0.port.myservice.required.hoge_interface.hoge_inteface1 00133 # 00134 # のように記述することができる。 00135 # 00136 # なお、ここで動的生成インターフェースのインスタンスのための特殊なタ 00137 # イプのインスタンス名記述子 00138 # 00139 # - <type_name>*: 動的生成型インスタンス名記述子 00140 # - <type_name>+: インクリメンタル生成型インスタンス名記述子 00141 # 00142 # を定義する。動的生成インターフェースとは、接続時にインスタンスが生 00143 # 成されるタイプのインターフェースである。(未実装) 00144 # 00145 # コンシューマが要求するプロバイダインターフェース記述子に動的生成型 00146 # インスタンス名記述子 "<type_name>#" が指定された場合、プロバイダは 00147 # インスタンスを1つ新規に生成する。"<type_name>#" の記述子によりプロバ 00148 # イダを要求する n 個のコンシューマが存在する場合、これらからの要求 00149 # (オペレーションコール)を1 つのプロバイダにより処理する関係を構築す 00150 # る(下図)。 00151 # 00152 # <pre> 00153 # consumer0 ]---< 00154 # consumer1 ]---< O----[ provider0 00155 # consumer2 ]---< 00156 # </pre> 00157 # 00158 # これに対し、コンシューマが要求するプロバイダインターフェース記述子 00159 # にインクリメンタル生成型インスタンス名記述子 "<type_name>+" が指定 00160 # された場合、記述子 "<type_name>+" の数だけプロバイダのインスタン 00161 # スが動的に生成される。すなわち、"<type_name>+" の記述子によりプロバ 00162 # イダを要求する n 個のコンシューマが存在する場合、n 個のプロバイダ 00163 # がそれぞれの要求を処理する以下のような関係が構築される。 00164 # 00165 # <pre> 00166 # consumer0 ]---< O----[ provider0 00167 # consumer1 ]---< O----[ provider1 00168 # consumer2 ]---< O----[ provider2 00169 # </pre> 00170 # 00171 # 00172 # 接続に際して、ツール等から ConnectorProfile::properties に適切なイ 00173 # ンターフェースマッピング指定を記述することで、相互のプロバイダ/コ 00174 # ンシューマインターフェースを自由に接続することができる。ただし、接 00175 # 続に関わる RTC の中に、異なるインスタンスでありながら、同一のインス 00176 # タンス名が存在する場合、インターフェース記述子の一意性が保証できな 00177 # いので、この方法による接続性は保証されない。 00178 # 00179 # ここでインターフェース記述子を簡単のために <if_desc0>, 00180 # <if_desc1>, ... とする。また、ConnectorProfile::properties の 00181 # NVListの key と value を key: value のように記述するものとする。 00182 # 00183 # いま、2つのコンポーネントのサービスポートを接続する場合を考える。 00184 # それぞれのコンポーネントのサービスポートが以下の場合、 00185 # 00186 # - rtc_iname: MyComp0 <br> 00187 # port_name: mycomp_service <br> 00188 # interfaces: 00189 # - if_polarity: provided <br> 00190 # if_iname: echo0 <br> 00191 # if_tname: Echo 00192 # - if_polarity: required <br> 00193 # if_iname: add0 <br> 00194 # if_tname: add 00195 # 00196 # - rtc_iname: YourComp0 <br> 00197 # port_name: yourcomp_service <br> 00198 # interfaces: 00199 # - if_polarity: required <br> 00200 # if_iname: echo9 <br> 00201 # if_tname: Echo 00202 # - if_polarity: provided <br> 00203 # if_iname: add9 <br> 00204 # if_tname: add 00205 # 00206 # <pre> 00207 # MyComp0 YourComp0 00208 # _______ mycomp_service yourcomp_service ______ 00209 # | | 00210 # |~~~|---O echo0 echo9 >---|~~~| 00211 # | |---< add0 add9 O---| | 00212 # ~T~ ~T~ 00213 # | | 00214 # </pre> 00215 # 00216 # MyComp0 の echo0 (プロバイダ) と YourComp0 の echo9 (コンシューマ)、 00217 # MyComp0 の add0 (コンシューマ) と YourComp0 の add9 (プロバイダ) 00218 # をそれぞれ対にして接続させるものと仮定する。この場合、 00219 # ConnectorProfile は以下のように設定する。 00220 # 00221 # <pre> 00222 # ConnectorProfile: 00223 # name: 任意のコネクタ名 00224 # connector_id: 空文字 00225 # ports[]: mycomp_service の参照, yourcomp_service の参照 00226 # properties: 00227 # <add0>: <add9> 00228 # <echo9>: <echo0> 00229 # </pre> 00230 # 00231 # ただし、それぞれ 00232 # 00233 # <pre> 00234 # <add0> は MyComp0.port.mycomp_service.required.add.add0 00235 # <add9> は YourComp0.port.yourcomp_service.provided.add.add9 00236 # <echo0> は MyComp0.port.mycomp_service.provided.echo.echo0 00237 # <echo9> は YourComp0.port.yourcomp_service.required.echo.echo9 00238 # </pre> 00239 # 00240 # である。接続プロセスにおいて、各ポートのプロバイダおよびコンシュー 00241 # マは、それぞれ以下の作業を、CorbaPort::publishInterfaces(), 00242 # CorbaPort::subscribeInterfaces() 仮想関数において行う。 00243 # 00244 # プロバイダは、publishInterfaces() 関数において、自分のインターフェー 00245 # ス記述子をキーとし、値にIORの文字列表記したものを 00246 # ConnectorProfile::properties に設定する。前提として、このインター 00247 # フェース記述子は今行おうとしているコネクタにおいては一意であるため、 00248 # 同じキーは1つしか存在してはいけない。 00249 # 00250 # [この部分の記述は未実装の機能] なお、動的生成インターフェースにつ 00251 # いては、以下の手続きに従い処理することとなる。publishInterface() 00252 # 関数において、動的生成インスタンス名記述子 "<type_name>*" または、 00253 # インクリメンタル生成型インスタンス名記述子 "<type_name>+" が存在す 00254 # るかどうかを走査する。動的生成インスタンス名記述子 "<type_name>*" 00255 # が存在する場合、プロバイダのインスタンスを1つ生成し、そのインター 00256 # フェース指定子を key に、IOR文字列を value に設定するとともに、動 00257 # 的生成インスタンス名記述子 "<type_name>*" を value に含むすべての 00258 # value 上のインターフェース指定子を、ここで生成したインターフェース 00259 # 指定子に置き換える。 00260 # 00261 # インクリメンタル生成型インスタンス名記述子"<type_name>+" が存在す 00262 # る場合、インスタンス名記述子の数だけプロバイダのインスタンスを生成 00263 # し、それぞれのインターフェース指定子をkey に、IOR文字列を value に 00264 # 設定するとともに、インクリメンタル生成型インスタンス名記述子 00265 # "<type_name>+" を value 含むすべての value 上のインターフェース指 00266 # 定子に対して順に、ここで生成したそれぞれのインターフェース指定子に 00267 # 置き換える。 00268 # 00269 # プロバイダは subscribeInterfaces() では特に操作は行わない。 00270 # 00271 # コンシューマは、 publishInterfaces() においては特に操作を行わない。 00272 # 00273 # 一方、 subscribeInterfaces() では、自分の記述子を key とする 00274 # key-value ペア が存在するかどうか調べ、もし存在すれば、その value 00275 # に設定されたプロバイダのインターフェース指定子で指定される参照を、 00276 # さらに ConnectorProfile::properties から探し、それをコンシューマの 00277 # 接続先として設定する。なお、意図的にコンシューマにプロバイダの参照 00278 # を設定しない場合は、予約文字列 "nil" または "null" を設定するもの 00279 # とする。 00280 # 00281 # コンシューマは、もし自分の記述子が存在しない場合、またはプロバイダ 00282 # の参照が Connector::properties に存在しない場合、コンシューマは、 00283 # 自分のインスタンス名および型名と同一のプロバイダを探し、その参照を 00284 # 自分自身に設定する。これは、OpenRTM-aist-0.4 との互換性を保持する 00285 # ためのルールであり、1.0以降では推奨されない。 00286 # 00287 # プロバイダ対コンシューマの対応は一対一である必要はなく、プロバイダ 00288 # 1 に対して、コンシューマ n、またはコンシューマ 1 に対してプロバイ 00289 # ダ n のケースも許される。プロバイダ 1 に対して、コンシューマ n の 00290 # ケースでは、あるプロバイダの指定子が、複数のコンシューマに対して、 00291 # 上記の方法で指定されることにより、実現される。一方、コンシューマ 00292 # 1 に対してプロバイダ n のケースでは、コンシューマ指定子の key に対 00293 # して、複数のプロバイダの指定子がカンマ区切りで列挙される形式となる 00294 # ものとする。 00295 # 00296 # なお、インターフェースの対応関係の厳密さを指定するオプションとして、 00297 # 以下のオプションを指定することができる。 00298 # 00299 # port.connection.strictness: strict, best_effort 00300 # 00301 # strict: すべてのコンシューマに指定した参照が存在し、かつナローイン 00302 # グにも成功しコンシューマに適切にセットできた場合にのみ Port 00303 # 間の接続を確立する。 00304 # 00305 # best_effort: ナローイング等に失敗した場合でも、エラーを返すことな 00306 # く Port 間の接続を確立する。 00307 # 00308 # @since 0.4.0 00309 # 00310 # @else 00311 # @class CorbaPort 00312 # @brief RT Conponent CORBA service/consumer Port 00313 # 00314 # CorbaPort is an implementation of the Port of RT-Component's that provides 00315 # user-defined CORBA Object Service and Consumer. 00316 # <p> 00317 # RT-Component can provide user-defined CORBA serivces, which is called 00318 # RT-Serivce (Provider), through the Ports. 00319 # RT-Component can also provide place-holder, which is called RT-Serivce 00320 # Consumer, to use other RT-Component's service. 00321 # <p> 00322 # The CorbaPort can manage any number of Providers and Consumers, can 00323 # associate Consumers with correspondent Providers when establishing 00324 # connection among Ports. 00325 # <p> 00326 # Usually, CorbaPort is used like the following. 00327 # 00328 # <pre> 00329 # RTC::CorbaPort m_port0; // declaration of Port 00330 # 00331 # MyService_impl m_mysvc0; // Serivce Provider that is provided by the Port 00332 # RTC::CorbaConsumer<YourService> m_cons0; // Consumer of the Port 00333 # 00334 # // register Service Provider to the Port 00335 # m_port0.registerProvider("MyService0", "Generic", m_mysvc0); 00336 # // register Service Consumer to the Port 00337 # m_port0.registerConsumer("YourService0", "Generic", m_cons0 ); 00338 # 00339 # // after connect established 00340 # 00341 # m_cons0->your_service_function(); // call a YourService's function 00342 # 00343 # // in another component that is connected with the Port 00344 # m_cons1->my_service_function(); // call a MyService's function 00345 # </pre> 00346 # 00347 # Registering Service Provider by registerProvider(), it can be 00348 # used from other RT-Components. Registering Service Consumer by 00349 # registerConsumer(), other RT-Component's services can be used 00350 # through the consumer object. 00351 # 00352 # PortInterfaceProfile is a one of the profile information to store 00353 # Provider interface and Consumer interface information. Tools or 00354 # other RTCs should call one of the Port::connect() with an 00355 # appropriate ConnectorProfile. 00356 # 00357 # In addition, the instance name "*" declares a special type of instance. 00358 # 00359 # When the name of the PROVIDED type interface that is the provider 00360 # interface is "*", Provider interface's instance does not exist at 00361 # the beginning of connection sequence. The instances will be 00362 # created dynamically according to the consumer interface 00363 # requirement at the connection sequence. Although the instance 00364 # name does not exist at the beginning of connection sequence, the 00365 # created providers shall publish its references to the 00366 # ConnectorProfile with interface descriptor adequately in the 00367 # interface publisher phase of the connection sequence. 00368 # 00369 # If REQUIRED interface name that is Consumer interface name is 00370 # "*", it shows that one Consumer interface is able to connect with 00371 # multiple Provider interfaces. (This feature is not implemented.) 00372 # 00373 # The following describes the rules that specify interface 00374 # connection between ports. 00375 # 00376 # The descriptor format of interfaces associated with Ports is 00377 # declared as follows. Now some of interface properties are assumed 00378 # as the followings. 00379 # 00380 # - RTC instance name: rtc_iname 00381 # - Port name: port_name 00382 # - Interface polarity: if_polarity 00383 # - Interface type name: if_tname 00384 # - INterface instance name: if_iname 00385 # 00386 # The interface descriptors shall be declared as follows. 00387 # 00388 # <rtc_iname>.port.<port_name>.<if_polarity>.<if_tname>.<if_iname> 00389 # 00390 # When PROVIDED that is Provider interface properties are the followings, 00391 # 00392 # - rtc_iname = MyComp0 00393 # - port_name = myservice 00394 # - if_polarity = provided 00395 # - if_tname = echo_interface 00396 # - if_iname = echo_interface2 00397 # the interface descriptor is here. 00398 # 00399 # MyComp0.port.myservice.provided.echo_interface.echo_interface2 00400 # 00401 # And, when REQUIRED that is Consumer interfaces properties are the 00402 # followings, 00403 # 00404 # - rtc_iname = YourComp0 00405 # - port_name = yourservice 00406 # - if_polarity = required 00407 # - if_tname = hoge_interface 00408 # - if_iname = hoge_interface1 00409 # 00410 # interface descriptor is as follows. 00411 # 00412 # YourComp0.port.myservice.required.hoge_interface.hoge_inteface1 00413 # 00414 # Specific instance name descriptors that are dynamically generated 00415 # at the connection time are defined here. 00416 # 00417 # - <type_name>*: "Dynamically generated" instance descriptor. 00418 # - <type_name>+: "Incrementally generated" instance descriptor. 00419 # 00420 # When the "Dynamically generated" instance descriptor: 00421 # "<type_name>*" is specified as interface descriptor that is 00422 # required by consumers, the provider will generate a instance. If 00423 # n consumers who demand a provider by the "<type_name>" descriptor 00424 # exist, the following relation which processes the call from these 00425 # consumers by one provider will be established. 00426 # 00427 # <pre> 00428 # consumer0 ]---< 00429 # consumer1 ]---< O----[ provider0 00430 # consumer2 ]---< 00431 # </pre> 00432 # 00433 # On the other hand, when incremental generated type instance name 00434 # descriptor "<type_name>+" is specified as the provider interface 00435 # descriptor whom consumers demand, provider's instances are 00436 # dynamically generated for the number of the descriptors 00437 # "<type_name>+". When n consumers who demand a provider by the 00438 # descriptor "<type_name>+" exist the following relations in which 00439 # n providers process each call from the consumers will be 00440 # established. 00441 # 00442 # <pre> 00443 # consumer0 ]---< O----[ provider0 00444 # consumer1 ]---< O----[ provider1 00445 # consumer2 ]---< O----[ provider2 00446 # </pre> 00447 # 00448 # 00449 # Describing the appropriate interface mapping specification in the 00450 # ConnectorProfile::properties, selective connections between 00451 # providers/consumers interface can be established at the time of 00452 # connection. However, when different RTC instances of the same 00453 # instance name exist in a connection, since an interface 00454 # descriptor uniqueness cannot be guaranteed, this connection 00455 # mapping rules cannot be used. 00456 # 00457 # Here, assume that an interface descriptor is given as <if_desc0>, 00458 # <if_desc1>, .... And assume that the key and the value of NVList 00459 # in ConnectorProfile::properties are given as "key: value". 00460 # 00461 # Now the case where the service ports of two components are 00462 # connected is considered. When the service port of each component 00463 # is the following, 00464 # 00465 # - rtc_iname: MyComp0 <br> 00466 # port_name: mycomp_service <br> 00467 # interfaces: 00468 # - if_polarity: provided <br> 00469 # if_iname: echo0 <br> 00470 # if_tname: Echo 00471 # - if_polarity: required <br> 00472 # if_iname: add0 <br> 00473 # if_tname: add 00474 # 00475 # - rtc_iname: YourComp0 <br> 00476 # port_name: yourcomp_service <br> 00477 # interfaces: 00478 # - if_polarity: required <br> 00479 # if_iname: echo9 <br> 00480 # if_tname: Echo 00481 # - if_polarity: provided <br> 00482 # if_iname: add9 <br> 00483 # if_tname: add 00484 # 00485 # 00486 # <pre> 00487 # MyComp0 YourComp0 00488 # _______ mycomp_service yourcomp_service ______ 00489 # | | 00490 # |~~~|---O echo0 echo9 >---|~~~| 00491 # | |---< add0 add9 O---| | 00492 # ~T~ ~T~ 00493 # | | 00494 # </pre> 00495 # 00496 # 00497 # 00498 # Assume that connection between echo0 (provider) of MyComp0 00499 # component and echo9 (consumer) of YourComp0 component, and add0 00500 # (consumer) of MyComp0 and add0 (provider) of YourComp0 is 00501 # established. In this case, ConnectorProfile is set up as 00502 # follows. 00503 # 00504 # <pre> 00505 # ConnectorProfile: 00506 # name: any connector name 00507 # connector_id: empty string 00508 # ports[]: mycomp_service's reference, yourcomp_service's reference 00509 # properties: 00510 # <add0>: <add9> 00511 # <echo9>: <echo0> 00512 # </pre> 00513 # 00514 # Please note that <add0>, <add9>, <echo0> and <echo9> are the following. 00515 # 00516 # <pre> 00517 # <add0> is MyComp0.port.mycomp_service.required.add.add0 00518 # <add9> is YourComp0.port.yourcomp_service.provided.add.add9 00519 # <echo0> is MyComp0.port.mycomp_service.provided.echo.echo0 00520 # <echo9> is YourComp0.port.yourcomp_service.required.echo.echo9 00521 # </pre> 00522 # 00523 # In the connection process, the provider and the consumer of each 00524 # port carries out the following process respectively in the 00525 # virtual functions such as CorbaPort::publishInterfaces() and 00526 # CorbaPort::subscribeInerfaces(). 00527 # 00528 # A provider sets its IOR string as a value and its interface 00529 # descriptor as a key in the ConnectorProfile::properties in a 00530 # publishInterfaces() function. Since this interface descriptor's 00531 # uniqueness is guaranteed in the current connector, the key of 00532 # NameValue in the ConnectorProfile::properties is unique. 00533 # 00534 # 00535 # [This functionalities are not implemented] The dynamically 00536 # generated provider is processed according to the following 00537 # procedure. The publishInterface() function scans dynamic instance 00538 # descriptors such as "<type_name>*" and "<type_name>+" in the 00539 # ConnectorProfile::properties. When the dynamic generation 00540 # instance descriptor "<tupe_name>*" exists, one instance of 00541 # provider is generated, and its descriptor and its IOR string are 00542 # set to ConnectorProfile::properties as the key and the value 00543 # respectively. Simultaneously, in the 00544 # ConnectorProfile::properties, all the instance descriptor with 00545 # the dynamic generation instance name "<type_name>*" will be 00546 # replaced with newly generated instance descriptor. 00547 # 00548 # When the incremental dynamic generation instance descriptor 00549 # exists, providers are generated for the number of the 00550 # descriptors, and its descriptor and its IOR string are set to 00551 # ConnectorProfile::properties as the key and the value 00552 # respectively. Simultaneously, in the 00553 # ConnectorProfile::properties, all the instance descriptor with 00554 # the dynamic generation instance name "<type_name>+" will be 00555 # replaced with newly generated instance descriptor. 00556 # 00557 # The providers do not perform particular operation in 00558 # subscribeInterfaces() function. 00559 # 00560 # 00561 # The consumers do not perform particular operation in 00562 # publisherInterfaces() function. 00563 # 00564 # On the other hand, a consumer searches a key-value pair with the 00565 # key of consumer interface descriptor, and if the pair exists, it 00566 # obtains provider's descriptor from the value. The consumer 00567 # searches again a key-value pair with the key of provider 00568 # interface descriptor, and it obtains provider's reference and the 00569 # reference is set as the consumer's service object. In addition, 00570 # reserved string "nil" or "null" are used not to set specific 00571 # provider. 00572 # 00573 # If consumer's interface descriptors does not exists in the 00574 # ConnectorProfile::properties, the consumer searches a provider 00575 # with same type name and instance name, and its reference is set 00576 # to the consumer. This rule is for only backward compatibility, 00577 # and it is not recommended from version 1.0. 00578 # 00579 # The correspondence of a provider versus a consumer does not need 00580 # to be one to one, and the case of one provider to n-consumers and 00581 # the case of m-providers to one consumer are allowed. The one 00582 # provider to n-consumers case can be realized by the above 00583 # mentioned methods. The one consumer to m-provider case can be 00584 # specified to set the consumer descriptor and comma-separated 00585 # provider descriptors into the key and the value respectively. 00586 # 00587 # The following option is available to specify the strictness of 00588 # interfaces connection. 00589 # 00590 # port.connection.strictness: strict, best_effort 00591 # 00592 # strict: The connection is established, if only all the specified 00593 # consumers are set appropriate references and narrowed 00594 # successfully. 00595 # 00596 # best_effort: The connection is established without any errors, 00597 # even if appropriate reference does not exist or reference 00598 # narrowing fails. 00599 # 00600 # @since 0.4.0 00601 # 00602 # @endif 00603 # 00604 class CorbaPort(OpenRTM_aist.PortBase): 00605 """ 00606 """ 00607 00608 ## 00609 # @if jp 00610 # @brief コンストラクタ 00611 # 00612 # @param self 00613 # @param name Port の名前 00614 # 00615 # @else 00616 # 00617 # @brief Constructor 00618 # 00619 # @param name The name of Port 00620 # 00621 # @endif 00622 def __init__(self, name): 00623 OpenRTM_aist.PortBase.__init__(self, name) 00624 self.addProperty("port.port_type", "CorbaPort") 00625 self._properties = OpenRTM_aist.Properties() 00626 self._providers = [] 00627 self._consumers = [] 00628 return 00629 00630 00631 def __del__(self, PortBase=OpenRTM_aist.PortBase): 00632 PortBase.__del__(self) 00633 00634 00635 ## 00636 # @if jp 00637 # @brief プロパティの初期化 00638 # 00639 # OutPortのプロパティを初期化する。このポートへの接続数を指定する 00640 # プロパティ "connection_limit" が含まれ、適切な数値が設定されてい 00641 # る場合、最大接続数としてその数値が設定される。プロパティが設定さ 00642 # れていない場合、もしくは適切な値が設定されていない場合には、最大 00643 # 接続数は無制限となる。 00644 # 00645 # @param prop CorbaPort のプロパティ 00646 # 00647 # @else 00648 # 00649 # @brief Initializing properties 00650 # 00651 # This operation initializes outport's properties. If a property 00652 # "connection_limit" is set and appropriate value is set to this 00653 # property value, the number of maximum connection is set as this 00654 # value. If the property does not exist or invalid value is set 00655 # to this property, the maximum number of connection will be set 00656 # unlimited. 00657 # 00658 # @param prop properties of the CorbaPort 00659 # 00660 # @endif 00661 # 00662 # void init(coil::Properties& prop); 00663 def init(self, prop): 00664 self._rtcout.RTC_TRACE("init()") 00665 00666 self._properties.mergeProperties(prop) 00667 00668 num = [-1] 00669 if not OpenRTM_aist.stringTo([num], 00670 self._properties.getProperty("connection_limit","-1")): 00671 self._rtcout.RTC_ERROR("invalid connection_limit value: %s", 00672 self._properties.getProperty("connection_limit")) 00673 00674 self.setConnectionLimit(num[0]) 00675 00676 00677 ## 00678 # @if jp 00679 # 00680 # @brief Provider を登録する 00681 # 00682 # この Port において提供したいサーバントをこの Port に対して登録す 00683 # る。サーバントは、引数で与えられる instance_name, type_name を、 00684 # サーバント自身のインスタンス名およびタイプ名として、サーバントに 00685 # 関連付けられる。この関数により、サーバントは CorbaPort 内部に保 00686 # 持されるとともに、PortInterfaceProfile にRTC::PROVIDED インター 00687 # フェースとして登録される。 00688 # 00689 # @param instance_name サーバントのインスタンス名 00690 # @param type_name サーバントのタイプ名 00691 # @param provider CORBA サーバント 00692 # 00693 # @return 既に同名の instance_name が登録されていれば false を返す。 00694 # 00695 # @else 00696 # 00697 # @brief Register the provider 00698 # 00699 # This operation registers a servant, which is provided in this 00700 # Port, to the Port. The servant is associated with 00701 # "instance_name" and "type_name" as the instance name of the 00702 # servant and as the type name of the servant. A given servant 00703 # will be stored in the CorbaPort, and this is registered as 00704 # RTC::PROVIDED interface into the PortInterfaceProfile. 00705 # 00706 # @param instance_name Instance name of servant 00707 # @param type_name Type name of the servant 00708 # @param provider CORBA servant 00709 # 00710 # @return Return false if the same name of instance_name is already 00711 # registered. 00712 # 00713 # @endif 00714 # 00715 # bool registerProvider(const char* instance_name, const char* type_name, 00716 # PortableServer::RefCountServantBase& provider); 00717 def registerProvider(self, instance_name, type_name, provider): 00718 self._rtcout.RTC_TRACE("registerProvider(instance=%s, type_name=%s)", 00719 (instance_name, type_name)) 00720 00721 try: 00722 self._providers.append(self.CorbaProviderHolder(type_name, 00723 instance_name, 00724 provider)) 00725 except: 00726 self._rtcout.RTC_ERROR("appending provider interface failed") 00727 self._rtcout.RTC_ERROR(OpenRTM_aist.Logger.print_exception()) 00728 return False 00729 00730 00731 if not self.appendInterface(instance_name, type_name, RTC.PROVIDED): 00732 return False 00733 00734 return True 00735 00736 00737 ## 00738 # @if jp 00739 # 00740 # @brief Consumer を登録する 00741 # 00742 # この Port が要求するサービスのプレースホルダであるコンシューマ 00743 # (Consumer) を登録する。Consumer が関連付けられるサービスのインス 00744 # タンス名およびタイプ名として、引数に instance_name, type_name お 00745 # よび Consumer 自身を与えることにより、内部でこれらが関連付けられ 00746 # る。Port 間の接続 (connect) 時 には、subscribeInterfaces() で述 00747 # べられているルールに基づき、Provider Interface の参照が自動的に 00748 # Consumer にセットされる。 00749 # 00750 # @param instance_name Consumer が要求するサービスのインスタンス名 00751 # @param type_name Consumer が要求するサービスのタイプ名 00752 # @param consumer CORBA サービスコンシューマ 00753 # 00754 # @return 既に同名の instance_name が登録されていれば false を返す。 00755 # 00756 # @else 00757 # 00758 # @brief Register the consumer 00759 # 00760 # This operation registers a consumer, which is a service 00761 # placeholder this port requires. These are associated internally 00762 # with specified instance_name, type_name and Consumer itself to 00763 # the argument as service's instance name and its type name 00764 # associated with Consumer. The service Provider interface' 00765 # references will be set automatically to the Consumer Interface 00766 # object when connections are established, according to the rules 00767 # that are described at the subscribeInterfaces() function's 00768 # documentation. 00769 # 00770 # @param instance_name Instance name of the service Consumer requires 00771 # @param type_name Type name of the service Consumer requires 00772 # @param consumer CORBA service consumer 00773 # 00774 # @return False would be returned if the same instance_name was registered 00775 # 00776 # @endif 00777 # 00778 # bool registerConsumer(const char* instance_name, const char* type_name, 00779 # CorbaConsumerBase& consumer); 00780 def registerConsumer(self, instance_name, type_name, consumer): 00781 self._rtcout.RTC_TRACE("registerConsumer()") 00782 00783 if not self.appendInterface(instance_name, type_name, RTC.REQUIRED): 00784 return False 00785 00786 self._consumers.append(self.CorbaConsumerHolder(type_name, 00787 instance_name, 00788 consumer, 00789 self)) 00790 return True 00791 00792 00793 ## 00794 # @if jp 00795 # 00796 # @brief Port の全てのインターフェースを activates する 00797 # 00798 # Port に登録されている全てのインターフェースを activate する。 00799 # 00800 # @else 00801 # 00802 # @brief Activate all Port interfaces 00803 # 00804 # This operation activate all interfaces that is registered in the 00805 # ports. 00806 # 00807 # @endif 00808 # 00809 # void CorbaPort::activateInterfaces() 00810 def activateInterfaces(self): 00811 for provider in self._providers: 00812 provider.activate() 00813 00814 return 00815 00816 00817 ## 00818 # @if jp 00819 # 00820 # @brief 全ての Port のインターフェースを deactivates する 00821 # 00822 # Port に登録されている全てのインターフェースを deactivate する。 00823 # 00824 # @else 00825 # 00826 # @brief Deactivate all Port interfaces 00827 # 00828 # This operation deactivate all interfaces that is registered in the 00829 # ports. 00830 # 00831 # @endif 00832 # 00833 # void CorbaPort::deactivateInterfaces() 00834 def deactivateInterfaces(self): 00835 for provider in self._providers: 00836 provider.deactivate() 00837 00838 return 00839 00840 00841 00842 ## 00843 # @if jp 00844 # 00845 # @brief Provider Interface 情報を公開する 00846 # 00847 # この Port が所有する Provider インターフェースに関する情報を 00848 # ConnectorProfile::properties に代入し他の Port に対して公開する。 00849 # 今、RTCのインスタンス名等の情報が以下の通りであるとして、 00850 # 00851 # - RTCインスタンス名: rtc_iname 00852 # - ポート名: port_name 00853 # - インターフェース極性: if_polarity 00854 # - インターフェース型名: if_tname 00855 # - インターフェースインスタンス名: if_iname 00856 # 00857 # NameValue 型の ConnectorProfile::properties の name と value として 00858 # 以下のものが格納される。 00859 # 00860 # - name 00861 # <rtc_iname>.port.<port_name>.provided.<if_tname>.<if_iname> 00862 # - value 00863 # Provider インターフェースの IOR 文字列 00864 # 00865 # なお、旧バージョンとの互換性のため以下の表記の NameValue も同時 00866 # に格納されるが、将来のバージョンでは削除される可能性がある。 00867 # 00868 # - name 00869 # port.<if_tname>.<if_iname> 00870 # - value 00871 # Provider インターフェースの IOR 文字列 00872 # 00873 # これらの値は ConnectorProfile::properties に格納され、他のポートに対して 00874 # 伝達される。他の Port でこのインターフェースを使用する Consumer が 00875 # 存在すれば、ConnectorProfile からこのキーからオブジェクトリファレンスを 00876 # 取得し何らかの形で使用される。 00877 # 00878 # @param connector_profile コネクタプロファイル 00879 # @return ReturnCode_t 型のリターンコード 00880 # 00881 # @else 00882 # 00883 # @brief Publish information about interfaces 00884 # 00885 # This operation publishes Provider interfaces information, which 00886 # is owned by this port, to the other Ports via 00887 # ConnectorProfile::properties. 00888 # Now it is assumed RTC instance name and other information is as follows, 00889 # 00890 # - RTC instance name: rtc_iname 00891 # - Port name: port_name 00892 # - Interface polarity: if_polarity 00893 # - Interface type name: if_tname 00894 # - Interface instance name: if_iname 00895 # 00896 # the following values are stored as the "name" and the "value" 00897 # of the NameValue typee element in ConnectorProfile::properties. 00898 # 00899 # - name 00900 # <rtc_iname>.port.<port_name>.provided.<if_tname>.<if_iname> 00901 # - value 00902 # IOR string value of interface reference 00903 # 00904 # In addition, although the following NameValue values are also 00905 # stored for the backward compatibility, this will be deleted in 00906 # the future version. 00907 # 00908 # - name 00909 # port.<if_tname>.<if_iname> 00910 # - value 00911 # IOR string value of interface reference 00912 # 00913 # These values are stored in the ConnectorProfile::properties and 00914 # are propagated to the other Ports. If the Consumer interface 00915 # exists that requires this Provider interface, it will retrieve 00916 # reference from the ConnectorProfile and utilize it. 00917 # 00918 # @param connector_profile Connector profile 00919 # @return The return code of ReturnCode_t type 00920 # 00921 # @endif 00922 # 00923 # virtual ReturnCode_t 00924 # publishInterfaces(ConnectorProfile& connector_profile); 00925 def publishInterfaces(self, connector_profile): 00926 self._rtcout.RTC_TRACE("publishInterfaces()") 00927 00928 returnvalue = self._publishInterfaces() 00929 00930 if returnvalue != RTC.RTC_OK: 00931 return returnvalue 00932 00933 properties = [] 00934 for provider in self._providers: 00935 #------------------------------------------------------------ 00936 # new version descriptor 00937 # <comp_iname>.port.<port_name>.provided.<type_name>.<instance_name> 00938 newdesc = self._profile.name[:len(self._ownerInstanceName)] + \ 00939 ".port" + self._profile.name[len(self._ownerInstanceName):] 00940 newdesc += ".provided." + provider.descriptor() 00941 00942 properties.append(OpenRTM_aist.NVUtil.newNV(newdesc, provider.ior())) 00943 00944 #------------------------------------------------------------ 00945 # old version descriptor 00946 # port.<type_name>.<instance_name> 00947 olddesc = "port." + provider.descriptor() 00948 properties.append(OpenRTM_aist.NVUtil.newNV(olddesc, provider.ior())) 00949 00950 OpenRTM_aist.CORBA_SeqUtil.push_back_list(connector_profile.properties, properties) 00951 00952 return RTC.RTC_OK 00953 00954 00955 ## 00956 # @if jp 00957 # 00958 # @brief Provider Interface 情報を取得する 00959 # 00960 # この Portが所有する Consumer Interface に適合する Provider 00961 # Interface に関する情報をConnectorProfile::properties から抽出し 00962 # Consumer Interface にオブジェクト参照をセットする。 00963 # 00964 # 今、RTC のインスタンス名や Consumer Interface 等の情報が以下のと 00965 # おりであると仮定すると、 00966 # 00967 # - RTCインスタンス名: rtc_iname 00968 # - ポート名: port_name 00969 # - インターフェース極性: if_polarity 00970 # - インターフェース型名: if_tname 00971 # - インターフェースインスタンス名: if_iname 00972 # 00973 # この Consumer Interface を表すインターフェース指定子は以下のよう 00974 # に表される。 00975 # 00976 # <rtc_iname>.port.<port_name>.required.<if_tname>.<if_iname> 00977 # 00978 # この関数は、まず引数 ConnectorProfile::properties に上記インター 00979 # フェース指定子をキーとして格納されている Provider Interface 指定 00980 # 子を探し出す。さらに、その Provider Interface 指定子をキーとして 00981 # 格納されている Provider Interface の参照を表す IOR 文字列を取得 00982 # し、Consumer Interface にセットする。 00983 # 00984 # 今、仮に、Provider を prov(n), その参照をIOR(n) さらに Consumer 00985 # をcons(n) のように記述し、これらすべてのインターフェースの型が同 00986 # 一であり、ConnectorProfile に以下の値が設定されているとする。 00987 # 00988 # <pre> 00989 # ConnectorProfile::properties = 00990 # { 00991 # prov0: IOR0, 00992 # prov1: IOR1, 00993 # prov2: IOR2, 00994 # cons0: prov2, 00995 # cons1: prov1, 00996 # cons2: prov0 00997 # } 00998 # </pre> 00999 # 01000 # このとき、cons(0..2) にはそれぞれ、参照が以下のようにセットされる。 01001 # 01002 # <pre> 01003 # cons0 = IOR2 01004 # cons1 = IOR1 01005 # cons2 = IOR0 01006 # </pre> 01007 # 01008 # なお、旧バージョンとの互換性のため、 01009 # ConnectorProfile::properties に Consumer Interface をキーとした 01010 # 値がセットされていない場合でも、次のルールが適用される。 01011 # 01012 # 今、仮に Consumer Interface が 01013 # 01014 # <pre> 01015 # PortInterfaceProfile 01016 # { 01017 # instance_name = "PA10_0"; 01018 # type_name = "Manipulator"; 01019 # polarity = REQUIRED; 01020 # } 01021 # </pre> 01022 # 01023 # として登録されていれば、他の Port の 01024 # 01025 # <pre> 01026 # PortInterfaceProfile 01027 # { 01028 # instance_name = "PA10_0"; 01029 # type_name = "Manipulator"; 01030 # polarity = PROVIDED; 01031 # } 01032 # </pre> 01033 # 01034 # として登録されている Serivce Provider のオブジェクト参照を探し、 01035 # Consumer にセットする。実際には、ConnectorProfile::properties に 01036 # 01037 # <pre> 01038 # NameValue = { "port.Manipulator.PA10_0": <Object reference> } 01039 # </pre> 01040 # 01041 # として登録されている NameValue を探し、そのオブジェクト参照を 01042 # Consumer にセットする。 01043 # 01044 # @param connector_profile コネクタプロファイル 01045 # @return ReturnCode_t 型のリターンコード 01046 # 01047 # @else 01048 # 01049 # @brief Subscribe to interface 01050 # 01051 # Retrieve information associated with Provider matches Consumer 01052 # owned by this port and set the object reference to Consumer. 01053 # 01054 # Now, Consumer is registered as the following: 01055 # <pre> 01056 # PortInterfaceProfile 01057 # { 01058 # instance_name = "PA10_0"; 01059 # type_name = "Manipulator"; 01060 # polarity = REQUIRED; 01061 # } 01062 # </pre> 01063 # Find the object reference of Serivce Provider that is registered as 01064 # the following of other ports: 01065 # <pre> 01066 # PortInterfaceProfile 01067 # { 01068 # instance_name = "PA10_0"; 01069 # type_name = "Manipulator"; 01070 # polarity = PROVIDED; 01071 # } 01072 # </pre> 01073 # and set to Consumer. 01074 # In fact, find NameValue that is registered as the following to 01075 # ConnectorProfile::properties: 01076 # <pre> 01077 # NameValue = { "port.Manipulator.PA10_0": <Object reference> } 01078 # </pre> 01079 # and set the object reference to Consumer. 01080 # 01081 # @param connector_profile Connector profile 01082 # 01083 # @return The return code of ReturnCode_t type 01084 # 01085 # @endif 01086 # 01087 # virtual ReturnCode_t 01088 # subscribeInterfaces(const ConnectorProfile& connector_profile); 01089 def subscribeInterfaces(self, connector_profile): 01090 self._rtcout.RTC_TRACE("subscribeInterfaces()") 01091 nv = connector_profile.properties 01092 01093 strict = False # default is "best_effort" 01094 index = OpenRTM_aist.NVUtil.find_index(nv, "port.connection.strictness") 01095 if index >= 0: 01096 strictness = str(any.from_any(nv[index].value, keep_structs=True)) 01097 if "best_effort" == strictness: 01098 strict = False 01099 elif "strict" == strictness: 01100 strict = True 01101 01102 self._rtcout.RTC_DEBUG("Connetion strictness is: %s",strictness) 01103 01104 for consumer in self._consumers: 01105 ior = [] 01106 if self.findProvider(nv, consumer, ior) and len(ior) > 0: 01107 self.setObject(ior[0], consumer) 01108 continue 01109 01110 ior = [] 01111 if self.findProviderOld(nv, consumer, ior) and len(ior) > 0: 01112 self.setObject(ior[0], consumer) 01113 continue 01114 01115 # never come here without error 01116 # if strict connection option is set, error is returned. 01117 if strict: 01118 self._rtcout.RTC_ERROR("subscribeInterfaces() failed.") 01119 return RTC.RTC_ERROR 01120 01121 self._rtcout.RTC_TRACE("subscribeInterfaces() successfully finished.") 01122 01123 return RTC.RTC_OK 01124 01125 01126 ## 01127 # @if jp 01128 # 01129 # @brief Interface への接続を解除する 01130 # 01131 # 与えられた ConnectorProfile に関連する Consumer にセットされた 01132 # すべての Object を解放し接続を解除する。 01133 # 01134 # @param self 01135 # @param connector_profile コネクタプロファイル 01136 # 01137 # @else 01138 # 01139 # @brief Unsubscribe interfaces 01140 # 01141 # Release all Objects that was set in Consumer associated with the given 01142 # ConnectorProfile. 01143 # 01144 # @param connector_profile Connector profile 01145 # 01146 # @endif 01147 # virtual void 01148 # unsubscribeInterfaces(const ConnectorProfile& connector_profile); 01149 def unsubscribeInterfaces(self, connector_profile): 01150 self._rtcout.RTC_TRACE("unsubscribeInterfaces()") 01151 nv = connector_profile.properties 01152 01153 for consumer in self._consumers: 01154 ior = [] 01155 if self.findProvider(nv, consumer, ior) and len(ior) > 0: 01156 self._rtcout.RTC_DEBUG("Correspoinding consumer found.") 01157 self.releaseObject(ior[0], consumer) 01158 continue 01159 01160 ior = [] 01161 if self.findProviderOld(nv, consumer, ior) and len(ior) > 0: 01162 self._rtcout.RTC_DEBUG("Correspoinding consumer found.") 01163 self.releaseObject(ior[0], consumer) 01164 continue 01165 01166 return 01167 01168 01169 ## 01170 # @if jp 01171 # @brief Consumer に合致する Provider を NVList の中から見つける 01172 # 01173 # NVList 中から CorbaConsumerHolder に保持されている Consumer に合 01174 # 致するキーを持つ Provider を見つけ、IOR を抽出しナローイングして 01175 # Consumer にセットする。対応するキーが存在しない、IOR が見つから 01176 # ない、ナローイングに失敗した場合、false を返す。 01177 # 01178 # @param nv Provider が含まれている ConnectorProfile::properties の NVList 01179 # @param cons Provider と対応する Consumer のホルダ 01180 # 01181 # @retrun bool Consumer に対応する Provider が見つからない場合 false 01182 # 01183 # @else 01184 # @brief Find out a provider corresponding to the consumer from NVList 01185 # 01186 # This function finds out a Provider with the key that is matched 01187 # with Cosumer's name in the CorbaConsumerHolder, extracts IOR 01188 # and performs narrowing into the Consumer and set it to the 01189 # Consumer. False is returned when there is no corresponding key 01190 # and IOR and the narrowing failed. 01191 # 01192 # @param nv NVlist of ConnectorProfile::properties that includes Provider 01193 # @param cons a Consumer holder to be matched with a Provider 01194 # 01195 # @return bool false is returned if there is no provider for the consumer 01196 # 01197 # @endif 01198 # 01199 # virtual bool findProvider(const NVList& nv, 01200 # CorbaConsumerHolder& cons, 01201 # std::string& iorstr); 01202 def findProvider(self, nv, cons, iorstr): 01203 # new consumer interface descriptor 01204 newdesc = self._profile.name[:len(self._ownerInstanceName)] + \ 01205 ".port" + self._profile.name[len(self._ownerInstanceName):] 01206 newdesc += ".required." + cons.descriptor() 01207 01208 # find a NameValue of the consumer 01209 cons_index = OpenRTM_aist.NVUtil.find_index(nv, newdesc) 01210 if cons_index < 0: 01211 return False 01212 01213 provider = str(any.from_any(nv[cons_index].value, keep_structs=True)) 01214 if not provider: 01215 self._rtcout.RTC_WARN("Cannot extract Provider interface descriptor") 01216 return False 01217 01218 # find a NameValue of the provider 01219 prov_index = OpenRTM_aist.NVUtil.find_index(nv, provider) 01220 if prov_index < 0: 01221 return False 01222 01223 ior_ = str(any.from_any(nv[prov_index].value, keep_structs=True)) 01224 if not ior_: 01225 self._rtcout.RTC_WARN("Cannot extract Provider IOR string") 01226 return False 01227 01228 if isinstance(iorstr, list): 01229 iorstr.append(ior_) 01230 01231 self._rtcout.RTC_ERROR("interface matched with new descriptor: %s", newdesc) 01232 01233 return True 01234 01235 01236 ## 01237 # @if jp 01238 # @brief Consumer に合致する Provider を NVList の中から見つける 01239 # 01240 # この関数は、古いバージョンの互換性のための関数である。 01241 # 01242 # NVList 中から CorbaConsumerHolder に保持されている Consumer に合 01243 # 致するキーを持つ Provider を見つける。対応するキーが存在しない、 01244 # IOR が見つからない場合、false を返す 01245 # 01246 # @param nv Provider が含まれている ConnectorProfile::properties の NVList 01247 # @param cons Provider と対応する Consumer のホルダ 01248 # @param iorstr 見つかったIOR文字列を格納する変数 01249 # 01250 # @retrun bool Consumer に対応する Provider が見つからない場合 false 01251 # 01252 # @else 01253 # @brief Find out a provider corresponding to the consumer from NVList 01254 # 01255 # This function is for the old version's compatibility. 01256 # 01257 # This function finds out a Provider with the key that is matched 01258 # with Cosumer's name in the CorbaConsumerHolder and extracts 01259 # IOR. False is returned when there is no corresponding key and 01260 # IOR. 01261 # 01262 # @param nv NVlist of ConnectorProfile::properties that includes Provider 01263 # @param cons a Consumer holder to be matched with a Provider 01264 # @param iorstr variable which is set IOR string 01265 # 01266 # @return bool false is returned if there is no provider for the consumer 01267 # 01268 # @endif 01269 # 01270 # virtual bool findProviderOld(const NVList&nv, 01271 # CorbaConsumerHolder& cons, 01272 # std::string& iorstr); 01273 def findProviderOld(self, nv, cons, iorstr): 01274 # old consumer interface descriptor 01275 olddesc = "port." + cons.descriptor() 01276 01277 # find a NameValue of the provider same as olddesc 01278 index = OpenRTM_aist.NVUtil.find_index(nv, olddesc) 01279 if index < 0: 01280 return False 01281 01282 ior_ = str(any.from_any(nv[index].value, keep_structs=True)) 01283 if not ior_: 01284 self._rtcout.RTC_WARN("Cannot extract Provider IOR string") 01285 return False 01286 01287 if isinstance(iorstr, list): 01288 iorstr.append(ior_) 01289 01290 self._rtcout.RTC_ERROR("interface matched with old descriptor: %s", olddesc) 01291 01292 return True 01293 01294 01295 ## 01296 # @if jp 01297 # @brief Consumer に IOR をセットする 01298 # 01299 # IOR をナローイングしてConsumer にセットする。ナローイングに失敗 01300 # した場合、false を返す。ただし、IOR文字列が、nullまたはnilの場合、 01301 # オブジェクトに何もセットせずに true を返す。 01302 # 01303 # @param ior セットする IOR 文字列 01304 # @param cons Consumer のホルダ 01305 # 01306 # @retrun bool Consumer へのナローイングに失敗した場合 false 01307 # 01308 # @else 01309 # @brief Setting IOR to Consumer 01310 # 01311 # This function performs narrowing into the Consumer and set it to the 01312 # Consumer. False is returned when the narrowing failed. But, if IOR 01313 # string is "null" or "nil", this function returns true. 01314 # 01315 # @param ior IOR string 01316 # @param cons Consumer holder 01317 # 01318 # @retrun bool false if narrowing failed. 01319 # 01320 # @endif 01321 # 01322 # bool setObject(const std::string& ior, CorbaConsumerHolder& cons); 01323 def setObject(self, ior, cons): 01324 # if ior string is "null" or "nil", ignore it. 01325 if "null" == ior: 01326 return True 01327 01328 if "nil" == ior: 01329 return True 01330 01331 # IOR should be started by "IOR:" 01332 if "IOR:" != ior[:4]: 01333 return False 01334 01335 # set IOR to the consumer 01336 if not cons.setObject(ior): 01337 self._rtcout.RTC_ERROR("Cannot narrow reference") 01338 return False 01339 01340 self._rtcout.RTC_TRACE("setObject() done") 01341 return True 01342 01343 ## 01344 # @if jp 01345 # @brief Consumer のオブジェクトをリリースする 01346 # 01347 # Consumer にセットされた参照をリリースする。ConsumerのIORが与えら 01348 # れたIOR文字列と異なる場合、falseを返す。 01349 # 01350 # @param ior セットする IOR 文字列 01351 # @param cons Consumer のホルダ 01352 # 01353 # @retrun ConsumerのIORが与えられたIOR文字列と異なる場合、falseを返す。 01354 # 01355 # @else 01356 # @brief Releasing Consumer Object 01357 # 01358 # This function releases object reference of Consumer. If the 01359 # given IOR string is different from Consumer's IOR string, it 01360 # returns false. 01361 # 01362 # @param ior IOR string 01363 # @param cons Consumer holder 01364 # 01365 # @retrun bool False if IOR and Consumer's IOR are different 01366 # 01367 # @endif 01368 # 01369 # bool releaseObject(const std::string& ior, CorbaConsumerHolder& cons); 01370 def releaseObject(self, ior, cons): 01371 if ior == cons.getIor(): 01372 cons.releaseObject() 01373 self._rtcout.RTC_DEBUG("Consumer %s released.", cons.descriptor()) 01374 return True 01375 01376 self._rtcout.RTC_WARN("IORs between Consumer and Connector are different.") 01377 return False 01378 01379 ## 01380 # @if jp 01381 # @class CorbaProviderHolder 01382 # @brief Provider の情報を格納する構造体 01383 # 01384 # CORBA Provider のホルダクラス 01385 # 01386 # @else 01387 # @class CorbaProviderHolder 01388 # @brief The structure to be stored Provider information. 01389 # 01390 # CORBA Provider holder class 01391 # 01392 # @endif 01393 class CorbaProviderHolder: 01394 # CorbaProviderHolder(const char* type_name, 01395 # const char* instance_name, 01396 # PortableServer::RefCountServantBase* servant) 01397 def __init__(self, type_name, instance_name, servant): 01398 self._typeName = type_name 01399 self._instanceName = instance_name 01400 self._servant = servant 01401 _mgr = OpenRTM_aist.Manager.instance() 01402 self._oid = _mgr.getPOA().servant_to_id(self._servant) 01403 01404 obj = _mgr.getPOA().id_to_reference(self._oid) 01405 self._ior = _mgr.getORB().object_to_string(obj) 01406 self.deactivate() 01407 return 01408 01409 def __del__(self): 01410 self.deactivate() 01411 01412 # std::string instanceName() { return m_instanceName; } 01413 def instanceName(self): 01414 return self._instanceName 01415 01416 # std::string typeName() { return m_typeName; } 01417 def typeName(self): 01418 return self._typeName 01419 01420 # std::string ior() { return m_ior; } 01421 def ior(self): 01422 return self._ior 01423 01424 # std::string descriptor() { return m_typeName + "." + m_instanceName; } 01425 def descriptor(self): 01426 return self._typeName + "." + self._instanceName 01427 01428 # void activate() 01429 def activate(self): 01430 try: 01431 OpenRTM_aist.Manager.instance().getPOA().activate_object_with_id(self._oid, self._servant) 01432 except: 01433 print OpenRTM_aist.Logger.print_exception() 01434 return 01435 01436 # void deactivate() 01437 def deactivate(self): 01438 try: 01439 OpenRTM_aist.Manager.instance().getPOA().deactivate_object(self._oid) 01440 except: 01441 print OpenRTM_aist.Logger.print_exception() 01442 return 01443 01444 01445 ## 01446 # @if jp 01447 # @brief Consumer の情報を格納する構造体 01448 # @else 01449 # @brief The structure to be stored Consumer information. 01450 # @endif 01451 # 01452 class CorbaConsumerHolder: 01453 # CorbaConsumerHolder(const char* type_name, 01454 # const char* instance_name, 01455 # CorbaConsumerBase* consumer, 01456 # string& owner) 01457 def __init__(self, type_name, instance_name, consumer, owner): 01458 self._typeName = type_name 01459 self._instanceName = instance_name 01460 self._consumer = consumer 01461 self._owner = owner 01462 self._ior = "" 01463 return 01464 01465 # std::string instanceName() { return m_instanceName; } 01466 def instanceName(self): 01467 return self._instanceName 01468 01469 # std::string typeName() { return m_typeName; } 01470 def typeName(self): 01471 return self._typeName 01472 01473 # std::string descriptor() { return m_typeName + "." + m_instanceName; } 01474 def descriptor(self): 01475 return self._typeName + "." + self._instanceName 01476 01477 ## 01478 # @if jp 01479 # @brief Consumer に IOR をセットする 01480 # @else 01481 # @brief Setting IOR to Consumer 01482 #@endif 01483 # 01484 # bool setObject(const char* ior) 01485 def setObject(self, ior): 01486 self._ior = ior 01487 orb = OpenRTM_aist.Manager.instance().getORB() 01488 obj = orb.string_to_object(ior) 01489 if CORBA.is_nil(obj): 01490 return False 01491 01492 return self._consumer.setObject(obj) 01493 01494 ## 01495 # @if jp 01496 # @brief Consumer のオブジェクトをリリースする 01497 # @else 01498 # @brief Releasing Consumer Object 01499 # @endif 01500 # 01501 # void releaseObject() 01502 def releaseObject(self): 01503 self._consumer.releaseObject() 01504 return 01505 01506 # const std::string& getIor() 01507 def getIor(self): 01508 return self._ior 01509 01510 01511 ## 01512 # @if jp 01513 # @brief ConnectorProfile と Consuemr の比較をしオブジェクト参照を 01514 # セットするための Functor 01515 # @else 01516 # @brief Subscription mutching functor for Consumer 01517 # @endif 01518 class subscribe: 01519 def __init__(self, cons): 01520 self._cons = cons 01521 self._len = len(cons) 01522 01523 def __call__(self, nv): 01524 for i in range(self._len): 01525 name_ = nv.name 01526 if self._cons[i].descriptor() == name_: 01527 try: 01528 obj = any.from_any(nv.value, keep_structs=True) 01529 self._cons[i].setObject(obj) 01530 except: 01531 print OpenRTM_aist.Logger.print_exception() 01532 01533 01534 01535 ## 01536 # @if jp 01537 # @brief Consumer のオブジェクトを解放するための Functor 01538 # @else 01539 # @brief Functor to release Consumer's object 01540 # @endif 01541 class unsubscribe: 01542 def __init__(self, cons): 01543 self._cons = cons 01544 self._len = len(cons) 01545 01546 def __call__(self, nv): 01547 for i in range(self._len): 01548 name_ = nv.name 01549 if self._cons[i].descriptor() == name_: 01550 self._cons[i].releaseObject() 01551 return 01552 01553 # for 0.4.x 01554 if "port."+self._cons[i].descriptor() == name_: 01555 self._cons[i].releaseObject() 01556 01557