Offer_Database.cpp

Go to the documentation of this file.
00001 // $Id: Offer_Database.cpp 77001 2007-02-12 07:54:49Z johnnyw $
00002 
00003 #ifndef TAO_OFFER_DATABASE_CPP
00004 #define TAO_OFFER_DATABASE_CPP
00005 
00006 #include "orbsvcs/Trader/Offer_Database.h"
00007 #include "ace/OS_NS_stdio.h"
00008 #include "ace/OS_NS_string.h"
00009 
00010 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00011 
00012 template <class LOCK_TYPE>
00013 TAO_Offer_Database<LOCK_TYPE>::TAO_Offer_Database (void)
00014 {
00015 }
00016 
00017 template <class LOCK_TYPE>
00018 TAO_Offer_Database<LOCK_TYPE>::~TAO_Offer_Database (void)
00019 {
00020   ACE_WRITE_GUARD (LOCK_TYPE, ace_mon, this->db_lock_);
00021 
00022   for (typename Offer_Database::iterator type_iter (this->offer_db_);
00023        ! type_iter.done ();
00024        type_iter++)
00025     {
00026       Offer_Map_Entry* offer_map_entry = (*type_iter).int_id_;
00027 
00028       {
00029         // Artificial scope, so the guard will release the lock before
00030         // we delete the lock along with the offer_map_entry.
00031         ACE_WRITE_GUARD (LOCK_TYPE, ace_mon, offer_map_entry->lock_);
00032 
00033         for (TAO_Offer_Map::iterator offer_iter (*offer_map_entry->offer_map_);
00034              ! offer_iter.done ();
00035              offer_iter++)
00036           {
00037             // Delete all the offers in the offer map.
00038             CosTrading::Offer* offer = (*offer_iter).int_id_;
00039             delete offer;
00040           }
00041 
00042         delete offer_map_entry->offer_map_;
00043       }
00044 
00045       delete offer_map_entry;
00046     }
00047 }
00048 
00049 template <class LOCK_TYPE> CosTrading::OfferId
00050 TAO_Offer_Database<LOCK_TYPE>::
00051 insert_offer (const char* type, CosTrading::Offer* offer)
00052 {
00053   CosTrading::OfferId return_value = 0;
00054   typename Offer_Database::ENTRY* database_entry = 0;
00055   CORBA::String_var service_type (type);
00056 
00057   ACE_READ_GUARD_RETURN (LOCK_TYPE, ace_mon, this->db_lock_, 0);
00058 
00059   if (this->offer_db_.find (service_type, database_entry) == -1)
00060     {
00061       // If there's no entry for the service type, create one.
00062 
00063       Offer_Map_Entry* new_offer_map_entry = 0;
00064       ACE_NEW_RETURN (new_offer_map_entry, Offer_Map_Entry, 0);
00065       ACE_NEW_RETURN (new_offer_map_entry->offer_map_, TAO_Offer_Map, 0);
00066       new_offer_map_entry->counter_ = 1;
00067 
00068       if (this->db_lock_.release () == -1)
00069         return 0;
00070       else
00071         {
00072           // Add the new entry; upgrade lock.
00073           ACE_WRITE_GUARD_RETURN (LOCK_TYPE, ace_mon, this->db_lock_, 0);
00074           this->offer_db_.bind (service_type,
00075                                 new_offer_map_entry,
00076                                 database_entry);
00077         }
00078 
00079       if (this->db_lock_.acquire_read () == -1)
00080         return 0;
00081     }
00082 
00083   Offer_Map_Entry* offer_map_entry =
00084     database_entry->int_id_;
00085   ACE_WRITE_GUARD_RETURN (LOCK_TYPE, ace_mon2, offer_map_entry->lock_, 0);
00086 
00087   // Add the offer to the service offer table for this service type.
00088   offer_map_entry->offer_map_->bind (offer_map_entry->counter_,
00089                                      offer);
00090   return_value = this->generate_offer_id (type,
00091                                           offer_map_entry->counter_);
00092   offer_map_entry->counter_++;
00093 
00094   return return_value;
00095 }
00096 
00097 template <class LOCK_TYPE> int
00098 TAO_Offer_Database<LOCK_TYPE>::
00099 remove_offer (const char* type, CORBA::ULong id)
00100 {
00101   ACE_READ_GUARD_RETURN (LOCK_TYPE, ace_mon, this->db_lock_, -1);
00102 
00103   int return_value = -1;
00104   typename Offer_Database::ENTRY* db_entry = 0;
00105   CORBA::String_var service_type (type);
00106 
00107   if (this->offer_db_.find (service_type, db_entry) == 0)
00108     {
00109       CosTrading::Offer* offer = 0;
00110       Offer_Map_Entry* offer_map_entry = db_entry->int_id_;
00111 
00112       if (offer_map_entry->lock_.acquire_write () == -1)
00113         return -1;
00114 
00115       return_value = offer_map_entry->offer_map_->unbind (id, offer);
00116       delete offer;
00117 
00118       // If the service type has no more offers, free the map, lest
00119       // the memory forever persist.
00120       if (offer_map_entry->offer_map_->current_size () == 0)
00121         {
00122           if (this->db_lock_.release () == -1)
00123             return -1;
00124           else
00125             {
00126               // Promote the database lock. Will be released by
00127               // guard.
00128               if (this->db_lock_.acquire_write () == -1)
00129                 return -1;
00130 
00131               // Unbind the service type from the database.
00132               this->offer_db_.unbind (service_type);
00133 
00134               // Now that the type has been removed, we can release
00135               // its lock.
00136               if (offer_map_entry->lock_.release () == -1)
00137                 return -1;
00138 
00139               // Delete the database resources for this type.
00140               delete offer_map_entry->offer_map_;
00141               delete offer_map_entry;
00142             }
00143         }
00144       else if (offer_map_entry->lock_.release () == -1)
00145         return -1;
00146     }
00147 
00148   return return_value;
00149 }
00150 
00151 template <class LOCK_TYPE> int
00152 TAO_Offer_Database<LOCK_TYPE>::
00153 remove_offer (const CosTrading::OfferId offer_id)
00154 {
00155   char* stype = 0;
00156   CORBA::ULong index;
00157 
00158   this->parse_offer_id (offer_id,
00159                         stype,
00160                         index);
00161 
00162   if (this->remove_offer (stype,
00163                           index) == -1)
00164     throw CosTrading::UnknownOfferId (offer_id);
00165 
00166   return 0;
00167 }
00168 
00169 template <class LOCK_TYPE> CosTrading::Offer*
00170 TAO_Offer_Database<LOCK_TYPE>::
00171 lookup_offer (const CosTrading::OfferId offer_id,
00172               char*& type_name)
00173 {
00174   CORBA::ULong index;
00175   CosTrading::Offer* offer = 0;
00176   this->parse_offer_id (offer_id, type_name, index);
00177 
00178   if ((offer = this->lookup_offer (type_name, index)) == 0)
00179     throw CosTrading::UnknownOfferId (offer_id);
00180 
00181   return offer;
00182 }
00183 
00184 
00185 template <class LOCK_TYPE> CosTrading::Offer*
00186 TAO_Offer_Database<LOCK_TYPE>::
00187 lookup_offer (const CosTrading::OfferId offer_id)
00188 {
00189   char* type_name;
00190   CORBA::ULong index;
00191   CosTrading::Offer* offer = 0;
00192 
00193   this->parse_offer_id (offer_id, type_name, index);
00194 
00195   if ((offer = this->lookup_offer (type_name, index)) == 0)
00196     throw CosTrading::UnknownOfferId (offer_id);
00197 
00198   return offer;
00199 }
00200 
00201 template <class LOCK_TYPE> CosTrading::Offer*
00202 TAO_Offer_Database<LOCK_TYPE>::
00203 lookup_offer (const char* type, CORBA::ULong id)
00204 {
00205   ACE_READ_GUARD_RETURN (LOCK_TYPE, ace_mon, this->db_lock_, 0);
00206 
00207   CosTrading::Offer* return_value = 0;
00208   typename Offer_Database::ENTRY* db_entry = 0;
00209   CORBA::String_var service_type (type);
00210 
00211   if (this->offer_db_.find (service_type, db_entry) == 0)
00212     {
00213       Offer_Map_Entry* offer_map_entry = db_entry->int_id_;
00214       ACE_READ_GUARD_RETURN (LOCK_TYPE, ace_mon, offer_map_entry->lock_, 0);
00215 
00216       TAO_Offer_Map::ENTRY* offer_entry_ptr = 0;
00217       if (offer_map_entry->offer_map_->find (id, offer_entry_ptr) == 0)
00218         return_value = offer_entry_ptr->int_id_;
00219     }
00220 
00221   return return_value;
00222 }
00223 
00224 template <class LOCK_TYPE> TAO_Offer_Id_Iterator*
00225 TAO_Offer_Database<LOCK_TYPE>::retrieve_all_offer_ids (void)
00226 {
00227   // Fill an TAO_Offer_Id_Iterator with the offer_ids of all offers
00228   // exported to the TAO_Offer_Database. Iterates through the entire
00229   // map, cramming offer_id strings into a newly constructed
00230   // TAO_Offer_Id_Iterator.
00231   TAO_Offer_Id_Iterator* id_iterator;
00232   ACE_NEW_RETURN (id_iterator,
00233                   TAO_Offer_Id_Iterator (),
00234                   0);
00235   ACE_READ_GUARD_RETURN (LOCK_TYPE, ace_mon, this->db_lock_, 0);
00236 
00237   for (typename Offer_Database::iterator type_iter (this->offer_db_);
00238        ! type_iter.done ();
00239        type_iter++)
00240     {
00241       const char* type_name = (*type_iter).ext_id_.in ();
00242       Offer_Map_Entry* offer_map_entry = (*type_iter).int_id_;
00243 
00244       ACE_READ_GUARD_RETURN (LOCK_TYPE, ace_mon, offer_map_entry->lock_, 0);
00245 
00246       for (TAO_Offer_Map::iterator offer_iter (*offer_map_entry->offer_map_);
00247            ! offer_iter.done ();
00248            offer_iter++)
00249         {
00250           CORBA::ULong offer_index = (*offer_iter).ext_id_;
00251           CosTrading::OfferId offer_id =
00252             this->generate_offer_id (type_name, offer_index);
00253 
00254           id_iterator->insert_id (offer_id);
00255         }
00256     }
00257 
00258   return id_iterator;
00259 }
00260 
00261 template <class LOCK_TYPE> void
00262 TAO_Offer_Database<LOCK_TYPE>::
00263 parse_offer_id (const CosTrading::OfferId offer_id,
00264                 char*&service_type,
00265                 CORBA::ULong& id)
00266 {
00267   // Get service type: it is everything from 17th character to the end.
00268   service_type = (char *) offer_id + 16;
00269 
00270   // Get id: temporarily put the end of string character where the service
00271   // type starts, convert to number, replace the character back.
00272   char* start_of_type =  (char *) (offer_id + 16);
00273   char temp = *start_of_type;
00274   *start_of_type = '\0';
00275   id = ACE_OS::atoi (offer_id);
00276 
00277   *start_of_type = temp;
00278 
00279   if (! TAO_Trader_Base::is_valid_identifier_name (service_type))
00280     throw CosTrading::IllegalOfferId (offer_id);
00281 }
00282 
00283 template <class LOCK_TYPE> CosTrading::OfferId
00284 TAO_Offer_Database<LOCK_TYPE>::
00285 generate_offer_id (const char *service_type_name, CORBA::ULong id)
00286 {
00287   // holds final id string.
00288   size_t total_size = 16 + ACE_OS::strlen (service_type_name);
00289 
00290   // hold portions of id string.
00291   CosTrading::OfferId offer_id =
00292      CORBA::string_alloc (static_cast<CORBA::ULong> (total_size));
00293   char* return_value = 0;
00294   ACE_OS::sprintf (offer_id, "%016u%s", id, service_type_name);
00295 
00296   return_value = CORBA::string_dup (offer_id);
00297   delete [] offer_id;
00298 
00299   return return_value;
00300 }
00301 
00302 
00303 template <class LOCK_TYPE>
00304 TAO_Service_Offer_Iterator<LOCK_TYPE>::
00305 TAO_Service_Offer_Iterator (const char* type,
00306                             TAO_Offer_Database<LOCK_TYPE>& offer_database)
00307   : stm_ (offer_database),
00308     lock_ (0),
00309     offer_iter_ (0),
00310     type_ (type)
00311 {
00312   CORBA::String_var service_type (type);
00313 
00314   if (this->stm_.db_lock_.acquire_read () == -1)
00315     return;
00316 
00317   typename TAO_Offer_Database<LOCK_TYPE>::Offer_Map_Entry* entry = 0;
00318   if (this->stm_.offer_db_.find (service_type, entry) == -1)
00319     return;
00320   else
00321     {
00322       this->lock_ = &entry->lock_;
00323       if (this->lock_->acquire_read () == -1)
00324         return;
00325 
00326       ACE_NEW (offer_iter_,
00327                TAO_Offer_Map::iterator (*entry->offer_map_));
00328     }
00329 }
00330 
00331 template <class LOCK_TYPE>
00332 TAO_Service_Offer_Iterator<LOCK_TYPE>::~TAO_Service_Offer_Iterator (void)
00333 {
00334   this->stm_.db_lock_.release ();
00335 
00336   if (this->lock_ != 0)
00337     {
00338       this->lock_->release ();
00339       delete this->offer_iter_;
00340     }
00341 }
00342 
00343 template <class LOCK_TYPE> CosTrading::OfferId
00344 TAO_Service_Offer_Iterator<LOCK_TYPE>::get_id (void)
00345 {
00346   return (this->offer_iter_ != 0)
00347     ? TAO_Offer_Database<LOCK_TYPE>::generate_offer_id (this->type_, (**this->offer_iter_).ext_id_)
00348     : 0;
00349 }
00350 
00351 template <class LOCK_TYPE> int
00352 TAO_Service_Offer_Iterator<LOCK_TYPE>::has_more_offers (void)
00353 {
00354   return (this->offer_iter_ != 0) ? ! this->offer_iter_->done () : 0;
00355 }
00356 
00357 
00358 template <class LOCK_TYPE> CosTrading::Offer*
00359 TAO_Service_Offer_Iterator<LOCK_TYPE>::get_offer (void)
00360 {
00361   return (this->offer_iter_ != 0) ? (**this->offer_iter_).int_id_ : 0;
00362 }
00363 
00364 template <class LOCK_TYPE> void
00365 TAO_Service_Offer_Iterator<LOCK_TYPE>::next_offer (void)
00366 {
00367   if (this->offer_iter_ != 0)
00368     this->offer_iter_->advance ();
00369 }
00370 
00371 TAO_END_VERSIONED_NAMESPACE_DECL
00372 
00373 #endif /* TAO_OFFER_DATABASE_CPP */

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