summaryrefslogtreecommitdiff
path: root/TAO/orbsvcs/orbsvcs/Trader/Trader_Interfaces.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/Trader/Trader_Interfaces.cpp')
-rw-r--r--TAO/orbsvcs/orbsvcs/Trader/Trader_Interfaces.cpp1940
1 files changed, 1940 insertions, 0 deletions
diff --git a/TAO/orbsvcs/orbsvcs/Trader/Trader_Interfaces.cpp b/TAO/orbsvcs/orbsvcs/Trader/Trader_Interfaces.cpp
new file mode 100644
index 00000000000..393d73a2e83
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/Trader/Trader_Interfaces.cpp
@@ -0,0 +1,1940 @@
+// $Id$
+
+#ifndef TAO_TRADER_INTERFACES_CPP
+#define TAO_TRADER_INTERFACES_CPP
+
+#include "orbsvcs/Trader/Trader_Interfaces.h"
+#include "orbsvcs/Trader/Trader_T.h"
+#include "ace/INET_Addr.h"
+#include "orbsvcs/Trader/Trader_Constraint_Visitors.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+TAO_Lookup<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+TAO_Lookup (TAO_Trader<TRADER_LOCK_TYPE,MAP_LOCK_TYPE> &trader)
+ : TAO_Trader_Components<POA_CosTrading::Lookup> (trader.trading_components ()),
+ TAO_Support_Attributes<POA_CosTrading::Lookup> (trader.support_attributes ()),
+ TAO_Import_Attributes<POA_CosTrading::Lookup> (trader.import_attributes ()),
+ IDS_SAVED (100),
+ trader_ (trader)
+{
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+TAO_Lookup<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::~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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE> void
+TAO_Lookup<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+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
+ ACE_ENV_ARG_DECL)
+ ACE_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 ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // If a federated query returns to us, ignore it to prevent
+ // redundant results and infinite loops.
+ CosTrading::Admin::OctetSeq* request_id = 0;
+ int check = this->seen_request_id (policies, request_id ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ if (check)
+ {
+ returned_offers = new CosTrading::OfferSeq;
+ returned_limits_applied = new CosTrading::PolicyNameSeq;
+ return;
+ }
+
+ // 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 (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+
+ 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
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ 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 ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // @@ Should throw a NO_MEMORY exception here...
+ ACE_NEW (returned_offers,
+ CosTrading::OfferSeq);
+
+ // Obtain a reference to the offer database.
+ TAO_Offer_Database<MAP_LOCK_TYPE>& 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
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ TAO_Trader_Constraint_Validator validator (type_struct.in ());
+ TAO_Constraint_Interpreter constr_inter (validator,
+ constraint
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ TAO_Preference_Interpreter pref_inter (validator,
+ preferences
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // 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);
+
+ CORBA::Boolean result = policies.exact_type_match (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+
+ if (!result)
+ {
+ // 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.
+ this->lookup_all_subtypes (type,
+ type_struct->incarnation,
+ offer_database,
+ rep,
+ constr_inter,
+ pref_inter,
+ offer_filter
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+ // 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
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // 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 ())
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ 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 ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ }
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Lookup<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+lookup_one_type (const char* type,
+ TAO_Offer_Database<MAP_LOCK_TYPE>& 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<MAP_LOCK_TYPE>::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<MAP_LOCK_TYPE>::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_Trader_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Lookup<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+lookup_all_subtypes (const char* type,
+ CosTradingRepos::ServiceTypeRepository::IncarnationNumber& inc_num,
+ TAO_Offer_Database<MAP_LOCK_TYPE>& offer_database,
+ CosTradingRepos::ServiceTypeRepository_ptr rep,
+ TAO_Constraint_Interpreter& constr_inter,
+ TAO_Preference_Interpreter& pref_inter,
+ TAO_Offer_Filter& offer_filter
+ ACE_ENV_ARG_DECL)
+{
+ // 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);
+
+ all_types = rep->list_types (sst ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // 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++)
+ {
+ // Obtain a description of the prospective type.
+ type_struct = rep->fully_describe_type (all_types[i]
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ 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;
+ }
+ }
+ }
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+int
+TAO_Lookup<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+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
+ ACE_ENV_ARG_DECL)
+ ACE_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 ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // RETURNING: Calculate how many offers go into the sequence
+ // Calculate how many go into the iterator
+
+ CORBA::ULong return_card = policies.return_card (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ CORBA::ULong i = 0;
+ CORBA::ULong size = static_cast<CORBA::ULong> (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 (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (total_offers - offers_in_iterator);
+
+ oi->_remove_ref (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (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.
+ size_t num_offers = pref_inter.num_offers ();
+ for (size_t j = 0; j < num_offers; j++)
+ {
+ 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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+TAO_Offer_Iterator *
+TAO_Lookup<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+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 ()))
+ ACE_NEW_RETURN (iterator,
+ TAO_Query_Only_Offer_Iterator (pfilter),
+ 0);
+ else
+ ACE_NEW_RETURN (iterator,
+ TAO_Register_Offer_Iterator<MAP_LOCK_TYPE> (this->trader_.offer_database (),
+ pfilter),
+ 0);
+ return iterator;
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CORBA::Boolean
+TAO_Lookup<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+retrieve_links (TAO_Policies& policies,
+ CORBA::ULong offers_returned,
+ CosTrading::LinkNameSeq_out links
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ CosTrading::Lookup::PolicyTypeMismatch))
+{
+ CORBA::Boolean should_follow = 0;
+ CosTrading::FollowOption follow_rule = policies.link_follow_rule (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (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)))
+ {
+ CORBA::ULong hc = policies.hop_count (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ if (hc > 0)
+ should_follow = 1;
+ }
+
+ if (should_follow)
+ {
+ // Grab the names of all the links in the trader, and push
+ // the suitable ones onto <valid_links>.
+ CosTrading::Link_ptr link_if =
+ this->trader_.trading_components ().link_if ();
+
+ links = link_if->list_links (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (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] ACE_ENV_ARG_PARAMETER));
+ ACE_CHECK_RETURN (should_follow);
+
+ // Compute the link follow rule.
+ CosTrading::FollowOption link_rule =
+ policies.link_follow_rule (link_info.in () ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Lookup<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+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
+ ACE_ENV_ARG_DECL)
+ ACE_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 = 0;
+ 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 ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ for (int i = links.length () - 1; i >= 0; i--)
+ {
+ CosTrading::OfferSeq *out_offers = 0;
+ CosTrading::OfferIterator *out_offer_iter = 0;
+ CosTrading::PolicyNameSeq *out_limits = 0;
+
+ ACE_TRY
+ {
+ // Obtain information about the link we're traversing.
+ CosTrading::Link::LinkInfo_var link_info =
+ link_interface->describe_link (links[i] ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Set the link follow policy for the query over the link.
+ policies.copy_in_follow_option (policies_to_pass,
+ link_info.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ 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)
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ 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];
+ }
+ ACE_CATCHANY
+ {
+ // Ah, well, this query failed, move on to the next one.
+ }
+ ACE_ENDTRY;
+ // ACE_CHECK;
+ }
+
+ // 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 (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+
+ offer_iter_collection->_remove_ref (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Lookup<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Lookup<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+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
+ ACE_ENV_ARG_DECL)
+ ACE_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 ();
+
+ ACE_TRY
+ {
+ CosTrading::Link::LinkInfo_var link_info =
+ link_interface->describe_link (next_hop ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CosTrading::Lookup_var remote_lookup =
+ CosTrading::Lookup::_duplicate (link_info->target.in ());
+
+ CORBA::Object_var us = this->_this (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::Boolean self_loop =
+ remote_lookup->_is_equivalent (us.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (! self_loop)
+ {
+ // Perform forwarding query.
+ remote_lookup->query (type,
+ constr,
+ pref,
+ policy_seq,
+ desired_props,
+ how_many,
+ offers,
+ offer_itr,
+ limits_applied
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ else
+ {
+ this->query (type,
+ constr,
+ pref,
+ policy_seq,
+ desired_props,
+ how_many,
+ offers,
+ offer_itr,
+ limits_applied
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ }
+ ACE_CATCHANY
+ {
+ CosTrading::Policy policy;
+ policy.name = TAO_Policies::POLICY_NAMES[TAO_Policies::STARTING_TRADER];
+ policy.value <<= next_hop;
+ ACE_TRY_THROW (CosTrading::Lookup::InvalidPolicyValue (policy));
+ }
+ ACE_ENDTRY;
+ // ACE_CHECK;
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CORBA::Boolean
+TAO_Lookup<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+seen_request_id (TAO_Policies& policies,
+ CosTrading::Admin::OctetSeq*& seq
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ CosTrading::Lookup::PolicyTypeMismatch))
+{
+ CORBA::Boolean return_value = 0;
+
+ seq = policies.request_id (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (1);
+
+ if (seq == 0)
+ {
+ CosTrading::Admin_ptr admin_if =
+ this->trader_.trading_components ().admin_if ();
+ seq = admin_if->request_id_stem (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (1);
+ }
+ else
+ {
+ // Allocate memory so memory mangement is the same for both
+ // cases.
+ ACE_NEW_THROW_EX (seq,
+ CosTrading::Admin::OctetSeq (*seq),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (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;
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+TAO_Register<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::TAO_Register (TAO_Trader<TRADER_LOCK_TYPE,MAP_LOCK_TYPE> &trader)
+ : TAO_Trader_Components<POA_CosTrading::Register> (trader.trading_components ()),
+ TAO_Support_Attributes<POA_CosTrading::Register> (trader.support_attributes ()),
+ trader_ (trader)
+{
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+TAO_Register<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::~TAO_Register (void)
+{
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CosTrading::OfferId
+TAO_Register<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+_cxx_export (CORBA::Object_ptr reference,
+ const char *type,
+ const CosTrading::PropertySeq &properties
+ ACE_ENV_ARG_DECL)
+ ACE_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))
+ ACE_THROW_RETURN (CosTrading::Register::InvalidObjectRef (), 0);
+
+ // Get service type map
+ TAO_Offer_Database<MAP_LOCK_TYPE> &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 ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // Oops the type is masked, we shouldn't let exporters know the type
+ // exists.
+ if (type_struct->masked)
+ ACE_THROW_RETURN (CosTrading::UnknownServiceType (type), 0);
+
+ // TAO-specific way to determine if an object is derived from or is
+ // an interface type.
+ int check = (! reference->_is_a (type_struct->if_name ACE_ENV_ARG_PARAMETER));
+ ACE_CHECK_RETURN (0);
+ if (check)
+ ACE_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 ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // CORBA::ULong plength = properties.length ();
+ ACE_NEW_THROW_EX (offer, CosTrading::Offer, CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (0);
+
+ // No copying, no memory leaks. Violates the "in" parameter semantics
+ // when this object is colocated with the client, however.
+ // CosTrading::PropertySeq* hack_seq =
+ // const_cast<CosTrading::PropertySeq*> (&properties);
+ // CosTrading::Property* pbuf = hack_seq->get_buffer (1);
+
+ // CosTrading::PropertySeq* hack_seq =
+ // 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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Register<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+withdraw (const char *id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ CosTrading::IllegalOfferId,
+ CosTrading::UnknownOfferId,
+ CosTrading::Register::ProxyOfferId))
+{
+ // Get service type map.
+ TAO_Offer_Database<MAP_LOCK_TYPE> &offer_database = this->trader_.offer_database ();
+ offer_database.remove_offer ((CosTrading::OfferId) id ACE_ENV_ARG_PARAMETER);
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CosTrading::Register::OfferInfo *
+TAO_Register<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+describe (const char *id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ CosTrading::IllegalOfferId,
+ CosTrading::UnknownOfferId,
+ CosTrading::Register::ProxyOfferId))
+{
+ // Get service type map.
+ char* type = 0;
+ TAO_Offer_Database<MAP_LOCK_TYPE> &offer_database = this->trader_.offer_database ();
+
+ // Perform a lookup to find the offer.
+ CosTrading::Offer* offer =
+ offer_database.lookup_offer ((CosTrading::OfferId) id, type ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ CosTrading::Register::OfferInfo *offer_info = 0;
+ ACE_NEW_THROW_EX (offer_info, CosTrading::Register::OfferInfo, CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Register<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+modify (const char *id,
+ const CosTrading::PropertyNameSeq& del_list,
+ const CosTrading::PropertySeq& modify_list
+ ACE_ENV_ARG_DECL)
+ ACE_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.
+ int check = (! this->supports_modifiable_properties (ACE_ENV_SINGLE_ARG_PARAMETER));
+ ACE_CHECK;
+
+ if (check)
+ ACE_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<MAP_LOCK_TYPE> &offer_database = this->trader_.offer_database ();
+
+ CosTrading::Offer* offer = offer_database.
+ lookup_offer (const_cast<CosTrading::OfferId> (id), type ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ if (offer != 0)
+ {
+ // Yank our friend, the type struct.
+ CosTradingRepos::ServiceTypeRepository::TypeStruct_var type_struct =
+ rep->fully_describe_type (type ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ TAO_Offer_Modifier offer_mod (type, type_struct.in (), offer);
+
+ // Delete, add, and change properties of the offer.
+ offer_mod.delete_properties (del_list ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ offer_mod.merge_properties (modify_list ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // 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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Register<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+withdraw_using_constraint (const char *type,
+ const char *constr
+ ACE_ENV_ARG_DECL)
+ ACE_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<MAP_LOCK_TYPE> &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 ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // 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<MAP_LOCK_TYPE>::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<MAP_LOCK_TYPE>::offer_iterator
+ offer_iter (type, offer_database);
+#endif /* _MSC_VER */
+
+ TAO_Trader_Constraint_Validator validator (type_struct.in ());
+ TAO_Constraint_Interpreter constr_inter (validator, constr ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ while (offer_iter.has_more_offers ())
+ {
+ CosTrading::Offer* offer = offer_iter.get_offer ();
+ // Add offer if it matches the constraints
+
+ TAO_Trader_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 ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ CORBA::string_free (offer_id);
+ }
+ }
+ else
+ ACE_THROW (CosTrading::Register::NoMatchingOffers (constr));
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CosTrading::Register_ptr
+TAO_Register<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+resolve (const CosTrading::TraderName &name
+ ACE_ENV_ARG_DECL)
+ ACE_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_link_name (name[0]))
+ ACE_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;
+
+ ACE_TRY
+ {
+ // Ensure that the link to the next trader exists.
+ link_info = link_if->describe_link (name[0] ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ remote_reg =
+ CosTrading::Register::_narrow (link_info->target_reg.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHANY
+ {
+ ACE_TRY_THROW (CosTrading::Register::UnknownTraderName (name));
+ }
+ ACE_ENDTRY;
+ ACE_CHECK_RETURN (CosTrading::Register::_nil ());
+
+ // Ensure that the register pointer isn't nil.
+ if (! CORBA::is_nil (remote_reg.in ()))
+ ACE_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 ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (CosTrading::Register::_nil ());
+ }
+
+ return return_value;
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Register<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+validate_properties (const char* type,
+ const CosTradingRepos::ServiceTypeRepository::TypeStruct* type_struct,
+ const CosTrading::PropertySeq& properties
+ ACE_ENV_ARG_DECL)
+ ACE_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 ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // 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)
+ ACE_THROW (CosTrading::MissingMandatoryProperty (type, prop_name));
+ }
+ else
+ {
+ int check =
+ (! prop_type->equal (prop_struct.value_type.in ()
+ ACE_ENV_ARG_PARAMETER));
+ ACE_CHECK;
+ if (check)
+ {
+ // Offer cannot redefine the type of an property.
+ const CosTrading::Property* prop =
+ prop_eval.get_property (prop_name);
+ ACE_THROW (CosTrading::PropertyTypeMismatch (type, *prop));
+ }
+ else if (prop_struct.mode ==
+ CosTradingRepos::ServiceTypeRepository::PROP_READONLY &&
+ prop_eval.is_dynamic_property (prop_name))
+ ACE_THROW (CosTrading::ReadonlyDynamicProperty (type, prop_name));
+ }
+ }
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+TAO_Admin (TAO_Trader<TRADER_LOCK_TYPE,MAP_LOCK_TYPE> &trader)
+ : TAO_Trader_Components <POA_CosTrading::Admin> (trader.trading_components ()),
+ TAO_Support_Attributes <POA_CosTrading::Admin> (trader.support_attributes ()),
+ TAO_Import_Attributes <POA_CosTrading::Admin> (trader.import_attributes ()),
+ TAO_Link_Attributes <POA_CosTrading::Admin> (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;
+ ACE_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] = static_cast<CORBA::Octet> ((ip_addr >> 24) & 0xff);
+ this->stem_id_[1] = static_cast<CORBA::Octet> ((ip_addr >> 16) & 0xff);
+ this->stem_id_[2] = static_cast<CORBA::Octet> ((ip_addr >> 8) & 0xff);
+ this->stem_id_[3] = static_cast<CORBA::Octet> (ip_addr & 0xff);
+ this->stem_id_[4] = static_cast<CORBA::Octet> ((pid >> 24) & 0xff);
+ this->stem_id_[5] = static_cast<CORBA::Octet> ((pid >> 16) & 0xff);
+ this->stem_id_[6] = static_cast<CORBA::Octet> ((pid >> 8) & 0xff);
+ this->stem_id_[7] = static_cast<CORBA::Octet> (pid & 0xff);
+ }
+
+ // The default way -- eight random integers.
+ else
+ {
+ time_t time_value = ACE_OS::time ();
+ ACE_OS::srand (static_cast<u_int> (time_value));
+
+ this->stem_id_[0] = static_cast<CORBA::Octet> (ACE_OS::rand () % 256);
+ this->stem_id_[1] = static_cast<CORBA::Octet> (ACE_OS::rand () % 256);
+ this->stem_id_[2] = static_cast<CORBA::Octet> (ACE_OS::rand () % 256);
+ this->stem_id_[3] = static_cast<CORBA::Octet> (ACE_OS::rand () % 256);
+ this->stem_id_[4] = static_cast<CORBA::Octet> (ACE_OS::rand () % 256);
+ this->stem_id_[5] = static_cast<CORBA::Octet> (ACE_OS::rand () % 256);
+ this->stem_id_[6] = static_cast<CORBA::Octet> (ACE_OS::rand () % 256);
+ this->stem_id_[7] = static_cast<CORBA::Octet> (ACE_OS::rand () % 256);
+ }
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::~TAO_Admin (void)
+{
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CosTrading::Admin::OctetSeq *
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::request_id_stem (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ ACE_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] = static_cast<CORBA::Octet> (this->sequence_number_ & 0xff);
+ this->stem_id_[9] = static_cast<CORBA::Octet> ((this->sequence_number_ >> 8) & 0xff);
+ this->stem_id_[10] = static_cast<CORBA::Octet> ((this->sequence_number_ >> 16) & 0xff);
+ this->stem_id_[11] = static_cast<CORBA::Octet> ((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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CORBA::ULong
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_def_search_card (CORBA::ULong value
+ ACE_ENV_ARG_DECL_NOT_USED )
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CORBA::ULong
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_max_search_card (CORBA::ULong value
+ ACE_ENV_ARG_DECL_NOT_USED )
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CORBA::ULong
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_def_match_card (CORBA::ULong value
+ ACE_ENV_ARG_DECL_NOT_USED )
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CORBA::ULong
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_max_match_card (CORBA::ULong value
+ ACE_ENV_ARG_DECL_NOT_USED )
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CORBA::ULong
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_def_return_card (CORBA::ULong value
+ ACE_ENV_ARG_DECL_NOT_USED )
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CORBA::ULong
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_max_return_card (CORBA::ULong value
+ ACE_ENV_ARG_DECL_NOT_USED )
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CORBA::ULong
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_max_list (CORBA::ULong value
+ ACE_ENV_ARG_DECL_NOT_USED )
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CORBA::Boolean
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_supports_modifiable_properties (CORBA::Boolean value
+ ACE_ENV_ARG_DECL_NOT_USED )
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CORBA::Boolean
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_supports_dynamic_properties (CORBA::Boolean value
+ ACE_ENV_ARG_DECL_NOT_USED )
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CORBA::Boolean
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_supports_proxy_offers (CORBA::Boolean value
+ ACE_ENV_ARG_DECL_NOT_USED )
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CORBA::ULong
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_def_hop_count (CORBA::ULong value
+ ACE_ENV_ARG_DECL_NOT_USED )
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CORBA::ULong
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_max_hop_count (CORBA::ULong value
+ ACE_ENV_ARG_DECL_NOT_USED )
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CosTrading::FollowOption
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_def_follow_policy (CosTrading::FollowOption policy
+ ACE_ENV_ARG_DECL_NOT_USED )
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CosTrading::FollowOption
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_max_follow_policy (CosTrading::FollowOption policy
+ ACE_ENV_ARG_DECL_NOT_USED )
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CosTrading::FollowOption
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_max_link_follow_policy (CosTrading::FollowOption policy
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CosTrading::TypeRepository_ptr
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_type_repos (CosTrading::TypeRepository_ptr repository
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CosTrading::Admin::OctetSeq*
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+set_request_id_stem (const CosTrading::Admin::OctetSeq& stem
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+list_offers (CORBA::ULong how_many,
+ CosTrading::OfferIdSeq_out ids,
+ CosTrading::OfferIdIterator_out id_itr
+ ACE_ENV_ARG_DECL)
+ ACE_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()))
+ ACE_THROW (CosTrading::NotImplemented());
+
+ TAO_Offer_Database<MAP_LOCK_TYPE>& 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)
+ {
+ int check = offer_id_iter->next_n (how_many, ids ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ if (check == 1)
+ {
+ id_itr = offer_id_iter->_this (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+ offer_id_iter->_remove_ref (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ else
+ delete offer_id_iter;
+ }
+ else
+ ids = new CosTrading::OfferIdSeq (0);
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Admin<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+list_proxies (CORBA::ULong,
+ CosTrading::OfferIdSeq_out,
+ CosTrading::OfferIdIterator_out
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ CosTrading::NotImplemented))
+{
+ ACE_THROW (CosTrading::NotImplemented ());
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+TAO_Link<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::TAO_Link (TAO_Trader<TRADER_LOCK_TYPE,MAP_LOCK_TYPE> &trader)
+ : TAO_Trader_Components <POA_CosTrading::Link> (trader.trading_components ()),
+ TAO_Support_Attributes <POA_CosTrading::Link> (trader.support_attributes ()),
+ TAO_Link_Attributes <POA_CosTrading::Link> (trader.link_attributes ()),
+ trader_ (trader)
+{
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+TAO_Link<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::~TAO_Link (void)
+{
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Link<TRADER_LOCK_TYPE, MAP_LOCK_TYPE>::
+add_link (const char *name,
+ CosTrading::Lookup_ptr target,
+ CosTrading::FollowOption def_pass_on_follow_rule,
+ CosTrading::FollowOption limiting_follow_rule
+ ACE_ENV_ARG_DECL)
+ ACE_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_link_name (name))
+ ACE_THROW (CosTrading::Link::IllegalLinkName (name));
+
+ // Ensure this isn't a duplicate link name.
+ CORBA::String_var link_name (name);
+ if (this->links_.find (link_name) == 0)
+ ACE_THROW (CosTrading::Link::DuplicateLinkName (name));
+
+ // Ensure the lookup_ptr isn't nil.
+ if (CORBA::is_nil (target))
+ ACE_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)
+ ACE_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.
+ CosTrading::FollowOption follow_policy =
+ this->max_link_follow_policy (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+ if (limiting_follow_rule < follow_policy)
+ ACE_THROW (CosTrading::Link::LimitingFollowTooPermissive
+ (limiting_follow_rule, follow_policy));
+
+ // 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;
+ ACE_CHECK;
+
+ // Insert this link into the collection of links.
+ this->links_.bind (link_name, link_info);
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Link<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+remove_link (const char *name
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ CosTrading::Link::IllegalLinkName,
+ CosTrading::Link::UnknownLinkName))
+{
+ // Ensure the link name is valid.
+ if (! TAO_Trader_Base::is_valid_link_name (name))
+ ACE_THROW (CosTrading::Link::IllegalLinkName (name));
+
+ // Ensure this isn't a duplicate link name.
+ CORBA::String_var link_name (name);
+ if (this->links_.find (link_name) == -1)
+ ACE_THROW (CosTrading::Link::UnknownLinkName (name));
+
+ // Erase the link state from the map.
+ this->links_.unbind (link_name);
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CosTrading::Link::LinkInfo *
+TAO_Link<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::describe_link (const char *name
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ CosTrading::Link::IllegalLinkName,
+ CosTrading::Link::UnknownLinkName))
+{
+ // Ensure the link name is valid.
+ if (! TAO_Trader_Base::is_valid_link_name (name))
+ ACE_THROW_RETURN (CosTrading::Link::IllegalLinkName (name), 0);
+
+ // Ensure this isn't a duplicate link name.
+ ACE_TYPENAME Links::ENTRY* link_entry = 0;
+ CORBA::String_var link_name (name);
+ if (this->links_.find (link_name, link_entry) == -1)
+ ACE_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_THROW_EX (new_link_info,
+ CosTrading::Link::LinkInfo,
+ CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (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 (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (new_link_info);
+
+ // return the link information for this link name.
+ return new_link_info;
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CosTrading::LinkNameSeq*
+TAO_Link<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::list_links (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ // Allocate space for the link names.
+ size_t size = this->links_.current_size ();
+ CORBA::ULong i = 0;
+ CosTrading::LinkName* link_seq =
+ CosTrading::LinkNameSeq::allocbuf (static_cast<CORBA::ULong> (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 <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Link<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+modify_link (const char *name,
+ CosTrading::FollowOption def_pass_on_follow_rule,
+ CosTrading::FollowOption limiting_follow_rule
+ ACE_ENV_ARG_DECL)
+ ACE_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_link_name (name))
+ ACE_THROW (CosTrading::Link::IllegalLinkName (name));
+
+ // Ensure this isn't a duplicate link name.
+ ACE_TYPENAME Links::ENTRY* link_entry = 0;
+ CORBA::String_var link_name (name);
+ if (this->links_.find (link_name, link_entry) == -1)
+ ACE_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)
+ ACE_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.
+ CosTrading::FollowOption follow_policy =
+ this->max_link_follow_policy (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+
+ if (limiting_follow_rule < follow_policy)
+ ACE_THROW (CosTrading::Link::LimitingFollowTooPermissive
+ (limiting_follow_rule, follow_policy));
+
+ // 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;
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+TAO_Proxy<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+TAO_Proxy (TAO_Trader<TRADER_LOCK_TYPE,MAP_LOCK_TYPE> &trader)
+ : TAO_Trader_Components <POA_CosTrading::Proxy> (trader.trading_components ()),
+ TAO_Support_Attributes <POA_CosTrading::Proxy> (trader.support_attributes ()),
+ trader_ (trader)
+{
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+TAO_Proxy<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::~TAO_Proxy (void)
+{
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CosTrading::OfferId
+TAO_Proxy<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+export_proxy (CosTrading::Lookup_ptr,
+ const char *,
+ const CosTrading::PropertySeq&,
+ CORBA::Boolean,
+ const char *,
+ const CosTrading::PolicySeq&
+ ACE_ENV_ARG_DECL)
+ ACE_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))
+{
+ ACE_THROW_RETURN (CORBA::UNKNOWN (), 0);
+
+ ACE_NOTREACHED (return 0;)
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Proxy<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+withdraw_proxy (const char *
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ CosTrading::IllegalOfferId,
+ CosTrading::UnknownOfferId,
+ CosTrading::Proxy::NotProxyOfferId))
+{
+ ACE_THROW (CORBA::UNKNOWN ());
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+CosTrading::Proxy::ProxyInfo *
+TAO_Proxy<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+describe_proxy (const char *
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ CosTrading::IllegalOfferId,
+ CosTrading::UnknownOfferId,
+ CosTrading::Proxy::NotProxyOfferId))
+{
+ ACE_THROW_RETURN (CORBA::UNKNOWN (), 0);
+
+ ACE_NOTREACHED (return 0;)
+}
+
+template <class TRADER_LOCK_TYPE, class MAP_LOCK_TYPE>
+void
+TAO_Proxy<TRADER_LOCK_TYPE,MAP_LOCK_TYPE>::
+list_proxies (CORBA::ULong,
+ CosTrading::OfferIdSeq*&,
+ CosTrading::OfferIdIterator_ptr&
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ CosTrading::NotImplemented))
+{
+ ACE_THROW (CORBA::UNKNOWN ());
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* TAO_TRADER_INTERFACES_CPP */