
- •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++
Chapter 14. Implementation Repositories
and Binding
14.1 Chapter Overview
This chapter presents a detailed picture of what happens beneath the covers of an ORB. In particular, this chapter shows how a client establishes connections to the servers it needs to access. Sections 14.2 to 14.4 discuss different modes of binding and explain the role of the implementation repository during binding and automatic server start-up. Section 14.5 discusses the design choices available for implementation repositories and explains how these choices affect object migration as well as reliability, performance, and scalability of an ORB. Sections 14.6 and 14.7 discuss the various activation modes for servers, and Section 14.8 concludes the chapter by discussing some of the security issues surrounding implementation repositories.
14.2 Binding Modes
In Chapter 13, we discuss how clients send requests to servers and receive replies via a connection-oriented protocol such as TCP/IP, but we largely skip over the issues of how a client can establish a connection to the correct server and how a server associates incoming requests with its servant. This process of opening a connection and associating an object reference with its servant is known as binding.
CORBA offers a large amount of flexibility in the way an ORB implements binding. Different ORBs offer different options, and, in general, the design of binding algorithms has profound influence on an ORB's flexibility, performance, and scalability.
ORBs typically support two binding modes: direct binding and indirect binding. Direct binding is supported by all ORBs. Indirect binding relies on an external location broker known as an implementation repository and is an optional component of CORBA (most general-purpose ORBs have an implementation repository). The implementation repository can provide additional features, such as server migration, object migration, automatic server start-up, and load balancing. The precise set of features of the implementation repository depends on the ORB vendor and the anticipated deployment environment of the ORB.
Both direct and indirect binding are protocol-specific. In particular, the addressing information embedded in an IOR depends on the underlying transport. For the remainder of this discussion, we assume that IIOP is used.
14.3 Direct Binding
549

IT-SC book: Advanced CORBA® Programming with C++
Whenever a server application creates an object reference, the server-side run time embeds information to support binding inside the object reference. Specifically, an IOR contains an IP address (or host name), TCP port number, and an object key. If a server inserts its own address and port number into a reference, the reference uses direct binding. An ORB can use direct binding for both transient and persistent references. As you saw in Section 11.4.1, a transient IOR continues to work only for as long as its associated POA exists. After the POA is destroyed or its server shuts down, a transient reference becomes permanently non-functional; it never works again even if its POA is re-created or its server is restarted. Conversely, a persistent IOR continues to denote the same object even if the server shuts down and is restarted.
14.3.1 Direct Binding for Transient References
Transient references always rely on direct binding.[1] When a server creates an IOR using a POA with a TRANSIENT life span policy, the server-side run time embeds binding information in the IOR.
[1] The CORBA specification does not require this, so transient references could also use indirect binding. However, no ORB we are aware of actually does this, because indirect binding for transient references complicates the ORB without providing any benefits.
The address and port number in the profile body are set to the server's own address and port number.
The object key of the IOR is set to contain two elements.
The name of the POA used to create the IOR.
Transient POAs must have names that are unique in space and time among all other POAs in an ORB domain. To enforce this, the ORB can prefix a unique identifier to the POA name when a transient POA is created. For example, the ORB can use a universally unique identifier (UUID) to ensure that no transient POA can ever have a name that was used for another transient POA at some time in the past.
An object ID that is unique within the scope of the associated POA.
Because the object ID need be unique only within the scope of its POA, ORBs, for example, can keep a counter in each POA using the TRANSIENT policy. The counter is incremented for every new reference created by this POA, so all IORs for this POA carry a different object ID. The ORB is not obliged to use a counter and can use some other strategy to generate unique object IDs.
When a client receives a transient reference and invokes the first request, the client-side run time extracts the address and port number from the profile body of the IOR and attempts to open a connection. This connection attempt can encounter one of the following cases.
550

IT-SC book: Advanced CORBA® Programming with C++
The server is running at the host and port indicated by the reference.
In this case, the client sends a request message to the server. The request message contains the object key. The object key consists of (among other things) the POA name and the object ID. The server uses the POA name to locate the appropriate POA, and the POA uses the object ID to locate the appropriate servant. If both POA and servant exist (or can be activated), binding succeeds and the request is dispatched to the servant.
No process is listening at the host and port indicated by the reference.
The client's attempt to open a connection to the server fails, and the client-side run time raises a TRANSIENT exception in the application.
The original server that created the reference was shut down, and a different server has since been started at the same port as the original server.
In this case, the client sends the request to the server that is listening at the port. The server receives the request and attempts to locate a POA with a matching name. However, because all transient POAs have unique names, the POA name in the object key does not match any of the server's POA names. Accordingly, the server returns an OBJECT_NOT_EXIST exception to the client, and binding fails, as it should.
The original server was shut down but later was restarted and happened to get the same port number.
Even though the same server is listening at the same address as originally, binding must fail because a transient reference is valid only for the lifetime of its POA. Again, the client sends the request to the server after opening the connection. However, the POA name in the object key is guaranteed not to match any of the POA names used by the server. Even if the server code creates a transient POA with the same name as that of a previous transient POA, the ORB enforces uniqueness of the transient POA name by prefixing a UUID (or a similar pseudo-random identifier) to the name. The POA name mismatch results in the server sending an OBJECT_NOT_EXIST exception to the client, and binding fails, as it should.
In summary, binding of transient references relies on the actual host address and port number of the server. If the server is still running at that address and port number when the client invokes a request, binding succeeds. If the server is no longer running, the client-side run time raises a TRANSIENT exception. If another server instance is running at that address and port number, the server receiving the request returns an OBJECT_NOT_EXIST exception to the client because the POA name in the object key does not match any of the server's POA names.
14.3.2 Direct Binding of Persistent References
551

IT-SC book: Advanced CORBA® Programming with C++
An ORB has many different options for how to make object references persistent. The simplest mechanism relies on direct binding.
When a server creates a reference using a POA that has a PERSISTENT life span policy, the ORB run time creates a profile body for the IOR that contains the server's address and port number. However, because the reference uses a persistent POA, the ORB does not make its name unique by adding a UUID. Instead, it uses the POA name that was specified by the application when it created the POA.
Binding of the reference now proceeds exactly as with transient references. The client connects to the address and port number found in the reference and sends a request. Provided that the server is running at the correct address, the request is bound to the correct servant. Direct binding for persistent references relies on the following.
The server must always use the same name for the same POA when it creates the POA. The server must always use the same object ID for a particular CORBA object when it creates an IOR for that object.
The server must always start up on the same host and port number.
You can easily take care of the first two points by using the same POA name and object ID when you create a POA or an IOR. However, CORBA does not specify how to enforce the third point, so how you instruct a server to always start on the same host and port varies from ORB to ORB. Typically, the ORB allows you to pass a port number as a command-line argument to the server. The port number is made known to the server-side run time via ORB_init, so the run time can arrange for the server to connect to the specified port. Some ORBs also allow you to use a configuration utility to store the port number that a server should use.
Direct binding of persistent references is simple and efficient. Because an IOR directly contains the host and port number of the server, the client can open a connection directly to the server without incurring any additional overhead. However, direct binding of persistent references also has some drawbacks.
You cannot start the server on a different host without breaking references to persistent objects in the server held by clients. Every reference contains the host domain name or IP address; if the server is moved to a host having a different domain name or a host having a different IP address, clients using a reference created while the server was running on its previous host can no longer bind requests.
The server must listen for requests on a fixed port that must be assigned to the server once and cannot be changed thereafter without breaking references. This requirement in itself is not bad, but it causes administrative problems in large installations because manual administration of port numbers is cumber-some.
552