- •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++
while (where != m_assets.end()) { if (num_found == 0) {
//First match overwrites reference
//in search record.
slist[i].device = where->second->_this();
}else {
//Each further match appends a new
//element to the search sequence. CORBA::ULong len = slist.length(); slist.length(len + 1); slist[len].key = slist[i].key;
slist[len].device = where->second->_this();
}
num_found++;
// Find next matching device with this key. where = find_if(
++where, m_assets.end(), StrFinder(sc, search_str)
);
}
}
}
}
We designed the find operation this way because it illustrates two important points.
If you look at the implementation code, you will find that it is remarkably free of CORBA artifacts. The code is complex because of the complex data types and semantics and not because we are using CORBA. In other words, the implementation would be equally complex using non-CORBA types.
At the IDL level, things look deceptively simple. It is tempting to create operations that do too much or to use operations that manipulate deeply nested data structures. As we suggest in Chapter 5, doing this is almost always an indication of poor design. And as you can see, when it comes to implementing such operations, you pay the price.
Defining the find operation as we do also gives us a convenient excuse to illustrate use of deeply nested IDL types. If you can understand the preceding example, you should be able to understand anything you are likely to encounter in real-life applications (which will be less complex if they are well designed).
10.10 Implementing the Server main Function
The server's main function is similar to what we saw in Chapter 3. The server initializes the ORB run time, obtains the Root POA, creates a servant manager, and activates the manager. The code then instantiates the controller singleton and sets its pointer in the static member Thermometer_impl::m_ctrl before writing the controller reference to the standard output. At this point, the controller servant is initialized and the code instantiates a number of thermometer and thermostat servants.
366
IT-SC book: Advanced CORBA® Programming with C++
Finally, the server calls run, which starts the event loop so that the server can accept requests.
int
main(int argc, char * argv[])
{
try {
// Initialize orb
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
//Get reference to Root POA. CORBA::Object_var obj
=orb->resolve_initial_references("RootPOA"); PortableServer::POA_var poa
=PortableServer::POA::_narrow(obj);
//Activate POA manager PortableServer::POAManager_var mgr
=poa->the_POAManager();
mgr->activate();
//Create a controller and set static m_ctrl member
//for thermostats and thermometers.
Controller_impl ctrl_servant;
Thermometer_impl::m_ctrl = &ctrl_servant;
//Write controller stringified reference to stdout CCS::Controller_var ctrl = ctrl_servant._this (); CORBA::String_var str = orb->object_to_string (ctrl); cout < str < endl < endl;
//Create a few devices. (Thermometers have odd asset
//numbers, thermostats have even asset numbers.) Thermometer_impl thermo1(2029, "Deep Thought"); Thermometer_impl thermo2(8053, "HAL"); Thermometer_impl thermo3(1027, "ENIAC"); Thermostat_impl tmstat1(3032, "Colossus", 68); Thermostat_impl tmstat2(4026, "ENIAC", 60); Thermostat_impl tmstat3(4088, "ENIAC", 50); Thermostat_impl tmstat4(8042, "HAL", 40);
//Accept requests
orb->run();
}
catch (const CORBA::Exception & e) {
cerr < "Uncaught CORBA exception: " < e < endl; return 1;
} |
|
catch (...) { |
// Unexpected exception, dump core |
abort(); |
|
} |
|
return 0; |
|
}
367
IT-SC book: Advanced CORBA® Programming with C++
Compiling, linking, and running the server proceeds as we show in Chapter 3, so we do not repeat these steps here.
10.11 The Complete Server Code
The complete code for the server is listed here once more for your reference. For simplicity, the entire code is distributed over only two files: server.hh and server.cc. For a production-quality application, you would probably choose a finergrained distribution over source files for maintainability. (See [11] for excellent advice on how to choose an appropriate file structure.)
10.11.1 The server.hh Header File
#ifndef server_HH_ #define server_HH_
#include <map> #include <stdlib.h> #include "CCSS.hh"
class Controller_impl;
class Thermometer_impl : public virtual POA_CCS::Thermometer {
public: |
|
// CORBA attributes |
model() |
virtual CCS::ModelType |
|
virtual CCS::AssetType |
throw(CORBA::SystemException); |
asset_num() |
|
virtual CCS::TempType |
throw(CORBA::SystemException); |
temperature() |
|
virtual CCS::LocType |
throw(CORBA::SystemException); |
location() |
|
virtual void |
throw(CORBA::SystemException); |
location(const char * loc) |
|
|
throw(CORBA::SystemException); |
// Constructor and destructor Thermometer_impl(CCS::AssetType anum, const char * location); virtual ~Thermometer_impl();
static Controller_impl * |
m_ctrl; // My controller |
|
protected: |
|
m_anum; // My asset number |
const CCS::AssetType |
||
private: |
|
|
// Helper functions |
|
|
CCS::ModelType |
get_model(); |
|
CCS::TempType |
get_temp(); |
|
CCS::LocType |
get_loc(); |
|
void |
set_loc(const char * new_loc); |
|
// Copy and assignment not supported
368
IT-SC book: Advanced CORBA® Programming with C++
Thermometer_impl(const Thermometer_impl &); void operator=(const Thermometer_impl &);
};
class Thermostat_impl :
public virtual POA_CCS::Thermostat, public virtual Thermometer_impl {
public:
// CORBA operations
virtual CCS::TempType get_nominal() throw(CORBA::SystemException);
virtual CCS::TempType set_nominal( CCS::TempType new_temp
) throw( CORBA::SystemException, CCS::Thermostat::BadTemp
); // Constructor and destructor Thermostat_impl(
CCS::AssetType anum, const char * location,
CCS::TempType nominal_temp
);
virtual ~Thermostat_impl() {}
private:
// Helper functions
CCS::TempType get_nominal_temp();
CCS::TempType set_nominal_temp(CCS::TempType new_temp) throw(CCS::Thermostat::BadTemp);
// Copy and assignment not supported Thermostat_impl(const Thermostat_impl &); void operator=(const Thermostat_impl &);
};
class Controller_impl : public virtual POA_CCS::Controller { public:
// CORBA operations
virtual CCS::Controller::ThermometerSeq *
list() throw(CORBA::SystemException); virtual void
find(CCS::Controller::SearchSeq & slist) throw(CORBA::SystemException);
virtual void change(
const CCS::Controller::Thermostat Seq & tlist, CORBA::Short delta
) throw( CORBA::SystemException, CCS::Controller::EChange
);
// Constructor and destructor Controller_impl() {}
virtual ~Controller_impl() {}
369
IT-SC book: Advanced CORBA® Programming with C++
//Helper functions to allow thermometers and
//thermostats to add themselves to the m_assets map
//and to remove themselves again.
void |
add_impl(CCS::AssetType anum, Thermometer_impl * tip); |
void |
remove_impl(CCS::AssetType anum); |
private:
// Map of known servants
typedef map<CCS::AssetType, Thermometer_impl *> AssetMap; AssetMap m_assets;
//Copy and assignment not supported Controller_impl(const Controller_impl &); void operator=(const Controller_impl &);
//Function object for the find_if algorithm to search for
//devices by location and model string.
class StrFinder { |
|
public: |
|
StrFinder( |
sc, |
CCS::Controller::SearchCriterion |
|
const char * |
str |
) : m_sc(sc), m_str(str) {} bool operator()(
pair<const CCS::AssetType, Thermometer_impl *> & p ) const
{
switch (m_sc) {
case CCS::Controller::LOCATION:
return strcmp(p.second->location(), m_str) == 0; break;
case CCS::Controller::MODEL:
return strcmp(p.second->model(), m_str) == 0; break;
default: |
// Precondition violation |
abort(); |
|
} |
|
} |
|
private: |
m_sc; |
CCS::Controller::SearchCriterion |
|
const char * |
m_str; |
}; |
|
}; |
|
#endif |
|
10.11.2 The server.cc Implementation File
#include |
<iostream.h> |
#include |
"icp.h" |
#include |
"server.hh" |
//----------------------------------------------------------------
Controller_impl * Thermometer_impl::m_ctrl; // static member
370
IT-SC book: Advanced CORBA® Programming with C++
// Helper function to read the model string from a device.
CCS::ModelType Thermometer_impl:: get_model()
{
char buf[32];
if (ICP_get(m_anum, "model", buf, sizeof(buf)) != 0) abort();
return CORBA::string_dup(buf);
}
// Helper function to read the temperature from a device.
CCS::TempType Thermometer_impl:: get_temp()
{
short temp;
if (ICP_get(m_anum, "temperature", &temp, sizeof(temp)) != 0) abort();
return temp;
}
// Helper function to read the location from a device.
CCS::LocType Thermometer_impl:: get_loc()
{
char buf[32];
if (ICP_get(m_anum, "location", buf, sizeof(buf)) != 0) abort();
return CORBA::string_dup(buf);
}
// Helper function to set the location of a device.
void Thermometer_impl::
set_loc(const char * loc)
{
if (ICP_set(m_anum, "location", loc) != 0) abort();
}
// Constructor. |
|
|
Thermometer_impl:: |
|
|
Thermometer_impl( |
anum, |
|
CCS::AssetType |
|
|
const char * |
location |
|
) : m_anum(anum) |
|
|
{ |
|
// Mark device as on-line |
if (ICP_online(anum) != 0) |
||
abort(); |
|
// Set location |
set_loc(location); |
|
|
371
IT-SC book: Advanced CORBA® Programming with C++
m_ctrl->add_impl(anum, this); // Add self to controller's map
}
// Destructor.
Thermometer_impl:: ~Thermometer_impl()
{
try {
m_ctrl->remove_impl(m_anum); // Remove self from map ICP_offline(m_anum); // Mark device as off-line
} catch (...) { abort();
}
}
// IDL model attribute.
CCS::ModelType Thermometer_impl::
model() throw(CORBA::SystemException)
{
return get_model();
}
// IDL asset_num attribute.
CCS::AssetType Thermometer_impl::
asset_num() throw(CORBA::SystemException)
{
return m_anum;
}
// IDL temperature attribute.
CCS::TempType Thermometer_impl::
temperature() throw(CORBA::SystemException)
{
return get_temp();
}
// IDL location attribute accessor.
CCS::LocType Thermometer_impl::
location() throw(CORBA::SystemException)
{
return get_loc();
}
// IDL location attribute modifier. void
Thermometer_impl::
location(const char * loc) throw(CORBA::SystemException)
{
set_loc(loc);
372
IT-SC book: Advanced CORBA® Programming with C++
}
//----------------------------------------------------------------
// Helper function to get a thermostat's nominal temperature.
CCS::TempType Thermostat_impl:: get_nominal_temp()
{
short temp;
if (ICP_get(m_anum, "nominal_temp", &temp, sizeof (temp)) != 0) abort();
return temp;
}
// Helper function to set a thermostat's nominal temperature.
CCS::TempType Thermostat_impl::
set_nominal_temp(CCS::TempType new_temp) throw(CCS::Thermostat::BadTemp)
{
short old_temp;
//We need to return the previous nominal temperature,
//so we first read the current nominal temperature before
//changing it.
if (ICP_get(
m_anum, "nominal_temp", &old_temp, sizeof(old_temp) ) != 0) {
abort();
}
// Now set the nominal temperature to the new value. if (ICP_set(m_anum, "nominal_temp", &new_temp) != 0) {
//If ICP_set() failed, read this thermostat's minimum
//and maximum so we can initialize the BadTemp exception. CCS::Thermostat::BtData btd;
ICP_get(
m_anum, "MIN_TEMP",
&btd.min_permitted, sizeof(btd.min_permitted)
); ICP_get(
m_anum, "MAX_TEMP",
&btd.max_permitted, sizeof(btd.max_permitted)
);
btd.requested = new_temp; btd.error_msg = CORBA::string_dup(
new_temp > btd.max_permitted ? "Too hot" : "Too cold"
);
throw CCS::Thermostat::BadTemp(btd);
}
return old_temp;
}
// Constructor.
373
IT-SC book: Advanced CORBA® Programming with C++
Thermostat_impl:: |
|
Thermostat_impl( |
anum, |
CCS::AssetType |
|
const char * |
location, |
CCS::TempType |
nominal_temp |
) : Thermometer_impl(anum, location)
{
//Base Thermometer_impl constructor does most of the
//work, so we need only set the nominal temperature here. set_nominal_temp(nominal_temp);
}
//IDL get_nominal operation. CCS::TempType Thermostat_impl::
get_nominal() throw(CORBA::SystemException)
{
return get_nominal_temp();
}
//IDL set_nominal operation.
CCS::TempType Thermostat_impl::
set_nominal(CCS::TempType new_temp) throw(CORBA::SystemException, CCS::Thermostat::BadTemp)
{
return set_nominal_temp(new_temp);
}
//----------------------------------------------------------------
//Helper function for thermometers and thermostats to
//add themselves to the m_assets map.
void Controller_impl::
add_impl(CCS::AssetType anum, Thermometer_impl * tip)
{
m_assets[anum] = tip;
}
//Helper function for thermometers and thermostats to
//remove themselves from the m_assets map.
void Controller_impl::
remove_impl(CCS::AssetType anum)
{
m_assets.erase(anum);
}
// IDL list operation.
CCS::Controller::ThermometerSeq * Controller_impl::
list() throw(CORBA::SystemException)
{
374
IT-SC book: Advanced CORBA® Programming with C++
//Create a new thermometer sequence. Because we know
//the number of elements we will put onto the sequence,
//we use the maximum constructor. CCS::Controller::ThermometerSeq_var listv
=new CCS::Controller::ThermometerSeq(m_assets.size()); listv->length(m_assets.size());
//Loop over the m_assets map and create a
//reference for each device.
CORBA::ULong count = 0; AssetMap::iterator i;
for (i = m_assets.begin(); i != m_assets.end(); i++) listv[count++] = i->second->_this();
return listv._retn();
}
// IDL change operation.
void Controller_impl:: change(
const CCS::Controller::ThermostatSeq & tlist, CORBA::Short delta
) throw(CORBA::SystemException, CCS::Controller::EChange)
{
CCS::Controller::EChange ec; |
// Just in case we need it |
//We cannot add a delta value to a thermostat's temperature
//directly, so for each thermostat, we read the nominal
//temperature, add the delta value to it, and write
//it back again.
for (CORBA::ULong i = 0; i < tlist.length(); i++) { if (CORBA::is_nil(tlist[i]))
continue;
// Read nominal temp and update it. CCS::TempType tnom = tlist[i]->get_nominal(); tnom += delta;
try { tlist[i]->set_nominal(tnom);
}
catch (const CCS::Thermostat::BadTemp & bt) {
//If the update failed because the temperature
//is out of range, we add the thermostat's info
//to the errors sequence.
CORBA::ULong len = ec.errors.length(); ec.errors.length(len + 1); ec.errors[len].tmstat_ref = tlist[i]; ec.errors[len].info = bt.details;
}
}
//If we encountered errors in the above loop,
//we will have added elements to the errors sequence. if (ec.errors.length() != 0)
throw ec;
}
375
IT-SC book: Advanced CORBA® Programming with C++
// IDL find operation
void Controller_impl::
find(CCS::Controller::SearchSeq & slist) throw(CORBA::SystemException)
{
// Loop over input list and look up each device. CORBA::ULong listlen = slist.length();
for (CORBA::ULong i = 0; i < listlen; i++) {
AssetMap::iterator where; |
// |
Iterator for asset map |
int num_found = 0; |
// |
Num matched per iteration |
//Assume we will not find a matching device. slist[i].device = CCS::Thermometer::_nil();
//Work out whether we are searching by asset,
//model, or location.
CCS::Controller::SearchCriterion sc = slist[i].key._d(); if (sc == CCS::Controller::ASSET) {
// Search for matching asset number.
where = m_assets.find(slist[i].key.asset_num()); if (where != m_assets.end())
slist[i].device = where->second->_this();
}else {
//Search for model or location string. const char * search_str;
if (sc == CCS::Controller::LOCATION) search_str = slist[i].key.loc();
else
search_str = slist[i].key.model_desc();
//Find first matching device (if any). where = find_if(
m_assets.begin(), m_assets.end(), StrFinder(sc, search_str)
);
//While there are matches...
while (where != m_assets.end()) { if (num_found == 0) {
//First match overwrites reference
//in search record.
slist[i].device = where->second->_this();
}else {
//Each further match appends a new
//element to the search sequence. CORBA::ULong len = slist.length(); slist.length(len + 1); slist[len].key = slist[i].key;
slist[len].device = where->second->_this();
}
num_found++;
// Find next matching device with this key.
376
IT-SC book: Advanced CORBA® Programming with C++
where = find_if(
++where, m_assets.end(), StrFinder(sc, search_str)
);
}
}
}
}
//----------------------------------------------------------------
int
main(int argc, char * argv[])
{
try {
// Initialize orb
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
//Get reference to Root POA. CORBA::Object_var obj
=orb->resolve_initial_references("RootPOA"); PortableServer::POA_var poa
=PortableServer::POA::_narrow(obj);
//Activate POA manager PortableServer::POAManager_var mgr
=poa->the_POAManager();
mgr->activate();
//Create a controller and set static m_ctrl member
//for thermostats and thermometers.
Controller_impl ctrl_servant;
Thermometer_impl::m_ctrl = &ctrl_servant;
//Write controller stringified reference to stdout CCS::Controller_var ctrl = ctrl_servant._this (); CORBA::String_var str = orb->object_to_string (ctrl); cout < str < endl < endl;
//Create a few devices. (Thermometers have odd asset
//numbers, thermostats have even asset numbers.) Thermometer_impl thermo1(2029, "Deep Thought"); Thermometer_impl thermo2(8053, "HAL"); Thermometer_impl thermo3(1027, "ENIAC");
Thermostat_impl tmstat1(3032, "Colossus", 68);
Thermostat_impl tmstat2(4026, "ENIAC", 60);
Thermostat_impl tmstat3(4088, "ENIAC", 50);
Thermostat_impl tmstat4(8042, "HAL", 40);
// Accept requests orb->run();
}
catch (const CORBA::Exception & e) {
cerr < "Uncaught CORBA exception: " < e < endl; return 1;
} catch (...) { abort();
}
377
