Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Advanced CORBA Programming wit C++ - M. Henning, S. Vinoski.pdf
Скачиваний:
65
Добавлен:
24.05.2014
Размер:
5 Mб
Скачать

IT-SC book: Advanced CORBA® Programming with C++

By initializing the remembered offer ID to the empty string, this technique does not require a special case for the first time a service offer is exported. In addition, it has the advantage that the service offer will be refreshed automatically if it has been deleted by another client.

19.21 Adding Trading to the Climate Control System

There are many ways to integrate trading into the climate control system, depending on client requirements. For example, we could advertise only the controller object, using properties to describe which building or group of buildings can be monitored via that controller. An alternative is to also advertise thermometers and thermostats. Relevant properties would be the asset number and the location, so clients can locate devices via a trader instead of using the controller's find operation (but be aware of the caveats about incomplete results mentioned in Section 19.18).

For this example, we restrict ourselves to advertising only the controller reference. For simplicity, we use manifest constants for property values throughout the code. For a more realistic application, you would read these values from a configuration file, obtain them from the command line, or use the values of member variables that store object state.

19.21.1 Creating a Service Type for the Controller

The first step is to create a service type for the controller. (We use the service type definition from Table 19.1.) Typically, service types are created only once—during installation of an application—so the client to create the service type is usually a standalone administrative program. We show only the relevant creation code here.

#include <CosTradingRepos.hh>

// ORB-specific

#include <CosTrading.hh>

// ORB-specific

// ...

 

using namespace CosTradingRepos; using namespace CosTrading;

//Get reference to Lookup interface. Lookup_var lookup;

lookup = resolve_init<Lookup>(orb, "TradingService");

//Read type_repos attribute to get IOR to type repository. CORBA::Object_var obj = lookup->type_repos();

//Narrow.

ServiceTypeRepository_var repos;

repos = ServiceTypeRepository::_narrow(obj); if (CORBA::is_nil(repos)) {

cerr < "Not a type repository reference" < endl; throw 0;

}

// Fill in property definitions for controllers.

788

IT-SC book: Advanced CORBA® Programming with C++

ServiceTypeRepository::PropStructSeq props; props.length(5);

props[0].name = CORBA::string_dup("Model"); props[0].value_type = CORBA::TypeCode::_duplicate(

CORBA::_tc_string );

props[0].mode = ServiceTypeRepository::PROP_MANDATORY_READONLY;

props[1].name = CORBA::string_dup("Manufacturer"); props[1].value_type = CORBA::TypeCode::_duplicate(

Manufacturing::_tc_AddressType );

props[1].mode = ServiceTypeRepository::PROP_NORMAL;

props[2].name = CORBA::string_dup("Phone"); props[2].value_type = CORBA::TypeCode::_duplicate(

CORBA::_tc_string );

props[2].mode = ServiceTypeRepository::PROP_MANDATORY;

props[3].name = CORBA::string_dup("Supports"); props[3].value_type = CORBA::TypeCode::_duplicate(

Airconditioning::_tc_ModelType );

props[3].mode = ServiceTypeRepository::PROP_READONLY;

props[4].name = CORBA::string_dup("MaxDevices"); props[4].value_type = CORBA::TypeCode::_duplicate(

CORBA::_tc_ulong );

props[4].mode = ServiceTypeRepository::PROP_NORMAL;

// Create Controllers service type. ServiceTypeRepository::ServiceTypeNameSeq base_types; repos->add_type(

"CCS::Controllers",

"IDL:acme.com/CCS/Controller:1.0",

props, base_types

);

Note that the code uses the resolve_init template function discussed in Section 18.14.1.

19.21.2 Exporting a Service Offer for the Controller

As with the way we advertised the controller in the Naming Service (see Section 18.14.2), the server ensures that the controller's advertisement in the trader is refreshed every time the server starts up. However, because the trader permits duplicate offers, we cannot blindly export a new service offer every time. Instead, the server stores the offer ID of the previous service offer in persistent storage, withdraws any previous offer, and replaces it with a new one:

789

IT-SC book: Advanced CORBA® Programming with C++

#include <CosTrading.hh>

// ORB-specific

// ...

using namespace CosTrading;

//Get reference to Lookup interface. Lookup_var lookup;

lookup = resolve_init<Lookup>(orb, "TradingService");

//Navigate to Register interface.

Register_var regis = lookup->register_if(); if (CORBA::is_nil(regis)) {

cout < "Trader does not support updates." < endl; throw 0;

}

//Read the offer ID of a previous offer from a file

//using the read_offer_id helper function (not shown).

//Assume that read_offer_id returns an empty string

//if no offer was previously remembered.

OfferId_var offer_id = read_offer_id(offer_id_file);

//Attempt to withdraw the previous offer. try {

regis->withdraw(offer_id);

} catch (const UnknownOfferId &) {

//Fine, there is no previous offer. } catch (const IllegalOfferId &) {

//Fine, there is no previous offer.

}

//Fill in property definition for controller. PropertySeq props;

props.length(3);

props[0].name = CORBA::string_dup("Model"); props[0].value <= "BFG-9000";

props[1].name = CORBA::string_dup("Phone"); props[1].value <= "123 456-7890";

props[2].name = CORBA::string_dup("Description"); props[2].value <= "Deluxe model for advanced users.";

//Create reference to the controller. CCS::Controller_var ctrl = ...;

//Export the offer.

offer_id = regis->_cxx_export(ctrl, "CCS::Controllers", props);

//Store the new offer ID in peristent storage

//using the write_offer_id helper function (not shown). write_offer_id(offer_id_file, offer_id);

//...

790

IT-SC book: Advanced CORBA® Programming with C++

19.21.3 Importing a Reference to the Controller

The client code imports the controller reference during start-up. We are using a manifest constant as the query string for this example, whereas a more realistic client would probably allow the query to be parameterized by, for example, obtaining user preferences via a graphical user interface. Unfortunately, the trader accepts as queries only strings and not expression trees. This means that to parameterize a query, you must write string manipulation code, which can end up being complex. Depending on your requirements, it may be sufficient to create a few simple query templates that allow the user to supply only a fixed number of predetermined property values.

#include <CosTrading.hh>

// ORB_specific

// ...

using namespace CosTrading;

//Get reference to Lookup interface. Lookup_var lookup;

lookup = resolve_init<Lookup>(orb, "TradingService");

//The policy sequence sets the return cardinality to 1

//because we are interested only in a single offer.

PolicySeq policies; policies.length(1);

policies[0].name = CORBA::string_dup("return_card"); policies[0].value <= (CORBA::ULong)1;

Lookup::SpecifiedProps desired_props;

// Don't return properties

desired_props._default();

 

desired_props._d(Lookup::none);

 

PolicyNameSeq_var policies_applied;

// out param

OfferSeq_var

offers;

// out param

OfferIterator_var

iterator;

// out param

//Run query without preferences using default policies. lookup->query(

"CCS::Controllers", "Model == 'BFG-9000'", "", policies, desired_props, 1,

offers, iterator, policies_applied

);

//Process results.

CCS::Controller_var ctrl; if (offers->length() == 0) {

cerr < "Cannot locate matching controller." < endl; exit(1);

}else {

//Extract controller reference from returned offer. ctrl = CCS::Controller::_narrow(offers[0].reference); if (CORBA::is_nil(ctrl)) {

cerr << "Service provider is not a controller!" < endl;

791