Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

Acceptor_Registry.cpp

Go to the documentation of this file.
00001 #include "tao_pch.h"
00002 // -*- C++ -*-
00003 //
00004 // $Id: Acceptor_Registry.cpp,v 1.1.1.4.2.1 2003/03/14 16:05:11 chad Exp $
00005 
00006 #include "tao/Acceptor_Registry.h"
00007 #include "tao/Profile.h"
00008 #include "tao/Transport_Acceptor.h"
00009 #include "tao/Protocol_Factory.h"
00010 #include "tao/Environment.h"
00011 #include "tao/ORB_Core.h"
00012 #include "tao/params.h"
00013 #include "tao/MProfile.h"
00014 #include "tao/debug.h"
00015 #include "tao/Acceptor_Filter.h"
00016 #include "tao/Endpoint.h"
00017 
00018 #include "ace/Auto_Ptr.h"
00019 
00020 #if !defined(__ACE_INLINE__)
00021 #include "tao/Acceptor_Registry.i"
00022 #endif /* __ACE_INLINE__ */
00023 
00024 ACE_RCSID (tao,
00025            Acceptor_Registry,
00026            "$Id: Acceptor_Registry.cpp,v 1.1.1.4.2.1 2003/03/14 16:05:11 chad Exp $")
00027 
00028 TAO_Acceptor_Registry::TAO_Acceptor_Registry (void)
00029   : acceptors_ (0),
00030     size_ (0)
00031 {
00032 }
00033 
00034 TAO_Acceptor_Registry::~TAO_Acceptor_Registry (void)
00035 {
00036   this->close_all ();
00037 
00038   delete [] this->acceptors_;
00039   this->acceptors_ = 0;
00040   this->size_ = 0;
00041 }
00042 
00043 size_t
00044 TAO_Acceptor_Registry::endpoint_count (void)
00045 {
00046   int count = 0;
00047   TAO_AcceptorSetIterator end = this->end ();
00048 
00049   for (TAO_AcceptorSetIterator i = this->begin (); i != end; ++i)
00050     count += (*i)->endpoint_count ();
00051 
00052   return count;
00053 }
00054 
00055 int
00056 TAO_Acceptor_Registry::is_collocated (const TAO_MProfile &mprofile)
00057 {
00058   TAO_AcceptorSetIterator end = this->end ();
00059 
00060   // If at least one endpoint in one of the profiles matches one of
00061   // the acceptors, we are collocated.
00062   for (TAO_AcceptorSetIterator i = this->begin (); i != end; ++i)
00063     {
00064       for (TAO_PHandle j = 0;
00065            j != mprofile.profile_count ();
00066            ++j)
00067         {
00068           const TAO_Profile *profile = mprofile.get_profile (j);
00069 
00070           // @@ We need to invoke a nonconst <endpoint> method on
00071           // <profile>.  The content of profile/endpoint
00072           // will not be modified.
00073           TAO_Profile *pf =
00074             ACE_const_cast (TAO_Profile *,
00075                             profile);
00076 
00077           // Check all endpoints for address equality.
00078           if ((*i)->tag () == pf->tag ())
00079             {
00080               // @note This can be a potentially expensive (O(n^2))
00081               //       operation if the below is_collocated() call
00082               //       also executes a loop.
00083               for (TAO_Endpoint *endp = pf->endpoint ();
00084                    endp != 0;
00085                    endp = endp->next ())
00086                 {
00087                   if ((*i)->is_collocated (endp))
00088                     return 1;
00089                 }
00090             }
00091         }
00092     }
00093 
00094   return 0;
00095 }
00096 
00097 TAO_Acceptor*
00098 TAO_Acceptor_Registry::get_acceptor (CORBA::ULong tag)
00099 {
00100   TAO_AcceptorSetIterator end = this->end ();
00101   TAO_AcceptorSetIterator acceptor = this->begin ();
00102 
00103   for (;
00104        acceptor != end ;
00105        ++acceptor)
00106     {
00107       if ((*acceptor)->tag () == tag)
00108         return *acceptor;
00109     }
00110 
00111   return 0;
00112 }
00113 
00114 int
00115 TAO_Acceptor_Registry::open (TAO_ORB_Core *orb_core,
00116                              ACE_Reactor *reactor,
00117                              int ignore_address
00118                               ACE_ENV_ARG_DECL)
00119   ACE_THROW_SPEC ((CORBA::SystemException))
00120 {
00121   // protocol_factories is in the following form
00122   //   IOP1://addr1,addr2,...,addrN/;IOP2://addr1,...addrM/;...
00123   TAO_EndpointSet endpoint_set = orb_core->orb_params ()->endpoints ();
00124 
00125   if (endpoint_set.is_empty ())
00126     {
00127       // No endpoints were specified, we let each protocol pick its
00128       // own default.
00129 
00130       // All TAO pluggable protocols are expected to have the ability
00131       // to create a default endpoint.
00132       if (this->open_default (orb_core,
00133                               reactor,
00134                               0) == -1)
00135         ACE_THROW_RETURN (CORBA::INTERNAL (
00136                             CORBA::SystemException::_tao_minor_code (
00137                               TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE,
00138                               0),
00139                             CORBA::COMPLETED_NO),
00140                           -1);
00141     }
00142 
00143   // Count the maximum number of endpoints in the set.  This will be
00144   // the maximum number of acceptors that need to be created.
00145   size_t acceptor_count = 0;
00146   TAO_EndpointSetIterator endpts = endpoint_set.begin ();
00147   for (ACE_CString *ep = 0;
00148        endpts.next (ep) != 0;
00149        endpts.advance ())
00150     {
00151       const ACE_CString &iop = (*ep);
00152 
00153       // IOP://address1,address2
00154       //    ^ slot
00155       int slot = iop.find ("://", 0);
00156 
00157       if (slot == iop.npos)
00158         {
00159           if (TAO_debug_level > 0)
00160             ACE_ERROR ((LM_ERROR,
00161                         ACE_LIB_TEXT ("(%P|%t) Invalid endpoint ")
00162                         ACE_LIB_TEXT ("specification: <%s>.\n"),
00163                         ACE_TEXT_CHAR_TO_TCHAR (iop.c_str ())));
00164 
00165           ACE_THROW_RETURN (CORBA::BAD_PARAM (
00166               CORBA::SystemException::_tao_minor_code (
00167                 TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE,
00168                 EINVAL),
00169               CORBA::COMPLETED_NO),
00170             -1);
00171         }
00172 
00173       ++acceptor_count;  // We've got at least one acceptor so far.
00174 
00175       // Now count the number of commas.  That number will be the
00176       // remaining number of endpoints in the current endpoint
00177       // specification.
00178       const char *ep_end =
00179         ep->c_str () + ACE_OS_String::strlen (ep->c_str ());
00180       for (const char *e = ACE_OS_String::strchr (ep->c_str (), ',');
00181            e != 0 && e != ep_end;
00182            e = ACE_OS_String::strchr (e, ','))
00183         {
00184           ++acceptor_count;
00185           ++e;
00186         }
00187     }
00188 
00189   // The array containing the TAO_Acceptors will never contain more
00190   // than the number of endpoints stored in TAO_ORB_Parameters.
00191   if (this->acceptors_ == 0)
00192     {
00193       ACE_NEW_THROW_EX (this->acceptors_,
00194                         TAO_Acceptor *[acceptor_count],
00195                         CORBA::NO_MEMORY (
00196                           CORBA::SystemException::_tao_minor_code (
00197                             TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE,
00198                             ENOMEM),
00199                           CORBA::COMPLETED_NO));
00200       ACE_CHECK_RETURN (-1);
00201     }
00202 
00203   TAO_EndpointSetIterator endpoints = endpoint_set.begin ();
00204   for (ACE_CString *endpoint = 0;
00205        endpoints.next (endpoint) != 0;
00206        endpoints.advance ())
00207     {
00208       const ACE_CString &iop = (*endpoint);
00209 
00210       // IOP://address1,address2
00211       //    ^ slot
00212       int slot = iop.find ("://", 0);
00213 
00214       if (slot == iop.npos)
00215         {
00216           if (TAO_debug_level > 0)
00217             ACE_ERROR ((LM_ERROR,
00218                         ACE_LIB_TEXT ("(%P|%t) Invalid endpoint ")
00219                         ACE_LIB_TEXT ("specification: <%s>.\n"),
00220                         ACE_TEXT_CHAR_TO_TCHAR (iop.c_str ())));
00221 
00222           ACE_THROW_RETURN (CORBA::BAD_PARAM (
00223               CORBA::SystemException::_tao_minor_code (
00224                 TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE,
00225                 EINVAL),
00226               CORBA::COMPLETED_NO),
00227             -1);
00228         }
00229 
00230       ACE_CString prefix = iop.substring (0, slot);
00231 
00232       // @@ We could move the protocol factory loop to the outermost
00233       //    level but for now we leave it inside the endpoint loop
00234       //    under the assumption that there will be more endpoints
00235       //    than protocols.
00236 
00237       // Now get the list of available protocol factories.
00238       TAO_ProtocolFactorySetItor end =
00239         orb_core->protocol_factories ()->end ();
00240 
00241       int found = 0;
00242       // If usable protocol (factory) is found then this will be
00243       // set equal to 1.
00244 
00245       for (TAO_ProtocolFactorySetItor factory =
00246              orb_core->protocol_factories ()->begin ();
00247            factory != end;
00248            ++factory)
00249         {
00250           if ((*factory)->factory ()->match_prefix (prefix))
00251             {
00252               // increment slot past the "://" (i.e. add 3)
00253               ACE_CString addrs = iop.substring (slot + 3);
00254 
00255               int result = this->open_i (orb_core,
00256                                          reactor,
00257                                          addrs,
00258                                          factory,
00259                                          ignore_address
00260                                           ACE_ENV_ARG_PARAMETER);
00261               ACE_CHECK_RETURN (-1);
00262 
00263               if (result != 0)
00264                 return -1;
00265 
00266               found = 1;  // A usable protocol was found.
00267             }
00268           else
00269             continue;
00270         }
00271 
00272       if (found == 0)
00273         {
00274           ACE_ERROR ((LM_ERROR,
00275                       ACE_LIB_TEXT ("TAO (%P|%t) ")
00276                       ACE_LIB_TEXT ("no usable transport protocol ")
00277                       ACE_LIB_TEXT ("was found.\n")));
00278 
00279           ACE_THROW_RETURN (CORBA::BAD_PARAM (
00280               CORBA::SystemException::_tao_minor_code (
00281                 TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE,
00282                 EINVAL),
00283               CORBA::COMPLETED_NO),
00284             -1);
00285         }
00286     }
00287 
00288   // No longer need the endpoint set since all associated acceptors
00289   // have been opened by now.  Reclaim the memory used by the endpoint
00290   // set.
00291   endpoint_set.reset ();
00292 
00293   return 0;
00294 }
00295 
00296 // Iterate through the loaded transport protocols and create a default
00297 // server for each protocol.
00298 int TAO_Acceptor_Registry::open_default (TAO_ORB_Core *orb_core,
00299                                          ACE_Reactor *reactor,
00300                                          const char *options)
00301 {
00302   TAO_ProtocolFactorySet *pfs = orb_core->protocol_factories ();
00303 
00304   // If the TAO_Acceptor array is zero by the time we get here then no
00305   // endpoints were specified by the user, meaning that the number of
00306   // acceptors will never be more than the number of loaded protocols
00307   // in the ORB core.
00308   if (this->acceptors_ == 0)
00309     ACE_NEW_RETURN (this->acceptors_,
00310                     TAO_Acceptor *[pfs->size ()],
00311                     -1);
00312 
00313   TAO_ProtocolFactorySetItor end = pfs->end ();
00314 
00315   // Flag that indicates at least one endpoint was opened.  If one
00316   // wasn't opened then there is a problem.
00317   int opened_endpoint = 0;
00318 
00319   // Loop through all the loaded protocols...
00320   for (TAO_ProtocolFactorySetItor i = pfs->begin ();
00321        i != end;
00322        ++i)
00323     {
00324       // If the protocol requires an explicit -ORBEndpoint option then
00325       // don't use it, otherwise open a default endpoint for that
00326       // protocol, this solves the problem with persistent endpoints
00327       // (such as UNIX domain rendesvouz points) that are not cleaned
00328       // up if the server crashes.
00329       if (!(*i)->factory ()->requires_explicit_endpoint ())
00330         {
00331           if (this->open_default (orb_core,
00332                                   reactor,
00333                                   TAO_DEF_GIOP_MAJOR,  // default major
00334                                   TAO_DEF_GIOP_MINOR,  // default minor
00335                                   i,
00336                                   options) != 0)
00337             return -1;
00338 
00339           opened_endpoint = 1;
00340         }
00341     }
00342 
00343   if (!opened_endpoint)
00344     {
00345       if (TAO_debug_level > 0)
00346         {
00347           ACE_ERROR ((LM_ERROR,
00348                       ACE_LIB_TEXT ("TAO (%P|%t) No default endpoints ")
00349                       ACE_LIB_TEXT ("opened.\n")
00350                       ACE_LIB_TEXT ("Please specify one or more using ")
00351                       ACE_LIB_TEXT ("the \"-ORBListenEndpoints\" ")
00352                       ACE_LIB_TEXT ("option.\n")));
00353         }
00354 
00355       return -1;
00356     }
00357 
00358   return 0;
00359 }
00360 
00361 // Used when no endpoints were specified.  Open a default server for
00362 // the indicated protocol.
00363 int
00364 TAO_Acceptor_Registry::open_default (TAO_ORB_Core *orb_core,
00365                                      ACE_Reactor *reactor,
00366                                      int major,
00367                                      int minor,
00368                                      TAO_ProtocolFactorySetItor &factory,
00369                                      const char *options)
00370 {
00371   // No endpoints were specified, we let each protocol pick its own
00372   // default endpoint.
00373 
00374   // Make an acceptor
00375   TAO_Acceptor *acceptor =
00376     (*factory)->factory ()->make_acceptor ();
00377 
00378   if (acceptor == 0)
00379     {
00380       if (TAO_debug_level > 0)
00381         ACE_ERROR ((LM_ERROR,
00382                     ACE_LIB_TEXT ("TAO (%P|%t) unable to create ")
00383                     ACE_LIB_TEXT ("an acceptor for <%s>\n"),
00384                     ACE_TEXT_CHAR_TO_TCHAR ((*factory)->protocol_name ().c_str ())));
00385 
00386       return -1;
00387     }
00388 
00389   // Initialize the acceptor to listen on a default endpoint.
00390   if (acceptor->open_default (orb_core,
00391                               reactor,
00392                               major,
00393                               minor,
00394                               options) == -1)
00395     {
00396       delete acceptor;
00397 
00398       if (TAO_debug_level > 0)
00399         ACE_ERROR ((LM_ERROR,
00400                     ACE_LIB_TEXT ("TAO (%P|%t) unable to open ")
00401                     ACE_LIB_TEXT ("default acceptor for <%s>%p\n"),
00402                     ACE_TEXT_CHAR_TO_TCHAR ((*factory)->protocol_name ().c_str ()),
00403                     ACE_LIB_TEXT ("")));
00404 
00405       return -1;
00406     }
00407 
00408   this->acceptors_[this->size_++] = acceptor;
00409 
00410   return 0;
00411 }
00412 
00413 int
00414 TAO_Acceptor_Registry::close_all (void)
00415 {
00416   TAO_AcceptorSetIterator end = this->end ();
00417 
00418   for (TAO_AcceptorSetIterator i = this->begin ();
00419        i != end;
00420        ++i)
00421     {
00422       if (*i == 0)
00423         continue;
00424 
00425       (*i)->close ();
00426 
00427       delete *i;
00428     }
00429 
00430   this->size_ = 0;
00431 
00432   return 0;
00433 }
00434 
00435 void
00436 TAO_Acceptor_Registry::extract_endpoint_options (ACE_CString &addrs,
00437                                                  ACE_CString &options,
00438                                                  TAO_Protocol_Factory *factory)
00439 {
00440   int options_index =
00441     addrs.find (factory->options_delimiter ());
00442 
00443   if (options_index == ACE_static_cast (int,
00444                                         addrs.length () - 1))
00445     {
00446       // Get rid of trailing option delimiter.
00447       addrs = addrs.substring (0, addrs.length () - 1);
00448     }
00449   else if (options_index != ACE_CString::npos)
00450     {
00451       options = addrs.substring (options_index + 1);
00452 
00453       addrs = addrs.substring (0, options_index);
00454     }
00455 }
00456 
00457 void
00458 TAO_Acceptor_Registry::extract_endpoint_version (ACE_CString &address,
00459                                                  int &major,
00460                                                  int &minor)
00461 {
00462   // Check if an "N.n@" version prefix was
00463   // specified.
00464   major = TAO_DEF_GIOP_MAJOR;
00465   minor = TAO_DEF_GIOP_MINOR;
00466   if (isdigit (address[0])
00467       && address[1] == '.'
00468       && isdigit (address[2])
00469       && address[3] == '@')
00470     {
00471       major = address[0] - '0';
00472       minor = address[2] - '0';
00473       address = address.substring (4);
00474     }
00475 }
00476 
00477 int
00478 TAO_Acceptor_Registry::open_i (TAO_ORB_Core *orb_core,
00479                                ACE_Reactor *reactor,
00480                                ACE_CString &addrs,
00481                                TAO_ProtocolFactorySetItor &factory,
00482                                int ignore_address
00483                                 ACE_ENV_ARG_DECL)
00484 {
00485   ACE_CString options_tmp;
00486   this->extract_endpoint_options (addrs,
00487                                   options_tmp,
00488                                   (*factory)->factory ());
00489 
00490   const char *options = 0;
00491   if (options_tmp.length () > 0)
00492     options = options_tmp.c_str ();
00493 
00494   char *last_addr = 0;
00495   ACE_Auto_Basic_Array_Ptr <char> addr_str (addrs.rep ());
00496 
00497   const char *astr = ACE_OS::strtok_r (addr_str.get (),
00498                                        ",",
00499                                        &last_addr);
00500 
00501   // Iterate over the addrs specified in the endpoint.
00502 
00503   do
00504     {
00505       // For the first time only through the loop, it is
00506       // possible for astr to be 0.  This indicates that
00507       // the user is requesting the default endpoint for
00508       // the specified protocol.
00509       ACE_CString address (astr == 0 ? "" : astr);
00510 
00511       TAO_Acceptor *acceptor =
00512         (*factory)->factory ()->make_acceptor ();
00513       if (acceptor != 0)
00514         {
00515           // Extract the desired endpoint/protocol version if one
00516           // exists.
00517           int major = TAO_DEF_GIOP_MAJOR;
00518           int minor = TAO_DEF_GIOP_MINOR;
00519           this->extract_endpoint_version (address,
00520                                           major,
00521                                           minor);
00522 
00523           // Check for existence of endpoint.
00524           if (address.length () == 0 ||
00525               ignore_address)
00526             {
00527               // Protocol prefix was specified without any endpoints.
00528               // All TAO pluggable protocols are expected to have the
00529               // ability to create a default endpoint.
00530               if (this->open_default (orb_core,
00531                                       reactor,
00532                                       major,
00533                                       minor,
00534                                       factory,
00535                                       options) == 0)
00536                 continue;
00537 
00538               // Could not open a default endpoint, nor an explicit
00539               // one.
00540               else
00541                 ACE_THROW_RETURN (CORBA::INTERNAL (
00542                     CORBA::SystemException::_tao_minor_code (
00543                       TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE,
00544                       0),
00545                     CORBA::COMPLETED_NO),
00546                   -1);
00547             }
00548 
00549           // An explicit endpoint was provided.
00550           else if (acceptor->open (orb_core,
00551                                    reactor,
00552                                    major,
00553                                    minor,
00554                                    address.c_str (),
00555                                    options) == -1)
00556             {
00557               /* Need to save the errno value from the acceptor->open(),
00558                * because errno will get reset when we delete acceptor */ 
00559               int errno_value = errno;
00560               delete acceptor;
00561 
00562               if (TAO_debug_level > 0)
00563                 ACE_ERROR ((LM_ERROR,
00564                             ACE_LIB_TEXT ("TAO (%P|%t) ")
00565                             ACE_LIB_TEXT ("unable to open acceptor ")
00566                             ACE_LIB_TEXT ("for <%s>%p\n"),
00567                             ACE_TEXT_CHAR_TO_TCHAR (address.c_str ()),
00568                             ACE_LIB_TEXT ("")));
00569 
00570               ACE_THROW_RETURN (CORBA::BAD_PARAM (
00571                   CORBA::SystemException::_tao_minor_code (
00572                     TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE,
00573                     errno_value),
00574                   CORBA::COMPLETED_NO),
00575                 -1);
00576             }
00577 
00578           // add acceptor to list
00579           this->acceptors_[this->size_++] = acceptor;
00580         }
00581       else
00582         {
00583           if (TAO_debug_level > 0)
00584             ACE_ERROR ((LM_ERROR,
00585                         ACE_LIB_TEXT ("TAO (%P|%t) unable to create ")
00586                         ACE_LIB_TEXT ("an acceptor for <%s>.\n"),
00587                         ACE_TEXT_CHAR_TO_TCHAR (address.c_str ())));
00588 
00589           ACE_THROW_RETURN (CORBA::NO_MEMORY (
00590               CORBA::SystemException::_tao_minor_code (
00591                 TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE,
00592                 ENOMEM),
00593               CORBA::COMPLETED_NO),
00594             -1);
00595         }
00596     }
00597   while ((astr != 0) &&
00598          ((astr = ACE_OS::strtok_r (0,
00599                                     ",",
00600                                     &last_addr)) != 0));
00601 
00602   return 0;
00603 }

Generated on Mon Jun 16 13:47:57 2003 for TAO by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002