Service_Type_Repository.cpp

Go to the documentation of this file.
00001 // $Id: Service_Type_Repository.cpp 77079 2007-02-12 19:41:31Z johnnyw $
00002 
00003 #include "orbsvcs/Trader/Service_Type_Repository.h"
00004 
00005 #include "ace/Lock_Adapter_T.h"
00006 
00007 
00008 ACE_RCSID (Trader,
00009            Service_Type_Repository,
00010            "$Id: Service_Type_Repository.cpp 77079 2007-02-12 19:41:31Z johnnyw $")
00011 
00012 
00013 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00014 
00015 TAO_Service_Type_Repository::TAO_Service_Type_Repository (ACE_Lock* lock)
00016   : lock_ (lock)
00017 {
00018   this->incarnation_.low = 0;
00019   this->incarnation_.high = 0;
00020 
00021   // If a lock wasn't provided, let's assume the user doesn't want any
00022   // kind of lock at all.
00023   if (this->lock_ == 0)
00024     ACE_NEW (this->lock_,
00025              ACE_Lock_Adapter<ACE_Null_Mutex>);
00026 }
00027 
00028 TAO_Service_Type_Repository::~TAO_Service_Type_Repository (void)
00029 {
00030   {
00031     // Make sure not to throw exceptions in destructors...
00032     ACE_WRITE_GUARD (ACE_Lock, ace_mon, *this->lock_);
00033 
00034     for (Service_Type_Map_Iterator service_map_iterator (this->type_map_);
00035          service_map_iterator.done () == 0;
00036          service_map_iterator++)
00037       {
00038         Type_Info *type_info = (*service_map_iterator).int_id_;
00039         delete type_info;
00040       }
00041   }
00042 
00043   delete this->lock_;
00044 }
00045 
00046 CosTradingRepos::ServiceTypeRepository::IncarnationNumber
00047 TAO_Service_Type_Repository::incarnation (void)
00048 {
00049   CosTradingRepos::ServiceTypeRepository::IncarnationNumber inc_num;
00050 
00051   if (this->lock_->acquire_read () == -1)
00052     {
00053       inc_num = this->incarnation_;
00054       this->lock_->release ();
00055     }
00056   else
00057     {
00058       inc_num.high = 0;
00059       inc_num.low = 0;
00060     }
00061 
00062   return inc_num;
00063 }
00064 
00065 
00066 CosTradingRepos::ServiceTypeRepository::IncarnationNumber
00067 TAO_Service_Type_Repository::
00068 add_type (const char *name,
00069           const char *if_name,
00070           const CosTradingRepos::ServiceTypeRepository::PropStructSeq &props,
00071           const CosTradingRepos::ServiceTypeRepository::ServiceTypeNameSeq &super_types)
00072 {
00073   Prop_Map prop_map;
00074   Service_Type_Map super_map;
00075 
00076   ACE_WRITE_GUARD_THROW_EX (ACE_Lock, ace_mon, *this->lock_, CORBA::INTERNAL ());
00077 
00078   // Make sure Type name is valid.
00079   if (TAO_Trader_Base::is_valid_identifier_name (name) == 0)
00080     throw CosTrading::IllegalServiceType (name);
00081 
00082   // Check if the service type already exists.
00083   CORBA::String_var type_name (name);
00084   if (this->type_map_.find (type_name) == 0)
00085     throw CosTradingRepos::ServiceTypeRepository::ServiceTypeExists ();
00086 
00087   // Make sure all property names are valid and appear only once.
00088   this->validate_properties (prop_map,
00089                              props);
00090 
00091   // Check that all super_types exist, and none are duplicated.
00092   this->validate_supertypes (super_map,
00093                              super_types);
00094 
00095   // NOTE: I don't really know a way to do this without an Interface
00096   // Repository, since the Interface Repository IDs don't contain
00097   // information about supertypes.
00098   //
00099   // make sure interface name is legal.
00100   //  this->validate_interface (if_name, super_types);
00101   //
00102   // Instead, we do this:
00103   //
00104   if (if_name == 0)
00105     throw CosTradingRepos::ServiceTypeRepository::InterfaceTypeMismatch ();
00106 
00107   // Collect and make sure that properties of all supertypes and this
00108   // type are compatible.  We can use prop_map and super_types_map for
00109   // the job.
00110   this->validate_inheritance (prop_map,
00111                               super_types);
00112 
00113   // We can now use prop_map to construct a sequence of all properties
00114   // the this type.
00115   this->update_type_map (name,
00116                          if_name,
00117                          props,
00118                          super_types,
00119                          prop_map,
00120                          super_map);
00121 
00122   CosTradingRepos::ServiceTypeRepository::IncarnationNumber return_value =
00123     this->incarnation_;
00124 
00125   // Increment incarnation number.
00126   this->incarnation_.low++;
00127 
00128   // If we wrapped around in lows...
00129   if (this->incarnation_.low == 0)
00130     this->incarnation_.high++;
00131 
00132   return return_value;
00133 }
00134 
00135 void
00136 TAO_Service_Type_Repository::remove_type (const char *name)
00137 {
00138   if (TAO_Trader_Base::is_valid_identifier_name (name) == 0)
00139     throw CosTrading::IllegalServiceType (name);
00140 
00141   ACE_WRITE_GUARD_THROW_EX (ACE_Lock, ace_mon, *this->lock_, CORBA::INTERNAL ());
00142 
00143   // Check if the type exists.
00144   Service_Type_Map::ENTRY* type_entry = 0; ;
00145   if (this->type_map_.find (name,
00146                             type_entry) == -1)
00147     throw CosTrading::UnknownServiceType (name);
00148 
00149   // Check if it has any subtypes.
00150   Type_Info *type_info = type_entry->int_id_;
00151   if (type_info->has_subtypes_)
00152     throw CosTradingRepos::ServiceTypeRepository::HasSubTypes (name, "");
00153 
00154   // Remove the type from the map.
00155   this->type_map_.unbind (type_entry);
00156   delete type_info;
00157 }
00158 
00159 CosTradingRepos::ServiceTypeRepository::ServiceTypeNameSeq *
00160 TAO_Service_Type_Repository::
00161 list_types (const CosTradingRepos::ServiceTypeRepository::SpecifiedServiceTypes &which_types)
00162 {
00163   ACE_READ_GUARD_THROW_EX (ACE_Lock, ace_mon, *this->lock_, CORBA::INTERNAL ());
00164 
00165   CORBA::ULong i = 0;
00166   CORBA::ULong length = static_cast<CORBA::ULong> (this->type_map_.current_size ());
00167   CosTrading::ServiceTypeName *types =
00168     CosTradingRepos::ServiceTypeRepository::ServiceTypeNameSeq::allocbuf (length);
00169 
00170   if (types == 0)
00171     return 0;
00172 
00173   int all = which_types._d () == CosTradingRepos::ServiceTypeRepository::all;
00174 
00175   CosTradingRepos::ServiceTypeRepository::IncarnationNumber num =
00176     which_types.incarnation ();
00177 
00178   for (Service_Type_Map_Iterator itr (this->type_map_);
00179        itr.done () == 0;
00180        itr++)
00181     {
00182       Type_Info* type_info = (*itr).int_id_;
00183       const char* type_name = (*itr).ext_id_.in ();
00184 
00185       if (all
00186           || num < type_info->type_struct_.incarnation)
00187         types[i++] = CORBA::string_dup (type_name);
00188     }
00189 
00190   CosTradingRepos::ServiceTypeRepository::ServiceTypeNameSeq *tmp = 0;
00191 
00192   ACE_NEW_RETURN (tmp,
00193                   CosTradingRepos::ServiceTypeRepository::
00194                   ServiceTypeNameSeq (length,
00195                                       i,
00196                                       types,
00197                                       1),
00198                   0);
00199   return tmp;
00200 }
00201 
00202 CosTradingRepos::ServiceTypeRepository::TypeStruct *
00203 TAO_Service_Type_Repository::
00204 describe_type (const char * name)
00205 {
00206   if (TAO_Trader_Base::is_valid_identifier_name (name) == 0)
00207     {
00208       throw CosTrading::IllegalServiceType (name);
00209     }
00210 
00211   ACE_READ_GUARD_THROW_EX
00212     (ACE_Lock,
00213      ace_mon,
00214      *this->lock_,
00215      CORBA::INTERNAL ());
00216 
00217   // Make sure the type exists.
00218   CORBA::String_var type_name (name);
00219   Service_Type_Map::ENTRY *type_entry = 0;
00220   if (this->type_map_.find (type_name,
00221                             type_entry) == -1)
00222     throw CosTrading::UnknownServiceType (name);
00223 
00224   // Return appropriate information about the type.
00225   CosTradingRepos::ServiceTypeRepository::TypeStruct *descr = 0;
00226   ACE_NEW_RETURN (descr,
00227                   CosTradingRepos::ServiceTypeRepository::TypeStruct,
00228                   0);
00229   CosTradingRepos::ServiceTypeRepository::TypeStruct &s =
00230     type_entry->int_id_->type_struct_;
00231 
00232   descr->if_name = s.if_name;
00233   descr->masked = s.masked;
00234   descr->incarnation = s.incarnation;
00235   descr->super_types = s.super_types;
00236   descr->props = s.props;
00237   /*
00238   CORBA::ULong length = s.props.length ();
00239   CosTradingRepos::ServiceTypeRepository::PropStruct* pstructs =
00240     s.props.get_buffer (0);
00241   descr->props.replace (length, length, pstructs, 0);
00242   */
00243   return descr;
00244 }
00245 
00246 CosTradingRepos::ServiceTypeRepository::TypeStruct *
00247 TAO_Service_Type_Repository::
00248 fully_describe_type (const char *name)
00249 {
00250   if (TAO_Trader_Base::is_valid_identifier_name (name) == 0)
00251     throw CosTrading::IllegalServiceType (name);
00252 
00253   ACE_READ_GUARD_THROW_EX (ACE_Lock, ace_mon, *this->lock_, CORBA::INTERNAL ());
00254 
00255   // Make sure the type exists.
00256   CORBA::String_var type_name (name);
00257   Service_Type_Map::ENTRY *type_entry = 0;
00258   if (this->type_map_.find (type_name,
00259                             type_entry) == -1)
00260     throw CosTrading::UnknownServiceType (name);
00261 
00262   // Return appropriate information about the type.
00263   CosTradingRepos::ServiceTypeRepository::TypeStruct *descr = 0;
00264   ACE_NEW_RETURN (descr,
00265                   CosTradingRepos::ServiceTypeRepository::TypeStruct,
00266                   0);
00267   CosTradingRepos::ServiceTypeRepository::TypeStruct &s =
00268     type_entry->int_id_->type_struct_;
00269 
00270   // Aggregate the Properties of this type and all its supertypes.
00271   // Compute the transitive closure of all supertypes.
00272   this->fully_describe_type_i (s,
00273                                descr->props,
00274                                descr->super_types);
00275 
00276   // We do the explicit copy, since otherwise we'd have excessive
00277   // properties copying.
00278   descr->if_name = s.if_name;
00279   descr->masked = s.masked;
00280   descr->incarnation = s.incarnation;
00281 
00282   return descr;
00283 }
00284 
00285 void
00286 TAO_Service_Type_Repository::
00287 mask_type (const char *name)
00288 {
00289   if (TAO_Trader_Base::is_valid_identifier_name (name) == 0)
00290     throw CosTrading::IllegalServiceType (name);
00291 
00292   ACE_WRITE_GUARD_THROW_EX (ACE_Lock, ace_mon, *this->lock_, CORBA::INTERNAL ());
00293 
00294   // Make sure the type exists.
00295   CORBA::String_var type_name (name);
00296   Service_Type_Map::ENTRY *type_entry = 0;
00297   if (this->type_map_.find (type_name,
00298                             type_entry) != -1)
00299     throw CosTrading::UnknownServiceType (name);
00300 
00301   // Make sure the type is unmasked.
00302   CORBA::Boolean &mask =
00303     type_entry->int_id_->type_struct_.masked;
00304 
00305   if (mask == 1)
00306     throw CosTradingRepos::ServiceTypeRepository::AlreadyMasked (name);
00307   else
00308     mask = 1;
00309 }
00310 
00311 void
00312 TAO_Service_Type_Repository::unmask_type (const char *name)
00313 {
00314   if (TAO_Trader_Base::is_valid_identifier_name (name) == 0)
00315     throw CosTrading::IllegalServiceType (name);
00316 
00317   ACE_WRITE_GUARD_THROW_EX (ACE_Lock, ace_mon, *this->lock_, CORBA::INTERNAL ());
00318 
00319   // Make sure the type exists.
00320   CORBA::String_var type_name (name);
00321   Service_Type_Map::ENTRY *type_entry = 0;
00322   if (this->type_map_.find (type_name,
00323                             type_entry) != -1)
00324     throw CosTrading::UnknownServiceType (name);
00325 
00326   // Make sure the type is masked.
00327   CORBA::Boolean &mask = type_entry->int_id_->type_struct_.masked;
00328 
00329   if (mask == 0)
00330     throw CosTradingRepos::ServiceTypeRepository::NotMasked (name);
00331   else
00332     mask = 0;
00333 }
00334 
00335 void
00336 TAO_Service_Type_Repository::
00337 fully_describe_type_i (const CosTradingRepos::ServiceTypeRepository::TypeStruct &type_struct,
00338                        CosTradingRepos::ServiceTypeRepository::PropStructSeq &props,
00339                        CosTradingRepos::ServiceTypeRepository::ServiceTypeNameSeq &super_types)
00340 {
00341   TAO_String_Queue service_type_queue;
00342   this->collect_inheritance_hierarchy (type_struct,
00343                                        service_type_queue);
00344 
00345   // Count the total number of properties.
00346   CORBA::ULong num_props = 0;
00347   CORBA::ULong num_types = static_cast<CORBA::ULong> (service_type_queue.size ());
00348 
00349   TAO_String_Queue::ITERATOR iterator (service_type_queue);
00350 
00351   for (;
00352        iterator.done () == 0;
00353        iterator.advance ())
00354     {
00355       char **next_type_name = 0;
00356       Service_Type_Map::ENTRY *type_entry = 0;
00357 
00358       iterator.next (next_type_name);
00359       CORBA::String_var hash_key (const_cast<const char *> (*next_type_name));
00360       this->type_map_.find (hash_key,
00361                             type_entry);
00362 
00363       CosTradingRepos::ServiceTypeRepository::TypeStruct &tstruct =
00364         type_entry->int_id_->type_struct_;
00365       num_props += tstruct.props.length ();
00366     }
00367 
00368   num_props += type_struct.props.length ();
00369   props.length (num_props);
00370   super_types.length (num_types);
00371 
00372   // Copy in all properties.
00373   int i = 0;
00374   CORBA::ULong prop_index = 0;
00375   CORBA::ULong type_index = 0;
00376 
00377   for (i = type_struct.props.length () - 1;
00378        i >= 0;
00379        i--)
00380     props[prop_index++] = type_struct.props[i];
00381 
00382   for (iterator.first ();
00383        iterator.done () == 0;
00384        iterator.advance ())
00385     {
00386       char **next_type_name = 0;
00387       Service_Type_Map::ENTRY *type_entry = 0;
00388 
00389       iterator.next (next_type_name);
00390       CORBA::String_var hash_key (const_cast<const char *> (*next_type_name));
00391       this->type_map_.find (hash_key,
00392                             type_entry);
00393 
00394       // Should never be zero.
00395       if (type_entry != 0)
00396         {
00397           CosTradingRepos::ServiceTypeRepository::TypeStruct& tstruct =
00398             type_entry->int_id_->type_struct_;
00399 
00400           for (i = tstruct.props.length () - 1;
00401                i >= 0;
00402                i--)
00403             props[prop_index++] = tstruct.props[i];
00404 
00405           super_types[type_index++] = hash_key.in ();
00406         }
00407     }
00408 }
00409 
00410 void
00411 TAO_Service_Type_Repository::
00412 collect_inheritance_hierarchy (const CosTradingRepos::ServiceTypeRepository::TypeStruct &type_struct,
00413                                TAO_String_Queue &target)
00414 {
00415   // Recurse for each super_type
00416   for (int i = type_struct.super_types.length () - 1;
00417        i >= 0;
00418        i--)
00419     {
00420       Service_Type_Map::ENTRY *next_type_entry = 0;
00421       CORBA::String_var next_type_name (type_struct.super_types[i]);
00422 
00423       if (this->type_map_.find (next_type_name, next_type_entry) != -1)
00424         {
00425           CosTradingRepos::ServiceTypeRepository::TypeStruct &next_type_struct =
00426             next_type_entry->int_id_->type_struct_;
00427 
00428           const char *type_name =
00429             type_struct.super_types[i];
00430           target.enqueue_tail (const_cast<char *> (type_name));
00431 
00432           this->collect_inheritance_hierarchy (next_type_struct,
00433                                                target);
00434         }
00435     }
00436 }
00437 
00438 void
00439 TAO_Service_Type_Repository::
00440 validate_properties (Prop_Map &prop_map,
00441                      const CosTradingRepos::ServiceTypeRepository::PropStructSeq &props)
00442 {
00443   for (CORBA::ULong i = 0;
00444        i < props.length ();
00445        i++)
00446     {
00447       const char *n = props[i].name;
00448       if (TAO_Trader_Base::is_valid_property_name (n) == 0)
00449         throw CosTrading::IllegalPropertyName (n);
00450       else
00451         {
00452           CORBA::String_var prop_name (n);
00453           CosTradingRepos::ServiceTypeRepository::PropStruct *prop_val =
00454             const_cast<CosTradingRepos::ServiceTypeRepository::PropStruct *> (&props[i]);
00455 
00456           if (prop_map.bind (prop_name,
00457                              prop_val) == 1)
00458             throw CosTrading::DuplicatePropertyName (n);
00459         }
00460     }
00461 }
00462 
00463 void
00464 TAO_Service_Type_Repository::
00465 validate_supertypes (Service_Type_Map &super_map,
00466                      const CosTradingRepos::ServiceTypeRepository::ServiceTypeNameSeq &super_types)
00467 {
00468   for (CORBA::ULong i = 0;
00469        i < super_types.length ();
00470        i++)
00471     {
00472       const char *type =
00473         super_types[i];
00474 
00475       if (TAO_Trader_Base::is_valid_identifier_name (type) == 0)
00476         throw CosTrading::IllegalServiceType (type);
00477       else
00478         {
00479           CORBA::String_var hash_type (type);
00480           Service_Type_Map::ENTRY *type_entry = 0;
00481 
00482           if (this->type_map_.find (hash_type,
00483                                     type_entry) == -1)
00484             throw CosTrading::UnknownServiceType (type);
00485           else
00486             {
00487               if (super_map.bind (hash_type,
00488                                   type_entry->int_id_) == 1)
00489                 throw CosTradingRepos::ServiceTypeRepository::DuplicateServiceTypeName (
00490                   type);
00491             }
00492         }
00493     }
00494 }
00495 
00496 void
00497 TAO_Service_Type_Repository::
00498 validate_inheritance (Prop_Map &prop_map,
00499                       const CosTradingRepos::ServiceTypeRepository::ServiceTypeNameSeq &super_types)
00500 {
00501   CORBA::ULong num_super_types = super_types.length ();
00502 
00503   for (CORBA::ULong i = 0;
00504        i < num_super_types;
00505        i++)
00506     {
00507       Service_Type_Map::ENTRY *super_type_entry = 0;
00508       CORBA::String_var super_type (super_types[i]);
00509       CosTradingRepos::ServiceTypeRepository::ServiceTypeNameSeq place_holder;
00510       CosTradingRepos::ServiceTypeRepository::PropStructSeq super_props;
00511 
00512       this->type_map_.find (super_type, super_type_entry);
00513 
00514       // Super_type_entry should never be zero.
00515       if (super_type_entry != 0)
00516         this->fully_describe_type_i (super_type_entry->int_id_->type_struct_,
00517                                      super_props,
00518                                      place_holder);
00519       else
00520         continue;
00521 
00522       CORBA::ULong num_props = super_props.length ();
00523 
00524       for (CORBA::ULong j = 0;
00525            j < num_props;
00526            j++)
00527         {
00528           Prop_Map::ENTRY *existing_prop = 0;
00529           CORBA::String_var prop_name (super_props[j].name);
00530 
00531           if (prop_map.bind (prop_name,
00532                              &super_props[j],
00533                              existing_prop) == 1)
00534             {
00535               // If already there, check that it is compatible with
00536               // properties of other types. Value Types have to be the
00537               // same.
00538               const CosTradingRepos::ServiceTypeRepository::PropStruct &property_in_map =
00539                 *existing_prop->int_id_;
00540 
00541               CORBA::TypeCode_ptr prop_type = property_in_map.value_type.in ();
00542               int compare = 0;
00543               try
00544                 {
00545                   compare =
00546                     super_props[j].value_type->equal (prop_type);
00547                 }
00548               catch (const CORBA::Exception&)
00549                 {
00550                 throw CosTradingRepos::ServiceTypeRepository::ValueTypeRedefinition(
00551                   super_props[j].name,
00552                   super_props[j],
00553                   property_in_map.name,
00554                   property_in_map);
00555                 }
00556 
00557               if (compare == 0
00558                   || super_props[j].mode > property_in_map.mode)
00559                 throw CosTradingRepos::ServiceTypeRepository::ValueTypeRedefinition(
00560                   super_props[j].name,
00561                   super_props[j],
00562                   property_in_map.name,
00563                   property_in_map);
00564             }
00565         }
00566     }
00567 }
00568 
00569 void
00570 TAO_Service_Type_Repository::
00571 update_type_map (const char *name,
00572                  const char *if_name,
00573                  const CosTradingRepos::ServiceTypeRepository::PropStructSeq &props,
00574                  const CosTradingRepos::ServiceTypeRepository::ServiceTypeNameSeq &super_types,
00575                  Prop_Map &,
00576                  Service_Type_Map &super_map)
00577 {
00578   // Update entries for all supertypes to include this type as a
00579   // subtype.  we can use the super_types_map we have constructed.
00580 
00581   for (Service_Type_Map_Iterator super_map_iterator (super_map);
00582        super_map_iterator.done () == 0;
00583        super_map_iterator++)
00584     {
00585       Type_Info *super_type_info =
00586         (*super_map_iterator).int_id_;
00587       super_type_info->has_subtypes_ = 0;
00588     }
00589 
00590   // All parameters are valid, create an entry for this service type
00591   // in the this->type_map_.
00592   Type_Info *type = 0;
00593   ACE_NEW (type,
00594            Type_Info);
00595 
00596   type->type_struct_.props = props;
00597   type->type_struct_.if_name = if_name;
00598   type->type_struct_.super_types = super_types;
00599   type->type_struct_.incarnation = this->incarnation_;
00600   type->type_struct_.masked = 0;
00601   type->has_subtypes_ = 0;
00602 
00603   // Move the prop struct sequences and super type names from the in
00604   // params to the internal storage.
00605   /*
00606   CORBA::ULong pslength = props.length ();
00607   CosTradingRepos::ServiceTypeRepository::PropStructSeq* pstructs =
00608     const_cast<CosTradingRepos::ServiceTypeRepository::PropStructSeq*> (&props);
00609   CosTradingRepos::ServiceTypeRepository::PropStruct* psbuf =
00610     pstructs->get_buffer (1);
00611   type->type_struct_.props.replace (pslength,
00612                                     pslength,
00613                                     psbuf,
00614                                     1);
00615   */
00616   CORBA::String_var type_name (name);
00617   this->type_map_.bind (type_name, type);
00618 }
00619 
00620 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:49:26 2010 for TAO_CosTrader by  doxygen 1.4.7