Previous Up Next

Chapter 20  Trading Service

CORBA provides several ways for a server to advertise an object reference. One way, discussed in Section 3.4.2, is for the server to stringify an object reference and write it to, say, a file. Another approach is for the server to advertise the object reference in the Naming Service (Chapter 4). This chapter discusses a third approach, called the Trading Service.

Just as the Naming Service is often compared to the white pages telephone book, the trading service is often compared to the yellow pages telephone book. The yellow pages contains numerous advertisements organized into different categories (such as Builders, Plumbers and Restaurants), while the Trading Service contains numerous service offers that are organized by their service offer types. Each advertisement in the yellow pages provides contact details (address and telephone number) for a company along with a description of the company (for example, “open 24 hours” or “cheapest prices in town”). Similarly, each service offer in the Trading Service provides contact details (an IOR) along with a description of the service offered by the object.

20.1  The ServiceTypeRepository Interface

Figure 20.1 shows a simplified version of the ServiceTypeRepository IDL interface. There are several simplifications in this interface, and the interfaces shown later in this chapter:

module CosTradingRepos { interface ServiceTypeRepository { enum PropertyMode { PROP_NORMAL, PROP_READONLY, PROP_MANDATORY, PROP_MANDATORY_READONLY}; struct PropStruct { string name; CORBA::TypeCode value_type; PropertyMode mode; }; typedef sequence<PropStruct> PropStructSeq; struct IncarnationNumber { unsigned long high; unsigned long low; }; struct TypeStruct { string name; PropStructSeq props; sequence<string> super_types; boolean masked; IncarnationNumber incarnation; }; ... readonly attribute IncarnationNumber incarnation; IncarnationNumber add_type( in string name, in string if_name, in PropStructSeq props, sequence<string> super_types) raises(...); void remove_type(in string name) raises(...); void mask_type(in string name) raises(...); void unmask_type(in string name) raises(...); ... }; };
Figure 20.1: Pseudo IDL Extract of ServiceTypeRepository

As mentioned earlier, the yellow pages telephone book groups the details of different companies into categories such as electricians and plumbers. The Trading Service equivalent of a “category” is a CosTradingRepos::ServiceTypeRepository::TypeStruct, although this is normally referred to as a service offer type. The ServiceTypeRepository interface is used to define service offer types.

20.1.1  The add_type() and remove_type() operations

The add_type() operation is used to define a new service offer type. The name parameter specifies the name of the category, for example, "Printer". The if_name parameter specifies a repository id (Section 9.4) for the IDL interface associated with this service offer type. Some readers may wonder why the service offer type’s name is not hard-coded to be the same as the repository id for its interface. The reason is to allow the name to be easier to read than a repository id. For example, "Printer" is easier to read than "". Inheritance is, of course, allowed. For example, the repository id in the previous sentence denotes an IDL interface called Equipment::Printer. An object of this type, or a sub-type of it, can be used in a "Printer" service offer.

The props parameter specifies a sequence of properties that are associated with the service offer type. This is where the analogy between the Trading Service and the yellow pages telephone book starts to break down. Some advertisements in the yellow pages may boast claims about a company such as “open 24 hours”, “all work has a 12-month guarantee” or “cheapest prices in town”. However, the yellow pages does not make any requirements about what claims should be made in an advertisement in the yellow pages. In contrast, a service offer type in the Trading Service does specify what properties (“claims”) each service offer (“advertisement”) should have. Each property (specified by the PropStruct type) has a name, a type1 (such as long, boolean or string) and a mode. The mode field is an enum that specifies whether or not the property is mandatory, and whether or not it is readonly.

The ServiceTypeRepository does not place any restriction on the types of properties. However, it is usually best to stick to using integers, floating point numbers, booleans, characters, strings and sequences of these types. The reason for this is that the constraint language used to make queries on the Trading Service provides full support for these types and only minimal support for other types.2

The super_types parameter lists the names of parent service offer types. A service offer type inherits the properties of its parents and is allowed to impose more restrictions on inherited properties. In particular, an optional property can be made mandatory, and a “normal” property can become readonly.

The return value of add_type() is an IncarnationNumber, which was intended to be a 64-bit integer. However, the unsigned long long IDL type did not yet exist when the Trading Service was being defined so a struct containing two unsigned long fields was used instead. The IncarnationNumber is conceptually a timestamp to indicate when a service offer type was defined. A list-style operation (not shown in Figure 20.1) can be used to list the service offer types defined since a particular incarnation number.

The remove_type() operation removes a service offer type.

20.1.2  The mask_type() and unmask_type() operations

The mask_type() operation is used to mask (hide) a service offer type. This has two uses. One use is to deprecate a service offer type, so that the Trading Service will not accept any more service offers (advertisements) for the specified service offer type. Another use is to indicate that the service offer type is an abstract base type that cannot be instantiated directly, but from which other service offer types can inherit. The unmask_type() operation unmasks a type that was previously masked with mask_type().

20.2  The Register Interface

When a service offer type has been defined, it is then possible for applications to actually export (advertise) an object reference in the Trading Service. This is done through the Register IDL interface (Figure 20.2).

module CosTrading { struct Property { string name; any value; }; typedef sequence<Property> PropertySeq; struct Offer { Object reference; PropertySeq properties; }; typedef sequence<Offer> OfferSeq; interface Register : TraderComponents, SupportAttributes { string export( in Object reference, in string type, in PropertySeq properties) raises(...); void withdraw(in string offer_id) raises(...); void modify( in string offer_id, in sequence<string> del_list, in PropertySeq modify_list ) raises(...); ... }; };
Figure 20.2: Pseudo IDL Extract of Register

20.2.1  The export() and withdraw() operations

The export() operation is used to create a service offer, that is, an advertisement for an object. Parameters to this operation specify an object reference, the service offer type that it matches, and its properties. The supplied properties must match those specified by the service offer type. The return value from export() is a unique string that denotes an offer id. This offer id can later be used to withdraw the advertisement or modify some of its (non-readonly) properties.

The withdraw() operation is used to withdraw (that is, delete) a service offer.

20.2.2  The modify() operation

The modify() operation is used to delete or modify some properties associated with a service offer. An exception is thrown if an attempt is made to delete a mandatory property. Likewise, an exception is thrown if an attempt is made to modify a readonly property.

20.3  The Lookup Interface

The Lookup interface (Figure 20.3) has just one operation, called query(). This operation is used to retrieve service offers (advertisements) from the Trading Service that match a specified constraint.

module CosTrading { struct Property { string name; any value; }; typedef sequence<Property> PropertySeq; struct Offer { Object reference; PropertySeq properties; }; typedef sequence<Offer> OfferSeq; interface OfferIterator { boolean next_n(in unsigned long n,     out OfferSeq ids) raises(...); ... }; interface Lookup : TraderComponents, SupportAttributes, ImportAttributes { enum HowManyProps {none, some, all}; union SpecifiedProps switch (HowManyProps) { case some: sequence<string> prop_names; }; ... void query( in string service_type_name, in string constraint, in string preference, ... in SpecifiedProps desired_props, in unsigned long how_many, out OfferSeq offers, out OfferIterator offer_iter, ...) raises(...); }; };
Figure 20.3: Pseudo IDL Extract of Lookup

The constraint parameter is a boolean expression that refers to the properties of service offers. For example, let us assume that a Printer service offer type defines an integer property called resolution and also a sequence<string> property called languages. The following constraint can be used to obtain a list of the printers that have a resolution of at least 600 and support the PostScript printer language:

resolution >= 600 && "PostScript" in languages

The in operator tests if the value specified on the left ("PostScript") is in the sequence specified on the right (languages). Constraints are specified in the syntax of the Trader Constraint Language (TCL), which is defined as part of the Trading Service specification.

There may be several service offers that are matched by the specified constraint. Details of these are returned through several out parameters. In particular, the offers parameter provides details of the first how_many matched service offers. If there are more then these can be accessed by invoking operations on the returned offer_iter iterator (Section object reference. The application that performs the query may be interested in seeing some of the properties of the matched service offers. The desired_props parameter is used to specify which properties should be accessible through offers and offer_iter.

The preference parameter is used to specify an ordering of the obtained service offers. For example, "max resolution" orders the offers by the resolution of the printers, while "random" provides the service offers in a random order, which might be useful if you want to use the Trading Service to load-balance many clients over several server processes.

20.4  Other Capabilities of the Trading Service

The Trading Service has several other important capabilities that I briefly mention here.

It is possible to join several Trading Services so that a query made to one Trading Service can propagate through the other Trading Services too. The Trading Service specification refers to this as linking or federating several Trading Services.

Most properties in a service offer will have static (that is, unchanging) values. For example, the resolution of a Printer is normally unchanging. However, the Trading Service allows for a property to be dynamic. A dynamic property is implemented with a reference to a callback object (Section When carrying out a query, the Trading Service invokes upon the callback object to obtain the current value of the desired property. Dynamic properties can be useful to denote, say, the queue_length of a Printer.

Further discussion of the above-mentioned capabilities is outside the scope of this chapter. Interested readers can find a more detailed discussion in other books [HV99, BVD01].

20.5  Using the Trading Service

The functionality of the Trading Service is spread over many IDL interfaces. This may lead you to think that there is a lot of programming involved in using the Trading Service. However, this need not be the case, as I now discuss.

Although it is not required by the Trading Service specification, each vendor is likely to provide command-line utilities and/or a graphical program that encapsulates the functionality of the IDL interfaces. These command-line utilities and/or graphical programs make it possible to do most of the administration of the Trading Service without having to do any coding. In particular:

This then reduces the coding burden to just applications that call query() on the Lookup interface. If an application has an interactive user then the user may wish to view the properties of the returned offers and manually choose one. For client applications in which interactive selection of returned offers is undesirable, the client application could randomly choose one of the returned offers. In fact, a command-line utility could be written that performs a query (specified as a command-line argument) and then prints out a randomly-chosen IOR from the returned offers. If a client application imports object references by using the importObjRef() utility function (Section 4.3) provided in the CORBA Utilities package [McH, Ch. 2] then the client need not be hard-coded to invoke the APIs of the Trading Service. Instead, the client can pass an instructions parameter to importObjRef() that tells it to execute the command-line utility and interpret its standard output as an stringified object reference.

Applications connect to the Lookup interface of the Trading Service by calling resolve_initial_references("TradingService"). All the functional interfaces of the Trading Service inherit from some base interfaces. These base interfaces provide readonly attributes that provide access to the other interfaces of the Trading Service. So, for example, once an application uses resolve_initial_references() to connect to the Lookup interface, the application can then invoke an attribute to navigate to the Register or ServiceTypeRepository interface.

20.6  Quality of Service

The Trading Service specification does not make any requirements about how an implementation stores details of service offer types and service offers.

Some implementations of the Trading Service store information only in RAM. These implementations are useful in embedded systems that do not have persistent storage, but are less desirable in computers that do have persistent storage because you would have to re-populate the Trading Service every time it dies and is restarted.

Some implementations of the Trading Service that store information persistently make use of plain files. This is fine for a small deployment but it may not scale well, and there is the possibility of information being corrupted if the Trading Service is killed while updating information in a file.

Some other implementations of the Trading Service store information in a database. This provides greater reliability than use of plain files but may involve extra administration overhead.

The functionality of the Trading Service specification is split over many IDL interfaces, and the Trading Service specification does not require that all the interfaces be implemented. Instead, some of the functionality of a Trading Service is optional. This makes it possible for a vendor to make trade-offs between how much functionality is provided by an implementation of the Trading Service and the amount of resources (RAM, disk space, CPU speed and so on) that it consumes.

If you decide to use a Trading Service in your applications then it is important to ask your Trading Service vendor how it stores data and whether it implements all the functionality of the Trading Service or a particular subset of functionality. Be sure to pick a Trading Service that offers a quality of service that is suitable for your needs.

The type is specified as a TypeCode, which is discussed in Section 15.2.
If a property is of a user-defined type then a constraint can check whether or not the property exists in a service offer, but the constraint cannot examine the value of the property.

Previous Up Next