// ======================================================================== // $Id$ // // = LIBRARY // orbsvcs // // = FILENAME // Trader_Interfaces.cpp // // = AUTHOR // Marina Spivak // Seth Widoff // // ======================================================================== #if !defined (TAO_TRADER_INTERFACES_C) #define TAO_TRADER_INTERFACES_C #include "Trader_Interfaces.h" #include "Trader_T.h" ACE_RCSID(Trader, Trader_Interfaces, "$Id$") // ************************************************************* // TAO_Lookup // ************************************************************* template TAO_Lookup:: TAO_Lookup (TAO_Trader &trader) : TAO_Trader_Components (trader.trading_components ()), TAO_Support_Attributes (trader.support_attributes ()), TAO_Import_Attributes (trader.import_attributes ()), IDS_SAVED (100), trader_ (trader) { } template TAO_Lookup::~TAO_Lookup (void) { ACE_GUARD (TRADER_LOCK_TYPE, trader_mon, this->lock_); for (Request_Ids::ITERATOR riter (this->request_ids_); ! riter.done (); riter.advance ()) { CosTrading::Admin::OctetSeq** old_seq = 0; riter.next (old_seq); delete *old_seq; } } template void TAO_Lookup:: query (const char *type, const char *constraint, const char *preferences, const CosTrading::PolicySeq &in_policies, const CosTrading::Lookup::SpecifiedProps &desired_props, CORBA::ULong how_many, CosTrading::OfferSeq_out returned_offers, CosTrading::OfferIterator_out returned_offer_iterator, CosTrading::PolicyNameSeq_out returned_limits_applied, CORBA::Environment& env) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::IllegalServiceType, CosTrading::UnknownServiceType, CosTrading::IllegalConstraint, CosTrading::Lookup::IllegalPreference, CosTrading::Lookup::IllegalPolicyName, CosTrading::Lookup::PolicyTypeMismatch, CosTrading::Lookup::InvalidPolicyValue, CosTrading::IllegalPropertyName, CosTrading::DuplicatePropertyName, CosTrading::DuplicatePolicyName)) { // Instantiate a class to help interpret query policies. TAO_Policies policies (this->trader_, in_policies, env); TAO_CHECK_ENV_RETURN_VOID (env); // If a federated query returns to us, ignore it to prevent // redundant results and infinite loops. CosTrading::Admin::OctetSeq* request_id = 0; if (this->seen_request_id (policies, request_id, env)) { returned_offers = new CosTrading::OfferSeq; returned_limits_applied = new CosTrading::PolicyNameSeq; return; } TAO_CHECK_ENV_RETURN_VOID (env); // The presence of a link interface determines whether we should // attempt to forward or propagate queries. CosTrading::Link_ptr link_if = this->trader_.trading_components ().link_if (); // If the importer has specified a starting trader, foward the // query. CosTrading::TraderName* trader_name = policies.starting_trader (env); TAO_CHECK_ENV_RETURN_VOID (env); if (! CORBA::is_nil (link_if) && trader_name != 0) { CosTrading::PolicySeq policies_to_forward; policies.copy_to_forward (policies_to_forward, *trader_name); const char* next_hop = (*trader_name)[0]; this->forward_query (next_hop, type, constraint, preferences, policies_to_forward, desired_props, how_many, returned_offers, returned_offer_iterator, returned_limits_applied, env); TAO_CHECK_ENV_RETURN_VOID (env); return; } // Retrieve the type description struct from the Service Type Repos. const TAO_Support_Attributes_i& support_attrs = this->trader_.support_attributes (); CosTradingRepos::ServiceTypeRepository_ptr rep = support_attrs.service_type_repos (); CosTradingRepos::ServiceTypeRepository::TypeStruct_var type_struct = rep->fully_describe_type (type, env); TAO_CHECK_ENV_RETURN_VOID (env); ACE_NEW (returned_offers, CosTrading::OfferSeq); // Obtain a reference to the offer database. TAO_Offer_Database& offer_database = this->trader_.offer_database (); // TAO_Offer_Filter -- ensures that we don't consider offers with // modifiable or dynamic properties if the Trader doesn't support // them, or the importer has turned them off using policies. // TAO_Constraint_Validator -- validates the constraint with the // property types in the supplied type. // TAO_Constraint_Interpreter -- parses the constraint string, and // determines whether an offer meets those constraints. // TAO_Preference_Interpreter -- parses the preference string and // orders offers according to those constraints. TAO_Offer_Filter offer_filter (policies, env); TAO_CHECK_ENV_RETURN_VOID (env); TAO_Constraint_Validator validator (type_struct.in ()); TAO_Constraint_Interpreter constr_inter (validator, constraint, env); TAO_CHECK_ENV_RETURN_VOID (env); TAO_Preference_Interpreter pref_inter (validator, preferences, env); TAO_CHECK_ENV_RETURN_VOID (env); // Try to find the map of offers of desired service type. offer_filter.configure_type (type_struct.ptr ()); this->lookup_one_type (type, offer_database, constr_inter, pref_inter, offer_filter); if (! policies.exact_type_match (env)) { // If the importer hasn't demanded an exact match search, we search // all the subtypes of the supplied type. NOTE: Only the properties // belonging to the provided type are considered on // subtypes. Additional properties on the subtype are generally // ignored. This is as it should be, consistent with the notions of // type inheritence. TAO_CHECK_ENV_RETURN_VOID (env); this->lookup_all_subtypes (type, type_struct->incarnation, offer_database, rep, constr_inter, pref_inter, offer_filter); } TAO_CHECK_ENV_RETURN_VOID (env); // Take note of the limits applied in this query. returned_limits_applied = offer_filter.limits_applied (); // Fill the return sequence and iterator with the bountiful results. CORBA::ULong offers_returned = this->fill_receptacles (type, how_many, desired_props, policies, pref_inter, *returned_offers.ptr (), returned_offer_iterator, env); TAO_CHECK_ENV_RETURN_VOID (env); // The following steps are only appropriate for a linked trader. if (! CORBA::is_nil (link_if)) { // Determine if we should perform a federated query, and if so // construct a sequence of links to follow. CosTrading::LinkNameSeq_var links; CORBA::Boolean should_follow = this->retrieve_links (policies, offers_returned, CosTrading::LinkNameSeq_out (links.out ()), env); TAO_CHECK_ENV_RETURN_VOID (env); if (should_follow && links->length () != 0) { // Query those links we've accumulated! this->federated_query (links.in (), policies, *request_id, pref_inter, type, constraint, preferences, desired_props, how_many, *returned_offers.ptr (), returned_offer_iterator.ptr (), *returned_limits_applied.ptr (), env); TAO_CHECK_ENV_RETURN_VOID (env); } } } template void TAO_Lookup:: lookup_one_type (const char* type, TAO_Offer_Database& offer_database, TAO_Constraint_Interpreter& constr_inter, TAO_Preference_Interpreter& pref_inter, TAO_Offer_Filter& offer_filter) { // Retrieve an iterator over the offers for a given type. // @@ Would have used Offer_Database::offer_iterator for less // coupling between TAO_Lookup and Offer_Database, but g++ barfs on // that. #if defined(_MSC_VER) TAO_Offer_Database::offer_iterator offer_iter (type, offer_database); #else // MSVC won't grok this for some reason, but it's necessary for the // HP compiler, which seriously requires the typename keyword // here. I apologize if this ifdef offends some ACE users' // sensibilities --- it certainly offends mine. ACE_TYPENAME TAO_Offer_Database::offer_iterator offer_iter (type, offer_database); #endif while (offer_filter.ok_to_consider_more () && offer_iter.has_more_offers ()) { // For each offer in the iterator, attempt to match it with // the constraints passed to the Query method. If it matches // the constraint, use the TAO_Preference_Interpreter to // order the matched offers with respect to the preference // string passed to the method. All the while the offer // filter ensures we don't exceed the match cardinality // constraints. CosTrading::Offer* offer = offer_iter.get_offer (); TAO_Constraint_Evaluator evaluator (offer); if (offer_filter.ok_to_consider (offer) && constr_inter.evaluate (evaluator)) { // Shove the offer and its id into the preference // ordering object, pref_inter. CosTrading::OfferId offer_id = offer_iter.get_id (); pref_inter.order_offer (evaluator, offer, offer_id); offer_filter.matched_offer (); } offer_iter.next_offer (); } } template void TAO_Lookup:: lookup_all_subtypes (const char* type, CosTradingRepos::ServiceTypeRepository::IncarnationNumber& inc_num, TAO_Offer_Database& offer_database, CosTradingRepos::ServiceTypeRepository_ptr rep, TAO_Constraint_Interpreter& constr_inter, TAO_Preference_Interpreter& pref_inter, TAO_Offer_Filter& offer_filter) { // BEGIN SPEC // The trader may return a service offer of a subtype of the "type" // requested. Sub-typing of service types is discussed in "Service // Types" on page 16-4. A service subtype can be described by the // properties of its supertypes. This ensures that a well-formed query // for the "type" is also a well-formed query with respect to any // subtypes. However, if the importer specifies the policy of // exact_type_match = TRUE, then only offers with the exact (no // subtype) service type requested are returned. // END SPEC CosTradingRepos::ServiceTypeRepository::SpecifiedServiceTypes sst; CosTradingRepos::ServiceTypeRepository::ServiceTypeNameSeq_var all_types; // Optimization: Since a subtype can't have a higher incarnation // number than a supertype, we don't need to consider those // types with lower incarnation numbers. sst.incarnation (inc_num); // TAO_TRY // { CORBA::Environment env; all_types = rep->list_types (sst, env); // TAO_CHECK_ENV; // } // TAO_CATCHANY { return; } // TAO_ENDTRY; // Scan all types inserted after the super types. If the transitive // closure of a type's super type relation includes the super type // being considered, then perform a search on that type. CORBA::ULong num_types = all_types->length (); CosTradingRepos::ServiceTypeRepository::TypeStruct_var type_struct; for (CORBA::ULong i = 0; i < num_types && offer_filter.ok_to_consider_more (); i++) { TAO_TRY { // Obtain a description of the prospective type. type_struct = rep->fully_describe_type (all_types[i], TAO_TRY_ENV); TAO_CHECK_ENV; CosTradingRepos::ServiceTypeRepository::ServiceTypeNameSeq& super_types = type_struct->super_types; CORBA::ULong num_super_types = super_types.length (); for (CORBA::ULong j = 0; j < num_super_types; j++) { if (ACE_OS::strcmp (type_struct->super_types[j], type) == 0) { // Egads, a subtype! This type has the type passed // to query in its list of super_types. offer_filter.configure_type (type_struct.ptr ()); this->lookup_one_type (all_types[i], offer_database, constr_inter, pref_inter, offer_filter); break; } } } TAO_CATCHANY { } TAO_ENDTRY; } } template int TAO_Lookup:: fill_receptacles (const char* type, CORBA::ULong how_many, const CosTrading::Lookup::SpecifiedProps& desired_props, TAO_Policies& policies, TAO_Preference_Interpreter& pref_inter, CosTrading::OfferSeq& offers, CosTrading::OfferIterator_ptr& offer_itr, CORBA::Environment& env) TAO_THROW_SPEC ((CosTrading::IllegalPropertyName, CosTrading::DuplicatePropertyName)) { // BEGIN SPEC // The returned offers are passed back in one of two ways (or a // combination of both). ° The "offers" return result conveys a list // of offers and the "offer_itr" is a reference to an interface at // which offers can be obtained. ° The "how_many" parameter states // how many offers are to be returned via the "offers" result, any // remaining offers are available via the iterator interface. If the // "how_many" exceeds the number of offers to be returned, then the // "offer_itr" will be nil. // END SPEC TAO_Property_Filter prop_filter (desired_props, env); TAO_CHECK_ENV_RETURN (env, 0); // RETURNING: Calculate how many offers go into the sequence // Calculate how many go into the iterator CORBA::ULong return_card = policies.return_card (env); TAO_CHECK_ENV_RETURN (env, 0); CORBA::ULong i = 0; CORBA::ULong size = pref_inter.num_offers (); CORBA::ULong offers_in_sequence = (how_many < size) ? how_many : size; CORBA::ULong offers_in_iterator = size - offers_in_sequence; // Ensure the total number of offers returned doesn't exceed return_card. offers_in_sequence = (offers_in_sequence > return_card) ? return_card : offers_in_sequence; return_card -= offers_in_sequence; offers_in_iterator = (offers_in_iterator > return_card) ? return_card : offers_in_iterator; CORBA::ULong total_offers = offers_in_sequence + offers_in_iterator; offers.length (offers_in_sequence); // Add to the sequence, filtering out the undesired properties. for (i = 0; i < offers_in_sequence; i++) { CosTrading::Offer* offer = 0; CosTrading::OfferId offer_id = 0; // Pull the next ordered offer out of the preference interpreter. pref_inter.remove_offer (offer, offer_id); // Filter out the undesired properties. prop_filter.filter_offer (offer, offers[i]); CORBA::string_free (offer_id); } // Any remaining offers under the return_card go into iterator if (offers_in_iterator > 0) { // Create an iterator implementation TAO_Offer_Iterator *oi = this->create_offer_iterator (prop_filter); // Register it with the POA. offer_itr = oi->_this (env); oi->_remove_ref (env); TAO_CHECK_ENV_RETURN (env, total_offers - offers_in_iterator); // Add to the iterator for (i = 0; i < offers_in_iterator; i++) { CosTrading::Offer* offer = 0; CosTrading::OfferId offer_id = 0; // Pull the next ordered offer out of the preference // intrerpreter and add it to the offer iterator. pref_inter.remove_offer (offer, offer_id); oi->add_offer (offer_id, offer); } } // Clear the preference intrerpreter of superfluous items. CORBA::ULong num_offers = pref_inter.num_offers (); for (i = 0; i < num_offers; i++) { CosTrading::Offer* offer = 0; CosTrading::OfferId offer_id = 0; pref_inter.remove_offer (offer, offer_id); CORBA::string_free (offer_id); } return total_offers; } template TAO_Offer_Iterator * TAO_Lookup:: create_offer_iterator (const TAO_Property_Filter& pfilter) { // This is the factory method that creates the appropriate type of // offer iterator. If there's no Register interface, then we can // just stick the offers directly into an iterator, since these // offers will never be removed from the Trader. If there's a // Register interface, then there's a chance that by the time the // importer calls the next_n method on the iterator that the offer // will have been withdrawn. So the Register_Offer_Iterator retains only // the offer ids, and will recognize when an offer id no longer // identifies an offer in the trader. // We pass the property filter to the iterators, so when the iterators // return the offers, they can remove the undesirable properties // from those offers. TAO_Offer_Iterator* iterator = 0; if (CORBA::is_nil (this->trader_.trading_components ().register_if ())) iterator = new TAO_Query_Only_Offer_Iterator (pfilter); else { iterator = new TAO_Register_Offer_Iterator (this->trader_.offer_database (), pfilter); } return iterator; } template CORBA::Boolean TAO_Lookup:: retrieve_links (TAO_Policies& policies, CORBA::ULong offers_returned, CosTrading::LinkNameSeq_out links, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::Lookup::PolicyTypeMismatch)) { CORBA::Boolean should_follow = 0; CosTrading::FollowOption follow_rule = policies.link_follow_rule (TAO_IN_ENV); TAO_CHECK_ENV_RETURN (TAO_IN_ENV, should_follow); // Determine whether or not a federated query is warranted. A query // is waranted if the follow_rule governing this query is 'always' // or if_no_local and the local query returned nothing. if ((follow_rule == CosTrading::always || (follow_rule == CosTrading::if_no_local && offers_returned == 0)) && policies.hop_count (TAO_IN_ENV) > 0) should_follow = 1; if (should_follow) { // Grab the names of all the links in the trader, and push // the suitable ones onto . CosTrading::Link_ptr link_if = this->trader_.trading_components ().link_if (); links = link_if->list_links (TAO_IN_ENV); TAO_CHECK_ENV_RETURN (TAO_IN_ENV, 0); // Determine which of the links registered with the Link // interface are suitable to follow. CORBA::ULong i = 0, j = 0, length = links->length (); for (i = 0; i < length; i++) { // Grab the link information. CosTrading::Link::LinkInfo_var link_info (link_if->describe_link (links[i], TAO_IN_ENV)); TAO_CHECK_ENV_RETURN (TAO_IN_ENV, should_follow); // Compute the link follow rule. CosTrading::FollowOption link_rule = policies.link_follow_rule (link_info.in (), TAO_IN_ENV); TAO_CHECK_ENV_RETURN (TAO_IN_ENV, should_follow); // Determine if the link follow rule applies. if (link_rule == CosTrading::always || (link_rule == CosTrading::if_no_local && offers_returned == 0)) { // Add the link to the list of links to follow. if (i > j) links[j] = links[i]; j++; } } links->length (j); } return should_follow; } template void TAO_Lookup:: federated_query (const CosTrading::LinkNameSeq& links, const TAO_Policies& policies, const CosTrading::Admin::OctetSeq& request_id, TAO_Preference_Interpreter& pref_inter, const char *type, const char *constr, const char *pref, const CosTrading::Lookup::SpecifiedProps& desired_props, CORBA::ULong how_many, CosTrading::OfferSeq& offers, CosTrading::OfferIterator_ptr& offer_iter, CosTrading::PolicyNameSeq& limits, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::IllegalServiceType, CosTrading::UnknownServiceType, CosTrading::IllegalConstraint, CosTrading::Lookup::IllegalPreference, CosTrading::Lookup::IllegalPolicyName, CosTrading::Lookup::PolicyTypeMismatch, CosTrading::Lookup::InvalidPolicyValue, CosTrading::IllegalPropertyName, CosTrading::DuplicatePropertyName, CosTrading::DuplicatePolicyName)) { // The general idea here is this: We've assembled a number of links // to follow, and we'll query each of them in turn. On each query we // adjust the policies for the new trader by reducing the hop_count, // changing the link_follow_rule etc..., and merge the results from // the new query with the results from the previous queries. // We'll need the link and admin interfaces for this part of the // federated query. It's ok to get the admin interface without // checking if it's nil, becase the conformance criteria dictate // that a trader can't implement the link interface without the // admin interface. CosTrading::Link_ptr link_interface = this->trader_.trading_components ().link_if (); // Begin collecting all the various offer_iterators into a // collection. The end result is a distributed tree of offer // iterators, which if traversed in its entirety is probably hugely // inefficient, but oh well, I can't think of a better solution. TAO_Offer_Iterator_Collection* offer_iter_collection; ACE_NEW (offer_iter_collection, TAO_Offer_Iterator_Collection); offer_iter_collection->add_offer_iterator (offer_iter); CosTrading::PolicySeq policies_to_pass; policies.copy_to_pass (policies_to_pass, request_id); for (int i = links.length () - 1; i >= 0; i--) { CosTrading::OfferSeq_ptr out_offers = 0; CosTrading::OfferIterator_ptr out_offer_iter = 0; CosTrading::PolicyNameSeq_ptr out_limits = 0; TAO_TRY { // Obtain information about the link we're traversing. CosTrading::Link::LinkInfo_var link_info = link_interface->describe_link (links[i], TAO_TRY_ENV); TAO_CHECK_ENV; // Set the link follow policy for the query over the link. policies.copy_in_follow_option (policies_to_pass, link_info.in (), TAO_TRY_ENV); TAO_CHECK_ENV; CosTrading::Lookup_var remote_lookup = CosTrading::Lookup::_duplicate (link_info->target.in ()); // Perform the federated query. remote_lookup->query (type, constr, pref, policies_to_pass, desired_props, how_many - offers.length (), CosTrading::OfferSeq_out (out_offers), CosTrading::OfferIterator_out (out_offer_iter), CosTrading::PolicyNameSeq_out (out_limits), TAO_TRY_ENV); TAO_CHECK_ENV; CORBA::ULong j = 0; CosTrading::OfferSeq_var out_offers_var (out_offers); CosTrading::PolicyNameSeq_var out_limits_var (out_limits); // Add another iterator to the collection. if (! CORBA::is_nil (out_offer_iter)) offer_iter_collection->add_offer_iterator (out_offer_iter); // Concatenate the limits applied. CORBA::ULong source_length = out_limits->length (), target_length = limits.length (), total_length = source_length + target_length; limits.length (total_length); for (j = 0; j < source_length; j++) limits[j + target_length] = out_limits_var[j]; // Concatenate the sequence offers. source_length = out_offers->length (); target_length = offers.length (); total_length = source_length + target_length; offers.length (total_length); for (j = 0; j < source_length; j++) offers[j + target_length] = out_offers_var[j]; } TAO_CATCHANY { // Ah, well, this query failed, move on to the next one. } TAO_ENDTRY; } // Sort the sequence in preference order. this->order_merged_sequence (pref_inter, offers); // Return the collection of offer iterators. offer_iter = offer_iter_collection->_this (TAO_IN_ENV); offer_iter_collection->_remove_ref (TAO_IN_ENV); } template void TAO_Lookup:: order_merged_sequence (TAO_Preference_Interpreter& pref_inter, CosTrading::OfferSeq& offers) { CORBA::ULong j = 0; CORBA::ULong length = offers.length (); // Grab ownership of the offers already in the target sequence. CosTrading::Offer* target_buf = offers.get_buffer (1); // Order the sequence. for (j = 0; j < length; j++) pref_inter.order_offer (&target_buf[j]); //pref_inter.order_offer (&offers[j]); // Reallocate the sequence. offers.length (length); // CosTrading::OfferSeq copy; // copy.length (length); // Copy in the ordered offers. for (j = 0; j < length; j++) { CosTrading::Offer* offer = 0; pref_inter.remove_offer (offer); //copy[j] = *offer; offers[j] = *offer; } // Release the orphaned memory. CosTrading::OfferSeq::freebuf (target_buf); // offers = copy } template void TAO_Lookup:: forward_query (const char* next_hop, const char *type, const char *constr, const char *pref, const CosTrading::PolicySeq& policy_seq, const CosTrading::Lookup::SpecifiedProps& desired_props, CORBA::ULong how_many, CosTrading::OfferSeq_out offers, CosTrading::OfferIterator_out offer_itr, CosTrading::PolicyNameSeq_out limits_applied, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::IllegalServiceType, CosTrading::UnknownServiceType, CosTrading::IllegalConstraint, CosTrading::Lookup::IllegalPreference, CosTrading::Lookup::IllegalPolicyName, CosTrading::Lookup::PolicyTypeMismatch, CosTrading::Lookup::InvalidPolicyValue, CosTrading::IllegalPropertyName, CosTrading::DuplicatePropertyName, CosTrading::DuplicatePolicyName)) { // Forward this query to the next link in the starting_trader sequence. CosTrading::Link_ptr link_interface = this->trader_.trading_components ().link_if (); TAO_TRY { CosTrading::Link::LinkInfo_var link_info = link_interface->describe_link (next_hop, TAO_TRY_ENV); TAO_CHECK_ENV; CosTrading::Lookup_var remote_lookup = CosTrading::Lookup::_duplicate (link_info->target.in ()); CORBA::Object_var us = this->_this (TAO_TRY_ENV); TAO_CHECK_ENV; CORBA::Boolean self_loop = remote_lookup->_is_equivalent (us.in (), TAO_TRY_ENV); TAO_CHECK_ENV; if (! self_loop) { // Perform forwarding query. remote_lookup->query (type, constr, pref, policy_seq, desired_props, how_many, offers, offer_itr, limits_applied, TAO_IN_ENV); TAO_CHECK_ENV_RETURN_VOID (TAO_IN_ENV); } else { this->query (type, constr, pref, policy_seq, desired_props, how_many, offers, offer_itr, limits_applied, TAO_IN_ENV); TAO_CHECK_ENV_RETURN_VOID (TAO_IN_ENV); } } TAO_CATCHANY { CosTrading::Policy policy; policy.name = TAO_Policies::POLICY_NAMES[TAO_Policies::STARTING_TRADER]; policy.value <<= next_hop; TAO_THROW (CosTrading::Lookup::InvalidPolicyValue (policy)); } TAO_ENDTRY; } template CORBA::Boolean TAO_Lookup:: seen_request_id (TAO_Policies& policies, CosTrading::Admin::OctetSeq*& seq, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::Lookup::PolicyTypeMismatch)) { CORBA::Boolean return_value = 0; seq = policies.request_id (TAO_IN_ENV); TAO_CHECK_ENV_RETURN (TAO_IN_ENV, 1); if (seq == 0) { CosTrading::Admin_ptr admin_if = this->trader_.trading_components ().admin_if (); seq = admin_if->request_id_stem (TAO_IN_ENV); TAO_CHECK_ENV_RETURN (TAO_IN_ENV, 1); } else { // Allocate memory so memory mangement is the same for both // cases. ACE_NEW_RETURN (seq, CosTrading::Admin::OctetSeq (*seq), 0); } if (seq == 0) TAO_THROW_RETURN (CORBA::NO_MEMORY (), 1); ACE_GUARD_RETURN (TRADER_LOCK_TYPE, trader_mon, this->lock_, 1); for (Request_Ids::ITERATOR riter (this->request_ids_); ! riter.done (); riter.advance ()) { CosTrading::Admin::OctetSeq** old_seq = 0; riter.next (old_seq); if (**old_seq == *seq) { return_value = 1; break; } } if (return_value == 0) { if (this->request_ids_.size () == IDS_SAVED) { CosTrading::Admin::OctetSeq* octet_seq = 0; this->request_ids_.dequeue_head (octet_seq); delete octet_seq; } this->request_ids_.enqueue_tail (seq); } return return_value; } // ************************************************************* // TAO_Register // ************************************************************* template TAO_Register::TAO_Register (TAO_Trader &trader) : TAO_Trader_Components (trader.trading_components ()), TAO_Support_Attributes (trader.support_attributes ()), trader_ (trader) { } template TAO_Register::~TAO_Register (void) { } template CosTrading::OfferId TAO_Register:: _cxx_export (CORBA::Object_ptr reference, const char *type, const CosTrading::PropertySeq &properties, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::Register::InvalidObjectRef, CosTrading::IllegalServiceType, CosTrading::UnknownServiceType, CosTrading::Register::InterfaceTypeMismatch, CosTrading::IllegalPropertyName, CosTrading::PropertyTypeMismatch, CosTrading::ReadonlyDynamicProperty, CosTrading::MissingMandatoryProperty, CosTrading::DuplicatePropertyName)) { // For robustness purposes -- if (CORBA::is_nil (reference)) TAO_THROW_RETURN (CosTrading::Register::InvalidObjectRef (), 0); // Get service type map TAO_Offer_Database &offer_database = this->trader_.offer_database (); CosTrading::Offer* offer = 0; TAO_Support_Attributes_i& support_attrs = this->trader_.support_attributes (); CosTradingRepos::ServiceTypeRepository_ptr rep = support_attrs.service_type_repos (); // Yank our friend, the type struct, and confirm that the given // properties match the type definition. CosTradingRepos::ServiceTypeRepository::TypeStruct_var type_struct = rep->fully_describe_type (type, TAO_IN_ENV); TAO_CHECK_ENV_RETURN (TAO_IN_ENV, 0); // Oops the type is masked, we shouldn't let exporters know the type // exists. if (type_struct->masked) TAO_THROW_RETURN (CosTrading::UnknownServiceType (type), 0); // TAO-specific way to determine if an object is derived from or is // an interface type. if (! reference->_is_a (type_struct->if_name, TAO_IN_ENV)) TAO_THROW_RETURN (CosTrading::Register:: InterfaceTypeMismatch (type, reference), 0); // Validate that the properties defined for this offer are correct // to their types and strength. this->validate_properties (type, type_struct.ptr (), properties, TAO_IN_ENV); TAO_CHECK_ENV_RETURN (TAO_IN_ENV, 0); // CORBA::ULong plength = properties.length (); ACE_NEW_RETURN (offer, CosTrading::Offer, 0); // No copying, no memory leaks. Violates the "in" parameter semantics // when this object is colocated with the client, however. // CosTrading::PropertySeq* hack_seq = // ACE_const_cast (CosTrading::PropertySeq*, &properties); // CosTrading::Property* pbuf = hack_seq->get_buffer (1); // CosTrading::PropertySeq* hack_seq = // ACE_const_cast (CosTrading::PropertySeq*, &properties); // CosTrading::Property* pbuf = hack_seq->get_buffer (0); // offer->properties.replace (plength, plength, pbuf, 0); // offer->properties._allocate_buffer (plength); offer->properties = properties; offer->reference = reference->_duplicate (reference); // Insert the offer into the underlying type map. CosTrading::OfferId id = offer_database.insert_offer (type, offer); return id; } template void TAO_Register:: withdraw (const char *id, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::IllegalOfferId, CosTrading::UnknownOfferId, CosTrading::Register::ProxyOfferId)) { // Get service type map. TAO_Offer_Database &offer_database = this->trader_.offer_database (); offer_database.remove_offer ((CosTrading::OfferId) id, TAO_IN_ENV); } template CosTrading::Register::OfferInfo * TAO_Register:: describe (const char *id, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::IllegalOfferId, CosTrading::UnknownOfferId, CosTrading::Register::ProxyOfferId)) { // Get service type map. char* type = 0; TAO_Offer_Database &offer_database = this->trader_.offer_database (); // Perform a lookup to find the offer. CosTrading::Offer* offer = offer_database.lookup_offer ((CosTrading::OfferId) id, type, TAO_IN_ENV); TAO_CHECK_ENV_RETURN (TAO_IN_ENV, (CosTrading::Register::OfferInfo *) 0); CosTrading::Register::OfferInfo *offer_info = 0; ACE_NEW_RETURN (offer_info, CosTrading::Register::OfferInfo, 0); offer_info->reference = CORBA::Object::_duplicate (offer->reference.in ()); offer_info->type = CORBA::string_dup (type); // Let the offer_info prop_seq "borrow" the sequence of properties. //CORBA::ULong length = offer->properties.length (); // CosTrading::Property* prop_buf = offer->properties.get_buffer (); offer_info->properties = offer->properties; return offer_info; } template void TAO_Register:: modify (const char *id, const CosTrading::PropertyNameSeq& del_list, const CosTrading::PropertySeq& modify_list, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::NotImplemented, CosTrading::IllegalOfferId, CosTrading::UnknownOfferId, CosTrading::Register::ProxyOfferId, CosTrading::IllegalPropertyName, CosTrading::Register::UnknownPropertyName, CosTrading::PropertyTypeMismatch, CosTrading::ReadonlyDynamicProperty, CosTrading::Register::MandatoryProperty, CosTrading::Register::ReadonlyProperty, CosTrading::DuplicatePropertyName)) { // Throw an exception if the trader is not configured // to support properties modification. if (! this->supports_modifiable_properties (TAO_IN_ENV)) TAO_THROW (CosTrading::NotImplemented ()); char* type = 0; TAO_Support_Attributes_i& support_attrs = this->trader_.support_attributes (); CosTradingRepos::ServiceTypeRepository_ptr rep = support_attrs.service_type_repos (); TAO_Offer_Database &offer_database = this->trader_.offer_database (); CosTrading::Offer* offer = offer_database. lookup_offer (ACE_const_cast (CosTrading::OfferId, id), type, TAO_IN_ENV); TAO_CHECK_ENV_RETURN_VOID (TAO_IN_ENV); if (offer != 0) { // Yank our friend, the type struct. CosTradingRepos::ServiceTypeRepository::TypeStruct_var type_struct = rep->fully_describe_type (type, TAO_IN_ENV); TAO_CHECK_ENV_RETURN_VOID (TAO_IN_ENV); TAO_Offer_Modifier offer_mod (type, type_struct.in (), offer); // Delete, add, and change properties of the offer. offer_mod.delete_properties (del_list, TAO_IN_ENV); TAO_CHECK_ENV_RETURN_VOID (TAO_IN_ENV); offer_mod.merge_properties (modify_list, TAO_IN_ENV); TAO_CHECK_ENV_RETURN_VOID (TAO_IN_ENV); // Alter our reference to the offer. We do this last, since the // spec says: modify either suceeds completely or fails // completely. offer_mod.affect_change (modify_list); } } template void TAO_Register:: withdraw_using_constraint (const char *type, const char *constr, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::IllegalServiceType, CosTrading::UnknownServiceType, CosTrading::IllegalConstraint, CosTrading::Register::NoMatchingOffers)) { TAO_Support_Attributes_i& support_attrs = this->trader_.support_attributes (); CosTradingRepos::ServiceTypeRepository_ptr rep = support_attrs.service_type_repos (); TAO_Offer_Database &offer_database = this->trader_.offer_database (); CORBA::Boolean dp_support = support_attrs.supports_dynamic_properties (); TAO_String_Queue ids; // Retrieve the type struct CosTradingRepos::ServiceTypeRepository::TypeStruct_var type_struct = rep->fully_describe_type (type, TAO_IN_ENV); TAO_CHECK_ENV_RETURN_VOID (TAO_IN_ENV); // Try to find the map of offers of desired service type. // @@ Again, should be Offer_Database::offer_iterator { #if defined(_MSC_VER) TAO_Offer_Database::offer_iterator offer_iter (type, offer_database); #else // MSVC won't grok this for some reason, but it's necessary for the // HP compiler, which seriously requires the typename keyword // here. I apologize if this ifdef offends some ACE users' // sensibilities --- it certainly offends mine. ACE_TYPENAME TAO_Offer_Database::offer_iterator offer_iter (type, offer_database); #endif TAO_Constraint_Validator validator (type_struct.in ()); TAO_Constraint_Interpreter constr_inter (validator, constr, TAO_IN_ENV); TAO_CHECK_ENV_RETURN_VOID (TAO_IN_ENV); while (offer_iter.has_more_offers ()) { CosTrading::Offer* offer = offer_iter.get_offer (); // Add offer if it matches the constraints TAO_Constraint_Evaluator evaluator (offer, dp_support); if (constr_inter.evaluate (evaluator)) ids.enqueue_tail (offer_iter.get_id ()); offer_iter.next_offer (); } } if (ids.size () != 0) { while (! ids.is_empty ()) { char* offer_id = 0; ids.dequeue_head (offer_id); offer_database.remove_offer (offer_id, TAO_IN_ENV); CORBA::string_free (offer_id); } } else TAO_THROW (CosTrading::Register::NoMatchingOffers (constr)); } template CosTrading::Register_ptr TAO_Register:: resolve (const CosTrading::TraderName &name, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::Register::IllegalTraderName, CosTrading::Register::UnknownTraderName, CosTrading::Register::RegisterNotSupported)) { // Determine if the first link is a legal link name. if (! TAO_Trader_Base::is_valid_identifier_name (name[0])) TAO_THROW_RETURN (CosTrading::Register::IllegalTraderName (name), CosTrading::Register::_nil ()); // Grab a reference to the link interface, and get a link description. CosTrading::Link_ptr link_if = this->trader_.trading_components ().link_if (); // Ensure that the link interface is supported. if (! CORBA::is_nil (link_if)) return CosTrading::Register::_nil (); CosTrading::Link::LinkInfo_var link_info; CosTrading::Register_var remote_reg; TAO_TRY { // Ensure that the link to the next trader exists. link_info = link_if->describe_link (name[0], TAO_TRY_ENV); TAO_CHECK_ENV; remote_reg = CosTrading::Register::_narrow (link_info->target_reg.in (), TAO_TRY_ENV); TAO_CHECK_ENV; } TAO_CATCHANY { TAO_THROW_RETURN (CosTrading::Register::UnknownTraderName (name), CosTrading::Register::_nil ()); } TAO_ENDTRY; // Ensure that the register pointer isn't nil. if (! CORBA::is_nil (remote_reg.in ())) TAO_THROW_RETURN (CosTrading::Register::RegisterNotSupported (name), CosTrading::Register::_nil ()); CosTrading::Register_ptr return_value = remote_reg.in (); if (name.length () > 1) { // Create a new Trader Name with the first link removed. CosTrading::TraderName trader_name (name.length () - 1); for (int i = trader_name.length () - 1; i >= 0; i--) trader_name[i] = name[i + 1]; return_value = remote_reg->resolve (trader_name, TAO_IN_ENV); TAO_CHECK_ENV_RETURN (TAO_IN_ENV, CosTrading::Register::_nil ()); } return return_value; } template void TAO_Register:: validate_properties (const char* type, const CosTradingRepos::ServiceTypeRepository::TypeStruct* type_struct, const CosTrading::PropertySeq& properties, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CosTrading::IllegalPropertyName, CosTrading::PropertyTypeMismatch, CosTrading::ReadonlyDynamicProperty, CosTrading::MissingMandatoryProperty, CosTrading::DuplicatePropertyName)) { CORBA::ULong length = properties.length (); const CosTradingRepos::ServiceTypeRepository::PropStructSeq& prop_types = type_struct->props; TAO_Property_Evaluator_By_Name prop_eval (properties, TAO_IN_ENV); TAO_CHECK_ENV_RETURN_VOID (TAO_IN_ENV); // Perform property validation length = prop_types.length (); for (CORBA::ULong i = 0; i < length; i++) { const CosTradingRepos::ServiceTypeRepository::PropStruct& prop_struct = prop_types[i]; const char* prop_name = prop_struct.name; // Obtain the type of the exported property. CORBA::TypeCode_var prop_type = prop_eval.property_type (prop_name); if (CORBA::is_nil (prop_type.in ())) { // Offer cannot have a missing mandatory property. if (prop_types[i].mode == CosTradingRepos::ServiceTypeRepository::PROP_MANDATORY) TAO_THROW (CosTrading::MissingMandatoryProperty (type, prop_name)); } else { if (! prop_type->equal (prop_struct.value_type.in (), TAO_IN_ENV)) { // Offer cannot redefine the type of an property. const CosTrading::Property* prop = prop_eval.get_property (prop_name); TAO_THROW (CosTrading::PropertyTypeMismatch (type, *prop)); } else if (prop_struct.mode == CosTradingRepos::ServiceTypeRepository::PROP_READONLY && prop_eval.is_dynamic_property (prop_name)) TAO_THROW (CosTrading::ReadonlyDynamicProperty (type, prop_name)); } } } // ************************************************************* // TAO_Admin // ************************************************************* template TAO_Admin:: TAO_Admin (TAO_Trader &trader) : TAO_Trader_Components (trader.trading_components ()), TAO_Support_Attributes (trader.support_attributes ()), TAO_Import_Attributes (trader.import_attributes ()), TAO_Link_Attributes (trader.link_attributes ()), trader_ (trader), sequence_number_ (0) { // A random 4-bytes will prefix the sequence number space for each // trader, making it extremely unlikely that the sequence spaces for // two traders will over lap. // @@ TODO: This is a bad way to generate pseudo random numbers. // Ok, then, Carlos, we'll do it a different way: ip addr + pid. ACE_UINT32 ip_addr = 0; ASYS_TCHAR host_name[BUFSIZ]; if (ACE_OS::hostname (host_name, BUFSIZ) != -1) { ACE_INET_Addr addr ((u_short) 0, host_name); ip_addr = addr.get_ip_address (); } // The better way to do unique stem identifiers. this->stem_id_.length (12); if (ip_addr != 0) { pid_t pid = ACE_OS::getpid (); this->stem_id_[0] = ACE_static_cast (CORBA::Octet, (ip_addr >> 24) & 0xff); this->stem_id_[1] = ACE_static_cast (CORBA::Octet, (ip_addr >> 16) & 0xff); this->stem_id_[2] = ACE_static_cast (CORBA::Octet, (ip_addr >> 8) & 0xff); this->stem_id_[3] = ACE_static_cast (CORBA::Octet, ip_addr & 0xff); this->stem_id_[4] = ACE_static_cast (CORBA::Octet, (pid >> 24) & 0xff); this->stem_id_[5] = ACE_static_cast (CORBA::Octet, (pid >> 16) & 0xff); this->stem_id_[6] = ACE_static_cast (CORBA::Octet, (pid >> 8) & 0xff); this->stem_id_[7] = ACE_static_cast (CORBA::Octet, pid & 0xff); } // The default way -- eight random integers. else { size_t time_value = ACE_OS::time (); ACE_OS::srand (ACE_static_cast (u_int, time_value)); this->stem_id_[0] = ACE_static_cast (CORBA::Octet, ACE_OS::rand () % 256); this->stem_id_[1] = ACE_static_cast (CORBA::Octet, ACE_OS::rand () % 256); this->stem_id_[2] = ACE_static_cast (CORBA::Octet, ACE_OS::rand () % 256); this->stem_id_[3] = ACE_static_cast (CORBA::Octet, ACE_OS::rand () % 256); this->stem_id_[4] = ACE_static_cast (CORBA::Octet, ACE_OS::rand () % 256); this->stem_id_[5] = ACE_static_cast (CORBA::Octet, ACE_OS::rand () % 256); this->stem_id_[6] = ACE_static_cast (CORBA::Octet, ACE_OS::rand () % 256); this->stem_id_[7] = ACE_static_cast (CORBA::Octet, ACE_OS::rand () % 256); } } template TAO_Admin::~TAO_Admin (void) { } template CosTrading::Admin::OctetSeq * TAO_Admin::request_id_stem (CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { ACE_GUARD_RETURN (TRADER_LOCK_TYPE, trader_mon, this->lock_, 0); // Add one to the sequence_number and concatenate it to the unique // prefix. The sequence number is four octets long, the unique // prefix, also 4 bytes long. this->stem_id_[8] = this->sequence_number_ & 0xff; this->stem_id_[9] = (this->sequence_number_ >> 8) & 0xff; this->stem_id_[10] = (this->sequence_number_ >> 16) & 0xff; this->stem_id_[11] = (this->sequence_number_ >> 24) & 0xff; // Increment the sequence number and return a copy of the stem_id. this->sequence_number_++; return new CosTrading::Admin::OctetSeq (this->stem_id_); } template CORBA::ULong TAO_Admin:: set_def_search_card (CORBA::ULong value, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CORBA::ULong return_value = this->trader_.import_attributes ().def_search_card (); this->trader_.import_attributes ().def_search_card (value); return return_value; } template CORBA::ULong TAO_Admin:: set_max_search_card (CORBA::ULong value, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CORBA::ULong return_value = this->trader_.import_attributes ().max_search_card (); this->trader_.import_attributes ().max_search_card (value); return return_value; } template CORBA::ULong TAO_Admin:: set_def_match_card (CORBA::ULong value, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CORBA::ULong return_value = this->trader_.import_attributes ().def_match_card (); this->trader_.import_attributes ().def_match_card (value); return return_value; } template CORBA::ULong TAO_Admin:: set_max_match_card (CORBA::ULong value, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CORBA::ULong return_value = this->trader_.import_attributes ().max_match_card (); this->trader_.import_attributes ().max_match_card (value); return return_value; } template CORBA::ULong TAO_Admin:: set_def_return_card (CORBA::ULong value, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CORBA::ULong return_value = this->trader_.import_attributes ().def_return_card (); this->trader_.import_attributes ().def_return_card (value); return return_value; } template CORBA::ULong TAO_Admin:: set_max_return_card (CORBA::ULong value, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CORBA::ULong return_value = this->trader_.import_attributes ().max_return_card (); this->trader_.import_attributes ().max_return_card (value); return return_value; } template CORBA::ULong TAO_Admin:: set_max_list (CORBA::ULong value, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CORBA::ULong return_value = this->trader_.import_attributes ().max_list (); this->trader_.import_attributes ().max_list (value); return return_value; } template CORBA::Boolean TAO_Admin:: set_supports_modifiable_properties (CORBA::Boolean value, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CORBA::Boolean return_value = this->trader_.support_attributes ().supports_modifiable_properties (); this->trader_.support_attributes ().supports_modifiable_properties (value); return return_value; } template CORBA::Boolean TAO_Admin:: set_supports_dynamic_properties (CORBA::Boolean value, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CORBA::Boolean return_value = this->trader_.support_attributes ().supports_dynamic_properties (); this->trader_.support_attributes ().supports_dynamic_properties (value); return return_value; } template CORBA::Boolean TAO_Admin:: set_supports_proxy_offers (CORBA::Boolean value, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CORBA::Boolean return_value = this->trader_.support_attributes ().supports_proxy_offers (); this->trader_.support_attributes ().supports_proxy_offers (value); return return_value; } template CORBA::ULong TAO_Admin:: set_def_hop_count (CORBA::ULong value, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CORBA::ULong return_value = this->trader_.import_attributes ().def_hop_count (); this->trader_.import_attributes ().def_hop_count (value); return return_value; } template CORBA::ULong TAO_Admin:: set_max_hop_count (CORBA::ULong value, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CORBA::ULong return_value = this->trader_.import_attributes ().max_hop_count (); this->trader_.import_attributes ().max_hop_count (value); return return_value; } template CosTrading::FollowOption TAO_Admin:: set_def_follow_policy (CosTrading::FollowOption policy, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CosTrading::FollowOption return_value = this->trader_.import_attributes ().def_follow_policy (); this->trader_.import_attributes ().def_follow_policy (policy); return return_value; } template CosTrading::FollowOption TAO_Admin:: set_max_follow_policy (CosTrading::FollowOption policy, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CosTrading::FollowOption return_value = this->trader_.import_attributes ().max_follow_policy (); this->trader_.import_attributes ().max_follow_policy (policy); return return_value; } template CosTrading::FollowOption TAO_Admin:: set_max_link_follow_policy (CosTrading::FollowOption policy, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CosTrading::FollowOption return_value = this->trader_.link_attributes ().max_link_follow_policy (); this->trader_.link_attributes ().max_link_follow_policy (policy); return return_value; } template CosTrading::TypeRepository_ptr TAO_Admin:: set_type_repos (CosTrading::TypeRepository_ptr repository, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { CosTrading::TypeRepository_ptr return_value = this->trader_.support_attributes ().type_repos (); this->trader_.support_attributes ().type_repos (repository); return return_value; } template CosTrading::Admin::OctetSeq* TAO_Admin:: set_request_id_stem (const CosTrading::Admin::OctetSeq& stem, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { ACE_GUARD_RETURN (TRADER_LOCK_TYPE, trader_mon, this->lock_, &this->stem_id_); this->stem_id_ = stem; return &this->stem_id_; } template void TAO_Admin:: list_offers (CORBA::ULong how_many, CosTrading::OfferIdSeq_out ids, CosTrading::OfferIdIterator_out id_itr, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::NotImplemented)) { // This method only applies when the register interface is implemented if (CORBA::is_nil (this->trader_.trading_components().register_if())) TAO_THROW (CosTrading::NotImplemented()); TAO_Offer_Database& type_map = this->trader_.offer_database (); TAO_Offer_Id_Iterator* offer_id_iter = type_map.retrieve_all_offer_ids (); id_itr = CosTrading::OfferIdIterator::_nil (); if (how_many > 0) { if (offer_id_iter->next_n (how_many, ids, TAO_IN_ENV) == 1) { id_itr = offer_id_iter->_this (TAO_IN_ENV); offer_id_iter->_remove_ref (TAO_IN_ENV); TAO_CHECK_ENV_RETURN_VOID (TAO_IN_ENV); } else delete offer_id_iter; } else ids = new CosTrading::OfferIdSeq (0); } template void TAO_Admin:: list_proxies (CORBA::ULong how_many, CosTrading::OfferIdSeq_out ids, CosTrading::OfferIdIterator_out id_itr, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::NotImplemented)) { TAO_THROW (CosTrading::NotImplemented ()); } // ************************************************************* // TAO_Link // ************************************************************* template TAO_Link::TAO_Link (TAO_Trader &trader) : TAO_Trader_Components (trader.trading_components ()), TAO_Support_Attributes (trader.support_attributes ()), TAO_Link_Attributes (trader.link_attributes ()), trader_ (trader) { } template TAO_Link::~TAO_Link (void) { } template void TAO_Link:: add_link (const char *name, CosTrading::Lookup_ptr target, CosTrading::FollowOption def_pass_on_follow_rule, CosTrading::FollowOption limiting_follow_rule, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::Link::IllegalLinkName, CosTrading::Link::DuplicateLinkName, CosTrading::InvalidLookupRef, CosTrading::Link::DefaultFollowTooPermissive, CosTrading::Link::LimitingFollowTooPermissive)) { // Ensure the link name is valid. if (! TAO_Trader_Base::is_valid_identifier_name (name)) TAO_THROW (CosTrading::Link::IllegalLinkName (name)); // Ensure this isn't a duplicate link name. TAO_String_Hash_Key link_name (name); if (this->links_.find (link_name) == 0) TAO_THROW (CosTrading::Link::DuplicateLinkName (name)); // Ensure the lookup_ptr isn't nil. if (CORBA::is_nil (target)) TAO_THROW (CosTrading::InvalidLookupRef (target)); // Ensure that the default link behavior isn't stronger than the // limiting link behavior. if (def_pass_on_follow_rule > limiting_follow_rule) TAO_THROW (CosTrading::Link::DefaultFollowTooPermissive (def_pass_on_follow_rule, limiting_follow_rule)); // Ensure that the limiting link behavior for this link doesn't // exceed the maximum allowed for a link. if (limiting_follow_rule < this->max_link_follow_policy (TAO_IN_ENV)) TAO_THROW (CosTrading::Link::LimitingFollowTooPermissive (limiting_follow_rule, this->max_link_follow_policy (TAO_IN_ENV))); // Create a link info structure for this link of the federation. CosTrading::Link::LinkInfo link_info; link_info.target = CosTrading::Lookup::_duplicate (target); link_info.def_pass_on_follow_rule = def_pass_on_follow_rule; link_info.limiting_follow_rule = limiting_follow_rule; TAO_CHECK_ENV_RETURN_VOID (TAO_IN_ENV); // Insert this link into the collection of links. this->links_.bind (link_name, link_info); } template void TAO_Link:: remove_link (const char *name, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::Link::IllegalLinkName, CosTrading::Link::UnknownLinkName)) { // Ensure the link name is valid. if (! TAO_Trader_Base::is_valid_identifier_name (name)) TAO_THROW (CosTrading::Link::IllegalLinkName (name)); // Ensure this isn't a duplicate link name. TAO_String_Hash_Key link_name (name); if (this->links_.find (link_name) == -1) TAO_THROW (CosTrading::Link::UnknownLinkName (name)); // Erase the link state from the map. this->links_.unbind (link_name); } template CosTrading::Link::LinkInfo * TAO_Link::describe_link (const char *name, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::Link::IllegalLinkName, CosTrading::Link::UnknownLinkName)) { // Ensure the link name is valid. if (! TAO_Trader_Base::is_valid_identifier_name (name)) TAO_THROW_RETURN (CosTrading::Link::IllegalLinkName (name), 0); // Ensure this isn't a duplicate link name. ACE_TYPENAME Links::ENTRY* link_entry = 0; TAO_String_Hash_Key link_name (name); if (this->links_.find (link_name, link_entry) == -1) TAO_THROW_RETURN (CosTrading::Link::UnknownLinkName (name), 0); // Build a new Link Info structure. CosTrading::Link::LinkInfo* new_link_info = 0; CosTrading::Link::LinkInfo& old_link_info = link_entry->int_id_; ACE_NEW_RETURN (new_link_info, CosTrading::Link::LinkInfo, 0); new_link_info->def_pass_on_follow_rule = old_link_info.def_pass_on_follow_rule; new_link_info->limiting_follow_rule = old_link_info.limiting_follow_rule; new_link_info->target = old_link_info.target; // Delayed retrieval of register interface. // This avoids the nested upcall that would occur were we to invoke // this method in the add_link method. new_link_info->target_reg = old_link_info.target->register_if (TAO_IN_ENV); TAO_CHECK_ENV_RETURN (TAO_IN_ENV, new_link_info); // return the link information for this link name. return new_link_info; } template CosTrading::LinkNameSeq* TAO_Link::list_links (CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException)) { // Allocate space for the link names. CORBA::ULong size = this->links_.current_size (), i = 0; CosTrading::LinkName* link_seq = CosTrading::LinkNameSeq::allocbuf (size); // Copy the link names into the buffer. for (ACE_TYPENAME Links::iterator links_iter (this->links_); ! links_iter.done (); links_iter++) link_seq[i++] = CORBA::string_dup ((*links_iter).ext_id_.in ()); // Return a sequence of the buf names. return new CosTrading::LinkNameSeq (i, i, link_seq, 1); } template void TAO_Link:: modify_link (const char *name, CosTrading::FollowOption def_pass_on_follow_rule, CosTrading::FollowOption limiting_follow_rule, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CosTrading::Link::IllegalLinkName, CosTrading::Link::UnknownLinkName, CosTrading::Link::DefaultFollowTooPermissive, CosTrading::Link::LimitingFollowTooPermissive)) { // Ensure the link name is valid. if (! TAO_Trader_Base::is_valid_identifier_name (name)) TAO_THROW (CosTrading::Link::IllegalLinkName (name)); // Ensure this isn't a duplicate link name. ACE_TYPENAME Links::ENTRY* link_entry = 0; TAO_String_Hash_Key link_name (name); if (this->links_.find (link_name, link_entry) == -1) TAO_THROW (CosTrading::Link::UnknownLinkName (name)); // Ensure that the default link behavior isn't stronger than the // limiting link behavior. if (def_pass_on_follow_rule > limiting_follow_rule) TAO_THROW (CosTrading::Link::DefaultFollowTooPermissive (def_pass_on_follow_rule, limiting_follow_rule)); // Ensure that the limiting link behavior for this link doesn't // exceed the maximum allowed for a link. if (limiting_follow_rule < this->max_link_follow_policy (TAO_IN_ENV)) TAO_THROW (CosTrading::Link::LimitingFollowTooPermissive (limiting_follow_rule, this->max_link_follow_policy (TAO_IN_ENV))); // Adjust the link settings CosTrading::Link::LinkInfo& link_info = link_entry->int_id_; link_info.def_pass_on_follow_rule = def_pass_on_follow_rule; link_info.limiting_follow_rule = limiting_follow_rule; } // ************************************************************* // TAO_Proxy // ************************************************************* template TAO_Proxy:: TAO_Proxy (TAO_Trader &trader) : TAO_Trader_Components (trader.trading_components ()), TAO_Support_Attributes (trader.support_attributes ()), trader_ (trader) { } template TAO_Proxy::~TAO_Proxy (void) { } template CosTrading::OfferId TAO_Proxy:: export_proxy (CosTrading::Lookup_ptr target, const char *type, const CosTrading::PropertySeq& properties, CORBA::Boolean if_match_all, const char * recipe, const CosTrading::PolicySeq& policies_to_pass_on, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::IllegalServiceType, CosTrading::UnknownServiceType, CosTrading::InvalidLookupRef, CosTrading::IllegalPropertyName, CosTrading::PropertyTypeMismatch, CosTrading::ReadonlyDynamicProperty, CosTrading::MissingMandatoryProperty, CosTrading::Proxy::IllegalRecipe, CosTrading::DuplicatePropertyName, CosTrading::DuplicatePolicyName)) { TAO_THROW_RETURN (CORBA::UNKNOWN (), 0); } template void TAO_Proxy:: withdraw_proxy (const char *id, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::IllegalOfferId, CosTrading::UnknownOfferId, CosTrading::Proxy::NotProxyOfferId)) { TAO_THROW (CORBA::UNKNOWN ()); } template CosTrading::Proxy::ProxyInfo * TAO_Proxy:: describe_proxy (const char *id, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::IllegalOfferId, CosTrading::UnknownOfferId, CosTrading::Proxy::NotProxyOfferId)) { TAO_THROW_RETURN (CORBA::UNKNOWN (), 0); } template void TAO_Proxy:: list_proxies (CORBA::ULong how_many, CosTrading::OfferIdSeq*& ids, CosTrading::OfferIdIterator_ptr& id_itr, CORBA::Environment& TAO_IN_ENV) TAO_THROW_SPEC ((CORBA::SystemException, CosTrading::NotImplemented)) { TAO_THROW (CORBA::UNKNOWN ()); } #endif /* TAO_TRADER_INTERFACES_C */