IIOP_Connector.cpp

Go to the documentation of this file.
00001 #include "tao/IIOP_Connector.h"
00002 
00003 #if defined (TAO_HAS_IIOP) && (TAO_HAS_IIOP != 0)
00004 
00005 #include "tao/IIOP_Profile.h"
00006 #include "tao/debug.h"
00007 #include "tao/ORB_Core.h"
00008 #include "tao/Environment.h"
00009 #include "tao/Protocols_Hooks.h"
00010 #include "tao/Connect_Strategy.h"
00011 #include "tao/Thread_Lane_Resources.h"
00012 #include "tao/Profile_Transport_Resolver.h"
00013 #include "tao/Base_Transport_Property.h"
00014 #include "tao/Transport.h"
00015 #include "tao/Wait_Strategy.h"
00016 #include "tao/SystemException.h"
00017 #include "tao/LF_Multi_Event.h"
00018 #include "ace/OS_NS_strings.h"
00019 #include "ace/OS_NS_string.h"
00020 #include "ace/OS_NS_time.h"
00021 
00022 ACE_RCSID (tao,
00023            IIOP_Connector,
00024            "IIOP_Connector.cpp,v 1.152 2006/05/16 06:10:47 mesnier_p Exp")
00025 
00026 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00027 
00028 
00029 
00030 //-----------------------------------------------------------------------------
00031 
00032 /**
00033  * @class TAO_Event_Handler_Array_var
00034  *
00035  * @brief Auto pointer like class for an array of Event Handlers.
00036  *
00037  * Used to manage lifecycle of handlers. This class calls
00038  * ACE_Event_Handler::remove_reference() on each handler in its destructor
00039  * This class started out life as a replacement for the ACE_Event_Handle_var
00040  * but is now pared down to be very specific in its role..
00041  */
00042 class TAO_IIOP_Connection_Handler_Array_Guard
00043 {
00044 public:
00045   TAO_IIOP_Connection_Handler_Array_Guard (TAO_IIOP_Connection_Handler **p, unsigned count);
00046   ~TAO_IIOP_Connection_Handler_Array_Guard (void);
00047 
00048 private:
00049   /// Handler.
00050   TAO_IIOP_Connection_Handler **ptr_;
00051   unsigned count_;
00052 };
00053 
00054 TAO_IIOP_Connection_Handler_Array_Guard::TAO_IIOP_Connection_Handler_Array_Guard (TAO_IIOP_Connection_Handler **p,
00055                                                           unsigned count)
00056   : ptr_ (p),
00057     count_ (count)
00058 {
00059 }
00060 
00061 TAO_IIOP_Connection_Handler_Array_Guard::~TAO_IIOP_Connection_Handler_Array_Guard (void)
00062 {
00063   if (this->ptr_ != 0)
00064     {
00065       for (unsigned i = 0; i < this->count_; i++)
00066         this->ptr_[i]->remove_reference ();
00067     }
00068 }
00069 
00070 //---------------------------------------------------------------------------
00071 
00072 
00073 TAO_IIOP_Connector::~TAO_IIOP_Connector (void)
00074 {
00075 }
00076 
00077 //@@ TAO_CONNECTOR_SPL_COPY_HOOK_START
00078 TAO_IIOP_Connector::TAO_IIOP_Connector (CORBA::Boolean flag)
00079   : TAO_Connector (IOP::TAG_INTERNET_IOP)
00080   , lite_flag_ (flag)
00081   , connect_strategy_ ()
00082   , base_connector_ ()
00083 {
00084 }
00085 
00086 int
00087 TAO_IIOP_Connector::open (TAO_ORB_Core *orb_core)
00088 {
00089   // @@todo: The functionality of the following two statements could
00090   // be done in the constructor, but that involves changing the
00091   // interface of the pluggable transport factory.
00092 
00093   // Set the ORB Core
00094   this->orb_core (orb_core);
00095 
00096   // Create our connect strategy
00097   if (this->create_connect_strategy () == -1)
00098     return -1;
00099 
00100   /// Our connect creation strategy
00101   TAO_IIOP_CONNECT_CREATION_STRATEGY *connect_creation_strategy = 0;
00102 
00103   ACE_NEW_RETURN (connect_creation_strategy,
00104                   TAO_IIOP_CONNECT_CREATION_STRATEGY
00105                       (orb_core->thr_mgr (),
00106                        orb_core,
00107                        this->lite_flag_),
00108                   -1);
00109 
00110   /// Our activation strategy
00111   TAO_IIOP_CONNECT_CONCURRENCY_STRATEGY *concurrency_strategy = 0;
00112 
00113   ACE_NEW_RETURN (concurrency_strategy,
00114                   TAO_IIOP_CONNECT_CONCURRENCY_STRATEGY (orb_core),
00115                   -1);
00116 
00117   return this->base_connector_.open (this->orb_core ()->reactor (),
00118                                      connect_creation_strategy,
00119                                      &this->connect_strategy_,
00120                                      concurrency_strategy);
00121 }
00122 
00123 int
00124 TAO_IIOP_Connector::close (void)
00125 {
00126   delete this->base_connector_.concurrency_strategy ();
00127   delete this->base_connector_.creation_strategy ();
00128   return this->base_connector_.close ();
00129 }
00130 
00131 int
00132 TAO_IIOP_Connector::supports_parallel_connects(void) const
00133 {
00134   return 1;
00135 }
00136 
00137 int
00138 TAO_IIOP_Connector::set_validate_endpoint (TAO_Endpoint *endpoint)
00139 {
00140   TAO_IIOP_Endpoint *iiop_endpoint =
00141     this->remote_endpoint (endpoint);
00142 
00143   if (iiop_endpoint == 0)
00144     return -1;
00145 
00146    const ACE_INET_Addr &remote_address =
00147      iiop_endpoint->object_addr ();
00148 
00149    // Verify that the remote ACE_INET_Addr was initialized properly.
00150    // Failure can occur if hostname lookup failed when initializing the
00151    // remote ACE_INET_Addr.
00152 #if defined (ACE_HAS_IPV6)
00153    if (remote_address.get_type () != AF_INET &&
00154        remote_address.get_type () != AF_INET6)
00155 #else /* ACE_HAS_IPV6 */
00156    if (remote_address.get_type () != AF_INET)
00157 #endif /* !ACE_HAS_IPV6 */
00158      {
00159        if (TAO_debug_level > 0)
00160          {
00161            ACE_DEBUG ((LM_DEBUG,
00162                        ACE_TEXT ("(%P|%t) IIOP connection failed.\n")
00163                        ACE_TEXT ("     This is most likely ")
00164                        ACE_TEXT ("due to a hostname lookup ")
00165                        ACE_TEXT ("failure.\n")));
00166          }
00167 
00168        return -1;
00169      }
00170 
00171    return 0;
00172 }
00173 
00174 TAO_Transport *
00175 TAO_IIOP_Connector::make_connection (TAO::Profile_Transport_Resolver *r,
00176                                      TAO_Transport_Descriptor_Interface &desc,
00177                                      ACE_Time_Value *timeout)
00178 {
00179   TAO_IIOP_Connection_Handler *svc_handler = 0;
00180   TAO_IIOP_Endpoint *iiop_endpoint =
00181     this->remote_endpoint (desc.endpoint());
00182   int result = -1;
00183   if (iiop_endpoint == 0)
00184     return 0;
00185 
00186   result = this->begin_connection (svc_handler, r, iiop_endpoint, timeout);
00187 
00188   if (result == -1 && errno != EWOULDBLOCK)
00189     {
00190       // connect completed unsuccessfully
00191       svc_handler->remove_reference();
00192        // Give users a clue to the problem.
00193       if (TAO_debug_level > 1)
00194         {
00195           ACE_DEBUG ((LM_ERROR,
00196                       ACE_TEXT ("(%P|%t) IIOP_Connector::make_connection, ")
00197                       ACE_TEXT("connection to <%s:%d> failed (%p)\n"),
00198                       ACE_TEXT_CHAR_TO_TCHAR (iiop_endpoint->host ()),
00199                       iiop_endpoint->port (),
00200                       ACE_TEXT("errno")));
00201         }
00202     return 0;
00203     }
00204   TAO_IIOP_Connection_Handler **sh_ptr = &svc_handler;
00205   TAO_IIOP_Endpoint **ep_ptr = &iiop_endpoint;
00206   TAO_LF_Multi_Event mev;
00207   mev.add_event(svc_handler);
00208   return this->complete_connection (result, desc,
00209                                     sh_ptr, ep_ptr,
00210                                     1U, r, &mev,  timeout);
00211 }
00212 
00213 TAO_Transport *
00214 TAO_IIOP_Connector::make_parallel_connection (TAO::Profile_Transport_Resolver *r,
00215                                      TAO_Transport_Descriptor_Interface &desc,
00216                                      ACE_Time_Value *timeout)
00217 {
00218   TAO_Endpoint *root_ep = desc.endpoint();
00219   unsigned max_count = 1;
00220   unsigned long ns_stagger =
00221     this->orb_core()->orb_params()->parallel_connect_delay();
00222   unsigned long sec_stagger = ns_stagger/1000;
00223   ns_stagger = (ns_stagger % 1000) * 1000000;
00224   for (TAO_Endpoint *ep = root_ep->next_filtered (this->orb_core(),0);
00225        ep != 0;
00226        ep = ep->next_filtered(this->orb_core(),root_ep))
00227     max_count++;
00228 
00229   if (TAO_debug_level > 2)
00230     ACE_DEBUG ((LM_DEBUG,
00231                 ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::")
00232                 ACE_TEXT ("make_parallel_connection, ")
00233                 ACE_TEXT ("to %d endpoints\n"), max_count));
00234   TAO_IIOP_Endpoint **eplist = 0;
00235   TAO_IIOP_Connection_Handler **shlist = 0;
00236   ACE_NEW_RETURN (shlist, TAO_IIOP_Connection_Handler *[max_count], 0);
00237   ACE_NEW_RETURN (eplist, TAO_IIOP_Endpoint *[max_count], 0);
00238 
00239   TAO_LF_Multi_Event mev;
00240   int result = 0;
00241   unsigned count = 0;
00242   for (TAO_Endpoint *ep = root_ep->next_filtered (this->orb_core(),0);
00243        ep != 0;
00244        ep = ep->next_filtered(this->orb_core(),root_ep))
00245     {
00246       eplist[count] = this->remote_endpoint (ep);
00247       shlist[count] = 0;
00248       result = this->begin_connection (shlist[count],
00249                                        r,
00250                                        eplist[count],
00251                                        timeout);
00252 
00253       // The connection may fail because it is slow, or for other reasons.
00254       // If it was an incomplete non-blocking connection, add it to the list
00255       // to be waited on, otherwise remove the reference to the handler and
00256       // move on to the next endpoint.
00257       if (result == -1)
00258         {
00259           if (errno == EWOULDBLOCK)
00260             {
00261               mev.add_event(shlist[count++]);
00262               if (ep->next() != 0)
00263                 {
00264                   struct timespec nsleep = {sec_stagger, ns_stagger};
00265                   ACE_OS::nanosleep (&nsleep);
00266                   result = this->active_connect_strategy_->poll (&mev);
00267                   if (result != -1)
00268                     break;
00269                 }
00270             }
00271           else
00272             {
00273               shlist[count]->remove_reference(); // done bump the list count
00274             }
00275           continue;
00276         }
00277 
00278       if (result != -1) // we have a winner!
00279         {
00280           count++;
00281           break; // no waiting involved since a connection is completed
00282         }
00283     }
00284 
00285   TAO_Transport *winner = 0;
00286   if (count > 0) // only complete if at least one pending or success
00287     winner = this->complete_connection (result,desc,
00288                                         shlist,eplist,count,r,&mev,timeout);
00289   delete [] shlist; // reference reductions should have been done already
00290   delete [] eplist;
00291   return winner;
00292 }
00293 
00294 int
00295 TAO_IIOP_Connector::begin_connection (TAO_IIOP_Connection_Handler *&svc_handler,
00296                                       TAO::Profile_Transport_Resolver *r,
00297                                       TAO_IIOP_Endpoint *iiop_endpoint,
00298                                       ACE_Time_Value *timeout)
00299 {
00300   const ACE_INET_Addr &remote_address =
00301     iiop_endpoint->object_addr ();
00302 
00303   u_short port = 0;
00304   const ACE_UINT32 ia_any = INADDR_ANY;
00305   ACE_INET_Addr local_addr(port, ia_any);
00306 
00307   if (iiop_endpoint->is_preferred_network ())
00308     local_addr.set (port,
00309                     iiop_endpoint->preferred_network ());
00310 #if defined (ACE_HAS_IPV6)
00311   else if (remote_address.get_type () == AF_INET6)
00312     local_addr.set (port,
00313                     ACE_IPV6_ANY);
00314 #endif /* ACE_HAS_IPV6 */
00315 
00316   if (TAO_debug_level > 2)
00317     ACE_DEBUG ((LM_DEBUG,
00318                 ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::begin_connection, ")
00319                 ACE_TEXT ("to <%s:%d> which should %s\n"),
00320                 ACE_TEXT_CHAR_TO_TCHAR(iiop_endpoint->host()),
00321                 iiop_endpoint->port(),
00322                 r->blocked_connect () ? ACE_TEXT("block") : ACE_TEXT("nonblock")));
00323 
00324   // Get the right synch options
00325   ACE_Synch_Options synch_options;
00326 
00327   this->active_connect_strategy_->synch_options (timeout,
00328                                                  synch_options);
00329 
00330   // If we don't need to block for a transport just set the timeout to
00331   // be zero.
00332   ACE_Time_Value tmp_zero (ACE_Time_Value::zero);
00333   if (!r->blocked_connect ())
00334     {
00335       synch_options.timeout (ACE_Time_Value::zero);
00336       timeout = &tmp_zero;
00337     }
00338 
00339   svc_handler = 0;
00340 
00341   int result =
00342     this->base_connector_.connect (svc_handler,
00343                                    remote_address,
00344                                    synch_options,
00345                                    local_addr);
00346 
00347   // The connect() method creates the service handler and bumps the
00348   // #REFCOUNT# up one extra.  There are four possibilities from
00349   // calling connect(): (a) connection succeeds immediately - in this
00350   // case, the #REFCOUNT# on the handler is two; (b) connection
00351   // completion is pending - in this case, the #REFCOUNT# on the
00352   // handler is also two; (c) connection fails immediately - in this
00353   // case, the #REFCOUNT# on the handler is one since close() gets
00354   // called on the handler; (d) the connect immediately returns when we
00355   // have specified that it shouldn't block.
00356   //
00357   // The extra reference count in
00358   // TAO_Connect_Creation_Strategy::make_svc_handler() is needed in
00359   // the case when connection completion is pending and we are going
00360   // to wait on a variable in the handler to changes, signifying
00361   // success or failure.  Note, that this increment cannot be done
00362   // once the connect() returns since this might be too late if
00363   // another thread pick up the completion and potentially deletes the
00364   // handler before we get a chance to increment the reference count.
00365   return result;
00366 }
00367 
00368 TAO_Transport *
00369 TAO_IIOP_Connector::complete_connection (int result,
00370                                          TAO_Transport_Descriptor_Interface &desc,
00371                                          TAO_IIOP_Connection_Handler **&sh_list,
00372                                          TAO_IIOP_Endpoint **ep_list,
00373                                          unsigned count,
00374                                          TAO::Profile_Transport_Resolver *r,
00375                                          TAO_LF_Multi_Event *mev,
00376                                          ACE_Time_Value *timeout)
00377 {
00378   // Make sure that we always do a remove_reference for every member
00379   // of the list
00380   TAO_IIOP_Connection_Handler_Array_Guard svc_handler_auto_ptr (sh_list,count);
00381   TAO_Transport *transport  = 0;
00382   TAO_Transport **tlist = 0;
00383   ACE_NEW_RETURN (tlist,TAO_Transport*[count],0);
00384 
00385   //  populate the transport list
00386   for (unsigned i = 0; i < count; i++)
00387     tlist[i] = sh_list[i]->transport();
00388 
00389   if (result != -1)
00390     {
00391       // We received a compeleted connection and 0 or more pending.
00392       // the winner is the last member of the list, because the
00393       // iterator stopped on a successful connect.
00394       transport = tlist[count-1];
00395     }
00396   else
00397     {
00398       if (count == 1)
00399         {
00400           transport = tlist[0];
00401           if (!this->wait_for_connection_completion (r,
00402                                                      transport,
00403                                                      timeout))
00404             {
00405               if (TAO_debug_level > 2)
00406                 ACE_ERROR ((LM_ERROR,
00407                             ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::")
00408                             ACE_TEXT ("complete_connection, wait for completion ")
00409                             ACE_TEXT ("failed for 1 pending connect\n")));
00410             }
00411         }
00412       else
00413         {
00414           if (!this->wait_for_connection_completion (r,
00415                                                      transport,
00416                                                      tlist,
00417                                                      count,
00418                                                      mev,
00419                                                      timeout))
00420             {
00421               if (TAO_debug_level > 2)
00422                 ACE_ERROR ((LM_ERROR,
00423                             ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::")
00424                             ACE_TEXT ("complete_connection, wait for completion ")
00425                             ACE_TEXT ("failed for %d pending connects\n"),
00426                             count));
00427             }
00428         }
00429     }
00430   // At this point, the connection has be successfully created
00431   // connected or not connected, but we have a connection.
00432   TAO_IIOP_Connection_Handler *svc_handler = 0;
00433   TAO_IIOP_Endpoint *iiop_endpoint = 0;
00434 
00435   if (transport != 0)
00436     {
00437       for (unsigned i = 0; i < count; i++)
00438         {
00439           if (transport == tlist[i])
00440             {
00441               svc_handler = sh_list[i];
00442               if (transport->connection_handler()->keep_waiting())
00443                 {
00444                   svc_handler->add_reference();
00445                 }
00446               iiop_endpoint = ep_list[i];
00447               break;
00448             }
00449         }
00450     }
00451 
00452 
00453   // Done with the transport list. It was a temporary that did not
00454   // affect the reference count.
00455   delete [] tlist;
00456 
00457   // In case of errors transport is zero
00458   if (transport == 0)
00459     {
00460       // Give users a clue to the problem.
00461       if (TAO_debug_level > 3)
00462         {
00463           for (unsigned i = 0; i < count; i++)
00464           ACE_DEBUG ((LM_ERROR,
00465                         ACE_TEXT ("(%P|%t) IIOP_Connector::make_connection, ")
00466                         ACE_TEXT("connection to <%s:%d> failed (%p)\n"),
00467                         ACE_TEXT_CHAR_TO_TCHAR (ep_list[i]->host ()),
00468                         ep_list[i]->port (),
00469                       ACE_TEXT("errno")));
00470         }
00471 
00472       return 0;
00473     }
00474 
00475 
00476   if (TAO_debug_level > 2)
00477     {
00478     ACE_DEBUG ((LM_DEBUG,
00479                   ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::make_connection, ")
00480                   ACE_TEXT ("new %s connection to <%s:%d> on Transport[%d]\n"),
00481                   transport->is_connected() ?
00482                   ACE_TEXT("connected") : ACE_TEXT("not connected"),
00483                   ACE_TEXT_CHAR_TO_TCHAR (iiop_endpoint->host ()),
00484                 iiop_endpoint->port (),
00485                 svc_handler->peer ().get_handle ()));
00486     }
00487 
00488   // Add the handler to Cache
00489   int retval = -1;
00490   if (count == 1U || desc.reset_endpoint(iiop_endpoint))
00491     {
00492       retval = this->orb_core ()->
00493         lane_resources ().transport_cache ().cache_transport (&desc,
00494                                                               transport);
00495     }
00496 
00497   // Failure in adding to cache.
00498   if (retval != 0)
00499     {
00500       // Close the handler.
00501       svc_handler->close ();
00502 
00503       if (TAO_debug_level > 0)
00504         {
00505           ACE_ERROR ((LM_ERROR,
00506                       ACE_TEXT ("(%P|%t) IIOP_Connector::make_connection, ")
00507                       ACE_TEXT ("could not add new connection to cache\n")));
00508         }
00509 
00510       return 0;
00511     }
00512 
00513   if (transport->is_connected () &&
00514       transport->wait_strategy ()->register_handler () != 0)
00515     {
00516       // Registration failures.
00517 
00518       // Purge from the connection cache, if we are not in the cache, this
00519       // just does nothing.
00520       (void) transport->purge_entry ();
00521 
00522       // Close the handler.
00523       (void) transport->close_connection ();
00524 
00525       if (TAO_debug_level > 0)
00526         ACE_ERROR ((LM_ERROR,
00527                     ACE_TEXT ("(%P|%t) IIOP_Connector [%d]::make_connection, ")
00528                     ACE_TEXT ("could not register the transport ")
00529                     ACE_TEXT ("in the reactor.\n"),
00530                     transport->id ()));
00531 
00532       return 0;
00533     }
00534 
00535   return transport;
00536 }
00537 
00538 TAO_Profile *
00539 TAO_IIOP_Connector::create_profile (TAO_InputCDR& cdr)
00540 {
00541   TAO_Profile *pfile = 0;
00542   ACE_NEW_RETURN (pfile,
00543                   TAO_IIOP_Profile (this->orb_core ()),
00544                   0);
00545 
00546   const int r = pfile->decode (cdr);
00547   if (r == -1)
00548     {
00549       pfile->_decr_refcnt ();
00550       pfile = 0;
00551     }
00552 
00553   return pfile;
00554 }
00555 
00556 TAO_Profile *
00557 TAO_IIOP_Connector::make_profile (ACE_ENV_SINGLE_ARG_DECL)
00558 {
00559   // The endpoint should be of the form:
00560   //    N.n@host:port/object_key
00561   // or:
00562   //    host:port/object_key
00563 
00564   TAO_Profile *profile = 0;
00565   ACE_NEW_THROW_EX (profile,
00566                     TAO_IIOP_Profile (this->orb_core ()),
00567                     CORBA::NO_MEMORY (
00568                       CORBA::SystemException::_tao_minor_code (
00569                         0,
00570                         ENOMEM),
00571                       CORBA::COMPLETED_NO));
00572   ACE_CHECK_RETURN (0);
00573 
00574   return profile;
00575 }
00576 
00577 int
00578 TAO_IIOP_Connector::check_prefix (const char *endpoint)
00579 {
00580   // Check for a valid string
00581   if (!endpoint || !*endpoint)
00582     return -1;  // Failure
00583 
00584   static const char *protocol[] = { "iiop", "iioploc" };
00585 
00586   const size_t slot = ACE_OS::strchr (endpoint, ':') - endpoint;
00587   if (slot == 0) // an empty string is valid for corbaloc.
00588     return 0;
00589 
00590   const size_t len0 = ACE_OS::strlen (protocol[0]);
00591   const size_t len1 = ACE_OS::strlen (protocol[1]);
00592 
00593   // Check for the proper prefix in the IOR.  If the proper prefix
00594   // isn't in the IOR then it is not an IOR we can use.
00595   if (slot == len0
00596       && ACE_OS::strncasecmp (endpoint, protocol[0], len0) == 0)
00597     return 0;
00598   else if (slot == len1
00599            && ACE_OS::strncasecmp (endpoint, protocol[1], len1) == 0)
00600     return 0;
00601 
00602   return -1;
00603   // Failure: not an IIOP IOR
00604   // DO NOT throw an exception here.
00605 }
00606 
00607 char
00608 TAO_IIOP_Connector::object_key_delimiter (void) const
00609 {
00610   return TAO_IIOP_Profile::object_key_delimiter_;
00611 }
00612 
00613 TAO_IIOP_Endpoint *
00614 TAO_IIOP_Connector::remote_endpoint (TAO_Endpoint *endpoint)
00615 {
00616   if (endpoint->tag () != IOP::TAG_INTERNET_IOP)
00617     return 0;
00618 
00619   TAO_IIOP_Endpoint *iiop_endpoint =
00620     dynamic_cast<TAO_IIOP_Endpoint *> (endpoint );
00621 
00622   if (iiop_endpoint == 0)
00623     return 0;
00624 
00625   return iiop_endpoint;
00626 }
00627 
00628 int
00629 TAO_IIOP_Connector::cancel_svc_handler (
00630   TAO_Connection_Handler * svc_handler)
00631 {
00632   TAO_IIOP_Connection_Handler* handler=
00633     dynamic_cast<TAO_IIOP_Connection_Handler*>(svc_handler);
00634 
00635   // Cancel from the connector
00636   if (handler)
00637     {
00638       handler->abort();
00639       return this->base_connector_.cancel (handler);
00640     }
00641 
00642   return -1;
00643 }
00644 
00645 
00646 //@@ TAO_CONNECTOR_SPL_COPY_HOOK_END
00647 
00648 TAO_END_VERSIONED_NAMESPACE_DECL
00649 
00650 #endif /* TAO_HAS_IIOP && TAO_HAS_IIOP != 0 */

Generated on Thu Nov 9 11:54:13 2006 for TAO by doxygen 1.3.6