
- •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++
Both the search cardinality and the hop count policy were introduced with these concerns in mind. The aim was to provide importers with at least some means, however inadequate, of limiting the propagation of a query.
19.17 Trader Tools
The OMG Trading Service specification does not place any requirements on implementations with respect to tools. Nevertheless, most vendors provide at least a minimal set of tools that allow you to administer a trader and to manipulate its offer space. Typically, traders provide command-line interfaces that allow you to change configuration values, maintain the service type repository, and add and remove service offers. Some vendors also provide graphical user interfaces that allow you to conveniently view and update the contents of a trader.
Because tools are outside the scope of the specification and differ from vendor to vendor, we do not cover them here. However, you should become familiar with the tools provided for your trader.
19.18 Architectural Considerations
Now that you have seen what a trader can do, an interesting question is, how should you use it? As with the Naming Service, there are a number trade-offs.
As soon as you make the decision to use a trader as part of your application, you gain a number of advantages.
The trader provides a standard way to dynamically select objects based on complex criteria. Because it is standardized, the trader is widely understood as an architectural component of CORBA. If your application requires some form of integration with applications from other vendors, using a trader instead of a proprietary mechanism makes such integration easier.
A trader is very efficient at evaluating constraints, and you can use it to run queries on large numbers of objects without generating significant messaging overhead.
A trader is a flexible tool and is suitable for use by many diverse applications. The cost of using a trader is typically far lower than the cost of developing a separate applicationspecific mechanism for object selection for each application. If selection criteria or policies change over time, applications are easily modified because a different constraint often is sufficient to implement the change.
Dynamic properties provide a way to easily build systems that are highly flexible and that dynamically adjust their behavior. For example, you can create dynamic properties that report the system load on different machines to select a service on the machine that has the lowest load.
784

IT-SC book: Advanced CORBA® Programming with C++
Traders permit you to advertise objects by criteria that are unknown to the objects themselves. Even though at least some properties are likely to reflect object state, we can add other criteria that are not part of an object's state. For example, we might choose to add properties to controller advertisements that describe the size and color of the physical cabinet. This approach adds an extra degree of flexibility because we can change the way objects are advertised without changing the objects themselves.
We believe that traders will continue to grow in importance as an architectural component of distributed systems. A trader's role in a distributed system is similar to that of a search engine for the Web. Traders are general-purpose information brokers and are suitable for a variety of commercial purposes. In particular, trading for easily described commodity items, such as shares and CDs, is likely to become more and more important. In addition, with appropriate service type definitions, traders can form the basis for applications such as on-line browsing of catalogs and other electronic commerce applications.
On the other hand, using a trader forces you to deal with many of the same issues you must deal with when using the Naming Service. Often, the most significant issue is reliability. Adding a trader to your application design adds a dependency on another system component that might fail. This exposes your application to the reliability of a component outside your control, and you must anticipate and deal with failure of an independent component. For many applications, it is sufficient to give up or to simply refuse service if their trader is non-functional. However, in more demanding environments, you may have to create sophisticated error-handling and recovery strategies to deal with failures in an acceptable way.
Performance and scalability also may be important to you. Even though you may have a trader that meets your reliability requirements, this does not mean that it can handle the query throughput your application requires. Similarly, a trader may work fine with a few dozen service types and a few thousand service offers, but its performance may degrade unacceptably if you have hundreds of service types and hundreds of thousands of service offers.
You may be tempted to use a proprietary mechanism for object discovery for performance reasons. Often, a custom-built search mechanism that is part of the application is faster than a general-purpose trader. For example, we can view the find operation in the climate control system as a special-purpose trader. The advantages of building our own object discovery operations, such as find, are that we remove the dependency on the trader and that we can make the find operation arbitrarily fast by using appropriate data structures. Implementing find with the help of a trader will likely be slower because the trader uses general-purpose data structures instead of something that is highly optimized for specific queries.
On the other hand, operations such as find are very inflexible. Whenever we want to change the criteria by which we locate objects, we must update the code and possibly even change the application's data structures to support the new search criteria efficiently.
785

IT-SC book: Advanced CORBA® Programming with C++
As soon as we require any degree of flexibility in the way clients search for objects, a trader is likely to be a better choice than tailor-made search operations because of the effort that is required to build a general-purpose search engine that supports a flexible query language.
When you are using a trader as part of an application architecture, a common mistake is to treat it as a database. Even though a trader has many database characteristics, it is not a general-purpose database. For one thing, traders are typically optimized to deal efficiently with the most common import scenario, in which the importer selects a single matching service offer. If you routinely use a trader for queries that return large sets of service offers, you may find that performance or memory consumption of the trader becomes a problem.
Second, a trader is unreliable in the sense that it can give incomplete answers. For example, the max_search_card and max_return_card policies can cause arbitrary truncation of query results. In addition, in a federation, one or more traders may be down or the max_hop_count policy can prevent searching of the complete offer space. A database guarantees either to return all matching results or to return an error indication. A trader, on the other hand, can silently return partial results. Do not create designs that rely on a trader for complete answers. If you require complete knowledge of matching data, you must use a database.
19.19 What to Advertise
Your application requirements determine which objects you should advertise. As with the Naming Service, the prime candidates are bootstrap objects and objects that are public integration points for your application. Typically, you will create the service types required by your application only once: during installation of the software. If you have singleton objects such as a controller, you might also create the service offers for these objects during installation (possibly using a command-line tool, which saves you having to write a separate client to do the exports).
For objects that support explicit life cycle operations, such as thermometers and thermostats, it is probably best to tie export and withdrawal to the create and remove operations to avoid leaving stale service offers in the trader. This also means that you must have a strategy of dealing with the situation in which the trader is not available at the time an object is created or destroyed.
If your objects have short lifetimes, it is probably best not to advertise them in the trader at all. In addition, service offers in the trader should have properties that change only rarely because that means you have less overhead in keeping the property values up-to- date. If you use properties that reflect writable object state, a good strategy is to have each object implementation update not only the object state but also the service offer. In that way, you minimize the likelihood that object state and property values will get out of sync. Another option is to use dynamic properties, but this requires more development effort and reduces query performance.
786

IT-SC book: Advanced CORBA® Programming with C++
19.20 Avoiding Duplicate Service Offers
One tempting strategy for ensuring that service offers are always present and up-to-date is to have the server automatically export the service offers for its objects on start-up. There is nothing wrong with this strategy, but you must be aware of a somewhat surprising behavior of the trader: if you call export twice with exactly the same parameters, the trader makes no attempt either to reject the second call or to update the service offer created by the first call. Instead, calling export twice with identical parameters results in two distinct service offers with identical contents.
You may think this behavior strange—after all, the trader could reject an export operation if it already holds a service offer with the same information, so why do this? The answer is that this behavior may be exactly what is desired. Consider commercial television. It is not uncommon to see the same advertisement multiple times during a movie or even twice in the same commercial break. Obviously, the advertiser believes (rightly or wrongly) that this practice has a positive effect on sales.
Now translate this into a trading environment where traders are used as brokers for commercial purposes, such as advertising bookstores. It is likely that each bookstore pays the trader operator a fee to place its advertisements. An aggressive bookstore may place multiple identical advertisements to increase its chances of being selected during an import operation. Alternatively, the bookstore might have an agreement with the trader operator that ensures that its advertisements will be returned for at least 70% of matching service offers.[5] Such agreements are not uncommon in the commercial world. In a trading context, they are equivalent to showing the same TV advertisement multiple times or paying for a full-page advertisement in a newspaper instead of a quarter-page advertisement.
[5] Note that setting the preference for a query to random does not necessarily change this. The specification requires the matching service offers to be randomized with this preference but does not state that the randomization function must be without bias.
The point is that the trader specification cannot impose a notion of fairness on service offers—and therefore cannot reject duplicate offers—because what is fair depends on the environment.
For many applications, duplicate service offers are undesirable. For example, if we blindly export a service offer for the controller every time the server starts up, we end up cluttering the trader with lots of duplicate service offers for no good reason. Worse, if we updated the controller's offer, we could forget to update some of the offers and leave different offers having different property values for the same controller.
There is a simple technique for avoiding duplicate service offers. Instead of blindly exporting the service offer every time the server starts up, we can remember the offer ID that was returned by the previous export. On start-up, we call describe to see whether the offer still exists. If the offer has disappeared for some reason or has not been exported previously, we export the offer and remember the offer ID returned by that export.
787