SHMIOP_Profile.cpp

Go to the documentation of this file.
00001 #include "tao/Strategies/SHMIOP_Profile.h"
00002 
00003 #if defined (TAO_HAS_SHMIOP) && (TAO_HAS_SHMIOP != 0)
00004 
00005 #include "tao/CDR.h"
00006 #include "tao/Environment.h"
00007 #include "tao/ORB.h"
00008 #include "tao/ORB_Core.h"
00009 #include "tao/debug.h"
00010 #include "tao/IIOP_EndpointsC.h"
00011 
00012 #include "ace/OS_NS_stdio.h"
00013 #include "ace/OS_NS_string.h"
00014 
00015 ACE_RCSID (Strategies,
00016            SHMIOP_Profile,
00017            "SHMIOP_Profile.cpp,v 1.34 2006/03/10 07:19:19 jtc Exp")
00018 
00019 #include "ace/os_include/os_netdb.h"
00020 
00021 static const char prefix_[] = "shmiop";
00022 
00023 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00024 
00025 const char TAO_SHMIOP_Profile::object_key_delimiter_ = '/';
00026 
00027 char
00028 TAO_SHMIOP_Profile::object_key_delimiter (void) const
00029 {
00030   return TAO_SHMIOP_Profile::object_key_delimiter_;
00031 }
00032 
00033 TAO_SHMIOP_Profile::TAO_SHMIOP_Profile (const ACE_MEM_Addr &addr,
00034                                         const TAO::ObjectKey &object_key,
00035                                         const TAO_GIOP_Message_Version &version,
00036                                         TAO_ORB_Core *orb_core)
00037   : TAO_Profile (TAO_TAG_SHMEM_PROFILE,
00038                  orb_core,
00039                  object_key,
00040                  version),
00041     endpoint_ (addr,
00042                orb_core->orb_params ()->use_dotted_decimal_addresses ()),
00043     count_ (1)
00044 {
00045 }
00046 
00047 TAO_SHMIOP_Profile::TAO_SHMIOP_Profile (const char* host,
00048                                         CORBA::UShort port,
00049                                         const TAO::ObjectKey &object_key,
00050                                         const ACE_INET_Addr &addr,
00051                                         const TAO_GIOP_Message_Version &version,
00052                                         TAO_ORB_Core *orb_core)
00053   : TAO_Profile (TAO_TAG_SHMEM_PROFILE,
00054                  orb_core,
00055                  object_key,
00056                  version),
00057     endpoint_ (host, port, addr),
00058     count_ (1)
00059 {
00060 }
00061 
00062 TAO_SHMIOP_Profile::TAO_SHMIOP_Profile (TAO_ORB_Core *orb_core)
00063   : TAO_Profile (TAO_TAG_SHMEM_PROFILE,
00064                  orb_core,
00065                  TAO_GIOP_Message_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)),
00066     endpoint_ (),
00067     count_ (1)
00068 {
00069 }
00070 
00071 TAO_SHMIOP_Profile::~TAO_SHMIOP_Profile (void)
00072 {
00073   // Clean up the list of endpoints since we own it.
00074   // Skip the head, since it is not dynamically allocated.
00075   TAO_Endpoint *tmp = 0;
00076 
00077   for (TAO_Endpoint *next = this->endpoint ()->next ();
00078        next != 0;
00079        next = tmp)
00080     {
00081       tmp = next->next ();
00082       delete next;
00083     }
00084 }
00085 
00086 TAO_Endpoint*
00087 TAO_SHMIOP_Profile::endpoint (void)
00088 {
00089   return &this->endpoint_;
00090 }
00091 
00092 CORBA::ULong
00093 TAO_SHMIOP_Profile::endpoint_count (void) const
00094 {
00095   return this->count_;
00096 }
00097 
00098 // return codes:
00099 // -1 -> error
00100 //  0 -> can't understand this version
00101 //  1 -> success.
00102 int
00103 TAO_SHMIOP_Profile::decode_profile (TAO_InputCDR& cdr)
00104 {
00105   // Decode host and port into the <endpoint_>.
00106   if (cdr.read_string (this->endpoint_.host_.out ()) == 0
00107       || cdr.read_ushort (this->endpoint_.port_) == 0)
00108     {
00109       if (TAO_debug_level > 0)
00110         {
00111           ACE_DEBUG ((LM_DEBUG,
00112                       ACE_TEXT ("TAO (%P|%t) SHMIOP_Profile::decode - ")
00113                       ACE_TEXT ("error while decoding host/port")));
00114         }
00115       return -1;
00116     }
00117 
00118   if (cdr.good_bit ())
00119     {
00120       // Invalidate the object_addr_ until first access.
00121       this->endpoint_.object_addr_.set_type (-1);
00122 
00123       return 1;
00124     }
00125 
00126   return -1;
00127 }
00128 
00129 void
00130 TAO_SHMIOP_Profile::parse_string_i (const char *string
00131                                     ACE_ENV_ARG_DECL)
00132 {
00133   // Pull off the "hostname:port/" part of the objref
00134   // Copy the string because we are going to modify it...
00135   CORBA::String_var copy (string);
00136 
00137   char *start = copy.inout ();
00138   char *cp = ACE_OS::strchr (start, ':');  // Look for a port
00139 
00140   if (cp == 0)
00141     {
00142       // No host/port delimiter!
00143       ACE_THROW (CORBA::INV_OBJREF (
00144                    CORBA::SystemException::_tao_minor_code (
00145                      TAO::VMCID,
00146                      EINVAL),
00147                    CORBA::COMPLETED_NO));
00148     }
00149 
00150   char *okd = ACE_OS::strchr (start, this->object_key_delimiter_);
00151 
00152   if (okd == 0)
00153     {
00154       // No object key delimiter!
00155       ACE_THROW (CORBA::INV_OBJREF (
00156                    CORBA::SystemException::_tao_minor_code (
00157                      TAO::VMCID,
00158                      EINVAL),
00159                    CORBA::COMPLETED_NO));
00160     }
00161 
00162   // Don't increment the pointer 'cp' directly since we still need
00163   // to use it immediately after this block.
00164 
00165   CORBA::ULong length = okd - (cp + 1);
00166   // Don't allocate space for the colon ':'.
00167 
00168   CORBA::String_var tmp = CORBA::string_alloc (length);
00169 
00170   ACE_OS::strncpy (tmp.inout (), cp + 1, length);
00171   tmp[length] = '\0';
00172 
00173   if (ACE_OS::strspn (tmp.in (), "1234567890") == length)
00174     {
00175       this->endpoint_.port_ =
00176         static_cast <CORBA::UShort> (ACE_OS::atoi (tmp.in ()));
00177     }
00178   else
00179     {
00180       ACE_INET_Addr ia;
00181       if (ia.string_to_addr (tmp.in ()) == -1)
00182         {
00183           ACE_THROW (CORBA::INV_OBJREF (
00184               CORBA::SystemException::_tao_minor_code (
00185                   TAO::VMCID,
00186                   EINVAL),
00187               CORBA::COMPLETED_NO));
00188         }
00189       else
00190         {
00191           this->endpoint_.port_ = ia.get_port_number ();
00192         }
00193     }
00194 
00195   length = cp - start;
00196 
00197   tmp = CORBA::string_alloc (length);
00198 
00199   ACE_OS::strncpy (tmp.inout (), start, length);
00200   tmp[length] = '\0';
00201 
00202   this->endpoint_.host_ = tmp._retn ();
00203 
00204   ACE_INET_Addr host_addr;
00205 
00206   if (ACE_OS::strcmp (this->endpoint_.host_.in (), "") == 0)
00207     {
00208       char tmp_host [MAXHOSTNAMELEN + 1];
00209 
00210       // If no host is specified: assign the default host : the local host.
00211       if (host_addr.get_host_name (tmp_host,
00212                                    sizeof (tmp_host)) != 0)
00213       {
00214         const char *tmp = host_addr.get_host_addr ();
00215         if (tmp == 0)
00216           {
00217             if (TAO_debug_level > 0)
00218               ACE_DEBUG ((LM_DEBUG,
00219                           ACE_TEXT ("\n\nTAO (%P|%t) ")
00220                           ACE_TEXT ("SHMIOP_Profile::parse_string ")
00221                           ACE_TEXT ("- %p\n\n"),
00222                           ACE_TEXT ("cannot determine hostname")));
00223 
00224             // @@ What's the right exception to throw here?
00225             ACE_THROW (CORBA::INV_OBJREF (
00226                          CORBA::SystemException::_tao_minor_code (
00227                            TAO::VMCID,
00228                            EINVAL),
00229                          CORBA::COMPLETED_NO));
00230           }
00231         else
00232           this->endpoint_.host_ = tmp;
00233       }
00234       else
00235         {
00236           this->endpoint_.host_ = (const char *) tmp_host;
00237         }
00238     }
00239 
00240   if (this->endpoint_.object_addr_.set (this->endpoint_.port_,
00241                                         this->endpoint_.host_.in ()) == -1)
00242     {
00243       if (TAO_debug_level > 0)
00244         {
00245           ACE_DEBUG ((LM_DEBUG,
00246                       ACE_TEXT ("TAO (%P|%t) SHMIOP_Profile::parse_string () - \n")
00247                       ACE_TEXT ("TAO (%P|%t) ACE_INET_Addr::set () failed")));
00248         }
00249 
00250       // @@ What's the right exception to throw here?
00251       ACE_THROW (CORBA::INV_OBJREF (
00252                    CORBA::SystemException::_tao_minor_code (
00253                      TAO::VMCID,
00254                      EINVAL),
00255                    CORBA::COMPLETED_NO));
00256     }
00257 
00258   start = ++okd;  // increment past the object key separator
00259 
00260   TAO::ObjectKey ok;
00261   TAO::ObjectKey::decode_string_to_sequence (ok,
00262                                              okd + 1);
00263 
00264   (void) this->orb_core ()->object_key_table ().bind (ok,
00265                                                       this->ref_object_key_);
00266 }
00267 
00268 CORBA::Boolean
00269 TAO_SHMIOP_Profile::do_is_equivalent (const TAO_Profile *other_profile)
00270 {
00271   const TAO_SHMIOP_Profile *op =
00272     dynamic_cast <const TAO_SHMIOP_Profile *> (other_profile);
00273 
00274   if (op == 0)
00275     return 0;
00276 
00277   // Check endpoints equivalence.
00278   const TAO_SHMIOP_Endpoint *other_endp = &op->endpoint_;
00279   for (TAO_SHMIOP_Endpoint *endp = &this->endpoint_;
00280        endp != 0;
00281        endp = endp->next_)
00282     {
00283       if (endp->is_equivalent (other_endp))
00284         other_endp = other_endp->next_;
00285       else
00286         return 0;
00287     }
00288 
00289   return 1;
00290 }
00291 
00292 CORBA::ULong
00293 TAO_SHMIOP_Profile::hash (CORBA::ULong max
00294                           ACE_ENV_ARG_DECL_NOT_USED)
00295 {
00296   // Get the hashvalue for all endpoints.
00297   CORBA::ULong hashval = 0;
00298   for (TAO_SHMIOP_Endpoint *endp = &this->endpoint_;
00299        endp != 0;
00300        endp = endp->next_)
00301     {
00302       hashval += endp->hash ();
00303     }
00304 
00305   hashval += this->version_.minor;
00306   hashval += this->tag ();
00307 
00308   const TAO::ObjectKey &ok =
00309     this->ref_object_key_->object_key ();
00310 
00311   if (ok.length () >= 4)
00312     {
00313       hashval += ok[1];
00314       hashval += ok[3];
00315     }
00316 
00317   hashval += this->hash_service_i (max);
00318 
00319   return hashval % max;
00320 }
00321 
00322 void
00323 TAO_SHMIOP_Profile::add_endpoint (TAO_SHMIOP_Endpoint *endp)
00324 {
00325   endp->next_ = this->endpoint_.next_;
00326   this->endpoint_.next_ = endp;
00327 
00328   this->count_++;
00329 }
00330 
00331 char *
00332 TAO_SHMIOP_Profile::to_string (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
00333 {
00334   CORBA::String_var key;
00335   TAO::ObjectKey::encode_sequence_to_string (key.inout(),
00336                                              this->ref_object_key_->object_key ());
00337 
00338   size_t buflen = (8 /* corbaloc */ +
00339                    1 /* colon separator */ +
00340                    ACE_OS::strlen (::prefix_) +
00341                    1 /* colon separator */ +
00342                    1 /* major version */ +
00343                    1 /* decimal point */ +
00344                    1 /* minor version */ +
00345                    1 /* `@' character */ +
00346                    ACE_OS::strlen (this->endpoint_.host ()) +
00347                    1 /* colon separator */ +
00348                    5 /* port number */ +
00349                    1 /* object key separator */ +
00350                    ACE_OS::strlen (key.in ()));
00351 
00352   char * buf = CORBA::string_alloc (static_cast <CORBA::ULong> (buflen));
00353 
00354   static const char digits [] = "0123456789";
00355 
00356   ACE_OS::sprintf (buf,
00357                    "corbaloc:%s:%c.%c@%s:%d%c%s",
00358                    ::prefix_,
00359                    digits [this->version_.major],
00360                    digits [this->version_.minor],
00361                    this->endpoint_.host (),
00362                    this->endpoint_.port (),
00363                    this->object_key_delimiter_,
00364                    key.in ());
00365   return buf;
00366 }
00367 
00368 const char *
00369 TAO_SHMIOP_Profile::prefix (void)
00370 {
00371   return ::prefix_;
00372 }
00373 
00374 void
00375 TAO_SHMIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const
00376 {
00377   encap.write_octet (TAO_ENCAP_BYTE_ORDER);
00378 
00379   // The GIOP version
00380   encap.write_octet (this->version_.major);
00381   encap.write_octet (this->version_.minor);
00382 
00383   // STRING hostname from profile
00384   encap.write_string (this->endpoint_.host ());
00385 
00386   // UNSIGNED SHORT port number
00387   encap.write_ushort (this->endpoint_.port ());
00388 
00389   // OCTET SEQUENCE for object key
00390   if (this->ref_object_key_)
00391     encap << this->ref_object_key_->object_key ();
00392   else
00393     {
00394       ACE_ERROR ((LM_ERROR,
00395                   "(%P|%t) TAO - UIOP_Profile::create_profile_body "
00396                   "no object key marshalled \n"));
00397     }
00398 
00399   if (this->version_.major > 1
00400       || this->version_.minor > 0)
00401     this->tagged_components ().encode (encap);
00402 }
00403 
00404 int
00405 TAO_SHMIOP_Profile::encode_endpoints (void)
00406 {
00407   // Create a data structure and fill it with endpoint info for wire
00408   // transfer.
00409   // We include information for the head of the list
00410   // together with other endpoints because even though its addressing
00411   // info is transmitted using standard ProfileBody components, its
00412   // priority is not!
00413   TAO::IIOPEndpointSequence endpoints;
00414   endpoints.length (this->count_);
00415 
00416   TAO_SHMIOP_Endpoint *endpoint = &this->endpoint_;
00417   for (CORBA::ULong i = 0;
00418        i < this->count_;
00419        ++i)
00420     {
00421       endpoints[i].host = endpoint->host ();
00422       endpoints[i].port = endpoint->port ();
00423       endpoints[i].priority = endpoint->priority ();
00424 
00425       endpoint = endpoint->next_;
00426     }
00427 
00428   // Encode the data structure.
00429   TAO_OutputCDR out_cdr;
00430   if ((out_cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER)
00431        == 0)
00432       || (out_cdr << endpoints) == 0)
00433     return -1;
00434   size_t length = out_cdr.total_length ();
00435 
00436   IOP::TaggedComponent tagged_component;
00437   tagged_component.tag = TAO_TAG_ENDPOINTS;
00438   tagged_component.component_data.length (static_cast <CORBA::ULong>(length));
00439   CORBA::Octet *buf =
00440     tagged_component.component_data.get_buffer ();
00441 
00442   for (const ACE_Message_Block *iterator = out_cdr.begin ();
00443        iterator != 0;
00444        iterator = iterator->cont ())
00445     {
00446       size_t i_length = iterator->length ();
00447       ACE_OS::memcpy (buf, iterator->rd_ptr (), i_length);
00448 
00449       buf += i_length;
00450     }
00451 
00452   // Add component with encoded endpoint data to this profile's
00453   // TaggedComponents.
00454   tagged_components_.set_component (tagged_component);
00455 
00456   return 0;
00457 }
00458 
00459 int
00460 TAO_SHMIOP_Profile::decode_endpoints (void)
00461 {
00462   IOP::TaggedComponent tagged_component;
00463   tagged_component.tag = TAO_TAG_ENDPOINTS;
00464 
00465   if (this->tagged_components_.get_component (tagged_component))
00466     {
00467       const CORBA::Octet *buf =
00468         tagged_component.component_data.get_buffer ();
00469 
00470       TAO_InputCDR in_cdr (reinterpret_cast <const char*> (buf),
00471                            tagged_component.component_data.length ());
00472 
00473       // Extract the Byte Order.
00474       CORBA::Boolean byte_order;
00475       if ((in_cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
00476         return -1;
00477       in_cdr.reset_byte_order (static_cast<int> (byte_order));
00478 
00479       // Extract endpoints sequence.
00480       TAO::IIOPEndpointSequence endpoints;
00481 
00482       if ((in_cdr >> endpoints) == 0)
00483         return -1;
00484 
00485       // Get the priority of the first endpoint (head of the list.
00486       // It's other data is extracted as part of the standard profile
00487       // decoding.
00488       this->endpoint_.priority (endpoints[0].priority);
00489 
00490       // Use information extracted from the tagged component to
00491       // populate the profile.  Skip the first endpoint, since it is
00492       // always extracted through standard profile body.  Also, begin
00493       // from the end of the sequence to preserve endpoint order,
00494       // since <add_endpoint> method reverses the order of endpoints
00495       // in the list.
00496       for (CORBA::ULong i = endpoints.length () - 1;
00497            i > 0;
00498            --i)
00499         {
00500           TAO_SHMIOP_Endpoint *endpoint = 0;
00501           ACE_NEW_RETURN (endpoint,
00502                           TAO_SHMIOP_Endpoint (endpoints[i].host,
00503                                                endpoints[i].port,
00504                                                endpoints[i].priority),
00505                           -1);
00506 
00507           this->add_endpoint (endpoint);
00508         }
00509     }
00510 
00511   return 0;
00512 }
00513 
00514 TAO_END_VERSIONED_NAMESPACE_DECL
00515 
00516 #endif /* TAO_HAS_SHMIOP && TAO_HAS_SHMIOP != 0 */

Generated on Thu Nov 9 13:39:30 2006 for TAO_Strategies by doxygen 1.3.6