
- •Advanced CORBA® Programming with C++
- •Review
- •Dedication
- •Preface
- •Prerequisites
- •Scope of this Book
- •Acknowledgments
- •Chapter 1. Introduction
- •1.1 Introduction
- •1.2 Organization of the Book
- •1.3 CORBA Version
- •1.4 Typographical Conventions
- •1.5 Source Code Examples
- •1.6 Vendor Dependencies
- •1.7 Contacting the Authors
- •Part I: Introduction to CORBA
- •Chapter 2. An Overview of CORBA
- •2.1 Introduction
- •2.2 The Object Management Group
- •2.3 Concepts and Terminology
- •2.4 CORBA Features
- •2.5 Request Invocation
- •2.6 General CORBA Application Development
- •2.7 Summary
- •Chapter 3. A Minimal CORBA Application
- •3.1 Chapter Overview
- •3.2 Writing and Compiling an IDL Definition
- •3.3 Writing and Compiling a Server
- •3.4 Writing and Compiling a Client
- •3.5 Running Client and Server
- •3.6 Summary
- •Part II: Core CORBA
- •Chapter 4. The OMG Interface Definition Language
- •4.1 Chapter Overview
- •4.2 Introduction
- •4.3 Compilation
- •4.4 Source Files
- •4.5 Lexical Rules
- •4.6 Basic IDL Types
- •4.7 User-Defined Types
- •4.8 Interfaces and Operations
- •4.9 User Exceptions
- •4.10 System Exceptions
- •4.11 System Exceptions or User Exceptions?
- •4.12 Oneway Operations
- •4.13 Contexts
- •4.14 Attributes
- •4.15 Modules
- •4.16 Forward Declarations
- •4.17 Inheritance
- •4.18 Names and Scoping
- •4.19 Repository Identifiers and pragma Directives
- •4.20 Standard Include Files
- •4.21 Recent IDL Extensions
- •4.22 Summary
- •Chapter 5. IDL for a Climate Control System
- •5.1 Chapter Overview
- •5.2 The Climate Control System
- •5.3 IDL for the Climate Control System
- •5.4 The Complete Specification
- •Chapter 6. Basic IDL-to-C++ Mapping
- •6.1 Chapter Overview
- •6.2 Introduction
- •6.3 Mapping for Identifiers
- •6.4 Mapping for Modules
- •6.5 The CORBA Module
- •6.6 Mapping for Basic Types
- •6.7 Mapping for Constants
- •6.8 Mapping for Enumerated Types
- •6.9 Variable-Length Types and _var Types
- •6.10 The String_var Wrapper Class
- •6.11 Mapping for Wide Strings
- •6.12 Mapping for Fixed-Point Types
- •6.13 Mapping for Structures
- •6.14 Mapping for Sequences
- •6.15 Mapping for Arrays
- •6.16 Mapping for Unions
- •6.17 Mapping for Recursive Structures and Unions
- •6.18 Mapping for Type Definitions
- •6.19 User-Defined Types and _var Classes
- •6.20 Summary
- •Chapter 7. Client-Side C++ Mapping
- •7.1 Chapter Overview
- •7.2 Introduction
- •7.3 Mapping for Interfaces
- •7.4 Object Reference Types
- •7.5 Life Cycle of Object References
- •7.6 Semantics of _ptr References
- •7.7 Pseudo-Objects
- •7.8 ORB Initialization
- •7.9 Initial References
- •7.10 Stringified References
- •7.11 The Object Pseudo-Interface
- •7.12 _var References
- •7.13 Mapping for Operations and Attributes
- •7.14 Parameter Passing Rules
- •7.15 Mapping for Exceptions
- •7.16 Mapping for Contexts
- •7.17 Summary
- •Chapter 8. Developing a Client for the Climate Control System
- •8.1 Chapter Overview
- •8.2 Introduction
- •8.3 Overall Client Structure
- •8.4 Included Files
- •8.5 Helper Functions
- •8.6 The main Program
- •8.7 The Complete Client Code
- •8.8 Summary
- •Chapter 9. Server-Side C++ Mapping
- •9.1 Chapter Overview
- •9.2 Introduction
- •9.3 Mapping for Interfaces
- •9.4 Servant Classes
- •9.5 Object Incarnation
- •9.6 Server main
- •9.7 Parameter Passing Rules
- •9.8 Raising Exceptions
- •9.9 Tie Classes
- •9.10 Summary
- •Chapter 10. Developing a Server for the Climate Control System
- •10.1 Chapter Overview
- •10.2 Introduction
- •10.3 The Instrument Control Protocol API
- •10.4 Designing the Thermometer Servant Class
- •10.5 Implementing the Thermometer Servant Class
- •10.6 Designing the Thermostat Servant Class
- •10.7 Implementing the Thermostat Servant Class
- •10.8 Designing the Controller Servant Class
- •10.9 Implementing the Controller Servant Class
- •10.10 Implementing the Server main Function
- •10.11 The Complete Server Code
- •10.12 Summary
- •Chapter 11. The Portable Object Adapter
- •11.1 Chapter Overview
- •11.2 Introduction
- •11.3 POA Fundamentals
- •11.4 POA Policies
- •11.5 POA Creation
- •11.6 Servant IDL Type
- •11.7 Object Creation and Activation
- •11.8 Reference, ObjectId, and Servant
- •11.9 Object Deactivation
- •11.10 Request Flow Control
- •11.11 ORB Event Handling
- •11.12 POA Activation
- •11.13 POA Destruction
- •11.14 Applying POA Policies
- •11.15 Summary
- •Chapter 12. Object Life Cycle
- •12.1 Chapter Overview
- •12.2 Introduction
- •12.3 Object Factories
- •12.4 Destroying, Copying, and Moving Objects
- •12.5 A Critique of the Life Cycle Service
- •12.6 The Evictor Pattern
- •12.7 Garbage Collection of Servants
- •12.8 Garbage Collection of CORBA Objects
- •12.9 Summary
- •Part III: CORBA Mechanisms
- •Chapter 13. GIOP, IIOP, and IORs
- •13.1 Chapter Overview
- •13.2 An Overview of GIOP
- •13.3 Common Data Representation
- •13.4 GIOP Message Formats
- •13.5 GIOP Connection Management
- •13.6 Detecting Disorderly Shutdown
- •13.7 An Overview of IIOP
- •13.8 Structure of an IOR
- •13.9 Bidirectional IIOP
- •13.10 Summary
- •14.1 Chapter Overview
- •14.2 Binding Modes
- •14.3 Direct Binding
- •14.4 Indirect Binding via an Implementation Repository
- •14.5 Migration, Reliability, Performance, and Scalability
- •14.6 Activation Modes
- •14.7 Race Conditions
- •14.8 Security Considerations
- •14.9 Summary
- •Part VI: Dynamic CORBA
- •Chapter 15 C++ Mapping for Type any
- •15.1 Chapter Overview
- •15.2 Introduction
- •15.3 Type any C++ Mapping
- •15.4 Pitfalls in Type Definitions
- •15.5 Summary
- •Chapter 16. Type Codes
- •16.1 Chapter Overview
- •16.2 Introduction
- •16.3 The TypeCode Pseudo-Object
- •16.4 C++ Mapping for the TypeCode Pseudo-Object
- •16.5 Type Code Comparisons
- •16.6 Type Code Constants
- •16.7 Type Code Comparison for Type any
- •16.8 Creating Type Codes Dynamically
- •16.9 Summary
- •Chapter 17. Type DynAny
- •17.1 Chapter Overview
- •17.2 Introduction
- •17.3 The DynAny Interface
- •17.4 C++ Mapping for DynAny
- •17.5 Using DynAny for Generic Display
- •17.6 Obtaining Type Information
- •17.7 Summary
- •Part V: CORBAservices
- •Chapter 18. The OMG Naming Service
- •18.1 Chapter Overview
- •18.2 Introduction
- •18.3 Basic Concepts
- •18.4 Structure of the Naming Service IDL
- •18.5 Semantics of Names
- •18.6 Naming Context IDL
- •18.7 Iterators
- •18.8 Pitfalls in the Naming Service
- •18.9 The Names Library
- •18.10 Naming Service Tools
- •18.11 What to Advertise
- •18.12 When to Advertise
- •18.13 Federated Naming
- •18.14 Adding Naming to the Climate Control System
- •18.15 Summary
- •Chapter 19. The OMG Trading Service
- •19.1 Chapter Overview
- •19.2 Introduction
- •19.3 Trading Concepts and Terminology
- •19.4 IDL Overview
- •19.5 The Service Type Repository
- •19.6 The Trader Interfaces
- •19.7 Exporting Service Offers
- •19.8 Withdrawing Service Offers
- •19.9 Modifying Service Offers
- •19.10 The Trader Constraint Language
- •19.11 Importing Service Offers
- •19.12 Bulk Withdrawal
- •19.13 The Admin Interface
- •19.14 Inspecting Service Offers
- •19.15 Exporting Dynamic Properties
- •19.16 Trader Federation
- •19.17 Trader Tools
- •19.18 Architectural Considerations
- •19.19 What to Advertise
- •19.20 Avoiding Duplicate Service Offers
- •19.21 Adding Trading to the Climate Control System
- •19.22 Summary
- •Chapter 20. The OMG Event Service
- •20.1 Chapter Overview
- •20.2 Introduction
- •20.3 Distributed Callbacks
- •20.4 Event Service Basics
- •20.5 Event Service Interfaces
- •20.6 Implementing Consumers and Suppliers
- •20.7 Choosing an Event Model
- •20.8 Event Service Limitations
- •20.9 Summary
- •Part VI: Power CORBA
- •Chapter 21. Multithreaded Applications
- •21.1 Chapter Overview
- •21.2 Introduction
- •21.3 Motivation for Multithreaded Programs
- •21.4 Fundamentals of Multithreaded Servers
- •21.5 Multithreading Strategies
- •21.6 Implementing a Multithreaded Server
- •21.7 Servant Activators and the Evictor Pattern
- •21.8 Summary
- •22.1 Chapter Overview
- •22.2 Introduction
- •22.3 Reducing Messaging Overhead
- •22.4 Optimizing Server Implementations
- •22.5 Federating Services
- •22.6 Improving Physical Design
- •22.7 Summary
- •Appendix A. Source Code for the ICP Simulator
- •Appendix B. CORBA Resources
- •Bibliography

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