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/SystemException.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            "$Id: SHMIOP_Profile.cpp 80558 2008-02-04 12:46:28Z smcqueen $")
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                                     )
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       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       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           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             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       throw ::CORBA::INV_OBJREF (
00252                    CORBA::SystemException::_tao_minor_code (
00253                      TAO::VMCID,
00254                      EINVAL),
00255                    CORBA::COMPLETED_NO);
00256     }
00257 
00258   TAO::ObjectKey ok;
00259   TAO::ObjectKey::decode_string_to_sequence (ok,
00260                                              okd + 1);  // increment past the object key separator
00261 
00262   (void) this->orb_core ()->object_key_table ().bind (ok,
00263                                                       this->ref_object_key_);
00264 }
00265 
00266 CORBA::Boolean
00267 TAO_SHMIOP_Profile::do_is_equivalent (const TAO_Profile *other_profile)
00268 {
00269   const TAO_SHMIOP_Profile *op =
00270     dynamic_cast <const TAO_SHMIOP_Profile *> (other_profile);
00271 
00272   if (op == 0)
00273     return 0;
00274 
00275   // Check endpoints equivalence.
00276   const TAO_SHMIOP_Endpoint *other_endp = &op->endpoint_;
00277   for (TAO_SHMIOP_Endpoint *endp = &this->endpoint_;
00278        endp != 0;
00279        endp = endp->next_)
00280     {
00281       if (endp->is_equivalent (other_endp))
00282         other_endp = other_endp->next_;
00283       else
00284         return 0;
00285     }
00286 
00287   return 1;
00288 }
00289 
00290 CORBA::ULong
00291 TAO_SHMIOP_Profile::hash (CORBA::ULong max
00292                           )
00293 {
00294   // Get the hashvalue for all endpoints.
00295   CORBA::ULong hashval = 0;
00296   for (TAO_SHMIOP_Endpoint *endp = &this->endpoint_;
00297        endp != 0;
00298        endp = endp->next_)
00299     {
00300       hashval += endp->hash ();
00301     }
00302 
00303   hashval += this->version_.minor;
00304   hashval += this->tag ();
00305 
00306   const TAO::ObjectKey &ok =
00307     this->ref_object_key_->object_key ();
00308 
00309   if (ok.length () >= 4)
00310     {
00311       hashval += ok[1];
00312       hashval += ok[3];
00313     }
00314 
00315   hashval += this->hash_service_i (max);
00316 
00317   return hashval % max;
00318 }
00319 
00320 void
00321 TAO_SHMIOP_Profile::add_endpoint (TAO_SHMIOP_Endpoint *endp)
00322 {
00323   endp->next_ = this->endpoint_.next_;
00324   this->endpoint_.next_ = endp;
00325 
00326   this->count_++;
00327 }
00328 
00329 char *
00330 TAO_SHMIOP_Profile::to_string (void)
00331 {
00332   CORBA::String_var key;
00333   TAO::ObjectKey::encode_sequence_to_string (key.inout(),
00334                                              this->ref_object_key_->object_key ());
00335 
00336   size_t buflen = (8 /* corbaloc */ +
00337                    1 /* colon separator */ +
00338                    ACE_OS::strlen (::prefix_) +
00339                    1 /* colon separator */ +
00340                    1 /* major version */ +
00341                    1 /* decimal point */ +
00342                    1 /* minor version */ +
00343                    1 /* `@' character */ +
00344                    ACE_OS::strlen (this->endpoint_.host ()) +
00345                    1 /* colon separator */ +
00346                    5 /* port number */ +
00347                    1 /* object key separator */ +
00348                    ACE_OS::strlen (key.in ()));
00349 
00350   char * buf = CORBA::string_alloc (static_cast <CORBA::ULong> (buflen));
00351 
00352   static const char digits [] = "0123456789";
00353 
00354   ACE_OS::sprintf (buf,
00355                    "corbaloc:%s:%c.%c@%s:%d%c%s",
00356                    ::prefix_,
00357                    digits [this->version_.major],
00358                    digits [this->version_.minor],
00359                    this->endpoint_.host (),
00360                    this->endpoint_.port (),
00361                    this->object_key_delimiter_,
00362                    key.in ());
00363   return buf;
00364 }
00365 
00366 const char *
00367 TAO_SHMIOP_Profile::prefix (void)
00368 {
00369   return ::prefix_;
00370 }
00371 
00372 void
00373 TAO_SHMIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const
00374 {
00375   encap.write_octet (TAO_ENCAP_BYTE_ORDER);
00376 
00377   // The GIOP version
00378   encap.write_octet (this->version_.major);
00379   encap.write_octet (this->version_.minor);
00380 
00381   // STRING hostname from profile
00382   encap.write_string (this->endpoint_.host ());
00383 
00384   // UNSIGNED SHORT port number
00385   encap.write_ushort (this->endpoint_.port ());
00386 
00387   // OCTET SEQUENCE for object key
00388   if (this->ref_object_key_)
00389     encap << this->ref_object_key_->object_key ();
00390   else
00391     {
00392       ACE_ERROR ((LM_ERROR,
00393                   "(%P|%t) TAO - UIOP_Profile::create_profile_body "
00394                   "no object key marshalled \n"));
00395     }
00396 
00397   if (this->version_.major > 1
00398       || this->version_.minor > 0)
00399     this->tagged_components ().encode (encap);
00400 }
00401 
00402 int
00403 TAO_SHMIOP_Profile::encode_endpoints (void)
00404 {
00405   // Create a data structure and fill it with endpoint info for wire
00406   // transfer.
00407   // We include information for the head of the list
00408   // together with other endpoints because even though its addressing
00409   // info is transmitted using standard ProfileBody components, its
00410   // priority is not!
00411   TAO::IIOPEndpointSequence endpoints;
00412   endpoints.length (this->count_);
00413 
00414   TAO_SHMIOP_Endpoint *endpoint = &this->endpoint_;
00415   for (CORBA::ULong i = 0;
00416        i < this->count_;
00417        ++i)
00418     {
00419       endpoints[i].host = endpoint->host ();
00420       endpoints[i].port = endpoint->port ();
00421       endpoints[i].priority = endpoint->priority ();
00422 
00423       endpoint = endpoint->next_;
00424     }
00425 
00426   // Encode the data structure.
00427   TAO_OutputCDR out_cdr;
00428   if ((out_cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER)
00429        == 0)
00430       || (out_cdr << endpoints) == 0)
00431     return -1;
00432   size_t length = out_cdr.total_length ();
00433 
00434   IOP::TaggedComponent tagged_component;
00435   tagged_component.tag = TAO_TAG_ENDPOINTS;
00436   tagged_component.component_data.length (static_cast <CORBA::ULong>(length));
00437   CORBA::Octet *buf =
00438     tagged_component.component_data.get_buffer ();
00439 
00440   for (const ACE_Message_Block *iterator = out_cdr.begin ();
00441        iterator != 0;
00442        iterator = iterator->cont ())
00443     {
00444       size_t i_length = iterator->length ();
00445       ACE_OS::memcpy (buf, iterator->rd_ptr (), i_length);
00446 
00447       buf += i_length;
00448     }
00449 
00450   // Add component with encoded endpoint data to this profile's
00451   // TaggedComponents.
00452   tagged_components_.set_component (tagged_component);
00453 
00454   return 0;
00455 }
00456 
00457 int
00458 TAO_SHMIOP_Profile::decode_endpoints (void)
00459 {
00460   IOP::TaggedComponent tagged_component;
00461   tagged_component.tag = TAO_TAG_ENDPOINTS;
00462 
00463   if (this->tagged_components_.get_component (tagged_component))
00464     {
00465       const CORBA::Octet *buf =
00466         tagged_component.component_data.get_buffer ();
00467 
00468       TAO_InputCDR in_cdr (reinterpret_cast <const char*> (buf),
00469                            tagged_component.component_data.length ());
00470 
00471       // Extract the Byte Order.
00472       CORBA::Boolean byte_order;
00473       if ((in_cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
00474         return -1;
00475       in_cdr.reset_byte_order (static_cast<int> (byte_order));
00476 
00477       // Extract endpoints sequence.
00478       TAO::IIOPEndpointSequence endpoints;
00479 
00480       if ((in_cdr >> endpoints) == 0)
00481         return -1;
00482 
00483       // Get the priority of the first endpoint (head of the list.
00484       // It's other data is extracted as part of the standard profile
00485       // decoding.
00486       this->endpoint_.priority (endpoints[0].priority);
00487 
00488       // Use information extracted from the tagged component to
00489       // populate the profile.  Skip the first endpoint, since it is
00490       // always extracted through standard profile body.  Also, begin
00491       // from the end of the sequence to preserve endpoint order,
00492       // since <add_endpoint> method reverses the order of endpoints
00493       // in the list.
00494       for (CORBA::ULong i = endpoints.length () - 1;
00495            i > 0;
00496            --i)
00497         {
00498           TAO_SHMIOP_Endpoint *endpoint = 0;
00499           ACE_NEW_RETURN (endpoint,
00500                           TAO_SHMIOP_Endpoint (endpoints[i].host,
00501                                                endpoints[i].port,
00502                                                endpoints[i].priority),
00503                           -1);
00504 
00505           this->add_endpoint (endpoint);
00506         }
00507     }
00508 
00509   return 0;
00510 }
00511 
00512 TAO_END_VERSIONED_NAMESPACE_DECL
00513 
00514 #endif /* TAO_HAS_SHMIOP && TAO_HAS_SHMIOP != 0 */

Generated on Tue Feb 2 17:47:18 2010 for TAO_Strategies by  doxygen 1.4.7