
- •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++
Part V: CORBAservices
Chapter 18. The OMG Naming Service
18.1 Chapter Overview
This chapter shows how you can use a Naming Service to obtain object references without having to pass them around as strings. Sections 18.2 and 18.3 present the fundamental ideas and concepts of the service. Sections 18.4 to 18.9 present the details of the IDL operations and explain how to manipulate and locate names and object references in a naming graph. Sections 18.10 to 18.13 discuss a number of design issues, such as the implications of using the Naming Service as part of your overall application architecture and the options for federated naming. Section 18.14 shows how to use the Naming Service in the climate control system.
18.2 Introduction
The OMG Naming Service [21] is the simplest and most basic of the standardized CORBA services. It provides a mapping from names to object references: given a name, the service returns an object reference stored under that name. This is similar to the Internet Domain Name Service (DNS), which translates Internet domain names (such as acme.com) into IP addresses (such as 234.234.234.234). Both the OMG Naming Service and the DNS implement simple mappings from a name to a lookup value and are often likened to a white pages phone book, which maps subscriber names to telephone numbers.
The Naming Service provides a number of advantages to clients.[1]
[1] In the context of this discussion, the term client is used to refer to a client of the Naming Service. That client may be either a client or a server as far as your application is concerned.
Clients can use meaningful names for objects instead of having to deal with stringified object references.
By changing the value of a reference advertised under a name, you can get clients to use a different implementation of an interface without having to change source code. The clients use the same name but get a different reference.
The Naming Service can be used to solve the problem of how application components get access to the initial references for an application. Advertising these references in the Naming Service eliminates the need to store them as stringified references in files.
18.3 Basic Concepts
668

IT-SC book: Advanced CORBA® Programming with C++
The Naming Service maps names to object references. A name-to-reference association is called a name binding. The same object reference can be stored several times under different names, but each name identifies exactly one reference. A naming context is an object that stores name bindings. In other words, each context object implements a table that maps names to object references. A name in the table can denote either an object reference to an application object (such as the CCS controller) or another context object in the Naming Service. This means that, like a file system, contexts can be connected to form hierarchies: contexts correspond to directories that store names to either directories (other contexts) or files (application objects). A hierarchy of contexts and bindings is known as a naming graph. Figure 18.1 shows an example of a naming graph.
Figure 18.1 A naming graph.
In this graph, hollow nodes are naming contexts and solid nodes are application objects. A context can appear either as an interior node or as a leaf node, whereas an application object always appears as a leaf node. Directed arcs represent object references and are labeled with the name they appear under in their context.
This naming graph is similar to what you would expect to see for a DOS or UNIX file system.
Within a particular context, name bindings are unique (each binding can appear only once within its parent context).
Given a starting context, you can navigate to a target node by traversing a path from the starting context to the target node. The sequence of bindings used in the traversal forms a pathname that uniquely identifies the target object.
The same name binding can appear multiple times provided that each binding is in a different parent context. For example, the binding bin appears twice in the graph in
Figure 18.1.
A single object or context can have multiple names. For example, the sample graph uses the name bindings sys and s1 for the same context. (This corresponds to the concept of multiple links to the same file or directory in a UNIX file system.)
669

IT-SC book: Advanced CORBA® Programming with C++
Apart from its similarities to hierarchical file systems, the naming graph in Figure 18.1 illustrates a few significant differences.
It is possible for the graph to have contexts that have no names. Such contexts are known as orphaned contexts. (This is different from a normal file system, which requires every file and directory to have a name.)
A naming graph has one or more distinguished contexts known as initial naming contexts. Typically, initial naming contexts are orphaned contexts (but they need not be). Conversely, if a context is orphaned, it is typically also an initial naming context. As you will see in Section 18.6.3, initial naming contexts determine the points at which clients gain access to a naming graph. An initial naming context corresponds to what we think of as the root directory of a file system.
A naming graph can have more than one root. Typically, each such root is also configured as an initial naming context.
A graph can consist of several disconnected subgraphs.
It is possible for the graph to have loops.
There are reasons for these differences. The OMG Naming Service can be implemented either as a stand-alone service or as a front end to some other existing naming service. If implemented as a front end, the OMG Naming Service must reflect the semantics of the back-end service. If the back end permits loops, the front end must also permit them. The OMG Naming Service therefore imposes as few restrictions as possible on the shape of the naming graph to avoid restricting the choice of back-end service.
Nevertheless, it is probably best if you avoid loops in your naming graph. Loops make the service harder to administer because they create an infinite number of pathnames for the same binding. For example, by traversing the collections, cd, and app2 bindings in a loop, the graph in Figure 18.1 contains an infinite number of pathnames. If a naming graph consists of several disconnected subgraphs, each root is typically configured as an initial naming context. Clients can gain access to initial naming contexts via a special API call (see Section 18.6.3).
18.4 Structure of the Naming Service IDL
The IDL definitions for the Naming Service are provided in a file called CosNaming.idl. The file contains a single module called CosNaming. This module contains a number of type definitions and two interfaces: NamingContext and BindingIterator. The overall structure of the IDL for the service is as follows:
//File: CosNaming.idl #pragma prefix "omg.org" module CosNaming {
// Type definitions here...
670

IT-SC book: Advanced CORBA® Programming with C++
interface NamingContext { // ...
};
interface BindingIterator { // ...
};
};
Note that the repository IDs for the entire specification carry the prefix omg.org. This is a common feature of all OMG specifications and avoids polluting the global namespace for repository IDs.
18.5 Semantics of Names
Intuitively, the names used by the Naming Service behave like file names in a file system. However, there are some differences you need to be aware of.
18.5.1 Name Structure
The names used by the OMG Naming Service are not quite the same as ordinary file names. Here are the relevant definitions:
module CosNaming {
typedef string Istring; struct NameComponent
Istring id; Istring kind;
};
typedef sequence<NameComponent> Name; // ...
};
The NameComponent structure corresponds to a single "hop" in a pathname. A sequence of name components corresponds to a pathname that defines a traversal from some starting context to a target binding. Note that each name component itself consists of a pair of strings: id and kind. In this respect, CosNaming names differ from ordinary pathnames for files (in a pathname, each component is a simple string and not a pair of strings).
18.5.2 Name Representation
The OMG Naming Service specification does not define a representation of names as strings. In other words, we cannot simply write something such as user/u1/fred to denote a pathname. For one thing, the OMG Naming Service places no restrictions on the characters that may be used in a name component (the full set of ISO Latin-1 characters is permissible, including non-printing characters).[2] This means that there is no dedicated separator character, such as "/," to separate name components. Second, because name components themselves consist of a pair of strings, stringified names would require a
671

IT-SC book: Advanced CORBA® Programming with C++
secondary separator (other than "/") to separate the id and kind parts of a name component.[3] Because there is no specified way to express a CosNaming name as a string, we can use tables to show names.
[2]The specification allows an implementation of the Naming Service to restrict the permissible characters, so it can use back-end naming services that support only a limited character set. Most implementations do not restrict the set of permissible characters, but you must inquire from your vendor whether your Naming Service has any restrictions.
[3]At the time of this writing, the OMG is evaluating submissions for a revised Naming Service. The revised service will define a stringified representation for names.
The name shown in Table 18.1 consists of three components. For all three components, only the id fields are used and the kind fields are the empty string. Another example of a name is shown in Table 18.2.
Table 18.1. A name represented as a table (all kind fields are the empty string).
Index |
id |
kind |
0 |
user |
|
1 |
u1 |
|
2 |
fred |
|
|
|
|
Table 18.2. A name using both id and kind fields.
Index |
id |
kind |
0 |
a/b |
dir |
1 |
|
|
2 |
ctrl |
factory |
This three-component name has a first component with an id field of a/b and a kind field of dir. The second component has the empty string as both the id and the kind fields, and the third component uses ctrl and factory as the values of the id and the kind fields, respectively.
For the remainder of this chapter, we use a typographical convention to represent names. For example, the following is the same name as the one shown in Table 18.1.
user/u1/fred
We use a slash as a separator for name components here; to avoid confusion in our notation, we do not use names that contain slashes themselves (even though it is perfectly legal as far as the Naming Service is concerned).
To show a name that also uses the kind fields, we use the notation
user(dir)/u1(dir)/fred(person)
672

IT-SC book: Advanced CORBA® Programming with C++
This corresponds to the three-component name shown in Table 18.3. Again, to avoid confusion with our separator convention, we do not use id or kind fields that contain parentheses themselves.
Although name components can contain non-printing characters, we recommend that you restrict your names to the same set of characters you would use for file names. This practice will make life easier if you want to use command-line tools or graphical user interfaces to manipulate the naming graph.
Table 18.3. Table representation of the name user(dir)/u1(dir)/fred(person).
Index |
id |
kind |
0 |
user |
dir |
1 |
u1 |
dir |
2 |
fred |
person |
18.5.3 Purpose of the kind Field
The kind field of name components can be used to describe the id field in some way. For example, you could use kind values of person, factory, or GIF_Image to classify the object advertised under a name. This idea is similar to that of file name extensions; for example, we frequently use file names such as file.cc and file.o to make the contents of a file obvious by its name.
Many people (including the authors) believe that the distinction between id and kind for name components is a bad idea. For one thing, the analogy with file names does not necessarily hold for object names. Second, even if name components were single strings, we could still use the idea of a name extension by using only the id field and "." as a separator character. As it stands, the Naming Service specification only complicates the type of name components without providing any additional functionality.
However, we must live with this wrinkle of the Naming Service. For your applications, you can choose to ignore the kind fields and always set them to the empty string.
18.5.4 Non-Support for Wide Strings
If you look at the IDL definition of names on page 775, you will find another wrinkle. Note that the IDL contains a type definition for Istring. An Istring is simply an alias for string, so why was this definition added? The reason is historical. At the time the Naming Service was defined, IDL did not provide a wide character type, but it was known that wide characters would be supported in a future version. The Istring definition was added in anticipation of this change. The idea was that by redefining Istring to wstring, the OMG could upgrade the Naming Service to support names containing wide characters.
Unfortunately, this idea does not work. Consider what would happen if the OMG changed Istring to be an alias for wstring now. We would end up with different
673

IT-SC book: Advanced CORBA® Programming with C++
Naming Services coexisting in CORBA. In some services, Istring would be an alias for string, and in others Istring would be an alias for wstring. We would have two different types with the same repository ID. In one service, the repository ID
IDL:omg.org/CosNaming/Istring:1.0
would denote the type string, whereas in another, the same repository ID would denote the type wstring.
We cannot permit this situation because CORBA intimately relies on repository IDs to provide type safety. CORBA makes the assumption that the same repository ID denotes the same type everywhere. If a single repository ID represented different types for different applications in a CORBA system, all type safety and interoperability would be lost. For example, if a client that takes Istring as type string were to send a name component to a server that takes Istring as type wstring, the server's marshaling code would misinterpret 8-bit ISO Latin-1 characters as wide characters. Not only would this lead to incorrect interpretation of the bit pattern of the name component, but it could also cause the server to lose synchronization with IIOP message boundaries. In a poorquality implementation, it could crash the server.
At the time of this writing, there are no plans to upgrade the Naming Service to support wide character names. If such an upgrade is provided in the future, a simple redefinition of Istring to wstring will not work. Instead, it will be necessary to add a new module containing new interfaces that support wide character names.
Upgrading the Naming Service for wide character support is just one example of the more general topic of versioning, a topic we briefly touch on in Section 4.19.3.
18.5.5 Name Equivalence
On page 773, we state that name components must be unique within their parent context. To determine uniqueness, the Naming Service compares both the id and the kind fields. This means that the same context can contain two name components that have the same id value and differ only in the values of their kind fields. Similarly, two name components are considered different if their kind fields are identical but their id fields are different. Formally, name equivalence is defined as follows.
Two name components are equivalent only if they have identical id and kind fields. Two names are equivalent only if all their components are equivalent.
For example, the following four single-component names are different and can all coexist within the same parent context:
Guinness(Beer)
Budweiser(Beer)
Chair(Person)
Chair(Furniture)
674