COIOP_Profile.cpp

Go to the documentation of this file.
00001 // $Id: COIOP_Profile.cpp 76995 2007-02-11 12:51:42Z johnnyw $
00002 
00003 #include "tao/Strategies/COIOP_Profile.h"
00004 
00005 #if defined (TAO_HAS_COIOP) && (TAO_HAS_COIOP != 0)
00006 
00007 #include "tao/CDR.h"
00008 #include "tao/SystemException.h"
00009 #include "tao/ORB.h"
00010 #include "tao/ORB_Core.h"
00011 #include "tao/debug.h"
00012 #include "tao/Strategies/COIOP_EndpointsC.h"
00013 
00014 #include "ace/OS_NS_stdio.h"
00015 #include "ace/OS_NS_string.h"
00016 
00017 ACE_RCSID (Strategies,
00018            COIOP_Profile,
00019            "$Id: COIOP_Profile.cpp 76995 2007-02-11 12:51:42Z johnnyw $")
00020 
00021 static const char the_prefix[] = "niop";
00022 
00023 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00024 
00025 const char TAO_COIOP_Profile::object_key_delimiter_ = '/';
00026 
00027 char
00028 TAO_COIOP_Profile::object_key_delimiter (void) const
00029 {
00030   return TAO_COIOP_Profile::object_key_delimiter_;
00031 }
00032 
00033 TAO_COIOP_Profile::TAO_COIOP_Profile (const ACE_Utils::UUID& uuid,
00034                                       const TAO::ObjectKey &object_key,
00035                                       const TAO_GIOP_Message_Version &version,
00036                                       TAO_ORB_Core *orb_core)
00037   : TAO_Profile (TAO_TAG_COIOP_PROFILE,
00038                  orb_core,
00039                  object_key,
00040                  version),
00041     endpoint_ (uuid),
00042     count_ (1)
00043 {
00044 }
00045 
00046 TAO_COIOP_Profile::TAO_COIOP_Profile (TAO_ORB_Core *orb_core)
00047   : TAO_Profile (TAO_TAG_COIOP_PROFILE,
00048                  orb_core,
00049                  TAO_GIOP_Message_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)),
00050     endpoint_ (),
00051     count_ (1)
00052 {
00053 }
00054 
00055 TAO_COIOP_Profile::~TAO_COIOP_Profile (void)
00056 {
00057   // Clean up the list of endpoints since we own it.
00058   // Skip the head, since it is not dynamically allocated.
00059   TAO_Endpoint *tmp = 0;
00060 
00061   for (TAO_Endpoint *next = this->endpoint ()->next ();
00062        next != 0;
00063        next = tmp)
00064     {
00065       tmp = next->next ();
00066       delete next;
00067     }
00068 }
00069 
00070 // return codes:
00071 // -1 -> error
00072 //  0 -> can't understand this version
00073 //  1 -> success.
00074 
00075 int
00076 TAO_COIOP_Profile::decode_profile (TAO_InputCDR& cdr)
00077 {
00078   // @@ NOTE: This code is repeated thrice. Need to factor out in a
00079   // better manner.
00080   // Decode uuid into the <endpoint_>.
00081   CORBA::String_var uuid;
00082   if (cdr.read_string (uuid.out ()) == 0)
00083     {
00084       if (TAO_debug_level > 0)
00085         ACE_DEBUG ((LM_DEBUG,
00086                     ACE_TEXT ("TAO (%P|%t) COIOP_Profile::decode - ")
00087                     ACE_TEXT ("error while uuid")));
00088       return -1;
00089     }
00090 
00091   if (cdr.good_bit ())
00092     {
00093       this->endpoint_.uuid_.from_string (uuid.in());
00094 
00095       return 1;
00096     }
00097 
00098   return -1;
00099 }
00100 
00101 void
00102 TAO_COIOP_Profile::parse_string_i (const char *ior)
00103 {
00104   // Pull off the "hostname:port/" part of the objref
00105   // Copy the string because we are going to modify it...
00106   const char *okd =
00107     ACE_OS::strchr (ior, this->object_key_delimiter_);
00108 
00109   if (okd == 0 || okd == ior)
00110     {
00111       // No object key delimiter or no hostname specified.
00112       throw ::CORBA::INV_OBJREF (
00113                    CORBA::SystemException::_tao_minor_code (
00114                      TAO::VMCID,
00115                      EINVAL),
00116                    CORBA::COMPLETED_NO);
00117     }
00118 
00119   // Length of host string.
00120   CORBA::ULong length_host = okd - ior;
00121 
00122   CORBA::String_var tmp = CORBA::string_alloc (length_host);
00123 
00124   // Skip the trailing '/'
00125   ACE_OS::strncpy (tmp.inout (), ior, length_host);
00126   tmp[length_host] = '\0';
00127 
00128   this->endpoint_.uuid_.from_string (tmp._retn ());
00129 
00130   TAO::ObjectKey ok;
00131   TAO::ObjectKey::decode_string_to_sequence (ok,
00132                                              okd + 1);
00133 
00134   (void) this->orb_core ()->object_key_table ().bind (ok,
00135                                                       this->ref_object_key_);
00136 }
00137 
00138 CORBA::Boolean
00139 TAO_COIOP_Profile::do_is_equivalent (const TAO_Profile *other_profile)
00140 {
00141   const TAO_COIOP_Profile *op =
00142     dynamic_cast<const TAO_COIOP_Profile *> (other_profile);
00143 
00144   // Check endpoints equivalence.
00145   const TAO_COIOP_Endpoint *other_endp = &op->endpoint_;
00146   for (TAO_COIOP_Endpoint *endp = &this->endpoint_;
00147        endp != 0;
00148        endp = endp->next_)
00149     {
00150       if (endp->is_equivalent (other_endp))
00151         other_endp = other_endp->next_;
00152       else
00153         return false;
00154     }
00155 
00156   return true;
00157 }
00158 
00159 CORBA::ULong
00160 TAO_COIOP_Profile::hash (CORBA::ULong max)
00161 {
00162   // Get the hashvalue for all endpoints.
00163   CORBA::ULong hashval = 0;
00164   for (TAO_COIOP_Endpoint *endp = &this->endpoint_;
00165        endp != 0;
00166        endp = endp->next_)
00167     {
00168       hashval += endp->hash ();
00169     }
00170 
00171   hashval += this->version_.minor;
00172   hashval += this->tag ();
00173 
00174   const TAO::ObjectKey &ok =
00175     this->ref_object_key_->object_key ();
00176 
00177   if (ok.length () >= 4)
00178     {
00179       hashval += ok[1];
00180       hashval += ok[3];
00181     }
00182 
00183   hashval += this->hash_service_i (max);
00184 
00185   return hashval % max;
00186 }
00187 
00188 TAO_Endpoint*
00189 TAO_COIOP_Profile::endpoint (void)
00190 {
00191   return &this->endpoint_;
00192 }
00193 
00194 CORBA::ULong
00195 TAO_COIOP_Profile::endpoint_count (void) const
00196 {
00197   return this->count_;
00198 }
00199 
00200 void
00201 TAO_COIOP_Profile::add_endpoint (TAO_COIOP_Endpoint *endp)
00202 {
00203   endp->next_ = this->endpoint_.next_;
00204   this->endpoint_.next_ = endp;
00205 
00206   this->count_++;
00207 }
00208 
00209 char *
00210 TAO_COIOP_Profile::to_string (void)
00211 {
00212   CORBA::String_var key;
00213   TAO::ObjectKey::encode_sequence_to_string (key.inout(),
00214                                             this->ref_object_key_->object_key ());
00215 
00216   const ACE_CString * uuidstr = this->endpoint_.uuid_.to_string ();
00217   size_t buflen = (8 /* "corbaloc" */ +
00218                    1 /* colon separator */ +
00219                    ACE_OS::strlen (::the_prefix) +
00220                    1 /* colon separator */ +
00221                    1 /* major version */ +
00222                    1 /* decimal point */ +
00223                    1 /* minor version */ +
00224                    1 /* `@' character */ +
00225                    uuidstr->length() +
00226                    1 /* colon separator */ +
00227                    5 /* port number */ +
00228                    1 /* object key separator */ +
00229                    ACE_OS::strlen (key.in ()));
00230 
00231   char * buf = CORBA::string_alloc (static_cast<CORBA::ULong> (buflen));
00232 
00233   static const char digits [] = "0123456789";
00234 
00235   ACE_OS::sprintf (buf,
00236                    "corbaloc:%s:%c.%c@%s%c%s",
00237                    ::the_prefix,
00238                    digits [this->version_.major],
00239                    digits [this->version_.minor],
00240                    uuidstr->c_str (),
00241                    this->object_key_delimiter_,
00242                    key.in ());
00243 
00244   return buf;
00245 }
00246 
00247 const char *
00248 TAO_COIOP_Profile::prefix (void)
00249 {
00250   return ::the_prefix;
00251 }
00252 
00253 void
00254 TAO_COIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const
00255 {
00256   encap.write_octet (TAO_ENCAP_BYTE_ORDER);
00257 
00258   // The GIOP version
00259   encap.write_octet (this->version_.major);
00260   encap.write_octet (this->version_.minor);
00261 
00262   // STRING hostname from profile
00263   const ACE_CString * uuid_str = this->endpoint_.uuid_.to_string();
00264   encap.write_string (uuid_str->c_str ());
00265 
00266   // OCTET SEQUENCE for object key
00267   if (this->ref_object_key_)
00268     encap << this->ref_object_key_->object_key ();
00269   else
00270     {
00271       ACE_ERROR ((LM_ERROR,
00272                   "(%P|%t) TAO - COIOP_Profile::create_profile_body "
00273                   "no object key marshalled \n"));
00274     }
00275 
00276   if (this->version_.major > 1
00277       || this->version_.minor > 0)
00278     this->tagged_components ().encode (encap);
00279 }
00280 
00281 int
00282 TAO_COIOP_Profile::encode_endpoints (void)
00283 {
00284   // Create a data structure and fill it with endpoint info for wire
00285   // transfer.
00286   // We include information for the head of the list
00287   // together with other endpoints because even though its addressing
00288   // info is transmitted using standard ProfileBody components, its
00289   // priority is not!
00290 
00291   TAO::COIOPEndpointSequence endpoints;
00292   endpoints.length (this->count_);
00293 
00294   const TAO_COIOP_Endpoint *endpoint = &this->endpoint_;
00295   for (CORBA::ULong i = 0;
00296        i < this->count_;
00297        ++i)
00298     {
00299       const ACE_CString* uuidstr = endpoint->uuid_.to_string();
00300       CORBA::String_var uuid (uuidstr->c_str());
00301       endpoints[i].uuid = uuid;
00302       endpoints[i].priority = endpoint->priority ();
00303 
00304       endpoint = endpoint->next_;
00305     }
00306 
00307   // Encode the data structure.
00308   TAO_OutputCDR out_cdr;
00309   if ((out_cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER)
00310        == 0)
00311       || (out_cdr << endpoints) == 0)
00312     return -1;
00313   size_t length = out_cdr.total_length ();
00314 
00315   IOP::TaggedComponent tagged_component;
00316   tagged_component.tag = TAO_TAG_ENDPOINTS;
00317   tagged_component.component_data.length (static_cast<CORBA::ULong> (length));
00318   CORBA::Octet *buf =
00319     tagged_component.component_data.get_buffer ();
00320 
00321   for (const ACE_Message_Block *iterator = out_cdr.begin ();
00322        iterator != 0;
00323        iterator = iterator->cont ())
00324     {
00325       size_t i_length = iterator->length ();
00326       ACE_OS::memcpy (buf, iterator->rd_ptr (), i_length);
00327 
00328       buf += i_length;
00329     }
00330 
00331   // Add component with encoded endpoint data to this profile's
00332   // TaggedComponents.
00333   tagged_components_.set_component (tagged_component);
00334 
00335   return  0;
00336 }
00337 
00338 int
00339 TAO_COIOP_Profile::decode_endpoints (void)
00340 {
00341   IOP::TaggedComponent tagged_component;
00342   tagged_component.tag = TAO_TAG_ENDPOINTS;
00343 
00344   if (this->tagged_components_.get_component (tagged_component))
00345     {
00346       const CORBA::Octet *buf =
00347         tagged_component.component_data.get_buffer ();
00348 
00349       TAO_InputCDR in_cdr (reinterpret_cast<const char*> (buf),
00350                            tagged_component.component_data.length ());
00351 
00352       // Extract the Byte Order.
00353       CORBA::Boolean byte_order;
00354       if ((in_cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
00355         return -1;
00356       in_cdr.reset_byte_order (static_cast<int> (byte_order));
00357 
00358       // Extract endpoints sequence.
00359       TAO::COIOPEndpointSequence endpoints;
00360 
00361       if (! (in_cdr >> endpoints))
00362         return -1;
00363 
00364       // Get the priority of the first endpoint (head of the list.
00365       // It's other data is extracted as part of the standard profile
00366       // decoding.
00367       this->endpoint_.priority (endpoints[0].priority);
00368 
00369       // Use information extracted from the tagged component to
00370       // populate the profile.  Skip the first endpoint, since it is
00371       // always extracted through standard profile body.  Also, begin
00372       // from the end of the sequence to preserve endpoint order,
00373       // since <add_endpoint> method reverses the order of endpoints
00374       // in the list.
00375       for (CORBA::ULong i = endpoints.length () - 1;
00376            i > 0;
00377            --i)
00378         {
00379           TAO_COIOP_Endpoint *endpoint = 0;
00380           CORBA::String_var strvar = CORBA::string_dup (endpoints[i].uuid);
00381           ACE_Utils::UUID uuid1 (strvar.in());
00382           ACE_NEW_RETURN (endpoint,
00383                           TAO_COIOP_Endpoint (uuid1),
00384                           -1);
00385 
00386           this->add_endpoint (endpoint);
00387         }
00388     }
00389 
00390   return 0;
00391 }
00392 
00393 TAO_END_VERSIONED_NAMESPACE_DECL
00394 
00395 #endif /* TAO_HAS_COIOP && TAO_HAS_COIOP != 0 */

Generated on Sun Jan 27 15:59:45 2008 for TAO_Strategies by doxygen 1.3.6