summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormm4 <mm4@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-08-24 21:35:33 +0000
committermm4 <mm4@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-08-24 21:35:33 +0000
commitcfc53c027528e6913576ad03cffcc3cf2fb0cbf6 (patch)
tree82d5c1c6b554a4d93275d31e23ec76d1707a56d5
parent75af2d468fab81009c366fa57d96e13f27e2e7cd (diff)
downloadATCD-cfc53c027528e6913576ad03cffcc3cf2fb0cbf6.tar.gz
Added examples suite from H&V
-rw-r--r--TAO/examples/Advanced/README48
-rw-r--r--TAO/examples/Advanced/ch_12/CCS.idl104
-rw-r--r--TAO/examples/Advanced/ch_12/CHANGES84
-rw-r--r--TAO/examples/Advanced/ch_12/Makefile88
-rw-r--r--TAO/examples/Advanced/ch_12/README55
-rw-r--r--TAO/examples/Advanced/ch_12/client.cpp278
-rw-r--r--TAO/examples/Advanced/ch_12/icp.cpp386
-rw-r--r--TAO/examples/Advanced/ch_12/icp.h42
-rwxr-xr-xTAO/examples/Advanced/ch_12/run_test.pl54
-rw-r--r--TAO/examples/Advanced/ch_12/server.cpp732
-rw-r--r--TAO/examples/Advanced/ch_12/server.h237
-rw-r--r--TAO/examples/Advanced/ch_18/CCS.idl103
-rw-r--r--TAO/examples/Advanced/ch_18/CHANGES98
-rw-r--r--TAO/examples/Advanced/ch_18/Makefile99
-rw-r--r--TAO/examples/Advanced/ch_18/README45
-rw-r--r--TAO/examples/Advanced/ch_18/client.cpp349
-rw-r--r--TAO/examples/Advanced/ch_18/icp.cpp386
-rw-r--r--TAO/examples/Advanced/ch_18/icp.h42
-rwxr-xr-xTAO/examples/Advanced/ch_18/run_test.pl72
-rw-r--r--TAO/examples/Advanced/ch_18/server.cpp791
-rw-r--r--TAO/examples/Advanced/ch_18/server.h238
-rw-r--r--TAO/examples/Advanced/ch_3/CHANGES47
-rw-r--r--TAO/examples/Advanced/ch_3/Makefile71
-rw-r--r--TAO/examples/Advanced/ch_3/README42
-rw-r--r--TAO/examples/Advanced/ch_3/client.cpp67
-rwxr-xr-xTAO/examples/Advanced/ch_3/run_test.pl54
-rw-r--r--TAO/examples/Advanced/ch_3/server.cpp89
-rw-r--r--TAO/examples/Advanced/ch_3/server.h31
-rw-r--r--TAO/examples/Advanced/ch_3/time.idl31
-rw-r--r--TAO/examples/Advanced/ch_8_and_10/CCS.idl88
-rw-r--r--TAO/examples/Advanced/ch_8_and_10/CHANGES51
-rw-r--r--TAO/examples/Advanced/ch_8_and_10/Makefile86
-rw-r--r--TAO/examples/Advanced/ch_8_and_10/README40
-rw-r--r--TAO/examples/Advanced/ch_8_and_10/client.cpp265
-rw-r--r--TAO/examples/Advanced/ch_8_and_10/icp.cpp300
-rw-r--r--TAO/examples/Advanced/ch_8_and_10/icp.h41
-rwxr-xr-xTAO/examples/Advanced/ch_8_and_10/run_test.pl54
-rw-r--r--TAO/examples/Advanced/ch_8_and_10/server.cpp464
-rw-r--r--TAO/examples/Advanced/ch_8_and_10/server.h167
-rwxr-xr-xTAO/examples/Advanced/run_test.pl62
40 files changed, 6381 insertions, 0 deletions
diff --git a/TAO/examples/Advanced/README b/TAO/examples/Advanced/README
new file mode 100644
index 00000000000..3d191a1c345
--- /dev/null
+++ b/TAO/examples/Advanced/README
@@ -0,0 +1,48 @@
+$Id$
+______________________________________________________________________________
+
+These examples have been taken from the book "Advanced CORBA
+Programming with C++" by Michi Henning and Steve Vinoski. Copyright
+1999. Addison-Wesley, Reading, MA. To make the examples work with TAO,
+some minor modifications to the source code have been made, with
+permission, by Mike Moran <mm4@cs.wustl.edu>. Each directory contains a
+file CHANGES which describes all modifications, as well as a README file
+documenting its use.
+
+The original source distribution can be found at the Addison-Wesley
+homepage:
+<http://cseng.aw.com/bookdetail.qry?ISBN=0-201-37927-9&ptype=0>
+
+
+
+The following is the README distibuted with the original code:
+______________________________________________________________________________
+
+
+Each directory contains one of the major code examples of the corresponding
+chapter.
+
+We have not provided Makefiles and a build environment simply because
+there are not enough ORBs with a POA around yet to make this feasible.
+
+You will almost certainly hit minor glitches with include file names.
+
+Another potential problem is the version of the iostream library supported
+by your compiler. The code here uses the old iostream library. If your
+compiler requires use of the new ISO/IEC library, you will have to replace
+occurences of "#include <iostream.h>" with "#include <iostream>" and
+use the std:: qualifier for I/O operations. (The easiest way to deal with
+this is probably to add a "using namespace ::std" directive to the
+code somewhere. (Similar comments apply to uses of the fstream and strstream
+classes.)
+
+It is also likely that you will encounter some compiler incompatibilities.
+If you do and update the source to work for your compiler, please drop
+us a note at corba@awl.com. Over time, we hope that with your help,
+we can turn the code into something that will work everywhere.
+
+If you find bugs, we'd appreciate it if you'd let us know.
+
+ Thanks,
+
+ Michi & Steve. \ No newline at end of file
diff --git a/TAO/examples/Advanced/ch_12/CCS.idl b/TAO/examples/Advanced/ch_12/CCS.idl
new file mode 100644
index 00000000000..44369297576
--- /dev/null
+++ b/TAO/examples/Advanced/ch_12/CCS.idl
@@ -0,0 +1,104 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_12
+//
+// = FILENAME
+// CCS.idl
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+
+#pragma prefix "acme.com"
+
+module CCS {
+ typedef unsigned long AssetType;
+ typedef string ModelType;
+ typedef short TempType;
+ typedef string LocType;
+
+ interface Thermometer {
+ readonly attribute ModelType model;
+ readonly attribute AssetType asset_num;
+ readonly attribute TempType temperature;
+ attribute LocType location;
+
+ void remove();
+ };
+
+ interface Thermostat : Thermometer {
+ struct BtData {
+ TempType requested;
+ TempType min_permitted;
+ TempType max_permitted;
+ string error_msg;
+ };
+ exception BadTemp { BtData details; };
+
+ TempType get_nominal();
+ TempType set_nominal(in TempType new_temp)
+ raises(BadTemp);
+ };
+
+ interface Controller {
+ exception DuplicateAsset {};
+
+ Thermometer create_thermometer(
+ in AssetType anum,
+ in LocType loc
+ ) raises(DuplicateAsset);
+ Thermostat create_thermostat(
+ in AssetType anum,
+ in LocType loc,
+ in TempType temp
+ ) raises(DuplicateAsset, Thermostat::BadTemp);
+
+ typedef sequence<Thermometer> ThermometerSeq;
+ typedef sequence<Thermostat> ThermostatSeq;
+
+ enum SearchCriterion { ASSET, LOCATION, MODEL };
+
+ union KeyType switch(SearchCriterion) {
+ case ASSET:
+ AssetType asset_num;
+ case LOCATION:
+ LocType loc;
+ case MODEL:
+ ModelType model_desc;
+ };
+
+ struct SearchType {
+ KeyType key;
+ Thermometer device;
+ };
+ typedef sequence<SearchType> SearchSeq;
+
+ struct ErrorDetails {
+ Thermostat tmstat_ref;
+ Thermostat::BtData info;
+ };
+ typedef sequence<ErrorDetails> ErrSeq;
+
+ exception EChange {
+ ErrSeq errors;
+ };
+
+ ThermometerSeq list();
+ void find(inout SearchSeq slist);
+ void change(
+ in ThermostatSeq tlist, in short delta
+ ) raises(EChange);
+
+ };
+};
diff --git a/TAO/examples/Advanced/ch_12/CHANGES b/TAO/examples/Advanced/ch_12/CHANGES
new file mode 100644
index 00000000000..4a09d079b18
--- /dev/null
+++ b/TAO/examples/Advanced/ch_12/CHANGES
@@ -0,0 +1,84 @@
+$Id$
+
+Changelog for chapter 8 and 10 example in "Advanced CORBA
+Programming with C++" by Michi Henning and Steve Vinoski,
+Copyright 1999, Addison-Wesley, Reading, MA. The following
+changes have been made to the book's source code to make the
+example work with TAO and with various platforms and compilers.
+
+_______________________________________________________________________________
+ESSENTIAL CHANGES:
+ 1. Changed filename extensions from .hh and .cc to .h
+ and .cpp, and made all necessary changes in file content.
+
+ 2. a) Commented-out "#include <corba/poaS.h>" in server.h
+
+ b) Added #include "icp.h" to server.h.
+
+ c) Unnecessary standard includes of <iostreams.h>, <assert.h>,
+ <fstream.h> and <stdlib.h> must be removed or moved to follow the
+ local includes in server.h, server.cpp, client.cpp, and icp.cpp.
+
+ d) The following files may need their includes further rearranged
+ to avoid warnings and errors (g++). The following orderings
+ seem to work fine:
+ - server.cpp: "server.h", <algorithm>, "icp.h", <strstream.h>
+ - server.h: "CCSS.h", "icp.h", <map>, <list>
+
+ 3. Added CORBA_Environment variable to
+ DeviceLocator::preinvoke() and ::postinvoke()
+ in server.h and server.cpp to match the signatures of parent
+ methods in TAO's ServanLocator class.
+
+ 4. removed if 0 code surrounding
+ operator<<(ostream & os, const CCS::Controller::EChange & ec)
+ definition in server.cpp and client.cpp.
+
+ 5. commented-out "delete this;" from method
+ Thermometer_impl::remove() in server.cpp.
+ (Change should soon be reflected in authors' code)
+_______________________________________________________________________________
+ADDITIONAL CHANGES:
+ 6. Added .in() to _var parameters wherever needed:
+ -client.cpp:
+ 4 times in operator<<(ostream, CCS::Thermometer_ptr)
+ 6 times in main(). 5 are is_nil(), 1 is _narrow()
+ 2 additions in main() of .inout to _var parameters to set_temp(..).
+
+ -server.cpp,
+ 2 changes in make_dref()
+ 2 changes in Controller_impl::Controller_impl()
+ 4 changes in Controller_impl::~Controller_impl()
+ 1 change in Controller_impl::create_thermometer
+ 2 changes in Controller_impl::create_thermostat()
+ 1 change in Controller_impl::list()
+ 3 changes in Controller_impl::find
+ 7 changes in main()
+
+ 7. created needed file at /tmp/CCS_DB. (location is hard-coded)
+ To run, move CCS_DB from this directory to /tmp on the
+ local machine.
+
+ 8. fixed warnings by commented out unused parameters in
+ -DeviceLocator_impl::postinvoke(..) in server.h
+ -DeviceLocator_impl::preinvoke(..) in server.cpp
+
+ 9. MAX_EQ_SIZE changed from int to unsigned int
+ in class DeviceLocator_impl in server.h.
+
+ 10. added cast to unsigned long in ~ICP_Persist() in icp.cpp:
+ db << (unsigned long)(i->second.type) << endl;
+
+
+______________________________________________________________________________
+To Do:
+ - fix error on 2 cases of fstream.close()
+ in server.cpp and icp.cpp
+
+
+
+
+
+
+
+
diff --git a/TAO/examples/Advanced/ch_12/Makefile b/TAO/examples/Advanced/ch_12/Makefile
new file mode 100644
index 00000000000..793da932839
--- /dev/null
+++ b/TAO/examples/Advanced/ch_12/Makefile
@@ -0,0 +1,88 @@
+#----------------------------------------------------------------------------
+#
+# $Id$
+#
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Local macros
+#----------------------------------------------------------------------------
+
+ifndef TAO_ROOT
+ TAO_ROOT = $(ACE_ROOT)/TAO
+endif
+
+LDLIBS = -lTAO
+IDL_SRC = CCSC.cpp CCSS.cpp
+IDL_HDR = CCSC.h CCSS.h
+
+PROG_SRCS = \
+ client.cpp \
+ server.cpp \
+ icp.cpp
+
+SRC = $(IDL_SRC) $(PROG_SRCS)
+
+SIMPLE_CLT_OBJS = \
+ CCSC.o \
+ CCSS.o \
+ client.o
+
+SIMPLE_SVR_OBJS = \
+ CCSC.o \
+ CCSS.o \
+ server.o \
+ icp.o
+
+
+BIN = server \
+ client
+BUILD = $(BIN)
+VLDLIBS = $(LDLIBS:%=%$(VAR))
+VBIN = $(BIN:%=%$(VAR))
+
+#----------------------------------------------------------------------------
+# Include macros and targets
+#----------------------------------------------------------------------------
+
+include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU
+include $(ACE_ROOT)/include/makeinclude/macros.GNU
+include $(TAO_ROOT)/rules.tao.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.common.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.local.GNU
+include $(TAO_ROOT)/taoconfig.mk
+
+#----------------------------------------------------------------------------
+# Local targets
+#----------------------------------------------------------------------------
+LDFLAGS += -L$(TAO_ROOT)/orbsvcs/orbsvcs -L$(TAO_ROOT)/tao -L$(TAO_ROOT)/orbsvcs/Naming_Service
+CPPFLAGS += -I$(TAO_ROOT)/orbsvcs
+
+.PRECIOUS: CCSC.cpp CCSC.i CCSC.h
+.PRECIOUS: CCSS.cpp CCSS.i CCSS.h
+.PRECIOUS: CCSS_T.cpp CCSS_T.i CCSS_T.h
+
+override TAO_IDLFLAGS += -hc .hh -hs S.hh -hT S_T.hh \
+ -cs C.cc -ci C.i \
+ -ss S.cc -sT S_T.cc
+CCFLAGS += -fimplicit-templates -frtti -O0
+
+$(IDL_SRC): CCS.idl
+ $(TAO_ROOT)/TAO_IDL/tao_idl CCS.idl -hc .h -hs S.h -hT S_T.h \
+ -cs C.cpp \
+ -ss S.cpp -sT S_T.cpp
+server: $(addprefix $(VDIR),$(SIMPLE_SVR_OBJS))
+ $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK)
+
+client: $(addprefix $(VDIR),$(SIMPLE_CLT_OBJS))
+ $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK)
+
+realclean: clean
+ -/bin/$(RM) -rf CCSC.* CCSS.* CCSS_T.* CCS.h
+
+# DO NOT DELETE THIS LINE -- g++dep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+
+
diff --git a/TAO/examples/Advanced/ch_12/README b/TAO/examples/Advanced/ch_12/README
new file mode 100644
index 00000000000..d099fbc905c
--- /dev/null
+++ b/TAO/examples/Advanced/ch_12/README
@@ -0,0 +1,55 @@
+$Id$
+
+Chapter 12 example.
+______________________________________________________________________________
+This example been taken from the book "Advanced CORBA Programming with C++"
+by Michi Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+MA. To make the examples work with TAO, some minor modifications to the
+source code have been made, with permission, by Mike Moran <mm4@cs.wustl.edu>.
+All of these changes are documented in the file CHANGES, in this directory.
+______________________________________________________________________________
+
+
+Summary:
+ This example builds on the climate control system presented in chapters 8
+ and 10. The added use of customized POA policies including the use of a
+ servant manager is discussed in chapter 11. The example also incorporates
+ a simulated ICP network within the server process with code from Appendix
+ A. The simulated network loads it's devices from
+
+Building:
+ This example must be built with native C++ exceptions, and with an ACE/TAO
+ build with exceptions. Make sure to use TAO_FLAG Ge=0 to ensure that the
+ IDL generated code uses c++ exceptions rather than creating
+ CORBA_Environment variables.
+
+ With GNU make, simply type
+ % make exceptions=1
+ to create the executable server and client
+
+server:
+ The server takes no parameters nor command line options and returns an
+ IOR to stdout. The server then waits infinitely for clients requests.
+
+client:
+ The client takes an IOR from the command line, narrows this to a
+ controller reference, makes several remote calls on this controller, and
+ finally terminates.
+
+run_test.pl:
+ This is currently a UNIX only script! It starts up the server, redirecting
+ stdout to a file, then passes the file's contents to the command line of
+ the client. After the client terminates, the server is killed.
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TAO/examples/Advanced/ch_12/client.cpp b/TAO/examples/Advanced/ch_12/client.cpp
new file mode 100644
index 00000000000..c30133c5f87
--- /dev/null
+++ b/TAO/examples/Advanced/ch_12/client.cpp
@@ -0,0 +1,278 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_12
+//
+// = FILENAME
+// client.cpp
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+
+
+#include "CCS.h" // ORB-specific
+// #include <iostream.h>
+// #include <fstream.h>
+
+//----------------------------------------------------------------
+
+// Generic ostream inserter for exceptions. Inserts the exception
+// name, if available, and the repository ID otherwise.
+
+//#if 0 // This inserter may or may not be needed for your ORB.
+
+static ostream &
+operator<<(ostream & os, const CORBA::Exception & e)
+{
+ CORBA::Any tmp;
+ tmp <<= e;
+
+ CORBA::TypeCode_var tc = tmp.type();
+ const char * p = tc->name();
+ if (*p != '\0')
+ os << p;
+ else
+ os << tc->id();
+ return os;
+}
+
+//#endif
+
+//----------------------------------------------------------------
+
+// Show the details for a thermometer or thermostat.
+
+static ostream &
+operator<<(ostream &os, CCS::Thermometer_ptr t)
+{
+ // Check for nil.
+ if (CORBA::is_nil(t)) {
+ os << "Cannot show state for nil reference." << endl;
+ return os;
+ }
+
+ // Try to narrow and print what kind of device it is.
+ CCS::Thermostat_var tmstat = CCS::Thermostat::_narrow(t);
+ os << (CORBA::is_nil(tmstat.in()) ? "Thermometer:" : "Thermostat:")
+ << endl;
+
+ // Show attribute values.
+ CCS::ModelType_var model = t->model();
+ CCS::LocType_var location = t->location();
+ os << "\tAsset number: " << t->asset_num() << endl;
+ os << "\tModel : " << model.in() << endl;
+ os << "\tLocation : " << location.in() << endl;
+ os << "\tTemperature : " << t->temperature() << endl;
+
+ // If device is a thermostat, show nominal temperature.
+ if (!CORBA::is_nil(tmstat.in()))
+ os << "\tNominal temp: " << tmstat->get_nominal() << endl;
+ return os;
+}
+
+//----------------------------------------------------------------
+
+// Show the information in a BtData struct.
+
+static ostream &
+operator<<(ostream &os, const CCS::Thermostat::BtData &btd)
+{
+ os << "CCS::Thermostat::BtData details:" << endl;
+ os << "\trequested : " << btd.requested << endl;
+ os << "\tmin_permitted: " << btd.min_permitted << endl;
+ os << "\tmax_permitted: " << btd.max_permitted << endl;
+ os << "\terror_msg : " << btd.error_msg << endl;
+ return os;
+}
+
+//----------------------------------------------------------------
+
+// Loop over the sequence of records in an EChange exception and
+// show the details of each record.
+
+static ostream &
+operator<<(ostream &os, const CCS::Controller::EChange &ec)
+{
+ for (CORBA::ULong i = 0; i < ec.errors.length(); i++) {
+ os << "Change failed:" << endl;
+ os << ec.errors[i].tmstat_ref.in(); // Overloaded <<
+ os << ec.errors[i].info << endl; // Overloaded <<
+ }
+ return os;
+}
+
+//----------------------------------------------------------------
+
+// Change the temperature of a thermostat.
+
+static void
+set_temp(CCS::Thermostat_ptr tmstat, CCS::TempType new_temp)
+{
+ if (CORBA::is_nil(tmstat)) // Don't call via nil reference
+ return;
+
+ CCS::AssetType anum = tmstat->asset_num();
+ try {
+ cout << "Setting thermostat " << anum
+ << " to " << new_temp << " degrees." << endl;
+ CCS::TempType old_nominal = tmstat->set_nominal(new_temp);
+ cout << "Old nominal temperature was: "
+ << old_nominal << endl;
+ cout << "New nominal temperature is: "
+ << tmstat->get_nominal() << endl;
+ } catch (const CCS::Thermostat::BadTemp &bt) {
+ cerr << "Setting of nominal temperature failed." << endl;
+ cerr << bt.details << endl; // Overloaded <<
+ }
+}
+
+//----------------------------------------------------------------
+
+int
+main(int argc, char * argv[])
+{
+ try {
+ // Initialize the ORB
+ CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
+
+ // Check arguments
+ if (argc != 2) {
+ cerr << "Usage: client IOR_string" << endl;
+ throw 0;
+ }
+
+ // Get controller reference from argv
+ // and convert to object.
+ CORBA::Object_var obj = orb->string_to_object(argv[1]);
+ if (CORBA::is_nil(obj.in())) {
+ cerr << "Nil controller reference" << endl;
+ throw 0;
+ }
+
+ // Try to narrow to CCS::Controller.
+ CCS::Controller_var ctrl;
+ try {
+ ctrl = CCS::Controller::_narrow(obj.in());
+ } catch (const CORBA::SystemException &se) {
+ cerr << "Cannot narrow controller reference: "
+ << se << endl;
+ throw 0;
+ }
+ if (CORBA::is_nil(ctrl.in())) {
+ cerr << "Wrong type for controller ref." << endl;
+ throw 0;
+ }
+
+ // Get list of devices
+ CCS::Controller::ThermometerSeq_var list = ctrl->list();
+
+ // Show number of devices.
+ CORBA::ULong len = list->length();
+ cout << "Controller has " << len << " device";
+ if (len != 1)
+ cout << "s";
+ cout << "." << endl;
+
+ CCS::Thermometer_var t = ctrl->create_thermometer(27, "Room 1");
+ CCS::Thermostat_var ts = ctrl->create_thermostat(28, "Room 2", 48);
+ CCS::Thermostat_var ts2 = ctrl->create_thermostat(30, "Room 3", 48);
+ CCS::Thermostat_var ts3 = ctrl->create_thermostat(32, "Room 3", 68);
+ CCS::Thermostat_var ts4 = ctrl->create_thermostat(34, "Room 3", 68);
+ CCS::Thermostat_var ts5 = ctrl->create_thermostat(36, "Room 3", 48);
+ cout << t->location() << endl;
+ cout << ts->location() << endl;
+ cout << ts2->location() << endl;
+ t->remove();
+
+ list = ctrl->list();
+ // Show details for each device.
+ for (CORBA::ULong i = 0; i < list->length(); i++)
+ cout << list[i];
+ cout << endl;
+
+ // Change the location of first device in the list
+ CCS::AssetType anum = list[0]->asset_num();
+ cout << "Changing location of device "
+ << anum << "." << endl;
+ list[0]->location("Earth");
+ // Check that the location was updated
+ cout << "New details for device "
+ << anum << " are:" << endl;
+ cout << list[0] << endl;
+
+ // Find first thermostat in list.
+ CCS::Thermostat_var tmstat;
+ for ( CORBA::ULong i = 0;
+ i < list->length() && CORBA::is_nil(tmstat.in());
+ i++) {
+ tmstat = CCS::Thermostat::_narrow(list[i]);
+ }
+
+ // Check that we found a thermostat on the list.
+ if (CORBA::is_nil(tmstat.in())) {
+ cout << "No thermostat devices in list." << endl;
+ } else {
+ // Set temperature of thermostat to
+ // 50 degrees (should work).
+ set_temp(tmstat.inout(), 50);
+ cout << endl;
+
+ // Set temperature of thermostat to
+ // -10 degrees (should fail).
+ set_temp(tmstat.inout(), -10);
+ }
+
+ // Look for device in Rooms Earth and HAL. This must
+ // locate at least one device because we earlier changed
+ // the location of the first device to Room Earth.
+ cout << "Looking for devices in Earth and HAL." << endl;
+ CCS::Controller::SearchSeq ss;
+ ss.length(2);
+ ss[0].key.loc(CORBA::string_dup("Earth"));
+ ss[1].key.loc(CORBA::string_dup("HAL"));
+ ctrl->find(ss);
+
+ // Show the devices found in that room.
+ for (CORBA::ULong i = 0; i < ss.length(); i++)
+ cout << ss[i].device.in(); // Overloaded <<
+ cout << endl;
+
+ // Increase the temperature of all thermostats
+ // by 40 degrees. First, make a new list (tss)
+ // containing only thermostats.
+ cout << "Increasing thermostats by 40 degrees." << endl;
+ CCS::Controller::ThermostatSeq tss;
+ for (CORBA::ULong i = 0; i < list->length(); i++) {
+ tmstat = CCS::Thermostat::_narrow(list[i]);
+ if (CORBA::is_nil(tmstat.in()))
+ continue; // Skip thermometers
+ len = tss.length();
+ tss.length(len + 1);
+ tss[len] = tmstat;
+ }
+
+ // Try to change all thermostats.
+ try {
+ ctrl->change(tss, 40);
+ } catch (const CCS::Controller::EChange &ec) {
+ cerr << ec; // Overloaded <<
+ }
+ } catch (const CORBA::Exception & e) {
+ cerr << "Uncaught CORBA exception: " << e << endl;
+ return 1;
+ } catch (...) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/TAO/examples/Advanced/ch_12/icp.cpp b/TAO/examples/Advanced/ch_12/icp.cpp
new file mode 100644
index 00000000000..deac39c9248
--- /dev/null
+++ b/TAO/examples/Advanced/ch_12/icp.cpp
@@ -0,0 +1,386 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_12
+//
+// = FILENAME
+// icp.cpp
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+
+#include <string>
+#include <map>
+#include <algorithm>
+#include "icp.h"
+//#include <stdlib.h>
+//----------------------------------------------------------------
+
+enum DeviceType { thermometer, thermostat };
+
+struct DeviceState { // State for a device
+ DeviceType type;
+ const char * model;
+ string location;
+ short nominal_temp; // For thermostats only
+};
+typedef map<unsigned long, DeviceState> StateMap;
+
+//----------------------------------------------------------------
+
+const size_t MAXSTR = 32; // Max len of string including NUL
+
+const short MIN_TEMP = 40; // 40 F == 4.44 C
+const short MAX_TEMP = 90; // 90 F == 32.22 C
+const short DFLT_TEMP = 68; // 68 F == 20.00 C
+
+static StateMap dstate; // Map of known devices
+
+//----------------------------------------------------------------
+
+// ICP_online() simulates adding a new device to the network by
+// adding it to the dstate map.
+//
+// For this simple simulation, devices with odd asset numbers
+// are thermometers and devices with even asset numbers
+// are thermostats.
+//
+// Thermostats get an initial nominal temperature of DFLT_TEMP.
+// The location string is intentionally left blank because it
+// must be programmed by the controller after putting the device
+// on-line (as should be the nominal temperature).
+//
+// If a device with the specified ID is already on-line, the
+// return value is -1. A zero return value indicates success.
+
+extern "C"
+int
+ICP_online(unsigned long id)
+{
+ // Look for id in state map.
+ StateMap::iterator pos = dstate.find(id);
+ if (pos != dstate.end())
+ return -1; // Already exists
+
+ // Fill in state.
+ DeviceState ds;
+ ds.type = (id % 2) ? thermometer : thermostat;
+ ds.model = (ds.type == thermometer)
+ ? "Sens-A-Temp" : "Select-A-Temp";
+ ds.nominal_temp = DFLT_TEMP;
+
+ // Insert new device into map
+ dstate[id] = ds;
+
+ return 0;
+}
+
+//----------------------------------------------------------------
+
+// ICP_offline() simulates removing a device from the network by
+// removing it from the dstate map. If the device isn't known, the
+// return value is -1. A zero return value indicates success.
+
+extern "C"
+int
+ICP_offline(unsigned long id)
+{
+ // Look for id in state map
+ StateMap::iterator pos = dstate.find(id);
+ if (pos == dstate.end())
+ return -1; // No such device
+ dstate.erase(id);
+ return 0;
+}
+
+//----------------------------------------------------------------
+
+// vary_temp() simulates the variation in actual temperature
+// around a thermostat.The function randomly varies the
+// temperature as a percentage of calls as follows:
+//
+// 3 degrees too cold: 5%
+// 3 degrees too hot: 5%
+// 2 degrees too cold: 10%
+// 2 degrees too hot: 10%
+// 1 degree too cold: 15%
+// 1 degree too hot: 15%
+// exact temperature: 40%
+
+static
+short
+vary_temp(short temp)
+{
+ long r = lrand48() % 50;
+ long delta;
+ if (r < 5)
+ delta = 3;
+ else if (r < 15)
+ delta = 2;
+ else if (r < 30)
+ delta = 1;
+ else
+ delta = 0;
+ if (lrand48() % 2)
+ delta = -delta;
+ return temp + delta;
+}
+
+//----------------------------------------------------------------
+
+// Function object. Locates a thermostat that is in the same room
+// as the device at position pos.
+
+class ThermostatInSameRoom {
+public:
+ ThermostatInSameRoom(
+ const StateMap::iterator & pos
+ ) : m_pos(pos) {}
+ bool operator()(
+ pair<const unsigned long, DeviceState> & p
+ ) const
+ {
+ return(
+ p.second.type == thermostat
+ && p.second.location
+ == m_pos->second.location
+ );
+ }
+private:
+ const StateMap::iterator & m_pos;
+};
+
+//----------------------------------------------------------------
+
+// actual_temp() is a helper function to determine the actual
+// temperature returned by a particular thermometer or thermostat.
+// The pos argument indicates the device.
+//
+// The function locates all thermostats that are in the same room
+// as the device denoted by pos and computes the average of all
+// the thermostats' nominal temperatures. (If no thermostats are
+// in the same room as the device, the function assumes that the
+// average of the nominal temperatures is DFLT_TEMP.)
+//
+// The returned temperature varies from the average as
+// determined by vary_temp().
+
+static
+short
+actual_temp(const StateMap::iterator & pos)
+{
+ long sum = 0;
+ long count = 0;
+ StateMap::iterator where = find_if(
+ dstate.begin(), dstate.end(),
+ ThermostatInSameRoom(pos)
+ );
+ while (where != dstate.end()) {
+ count++;
+ sum += where->second.nominal_temp;
+ where = find_if(
+ ++where, dstate.end(),
+ ThermostatInSameRoom(pos)
+ );
+ }
+ return vary_temp(count == 0 ? DFLT_TEMP : sum / count);
+}
+
+//----------------------------------------------------------------
+
+// ICP_get() returns an attribute value of the device with the
+// given id. The attribute is named by the attr parameter. The
+// value is copied into the buffer pointed to by the value
+// pointer. The len parameter is the size of the passed buffer,
+// so ICP_get can avoid overrunning the buffer.
+//
+// By default, thermometers report a temperature that varies
+// somewhat around DFLT_TEMP. However, if there is another
+// thermostat in the same room as the the thermometer, the
+// thermometer reports a temperature that varies around that
+// thermostat's temperature. For several thermostats that are in
+// the same room, the thermometer reports around the average
+// nominal temperature of all the thermostats.
+//
+// Attempts to read from a non-existent device or to read a
+// non-existent attribute return -1. A return value of zero
+// indicates success. If the supplied buffer is too short to hold
+// a value, ICP_get() silently truncates the value and
+// returns success.
+
+extern "C"
+int
+ICP_get(
+ unsigned long id,
+ const char * attr,
+ void * value,
+ size_t len)
+{
+ // Look for id in state map
+ StateMap::iterator pos = dstate.find(id);
+ if (pos == dstate.end())
+ return -1; // No such device
+
+ // Depending on the attribute, return the
+ // corresponding piece of state.
+ if (strcmp(attr, "model") == 0) {
+ strncpy((char *)value, pos->second.model, len);
+ } else if (strcmp(attr, "location") == 0) {
+ strncpy((char *)value, pos->second.location.c_str(), len);
+ } else if (strcmp(attr, "nominal_temp") == 0) {
+ if (pos->second.type != thermostat)
+ return -1; // Must be thermostat
+ memcpy(
+ value, &pos->second.nominal_temp,
+ min(len, sizeof(pos->second.nominal_temp))
+ );
+ } else if (strcmp(attr, "temperature") == 0) {
+ short temp = actual_temp(pos);
+ memcpy(value, &temp, min(len, sizeof(temp)));
+ } else if (strcmp(attr, "MIN_TEMP") == 0) {
+ memcpy(value, &MIN_TEMP, min(len, sizeof(MIN_TEMP)));
+ } else if (strcmp(attr, "MAX_TEMP") == 0) {
+ memcpy(value, &MAX_TEMP, min(len, sizeof(MAX_TEMP)));
+ } else {
+ return -1; // No such attribute
+ }
+ return 0; // OK
+}
+
+//----------------------------------------------------------------
+
+// ICP_set() sets the the attributed specified by attr to the
+// value specified by value for the device with ID id. Attempts to
+// write a string longer than MAXSTR bytes (including the
+// terminating NUL) result in silent truncation of the string.
+// Attempts to access a non-existent device or attribute
+// return -1. Attempts to set a nominal temperature outside the
+// legal range also return -1. A zero return value
+// indicates success.
+
+extern "C"
+int
+ICP_set(unsigned long id, const char * attr, const void * value)
+{
+ // Look for id in state map
+ StateMap::iterator pos = dstate.find(id);
+ if (pos == dstate.end())
+ return -1; // No such device
+
+ // Change either location or nominal temp, depending on attr.
+ if (strcmp(attr, "location") == 0) {
+ pos->second.location.assign(
+ (const char *)value, MAXSTR - 1
+ );
+ } else if (strcmp(attr, "nominal_temp") == 0) {
+ if (pos->second.type != thermostat)
+ return -1; // Must be thermostat
+ short temp;
+ memcpy(&temp, value, sizeof(temp));
+ if (temp < MIN_TEMP || temp > MAX_TEMP)
+ return -1;
+ pos->second.nominal_temp = temp;
+ } else {
+ return -1; // No such attribute
+ }
+ return 0; // OK
+}
+
+//----------------------------------------------------------------
+
+#include <fstream.h>
+
+class ICP_Persist {
+public:
+ ICP_Persist(const char * file);
+ ~ICP_Persist();
+private:
+ string m_filename;
+};
+
+// Read device state from a file and initialize the dstate map.
+
+ICP_Persist::
+ICP_Persist(const char * file) : m_filename(file)
+{
+ // Open input file, creating it if necessary.
+ fstream db(m_filename.c_str(), ios::in|ios::out, 0666);
+ if (!db) {
+ cerr << "Error opening " << m_filename << endl;
+ exit(1);
+ }
+
+ // Read device details, one attribute per line.
+ DeviceState ds;
+ unsigned long id;
+ while (db >> id) {
+ // Read device type and set model string accordingly.
+ int dtype;
+ db >> dtype;
+ ds.type = dtype == thermometer
+ ? thermometer : thermostat;
+ ds.model = dtype == thermometer
+ ? "Sens-A-Temp" : "Select-A-Temp";
+ char loc[MAXSTR];
+ db.get(loc[0]); // Skip newline
+ db.getline(loc, sizeof(loc)); // Read location
+ ds.location = loc;
+ if (ds.type == thermostat)
+ db >> ds.nominal_temp; // Read temperature
+ dstate[id] = ds; // Add entry to map
+ }
+
+ //db.close();
+ //if (!db) {
+ // cerr << "Error closing " << m_filename << endl;
+ // exit(1);
+ //}
+}
+
+// Write device state to the file.
+
+ICP_Persist::
+~ICP_Persist()
+{
+ cout<<"~ICP_Persist"<<endl;///////////////////////
+ // Open input file, truncating it.
+ ofstream db(m_filename.c_str());
+ if (!db) {
+ cerr << "Error opening " << m_filename << endl;
+ exit(1);
+ }
+
+ // Write the state details for each device.
+ StateMap::iterator i;
+ for (i = dstate.begin(); i != dstate.end(); i++) {
+ db << i->first << endl;
+ db << (unsigned long)(i->second.type) << endl;
+ db << i->second.location << endl;
+ if (i->second.type == thermostat)
+ db << i->second.nominal_temp << endl;
+ }
+ if (!db) {
+ cerr << "Error writing " << m_filename << endl;
+ exit(1);
+ }
+
+ db.close();
+ if (!db) {
+ cerr << "Error closing " << m_filename << endl;
+ exit(1);
+ }
+}
+
+// Instantiate a single global instance of the class.
+static ICP_Persist mydb("/tmp/CCS_DB");
diff --git a/TAO/examples/Advanced/ch_12/icp.h b/TAO/examples/Advanced/ch_12/icp.h
new file mode 100644
index 00000000000..a64ec00f28e
--- /dev/null
+++ b/TAO/examples/Advanced/ch_12/icp.h
@@ -0,0 +1,42 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_12
+//
+// = FILENAME
+// icp.h
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+
+#ifndef _ICP_H
+#define _ICP_H
+
+extern "C" {
+ int ICP_online(unsigned long id); // Add device
+ int ICP_offline(unsigned long id); // Remove device
+ int ICP_get( // Get attribute
+ unsigned long id,
+ const char * attr,
+ void * value,
+ size_t len
+ );
+ int ICP_set( // Set attribute
+ unsigned long id,
+ const char * attr,
+ const void * value
+ );
+}
+
+#endif /* _ICP_H */
diff --git a/TAO/examples/Advanced/ch_12/run_test.pl b/TAO/examples/Advanced/ch_12/run_test.pl
new file mode 100755
index 00000000000..74c52a910be
--- /dev/null
+++ b/TAO/examples/Advanced/ch_12/run_test.pl
@@ -0,0 +1,54 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib "../../../../bin";
+
+require ACEutils;
+require Process;
+
+$status = 0;
+$iorfile = "chapter_test.ior";
+unlink $iorfile;
+
+
+
+# Hacked call
+$server = Process::Create ("exec ".$EXEPREFIX."server".$EXE_EXT.">$iorfile",
+ "");
+# Proper call
+#$server = Process::Create ($EXEPREFIX."server".$EXE_EXT, ">$iorfile");
+
+if (ACE::waitforfile_timed ($iorfile, 15) == -1) {
+ print STDERR "ERROR: timedout waiting for file <$iorfile>\n";
+ $server->Kill (); $server->TimedWait (1);
+ exit 1;
+}
+
+open(ior_handle, "$iorfile");
+$ior_content = <ior_handle>;
+
+$client = Process::Create($EXEPREFIX."client$EXE_EXT", "$ior_content");
+
+if ($client->TimedWait (60) == -1) {
+ print STDERR "ERROR: client timedout\n";
+ $status = 1;
+ $client->Kill (); $client->TimedWait (1);
+}
+
+
+
+
+$server->Terminate ();
+if ($server->TimedWait (5) == -1) {
+ print STDERR "ERROR: cannot terminate the server\n";
+ $server->Kill (); $server->TimedWait (1);
+ $status = 1;
+}
+
+unlink $iorfile;
+
+exit $status;
diff --git a/TAO/examples/Advanced/ch_12/server.cpp b/TAO/examples/Advanced/ch_12/server.cpp
new file mode 100644
index 00000000000..f70e98dea1d
--- /dev/null
+++ b/TAO/examples/Advanced/ch_12/server.cpp
@@ -0,0 +1,732 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_12
+//
+// = FILENAME
+// server.cpp
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+
+#include "server.h"
+#include <algorithm>
+#include "icp.h"
+#include <strstream.h>
+// #include <fstream.h>
+// #include <iostream.h>
+
+const char * Controller_oid = "Controller";
+
+//----------------------------------------------------------------
+
+// Generic ostream inserter for exceptions. Inserts the exception
+// name, if available, and the repository ID otherwise.
+
+//#if 0 // This inserter may or may not be needed for your ORB.
+
+static ostream &
+operator<<(ostream & os, const CORBA::Exception & e)
+{
+ CORBA::Any tmp;
+ tmp <<= e;
+
+ CORBA::TypeCode_var tc = tmp.type();
+ const char * p = tc->name();
+ if (*p != '\0')
+ os << p;
+ else
+ os << tc->id();
+ return os;
+}
+
+//#endif
+
+//----------------------------------------------------------------
+
+// Helper function to create object references.
+
+static CCS::Thermometer_ptr
+make_dref(PortableServer::POA_ptr poa, CCS::AssetType anum)
+{
+ // Convert asset number to OID.
+ ostrstream ostr;
+ ostr << anum << ends;
+ char * anum_str = ostr.str();
+ PortableServer::ObjectId_var oid
+ = PortableServer::string_to_ObjectId(anum_str);
+ delete[] anum_str;
+
+ // Look at the model via the network to determine
+ // the repository ID.
+ char buf[32];
+ assert(ICP_get(anum, "model", buf, sizeof(buf)) == 0);
+ const char * rep_id = strcmp(buf, "Sens-A-Temp") == 0
+ ? "IDL:acme.com/CCS/Thermometer:1.0"
+ : "IDL:acme.com/CCS/Thermostat:1.0";
+
+ // Make a new reference.
+ CORBA::Object_var obj
+ = poa->create_reference_with_id(oid.in(), rep_id);
+ return CCS::Thermometer::_narrow(obj.in());
+}
+
+//----------------------------------------------------------------
+
+Controller_impl * Thermometer_impl::m_ctrl; // static member
+
+// Helper function to read the model string from a device.
+
+CCS::ModelType
+Thermometer_impl::
+get_model()
+{
+ char buf[32];
+ assert(ICP_get(m_anum, "model", buf, sizeof(buf)) == 0);
+ return CORBA::string_dup(buf);
+}
+
+// Helper function to read the temperature from a device.
+
+CCS::TempType
+Thermometer_impl::
+get_temp()
+{
+ short temp;
+ assert(ICP_get(m_anum, "temperature", &temp, sizeof(temp)) == 0);
+ return temp;
+}
+
+// Helper function to read the location from a device.
+
+CCS::LocType
+Thermometer_impl::
+get_loc()
+{
+ char buf[32];
+ assert(ICP_get(m_anum, "location", buf, sizeof(buf)) == 0);
+ return CORBA::string_dup(buf);
+}
+
+// Helper function to set the location of a device.
+
+void
+Thermometer_impl::
+set_loc(const char * loc)
+{
+ assert(ICP_set(m_anum, "location", loc) == 0);
+}
+
+// Constructor.
+
+Thermometer_impl::
+Thermometer_impl(CCS::AssetType anum) : m_anum(anum)
+{
+ m_ctrl->add_impl(anum, this); // Add self to controller's set
+}
+
+// Destructor.
+
+Thermometer_impl::
+~Thermometer_impl()
+{
+ if (m_ctrl->exists(m_anum))
+ m_ctrl->add_impl(m_anum, 0); // Clear servant pointer
+}
+
+// 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 remove operation.
+
+void
+Thermometer_impl::
+remove() throw(CORBA::SystemException)
+{
+ m_ctrl->remove_impl(m_anum);
+ assert(ICP_offline(m_anum) == 0);
+ // delete this;
+}
+
+// IDL location attribute modifier.
+
+void
+Thermometer_impl::
+location(const char *loc) throw(CORBA::SystemException)
+{
+ set_loc(loc);
+}
+
+//----------------------------------------------------------------
+
+// Helper function to get a thermostat's nominal temperature.
+
+CCS::TempType
+Thermostat_impl::
+get_nominal_temp()
+{
+ short temp;
+ assert(ICP_get(m_anum, "nominal_temp", &temp, sizeof(temp)) == 0);
+ 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.
+ assert(
+ ICP_get(
+ m_anum, "nominal_temp", &old_temp, sizeof(old_temp)
+ ) == 0
+ );
+
+ // 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.
+
+Thermostat_impl::
+Thermostat_impl(CCS::AssetType anum) : Thermometer_impl(anum)
+{
+ // Intentionally empty.
+}
+
+// Destructor.
+
+Thermostat_impl::
+~Thermostat_impl()
+{
+ // Intentionally empty.
+}
+
+// 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 to add an entry to the asset map.
+
+void
+Controller_impl::
+add_impl(CCS::AssetType anum, Thermometer_impl * tip)
+{
+ m_assets[anum] = tip;
+}
+
+// Helper function to remove an entry from the asset map.
+
+void
+Controller_impl::
+remove_impl(CCS::AssetType anum)
+{
+ m_assets.erase(anum);
+}
+
+// Helper function to locate a servant in the asset map.
+
+bool
+Controller_impl::
+exists(CCS::AssetType anum)
+{
+ return m_assets.find(anum) != m_assets.end();
+}
+
+// Constructor
+
+Controller_impl::
+Controller_impl(
+ PortableServer::POA_ptr poa,
+ const char * asset_file
+) throw(int) : m_poa(PortableServer::POA::_duplicate(poa)),
+ m_asset_file(asset_file)
+{
+ fstream afile(m_asset_file.in(), ios::in|ios::out, 0666);
+ if (!afile) {
+ cerr << "Cannot open " << m_asset_file.in() << endl;
+ throw 0;
+ }
+ CCS::AssetType anum;
+ while (afile >> anum)
+ m_assets[anum] = 0;
+ //afile.close();
+ //if (!afile) {
+ // cerr << "Cannot close " << m_asset_file << endl;
+ // throw 0;
+ //}
+}
+
+// Destructor
+
+Controller_impl::
+~Controller_impl()
+{
+ // Write out the current set of asset numbers
+ // and clean up all servant instances.
+ ofstream afile(m_asset_file.in());
+ if (!afile) {
+ cerr << "Cannot open " << m_asset_file.in() << endl;
+ assert(0);
+ }
+ AssetMap::iterator i;
+ for (i = m_assets.begin(); i != m_assets.end(); i++) {
+ afile << i->first << endl;
+ if (!afile) {
+ cerr << "Cannot update " << m_asset_file.in() << endl;
+ assert(0);
+ }
+ delete i->second;
+ }
+ afile.close();
+ if (!afile) {
+ cerr << "Cannot close " << m_asset_file.in() << endl;
+ assert(0);
+ }
+}
+
+CCS::Thermometer_ptr
+Controller_impl::
+create_thermometer(CCS::AssetType anum, const char * loc)
+throw(CORBA::SystemException, CCS::Controller::DuplicateAsset)
+{
+ if (anum % 2 == 0)
+ throw CORBA::BAD_PARAM(); // Thermometers have odd numbers
+ if (exists(anum))
+ throw CCS::Controller::DuplicateAsset();
+
+ assert(ICP_online(anum) == 0);
+ assert(ICP_set(anum, "location", loc) == 0);
+ add_impl(anum, 0);
+ return make_dref(m_poa.in(), anum);
+}
+
+CCS::Thermostat_ptr
+Controller_impl::
+create_thermostat(
+ CCS::AssetType anum,
+ const char* loc,
+ CCS::TempType temp)
+throw(
+ CORBA::SystemException,
+ CCS::Controller::DuplicateAsset,
+ CCS::Thermostat::BadTemp)
+{
+ if (anum % 2 != 0)
+ throw CORBA::BAD_PARAM(); // Thermostats have even numbers
+ if (exists(anum))
+ throw CCS::Controller::DuplicateAsset();
+
+ assert(ICP_online(anum) == 0);
+ assert(ICP_set(anum, "location", loc) == 0);
+ // Set the nominal temperature.
+ if (ICP_set(anum, "nominal_temp", &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(
+ anum, "MIN_TEMP",
+ &btd.min_permitted, sizeof(btd.min_permitted)
+ );
+ ICP_get(
+ anum, "MAX_TEMP",
+ &btd.max_permitted, sizeof(btd.max_permitted)
+ );
+ btd.requested = temp;
+ btd.error_msg = CORBA::string_dup(
+ temp > btd.max_permitted ? "Too hot" : "Too cold"
+ );
+ ICP_offline(anum);
+ throw CCS::Thermostat::BadTemp(btd);
+ }
+
+ add_impl(anum, 0);
+ CORBA::Object_var obj = make_dref(m_poa.in(), anum);
+ return CCS::Thermostat::_narrow(obj.in());
+}
+
+// IDL list operation.
+
+CCS::Controller::ThermometerSeq *
+Controller_impl::
+list() throw(CORBA::SystemException)
+{
+ // 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 set 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++] = make_dref(m_poa.in(), i->first);
+ 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; // Skip nil references
+
+ // 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;
+}
+
+// IDL find operation
+
+void
+Controller_impl::
+find(CCS::Controller::SearchSeq & slist)
+throw(CORBA::SystemException)
+{
+ // Loop over input list and lookup each device.
+ CORBA::ULong listlen = slist.length();
+ for (CORBA::ULong i = 0; i < listlen; i++) {
+
+ AssetMap::iterator where; // Iterator for asset set
+ 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 = make_dref(m_poa.in(), where->first);
+ } 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 = make_dref(m_poa.in(), where->first);
+ } else {
+ // Further matches each append 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 = make_dref(m_poa.in(), where->first);
+ }
+ num_found++;
+
+ // Find next matching device with this key.
+ where = find_if(
+ ++where, m_assets.end(),
+ StrFinder(sc, search_str)
+ );
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------
+
+DeviceLocator_impl::
+DeviceLocator_impl(Controller_impl * ctrl) : m_ctrl(ctrl)
+{
+ // Intentionally empty
+}
+
+PortableServer::Servant
+DeviceLocator_impl::
+preinvoke(
+ const PortableServer::ObjectId & oid,
+ PortableServer::POA_ptr /*poa*/,
+ const char * operation,
+ void * & /*cookie*/,
+ CORBA_Environment &
+) throw(CORBA::SystemException, PortableServer::ForwardRequest)
+{
+ // Convert object id into asset number.
+ CORBA::String_var oid_string;
+ try {
+ oid_string = PortableServer::ObjectId_to_string(oid);
+ } catch (const CORBA::BAD_PARAM &) {
+ throw CORBA::OBJECT_NOT_EXIST();
+ }
+
+ if (strcmp(oid_string.in(), Controller_oid) == 0)
+ return m_ctrl;
+
+ istrstream istr(oid_string.in());
+ CCS::AssetType anum;
+ istr >> anum;
+ if (istr.fail())
+ throw CORBA::OBJECT_NOT_EXIST();
+
+ // Check whether the device is known.
+ if (!m_ctrl->exists(anum))
+ throw CORBA::OBJECT_NOT_EXIST();
+
+ // Look at the object map to find out whether
+ // we have a servant in memory.
+ Thermometer_impl * servant;
+ ActiveObjectMap::iterator servant_pos = m_aom.find(anum);
+ if (servant_pos == m_aom.end()) {
+ // No servant in memory. If evictor queue is full,
+ // evict servant at head of queue.
+ if (m_eq.size() == MAX_EQ_SIZE) {
+ servant = m_eq.back();
+ m_aom.erase(servant->m_anum);
+ m_eq.pop_back();
+ delete servant;
+ }
+ // Instantiate correct type of servant.
+ char buf[32];
+ assert(ICP_get(anum, "model", buf, sizeof(buf)) == 0);
+ if (strcmp(buf, "Sens-A-Temp") == 0)
+ servant = new Thermometer_impl(anum);
+ else
+ servant = new Thermostat_impl(anum);
+ } else {
+ // Servant already in memory.
+ servant = *(servant_pos->second); // Remember servant
+ m_eq.erase(servant_pos->second); // Remove from queue
+
+ // If operation is "remove", also remove entry from
+ // active object map -- the object is about to be deleted.
+ if (strcmp(operation, "remove") == 0)
+ m_aom.erase(servant_pos);
+ }
+
+ // We found a servant, or just instantiated it.
+ // If the operation is not a remove, move
+ // the servant to the tail of the evictor queue
+ // and update its queue position in the map.
+ if (strcmp(operation, "remove") != 0) {
+ m_eq.push_front(servant);
+ m_aom[anum] = m_eq.begin();
+ }
+
+ return servant;
+}
+
+//----------------------------------------------------------------
+
+int
+main(int argc, char * argv[])
+{
+ CORBA::ORB_var orb;
+
+ try {
+ // Initialize orb
+ 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.in());
+
+ // Get POA manager
+ PortableServer::POAManager_var poa_mgr = poa->the_POAManager();
+
+ // Create a policy list. We use persistent objects with
+ // user-assigned IDs, and explicit activation.
+ CORBA::PolicyList policy_list;
+ policy_list.length(6);
+ policy_list[0] = poa->create_lifespan_policy(
+ PortableServer::TRANSIENT // REVISIT
+ );
+ policy_list[1] = poa->create_id_assignment_policy(
+ PortableServer::USER_ID
+ );
+ policy_list[2] = poa->create_implicit_activation_policy(
+ PortableServer::NO_IMPLICIT_ACTIVATION
+ );
+ policy_list[3] = poa->create_request_processing_policy(
+ PortableServer::USE_SERVANT_MANAGER
+ );
+ policy_list[4] = poa->create_servant_retention_policy(
+ PortableServer::NON_RETAIN
+ );
+ policy_list[5] = poa->create_thread_policy(
+ PortableServer::SINGLE_THREAD_MODEL
+ );
+
+ // Create a POA for all CCS elements.
+ PortableServer::POA_var ccs_poa
+ = poa->create_POA("CCS_POA", poa_mgr.in(), policy_list);
+
+ // Create a controller and set static m_ctrl member
+ // for thermostats and thermometers.
+ Controller_impl ctrl_servant(ccs_poa.in(), "/tmp/CCS_assets");
+ Thermometer_impl::m_ctrl = &ctrl_servant;
+
+ // Create a reference for the controller and
+ // create the corresponding CORBA object.
+ PortableServer::ObjectId_var oid
+ = PortableServer::string_to_ObjectId(Controller_oid);
+ obj = ccs_poa->create_reference_with_id(
+ oid.in(), "IDL:acme.com/CCS/Controller:1.0"
+ );
+
+ // Write a reference for the controller to stdout.
+ CORBA::String_var str = orb->object_to_string(obj.in());
+ cout << str.in() << endl << endl;
+
+ // Instantiate the servant locator for devices.
+ DeviceLocator_impl my_locator(&ctrl_servant);
+ PortableServer::ServantManager_var locator
+ = my_locator._this();
+
+ // Set servant locator.
+ ccs_poa->set_servant_manager(locator.in());
+
+ // Activate the POA manager.
+ poa_mgr->activate();
+
+ // Accept requests
+ orb->run();
+ }
+ catch (const CORBA::Exception & e) {
+ cerr << "Uncaught CORBA exception: " << e << endl;
+ return 1;
+ }
+ catch (...) {
+ assert(0); // Uncaught exception, dump core
+ }
+ return 0;
+}
diff --git a/TAO/examples/Advanced/ch_12/server.h b/TAO/examples/Advanced/ch_12/server.h
new file mode 100644
index 00000000000..6ee21ee87c9
--- /dev/null
+++ b/TAO/examples/Advanced/ch_12/server.h
@@ -0,0 +1,237 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_12
+//
+// = FILENAME
+// server.h
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+
+#ifndef server_HH_
+#define server_HH_
+
+#include "CCSS.h"
+#include "icp.h" // mine
+#include <map>
+#include <list>
+//#include <assert.h>
+//#include <corba/poaS.h>
+
+
+class Controller_impl;
+
+class Thermometer_impl : public virtual POA_CCS::Thermometer {
+public:
+ // CORBA attributes
+ virtual CCS::ModelType model()
+ throw(CORBA::SystemException);
+ virtual CCS::AssetType asset_num()
+ throw(CORBA::SystemException);
+ virtual CCS::TempType temperature()
+ throw(CORBA::SystemException);
+ virtual CCS::LocType location()
+ throw(CORBA::SystemException);
+ virtual void location(const char *loc)
+ throw(CORBA::SystemException);
+ virtual void remove()
+ throw(CORBA::SystemException);
+
+ // Constructor & destructor
+ Thermometer_impl(CCS::AssetType anum);
+ virtual ~Thermometer_impl();
+
+ static Controller_impl * m_ctrl; // My controller
+ const CCS::AssetType m_anum; // My asset number
+
+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
+ 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);
+ 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::ThermostatSeq & tlist,
+ CORBA::Short delta
+ ) throw(
+ CORBA::SystemException,
+ CCS::Controller::EChange
+ );
+ virtual CCS::Thermometer_ptr
+ create_thermometer(
+ CCS::AssetType anum,
+ const char* loc
+ ) throw(
+ CORBA::SystemException,
+ CCS::Controller::DuplicateAsset
+ );
+ virtual CCS::Thermostat_ptr
+ create_thermostat(
+ CCS::AssetType anum,
+ const char* loc,
+ CCS::TempType temp
+ ) throw(
+ CORBA::SystemException,
+ CCS::Controller::DuplicateAsset,
+ CCS::Thermostat::BadTemp
+ );
+
+ // Constructor and destructor
+ Controller_impl(
+ PortableServer::POA_ptr poa,
+ const char * asset_file
+ ) throw(int);
+ virtual ~Controller_impl();
+
+ // Helper functions to allow access to the object map
+ void add_impl(
+ CCS::AssetType anum,
+ Thermometer_impl * tip
+ );
+ void remove_impl(CCS::AssetType anum);
+ bool exists(CCS::AssetType anum);
+
+private:
+ // Map of existing assets. The servant pointer is null
+ // the corresponding servant is not in memory.
+ typedef map<CCS::AssetType, Thermometer_impl *> AssetMap;
+ AssetMap m_assets;
+
+ // POA for thermometers and thermostats
+ PortableServer::POA_var m_poa;
+
+ // Name of asset number file
+ CORBA::String_var m_asset_file;
+
+ // 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(
+ CCS::Controller::SearchCriterion sc,
+ const char * str
+ ) : m_sc(sc), m_str(str) {}
+ bool operator()(
+ pair<const CCS::AssetType, Thermometer_impl *> & p
+ ) const
+ {
+ char buf[32];
+ switch (m_sc) {
+ case CCS::Controller::LOCATION:
+ ICP_get(p.first, "location", buf, sizeof(buf));
+ break;
+ case CCS::Controller::MODEL:
+ ICP_get(p.first, "model", buf, sizeof(buf));
+ break;
+ default:
+ assert(0); // Precondition violation
+ }
+ return strcmp(buf, m_str) == 0;
+ }
+ private:
+ CCS::Controller::SearchCriterion m_sc;
+ const char * m_str;
+ };
+};
+
+class DeviceLocator_impl :
+ public virtual POA_PortableServer::ServantLocator {
+public:
+ DeviceLocator_impl(Controller_impl * ctrl);
+
+ virtual PortableServer::Servant
+ preinvoke(
+ const PortableServer::ObjectId & oid,
+ PortableServer::POA_ptr poa,
+ const char * operation,
+ void * & cookie,
+ CORBA_Environment &
+ ) throw(
+ CORBA::SystemException,
+ PortableServer::ForwardRequest);
+ virtual void
+ postinvoke(
+ const PortableServer::ObjectId & /*oid*/,
+ PortableServer::POA_ptr /*poa*/,
+ const char * /*operation*/,
+ void * /*cookie*/,
+ PortableServer::Servant /*servant*/,
+ CORBA_Environment &
+ ) throw(CORBA::SystemException) {}
+private:
+ Controller_impl * m_ctrl;
+
+ typedef list<Thermometer_impl *> EvictorQueue;
+ typedef map<CCS::AssetType, EvictorQueue::iterator>
+ ActiveObjectMap;
+
+ static const unsigned int MAX_EQ_SIZE = 100;
+ EvictorQueue m_eq;
+ ActiveObjectMap m_aom;
+
+ // Copy and assignment not supported
+ DeviceLocator_impl(const DeviceLocator_impl &);
+ void operator=(const DeviceLocator_impl &);
+};
+
+#endif
diff --git a/TAO/examples/Advanced/ch_18/CCS.idl b/TAO/examples/Advanced/ch_18/CCS.idl
new file mode 100644
index 00000000000..c0daa0f995f
--- /dev/null
+++ b/TAO/examples/Advanced/ch_18/CCS.idl
@@ -0,0 +1,103 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_18
+//
+// = FILENAME
+// CCS.idl
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+#pragma prefix "acme.com"
+
+module CCS {
+ typedef unsigned long AssetType;
+ typedef string ModelType;
+ typedef short TempType;
+ typedef string LocType;
+
+ interface Thermometer {
+ readonly attribute ModelType model;
+ readonly attribute AssetType asset_num;
+ readonly attribute TempType temperature;
+ attribute LocType location;
+
+ void remove();
+ };
+
+ interface Thermostat : Thermometer {
+ struct BtData {
+ TempType requested;
+ TempType min_permitted;
+ TempType max_permitted;
+ string error_msg;
+ };
+ exception BadTemp { BtData details; };
+
+ TempType get_nominal();
+ TempType set_nominal(in TempType new_temp)
+ raises(BadTemp);
+ };
+
+ interface Controller {
+ exception DuplicateAsset {};
+
+ Thermometer create_thermometer(
+ in AssetType anum,
+ in LocType loc
+ ) raises(DuplicateAsset);
+ Thermostat create_thermostat(
+ in AssetType anum,
+ in LocType loc,
+ in TempType temp
+ ) raises(DuplicateAsset, Thermostat::BadTemp);
+
+ typedef sequence<Thermometer> ThermometerSeq;
+ typedef sequence<Thermostat> ThermostatSeq;
+
+ enum SearchCriterion { ASSET, LOCATION, MODEL };
+
+ union KeyType switch(SearchCriterion) {
+ case ASSET:
+ AssetType asset_num;
+ case LOCATION:
+ LocType loc;
+ case MODEL:
+ ModelType model_desc;
+ };
+
+ struct SearchType {
+ KeyType key;
+ Thermometer device;
+ };
+ typedef sequence<SearchType> SearchSeq;
+
+ struct ErrorDetails {
+ Thermostat tmstat_ref;
+ Thermostat::BtData info;
+ };
+ typedef sequence<ErrorDetails> ErrSeq;
+
+ exception EChange {
+ ErrSeq errors;
+ };
+
+ ThermometerSeq list();
+ void find(inout SearchSeq slist);
+ void change(
+ in ThermostatSeq tlist, in short delta
+ ) raises(EChange);
+
+ };
+};
diff --git a/TAO/examples/Advanced/ch_18/CHANGES b/TAO/examples/Advanced/ch_18/CHANGES
new file mode 100644
index 00000000000..404883d09de
--- /dev/null
+++ b/TAO/examples/Advanced/ch_18/CHANGES
@@ -0,0 +1,98 @@
+$Id$
+
+Changelog for chapter 8 and 10 example in "Advanced CORBA
+Programming with C++" by Michi Henning and Steve Vinoski,
+Copyright 1999, Addison-Wesley, Reading, MA. The following
+changes have been made to the book's source code to make the
+example work with TAO and with various platforms and compilers.
+
+_______________________________________________________________________________
+ESSENTIAL CHANGES:
+ 1. Changed filename extensions from .hh and .cc to .h
+ and .cpp, and made all necessary changes in file content.
+
+ 2. a) Commented-out "#include <corba/poaS.h>" in server.h
+
+ b) Added #include "icp.h" to server.h.
+
+ c) changed #include <CosNaming.h> to <orbsvcs/CosNamingC.h>
+ in server.cpp and client.cpp
+
+ d) Unnecessary standard includes of <iostreams.h>, <assert.h>,
+ <fstream.h> and <stdlib.h> must be removed or moved to follow the
+ local includes in server.h, server.cpp, client.cpp, and icp.cpp.
+
+ e) The following files may need their includes further rearranged
+ to avoid warnings and errors (g++). The following orderings
+ seem to work fine:
+ - server.cpp: "server.h", <algorithm>, "icp.h",
+ <orbsvcs/CosNamingC.h>, <strstream.h>
+ - server.h: "CCSS.h", "icp.h", <map>, <list>
+
+ 3. Added CORBA_Environment variable to
+ DeviceLocator::preinvoke() and ::postinvoke()
+ in server.h and server.cpp to match the signatures of parent
+ methods in TAO's ServanLocator class.
+
+ 4. removed if 0 code surrounding
+ operator<<(ostream & os, const CCS::Controller::EChange & ec)
+ definition in server.cpp and client.cpp.
+
+ 5. commented-out "delete this;" from method
+ Thermometer_impl::remove() in server.cpp.
+ (Change should soon be reflected in authors' code)
+
+_______________________________________________________________________________
+ADDITIONAL CHANGES:
+ 6. Added .in() to _var parameters wherever needed:
+ -client.cpp:
+ 4 times in operator<<(ostream, CCS::Thermometer_ptr)
+ 3 times in resolve_init()
+ 3 times in resolve_name()
+ 5 times in main()
+ Also added .inout() 2 times in main() for parameters to set_temp()
+
+ -server.cpp:
+ 3 changes in resolve_init()
+ 2 changes in make_dref()
+ 2 changes in Controller_impl::Controller_impl()
+ 3 changes in Controller_impl::~Controller_impl()
+ 1 change in Controller_impl::create_thermometer()
+ 2 changes in Controller_impl::create_thermostat()
+ 1 change in Controller_impl::list()
+ 3 changes in Controller_impl::find()
+ 7 change in main()
+
+ 7. created needed file at /tmp/CCS_DB. (location is hard-coded)
+ To run, move CCS_DB from this directory to /tmp on the
+ local machine.
+
+ 8. fixed warnings by commented out unused parameters in
+ -DeviceLocator_impl::postinvoke(..) in server.h
+ -DeviceLocator_impl::preinvoke(..) in server.cpp
+
+ 9. MAX_EQ_SIZE changed from int to unsigned int
+ in class DeviceLocator_impl in server.h.
+
+ 10. added cast to unsigned long in ~ICP_Persist() in icp.cpp:
+ db << (unsigned long)(i->second.type) << endl;
+
+_______________________________________________________________________________
+To Do:
+ - fix error on 4 cases of fstream.close()
+ in server.cpp and icp.cpp, now commented-out
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TAO/examples/Advanced/ch_18/Makefile b/TAO/examples/Advanced/ch_18/Makefile
new file mode 100644
index 00000000000..5ebb8b39e2d
--- /dev/null
+++ b/TAO/examples/Advanced/ch_18/Makefile
@@ -0,0 +1,99 @@
+#----------------------------------------------------------------------------
+#
+# $Id$
+#
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Local macros
+#----------------------------------------------------------------------------
+
+ifndef TAO_ROOT
+ TAO_ROOT = $(ACE_ROOT)/TAO
+endif
+
+LDLIBS = -lorbsvcs -lTAO
+IDL_SRC = CCSC.cpp CCSS.cpp
+IDL_HDR = CCSC.h CCSS.h
+
+PROG_SRCS = \
+ client.cpp \
+ server.cpp \
+ icp.cpp
+
+SRC = $(IDL_SRC) $(PROG_SRCS)
+
+SIMPLE_CLT_OBJS = \
+ CCSC.o \
+ CCSS.o \
+ client.o
+
+SIMPLE_SVR_OBJS = \
+ CCSC.o \
+ CCSS.o \
+ server.o \
+ icp.o
+
+
+BIN2 = server \
+ client
+
+#### If the TAO orbsvcs library wasn't built with sufficient components,
+#### don't try to build here.
+TAO_ORBSVCS := $(shell sh $(ACE_ROOT)/bin/ace_components --orbsvcs)
+ifeq (Naming,$(findstring Naming,$(TAO_ORBSVCS)))
+ BIN = $(BIN2)
+endif # Naming
+
+BUILD = $(BIN)
+VLDLIBS = $(LDLIBS:%=%$(VAR))
+VBIN = $(BIN:%=%$(VAR))
+
+#----------------------------------------------------------------------------
+# Include macros and targets
+#----------------------------------------------------------------------------
+
+include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU
+include $(ACE_ROOT)/include/makeinclude/macros.GNU
+include $(TAO_ROOT)/rules.tao.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.common.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.local.GNU
+include $(TAO_ROOT)/taoconfig.mk
+
+#----------------------------------------------------------------------------
+# Local targets
+#----------------------------------------------------------------------------
+LDFLAGS += -L$(TAO_ROOT)/orbsvcs/orbsvcs -L$(TAO_ROOT)/tao -L$(ACE_ROOT)/ace
+CPPFLAGS += -I$(TAO_ROOT)/orbsvcs
+
+.PRECIOUS: CCSC.cpp CCSC.i CCSC.h
+.PRECIOUS: CCSS.cpp CCSS.i CCSS.h
+.PRECIOUS: CCSS_T.cpp CCSS_T.i CCSS_T.h
+
+override TAO_IDLFLAGS += -hc .hh -hs S.hh -hT S_T.hh \
+ -cs C.cc -ci C.i \
+ -ss S.cc -sT S_T.cc
+CCFLAGS += -fimplicit-templates -frtti -O0
+
+$(IDL_SRC): CCS.idl
+ $(TAO_ROOT)/TAO_IDL/tao_idl CCS.idl -hc .h -hs S.h -hT S_T.h \
+ -cs C.cpp \
+ -ss S.cpp -sT S_T.cpp
+server: $(addprefix $(VDIR),$(SIMPLE_SVR_OBJS))
+ $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK)
+
+client: $(addprefix $(VDIR),$(SIMPLE_CLT_OBJS))
+ $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK)
+
+realclean: clean
+ -/bin/$(RM) -rf CCSC.* CCSS.* CCSS_T.* CCS.h
+
+# DO NOT DELETE THIS LINE -- g++dep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+
+
+
+
+
diff --git a/TAO/examples/Advanced/ch_18/README b/TAO/examples/Advanced/ch_18/README
new file mode 100644
index 00000000000..5e0856df7d7
--- /dev/null
+++ b/TAO/examples/Advanced/ch_18/README
@@ -0,0 +1,45 @@
+$Id$
+
+Chapter 18 example
+______________________________________________________________________________
+This example been taken from the book "Advanced CORBA Programming with C++"
+by Michi Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+MA. To make the examples work with TAO, some minor modifications to the
+source code have been made, with permission, by Mike Moran <mm4@cs.wustl.edu>.
+All of these changes are documented in the file CHANGES, in this directory.
+______________________________________________________________________________
+
+
+Summary:
+ This example adds the use of the Naming Service to the climate control
+ system of chapter 12.
+
+Building:
+ This example must be built with native C++ exceptions, and with an ACE/TAO
+ build with exceptions. Make sure to use TAO_FLAG Ge=0 to ensure that the
+ IDL generated code uses c++ exceptions rather than creating
+ CORBA_Environment variables.
+
+ With GNU make, simply type
+ % make exceptions=1
+ to create the executable server and client.
+
+ Also, make sure that the Naming Service executable has been built at
+ $TAO_ROOT/orbsvcs/Naming_Service/Naming_Service.
+
+server:
+ The server takes no parameters nor command line options and registers the
+ controller object with the naming service. The server then waits
+ infinitely for clients requests.
+
+client:
+ The client gets reference to the controller through the naming service,
+ makes several remote calls on this controller, and terminates.
+
+run_test.pl:
+ The script starts up a new Naming Service, starts thc server and client,
+ and when the client has completed terminates the server and NamingService.
+
+
+
+
diff --git a/TAO/examples/Advanced/ch_18/client.cpp b/TAO/examples/Advanced/ch_18/client.cpp
new file mode 100644
index 00000000000..bdf1db1f6b6
--- /dev/null
+++ b/TAO/examples/Advanced/ch_18/client.cpp
@@ -0,0 +1,349 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_18
+//
+// = FILENAME
+// client.cpp
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+#include "CCS.h" // ORB-specific
+#include <orbsvcs/CosNamingC.h>
+// #include <iostream.h>
+// #include <fstream.h>
+// ----------------------------------------------------------------
+
+template<class T>
+typename T::_ptr_type
+resolve_init(CORBA::ORB_ptr orb, const char * id)
+{
+ CORBA::Object_var obj;
+ try {
+ obj = orb->resolve_initial_references(id);
+ }
+ catch (const CORBA::ORB::InvalidName & e) {
+ throw;
+ }
+ catch (const CORBA::Exception & e) {
+ cerr << "Cannot get initial reference for "
+ << id << ": " << e << endl;
+ throw 0;
+ }
+ assert(!CORBA::is_nil(obj.in()));
+
+ typename T::_var_type ref;
+ try {
+ ref = T::_narrow(obj.in());
+ }
+ catch (const CORBA::Exception & e) {
+ cerr << "Cannot narrow reference for "
+ << id << ": " << e << endl;
+ throw 0;
+ }
+ if (CORBA::is_nil(ref.in())) {
+ cerr << "Incorrect type of reference for "
+ << id << endl;
+ throw 0;
+ }
+ return ref._retn();
+}
+
+//----------------------------------------------------------------
+
+template<class T>
+typename T::_ptr_type
+resolve_name(
+ CosNaming::NamingContext_ptr nc,
+ const CosNaming::Name & name)
+{
+ CORBA::Object_var obj;
+ try {
+ obj = nc->resolve(name);
+ }
+ catch (const CosNaming::NamingContext::NotFound & e) {
+ throw;
+ }
+ catch (const CORBA::Exception & e) {
+ cerr << "Cannot resolve binding: " << e << endl;
+ throw 0;
+ }
+ if (CORBA::is_nil(obj.in())) {
+ cerr << "Nil binding in Naming Service" << endl;
+ throw 0;
+ }
+
+ typename T::_var_type ref;
+ try {
+ ref = T::_narrow(obj.in());
+ }
+ catch (const CORBA::Exception & e) {
+ cerr << "Cannot narrow reference: " << e << endl;
+ throw 0;
+ }
+ if (CORBA::is_nil(ref.in())) {
+ cerr << "Reference has incorrect type" << endl;
+ throw 0;
+ }
+ return ref._retn();
+}
+
+//----------------------------------------------------------------
+
+// Generic ostream inserter for exceptions. Inserts the exception
+// name, if available, and the repository ID otherwise.
+
+//#if 0 // This inserter may or may not be needed for your ORB.
+
+static ostream &
+operator<<(ostream & os, const CORBA::Exception & e)
+{
+ CORBA::Any tmp;
+ tmp <<= e;
+
+ CORBA::TypeCode_var tc = tmp.type();
+ const char * p = tc->name();
+ if (*p != '\0')
+ os << p;
+ else
+ os << tc->id();
+ return os;
+}
+
+//#endif
+
+//----------------------------------------------------------------
+
+// Show the details for a thermometer or thermostat.
+
+static ostream &
+operator<<(ostream &os, CCS::Thermometer_ptr t)
+{
+ // Check for nil.
+ if (CORBA::is_nil(t)) {
+ os << "Cannot show state for nil reference." << endl;
+ return os;
+ }
+
+ // Try to narrow and print what kind of device it is.
+ CCS::Thermostat_var tmstat = CCS::Thermostat::_narrow(t);
+ os << (CORBA::is_nil(tmstat.in()) ? "Thermometer:" : "Thermostat:")
+ << endl;
+
+ // Show attribute values.
+ CCS::ModelType_var model = t->model();
+ CCS::LocType_var location = t->location();
+ os << "\tAsset number: " << t->asset_num() << endl;
+ os << "\tModel : " << model.in() << endl;
+ os << "\tLocation : " << location.in() << endl;
+ os << "\tTemperature : " << t->temperature() << endl;
+
+ // If device is a thermostat, show nominal temperature.
+ if (!CORBA::is_nil(tmstat.in()))
+ os << "\tNominal temp: " << tmstat->get_nominal() << endl;
+ return os;
+}
+
+//----------------------------------------------------------------
+
+// Show the information in a BtData struct.
+
+static ostream &
+operator<<(ostream &os, const CCS::Thermostat::BtData &btd)
+{
+ os << "CCS::Thermostat::BtData details:" << endl;
+ os << "\trequested : " << btd.requested << endl;
+ os << "\tmin_permitted: " << btd.min_permitted << endl;
+ os << "\tmax_permitted: " << btd.max_permitted << endl;
+ os << "\terror_msg : " << btd.error_msg << endl;
+ return os;
+}
+
+//----------------------------------------------------------------
+
+// Loop over the sequence of records in an EChange exception and
+// show the details of each record.
+
+static ostream &
+operator<<(ostream &os, const CCS::Controller::EChange &ec)
+{
+ for (CORBA::ULong i = 0; i < ec.errors.length(); i++) {
+ os << "Change failed:" << endl;
+ os << ec.errors[i].tmstat_ref.in(); // Overloaded <<
+ os << ec.errors[i].info << endl; // Overloaded <<
+ }
+ return os;
+}
+
+//----------------------------------------------------------------
+
+// Change the temperature of a thermostat.
+
+static void
+set_temp(CCS::Thermostat_ptr tmstat, CCS::TempType new_temp)
+{
+ if (CORBA::is_nil(tmstat)) // Don't call via nil reference
+ return;
+
+ CCS::AssetType anum = tmstat->asset_num();
+ try {
+ cout << "Setting thermostat " << anum
+ << " to " << new_temp << " degrees." << endl;
+ CCS::TempType old_nominal = tmstat->set_nominal(new_temp);
+ cout << "Old nominal temperature was: "
+ << old_nominal << endl;
+ cout << "New nominal temperature is: "
+ << tmstat->get_nominal() << endl;
+ } catch (const CCS::Thermostat::BadTemp &bt) {
+ cerr << "Setting of nominal temperature failed." << endl;
+ cerr << bt.details << endl; // Overloaded <<
+ }
+}
+
+//----------------------------------------------------------------
+
+int
+main(int argc, char * argv[])
+{
+ try {
+ // Initialize the ORB
+ CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
+
+ // Check arguments
+ if (argc != 1) {
+ cerr << "Usage: client" << endl;
+ throw 0;
+ }
+
+ // Get reference to initial naming context.
+ CosNaming::NamingContext_var inc
+ = resolve_init<CosNaming::NamingContext>(
+ orb.in(), "NameService"
+ );
+
+ // Look for controller in the Naming Service.
+ CosNaming::Name n;
+ n.length(2);
+ n[0].id = CORBA::string_dup("CCS");
+ n[1].id = CORBA::string_dup("Controller");
+ CCS::Controller_var ctrl;
+ try {
+ ctrl = resolve_name<CCS::Controller>(inc.in(), n);
+ } catch (const CosNaming::NamingContext::NotFound &) {
+ cerr << "No controller in Naming Service" << endl;
+ throw(0);
+ }
+
+ // Get list of devices
+ CCS::Controller::ThermometerSeq_var list = ctrl->list();
+
+ // Show number of devices.
+ CORBA::ULong len = list->length();
+ cout << "Controller has " << len << " device";
+ if (len != 1)
+ cout << "s";
+ cout << "." << endl;
+
+ CCS::Thermometer_var t = ctrl->create_thermometer(27, "Room 1");
+ CCS::Thermostat_var ts = ctrl->create_thermostat(28, "Room 2", 48);
+ CCS::Thermostat_var ts2 = ctrl->create_thermostat(30, "Room 3", 48);
+ CCS::Thermostat_var ts3 = ctrl->create_thermostat(32, "Room 3", 68);
+ CCS::Thermostat_var ts4 = ctrl->create_thermostat(34, "Room 3", 68);
+ CCS::Thermostat_var ts5 = ctrl->create_thermostat(36, "Room 3", 48);
+ cout << t->location() << endl;
+ cout << ts->location() << endl;
+ cout << ts2->location() << endl;
+ t->remove();
+
+ list = ctrl->list();
+ // Show details for each device.
+ for (CORBA::ULong i = 0; i < list->length(); i++)
+ cout << list[i];
+ cout << endl;
+
+ // Change the location of first device in the list
+ CCS::AssetType anum = list[0]->asset_num();
+ cout << "Changing location of device "
+ << anum << "." << endl;
+ list[0]->location("Earth");
+ // Check that the location was updated
+ cout << "New details for device "
+ << anum << " are:" << endl;
+ cout << list[0] << endl;
+
+ // Find first thermostat in list.
+ CCS::Thermostat_var tmstat;
+ for ( CORBA::ULong i = 0;
+ i < list->length() && CORBA::is_nil(tmstat.in());
+ i++) {
+ tmstat = CCS::Thermostat::_narrow(list[i]);
+ }
+
+ // Check that we found a thermostat on the list.
+ if (CORBA::is_nil(tmstat.in())) {
+ cout << "No thermostat devices in list." << endl;
+ } else {
+ // Set temperature of thermostat to
+ // 50 degrees (should work).
+ set_temp(tmstat.inout(), 50);
+ cout << endl;
+
+ // Set temperature of thermostat to
+ // -10 degrees (should fail).
+ set_temp(tmstat.inout(), -10);
+ }
+
+ // Look for device in Rooms Earth and HAL. This must
+ // locate at least one device because we earlier changed
+ // the location of the first device to Room Earth.
+ cout << "Looking for devices in Earth and HAL." << endl;
+ CCS::Controller::SearchSeq ss;
+ ss.length(2);
+ ss[0].key.loc(CORBA::string_dup("Earth"));
+ ss[1].key.loc(CORBA::string_dup("HAL"));
+ ctrl->find(ss);
+
+ // Show the devices found in that room.
+ for (CORBA::ULong i = 0; i < ss.length(); i++)
+ cout << ss[i].device.in(); // Overloaded <<
+ cout << endl;
+
+ // Increase the temperature of all thermostats
+ // by 40 degrees. First, make a new list (tss)
+ // containing only thermostats.
+ cout << "Increasing thermostats by 40 degrees." << endl;
+ CCS::Controller::ThermostatSeq tss;
+ for (CORBA::ULong i = 0; i < list->length(); i++) {
+ tmstat = CCS::Thermostat::_narrow(list[i]);
+ if (CORBA::is_nil(tmstat.in()))
+ continue; // Skip thermometers
+ len = tss.length();
+ tss.length(len + 1);
+ tss[len] = tmstat;
+ }
+
+ // Try to change all thermostats.
+ try {
+ ctrl->change(tss, 40);
+ } catch (const CCS::Controller::EChange &ec) {
+ cerr << ec; // Overloaded <<
+ }
+ } catch (const CORBA::Exception & e) {
+ cerr << "Uncaught CORBA exception: " << e << endl;
+ return 1;
+ } catch (...) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/TAO/examples/Advanced/ch_18/icp.cpp b/TAO/examples/Advanced/ch_18/icp.cpp
new file mode 100644
index 00000000000..e8ba75d6ef7
--- /dev/null
+++ b/TAO/examples/Advanced/ch_18/icp.cpp
@@ -0,0 +1,386 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_18
+//
+// = FILENAME
+// icp.cpp
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+
+#include <string>
+#include <map>
+#include <algorithm>
+#include "icp.h"
+// #include <stdlib.h>
+
+//----------------------------------------------------------------
+
+enum DeviceType { thermometer, thermostat };
+
+struct DeviceState { // State for a device
+ DeviceType type;
+ const char * model;
+ string location;
+ short nominal_temp; // For thermostats only
+};
+typedef map<unsigned long, DeviceState> StateMap;
+
+//----------------------------------------------------------------
+
+const size_t MAXSTR = 32; // Max len of string including NUL
+
+const short MIN_TEMP = 40; // 40 F == 4.44 C
+const short MAX_TEMP = 90; // 90 F == 32.22 C
+const short DFLT_TEMP = 68; // 68 F == 20.00 C
+
+static StateMap dstate; // Map of known devices
+
+//----------------------------------------------------------------
+
+// ICP_online() simulates adding a new device to the network by
+// adding it to the dstate map.
+//
+// For this simple simulation, devices with odd asset numbers
+// are thermometers and devices with even asset numbers
+// are thermostats.
+//
+// Thermostats get an initial nominal temperature of DFLT_TEMP.
+// The location string is intentionally left blank because it
+// must be programmed by the controller after putting the device
+// on-line (as should be the nominal temperature).
+//
+// If a device with the specified ID is already on-line, the
+// return value is -1. A zero return value indicates success.
+
+extern "C"
+int
+ICP_online(unsigned long id)
+{
+ // Look for id in state map.
+ StateMap::iterator pos = dstate.find(id);
+ if (pos != dstate.end())
+ return -1; // Already exists
+
+ // Fill in state.
+ DeviceState ds;
+ ds.type = (id % 2) ? thermometer : thermostat;
+ ds.model = (ds.type == thermometer)
+ ? "Sens-A-Temp" : "Select-A-Temp";
+ ds.nominal_temp = DFLT_TEMP;
+
+ // Insert new device into map
+ dstate[id] = ds;
+
+ return 0;
+}
+
+//----------------------------------------------------------------
+
+// ICP_offline() simulates removing a device from the network by
+// removing it from the dstate map. If the device isn't known, the
+// return value is -1. A zero return value indicates success.
+
+extern "C"
+int
+ICP_offline(unsigned long id)
+{
+ // Look for id in state map
+ StateMap::iterator pos = dstate.find(id);
+ if (pos == dstate.end())
+ return -1; // No such device
+ dstate.erase(id);
+ return 0;
+}
+
+//----------------------------------------------------------------
+
+// vary_temp() simulates the variation in actual temperature
+// around a thermostat.The function randomly varies the
+// temperature as a percentage of calls as follows:
+//
+// 3 degrees too cold: 5%
+// 3 degrees too hot: 5%
+// 2 degrees too cold: 10%
+// 2 degrees too hot: 10%
+// 1 degree too cold: 15%
+// 1 degree too hot: 15%
+// exact temperature: 40%
+
+static
+short
+vary_temp(short temp)
+{
+ long r = lrand48() % 50;
+ long delta;
+ if (r < 5)
+ delta = 3;
+ else if (r < 15)
+ delta = 2;
+ else if (r < 30)
+ delta = 1;
+ else
+ delta = 0;
+ if (lrand48() % 2)
+ delta = -delta;
+ return temp + delta;
+}
+
+//----------------------------------------------------------------
+
+// Function object. Locates a thermostat that is in the same room
+// as the device at position pos.
+
+class ThermostatInSameRoom {
+public:
+ ThermostatInSameRoom(
+ const StateMap::iterator & pos
+ ) : m_pos(pos) {}
+ bool operator()(
+ pair<const unsigned long, DeviceState> & p
+ ) const
+ {
+ return(
+ p.second.type == thermostat
+ && p.second.location
+ == m_pos->second.location
+ );
+ }
+private:
+ const StateMap::iterator & m_pos;
+};
+
+//----------------------------------------------------------------
+
+// actual_temp() is a helper function to determine the actual
+// temperature returned by a particular thermometer or thermostat.
+// The pos argument indicates the device.
+//
+// The function locates all thermostats that are in the same room
+// as the device denoted by pos and computes the average of all
+// the thermostats' nominal temperatures. (If no thermostats are
+// in the same room as the device, the function assumes that the
+// average of the nominal temperatures is DFLT_TEMP.)
+//
+// The returned temperature varies from the average as
+// determined by vary_temp().
+
+static
+short
+actual_temp(const StateMap::iterator & pos)
+{
+ long sum = 0;
+ long count = 0;
+ StateMap::iterator where = find_if(
+ dstate.begin(), dstate.end(),
+ ThermostatInSameRoom(pos)
+ );
+ while (where != dstate.end()) {
+ count++;
+ sum += where->second.nominal_temp;
+ where = find_if(
+ ++where, dstate.end(),
+ ThermostatInSameRoom(pos)
+ );
+ }
+ return vary_temp(count == 0 ? DFLT_TEMP : sum / count);
+}
+
+//----------------------------------------------------------------
+
+// ICP_get() returns an attribute value of the device with the
+// given id. The attribute is named by the attr parameter. The
+// value is copied into the buffer pointed to by the value
+// pointer. The len parameter is the size of the passed buffer,
+// so ICP_get can avoid overrunning the buffer.
+//
+// By default, thermometers report a temperature that varies
+// somewhat around DFLT_TEMP. However, if there is another
+// thermostat in the same room as the the thermometer, the
+// thermometer reports a temperature that varies around that
+// thermostat's temperature. For several thermostats that are in
+// the same room, the thermometer reports around the average
+// nominal temperature of all the thermostats.
+//
+// Attempts to read from a non-existent device or to read a
+// non-existent attribute return -1. A return value of zero
+// indicates success. If the supplied buffer is too short to hold
+// a value, ICP_get() silently truncates the value and
+// returns success.
+
+extern "C"
+int
+ICP_get(
+ unsigned long id,
+ const char * attr,
+ void * value,
+ size_t len)
+{
+ // Look for id in state map
+ StateMap::iterator pos = dstate.find(id);
+ if (pos == dstate.end())
+ return -1; // No such device
+
+ // Depending on the attribute, return the
+ // corresponding piece of state.
+ if (strcmp(attr, "model") == 0) {
+ strncpy((char *)value, pos->second.model, len);
+ } else if (strcmp(attr, "location") == 0) {
+ strncpy((char *)value, pos->second.location.c_str(), len);
+ } else if (strcmp(attr, "nominal_temp") == 0) {
+ if (pos->second.type != thermostat)
+ return -1; // Must be thermostat
+ memcpy(
+ value, &pos->second.nominal_temp,
+ min(len, sizeof(pos->second.nominal_temp))
+ );
+ } else if (strcmp(attr, "temperature") == 0) {
+ short temp = actual_temp(pos);
+ memcpy(value, &temp, min(len, sizeof(temp)));
+ } else if (strcmp(attr, "MIN_TEMP") == 0) {
+ memcpy(value, &MIN_TEMP, min(len, sizeof(MIN_TEMP)));
+ } else if (strcmp(attr, "MAX_TEMP") == 0) {
+ memcpy(value, &MAX_TEMP, min(len, sizeof(MAX_TEMP)));
+ } else {
+ return -1; // No such attribute
+ }
+ return 0; // OK
+}
+
+//----------------------------------------------------------------
+
+// ICP_set() sets the the attributed specified by attr to the
+// value specified by value for the device with ID id. Attempts to
+// write a string longer than MAXSTR bytes (including the
+// terminating NUL) result in silent truncation of the string.
+// Attempts to access a non-existent device or attribute
+// return -1. Attempts to set a nominal temperature outside the
+// legal range also return -1. A zero return value
+// indicates success.
+
+extern "C"
+int
+ICP_set(unsigned long id, const char * attr, const void * value)
+{
+ // Look for id in state map
+ StateMap::iterator pos = dstate.find(id);
+ if (pos == dstate.end())
+ return -1; // No such device
+
+ // Change either location or nominal temp, depending on attr.
+ if (strcmp(attr, "location") == 0) {
+ pos->second.location.assign(
+ (const char *)value, MAXSTR - 1
+ );
+ } else if (strcmp(attr, "nominal_temp") == 0) {
+ if (pos->second.type != thermostat)
+ return -1; // Must be thermostat
+ short temp;
+ memcpy(&temp, value, sizeof(temp));
+ if (temp < MIN_TEMP || temp > MAX_TEMP)
+ return -1;
+ pos->second.nominal_temp = temp;
+ } else {
+ return -1; // No such attribute
+ }
+ return 0; // OK
+}
+
+//----------------------------------------------------------------
+
+#include <fstream.h>
+
+class ICP_Persist {
+public:
+ ICP_Persist(const char * file);
+ ~ICP_Persist();
+private:
+ string m_filename;
+};
+
+// Read device state from a file and initialize the dstate map.
+
+ICP_Persist::
+ICP_Persist(const char * file) : m_filename(file)
+{
+ // Open input file, creating it if necessary.
+ fstream db(m_filename.c_str(), ios::in|ios::out, 0666);
+ if (!db) {
+ cerr << "Error opening " << m_filename << endl;
+ exit(1);
+ }
+
+ // Read device details, one attribute per line.
+ DeviceState ds;
+ unsigned long id;
+ while (db >> id) {
+ // Read device type and set model string accordingly.
+ int dtype;
+ db >> dtype;
+ ds.type = dtype == thermometer
+ ? thermometer : thermostat;
+ ds.model = dtype == thermometer
+ ? "Sens-A-Temp" : "Select-A-Temp";
+ char loc[MAXSTR];
+ db.get(loc[0]); // Skip newline
+ db.getline(loc, sizeof(loc)); // Read location
+ ds.location = loc;
+ if (ds.type == thermostat)
+ db >> ds.nominal_temp; // Read temperature
+ dstate[id] = ds; // Add entry to map
+ }
+
+ //db.close();
+ //if (!db) {
+ // cerr << "Error closing " << m_filename << endl;
+ // exit(1);
+ //}
+}
+
+// Write device state to the file.
+
+ICP_Persist::
+~ICP_Persist()
+{
+ // Open input file, truncating it.
+ ofstream db(m_filename.c_str());
+ if (!db) {
+ cerr << "Error opening " << m_filename << endl;
+ exit(1);
+ }
+
+ // Write the state details for each device.
+ StateMap::iterator i;
+ for (i = dstate.begin(); i != dstate.end(); i++) {
+ db << i->first << endl;
+ db << (unsigned long)(i->second.type) << endl;
+ db << i->second.location << endl;
+ if (i->second.type == thermostat)
+ db << i->second.nominal_temp << endl;
+ }
+ if (!db) {
+ cerr << "Error writing " << m_filename << endl;
+ exit(1);
+ }
+
+ db.close();
+ if (!db) {
+ cerr << "Error closing " << m_filename << endl;
+ exit(1);
+ }
+}
+
+// Instantiate a single global instance of the class.
+static ICP_Persist mydb("/tmp/CCS_DB");
diff --git a/TAO/examples/Advanced/ch_18/icp.h b/TAO/examples/Advanced/ch_18/icp.h
new file mode 100644
index 00000000000..68f6b120105
--- /dev/null
+++ b/TAO/examples/Advanced/ch_18/icp.h
@@ -0,0 +1,42 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_18
+//
+// = FILENAME
+// icp.h
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+
+#ifndef _ICP_H
+#define _ICP_H
+
+extern "C" {
+ int ICP_online(unsigned long id); // Add device
+ int ICP_offline(unsigned long id); // Remove device
+ int ICP_get( // Get attribute
+ unsigned long id,
+ const char * attr,
+ void * value,
+ size_t len
+ );
+ int ICP_set( // Set attribute
+ unsigned long id,
+ const char * attr,
+ const void * value
+ );
+}
+
+#endif /* _ICP_H */
diff --git a/TAO/examples/Advanced/ch_18/run_test.pl b/TAO/examples/Advanced/ch_18/run_test.pl
new file mode 100755
index 00000000000..b0da026b271
--- /dev/null
+++ b/TAO/examples/Advanced/ch_18/run_test.pl
@@ -0,0 +1,72 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib "../../../../bin";
+
+require ACEutils;
+require Process;
+
+$status = 0;
+
+# amount of delay between starting servers and client
+$sleeptime = 5;
+
+
+
+sub name_server
+{
+ my $prog = "..$DIR_SEPARATOR".
+ "..$DIR_SEPARATOR".
+ "..$DIR_SEPARATOR".
+ "orbsvcs$DIR_SEPARATOR".
+ "Naming_Service$DIR_SEPARATOR".
+ "Naming_Service$EXE_EXT";
+ $NS = Process::Create ($prog,"");
+}
+
+
+
+# create naming service, server, client
+name_server ();
+sleep $sleeptime;
+
+$server = Process::Create ($EXEPREFIX."server".$EXE_EXT, "");
+sleep $sleeptime;
+
+$client = Process::Create($EXEPREFIX."client".$EXE_EXT, "");
+
+
+
+# wait for client to finish
+if ($client->TimedWait (60) == -1) {
+ print STDERR "ERROR: client timedout\n";
+ $status = 1;
+ $client->Kill (); $client->TimedWait (1);
+}
+
+
+# gracefully kill the server
+$server->Terminate ();
+if ($server->TimedWait (5) == -1) {
+ print STDERR "ERROR: cannot terminate the server\n";
+ $server->Kill (); $server->TimedWait (1);
+ $status = 1;
+}
+
+# gracefully kill the Naming Service
+$NS->Terminate ();
+if ($NS->TimedWait (5) == -1) {
+ print STDERR "ERROR: cannot terminate the server\n";
+ $NS->Kill (); $server->TimedWait (1);
+ $status = 1;
+}
+
+exit $status;
+
+
+
+
diff --git a/TAO/examples/Advanced/ch_18/server.cpp b/TAO/examples/Advanced/ch_18/server.cpp
new file mode 100644
index 00000000000..8cf4fac044a
--- /dev/null
+++ b/TAO/examples/Advanced/ch_18/server.cpp
@@ -0,0 +1,791 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_18
+//
+// = FILENAME
+// server.cpp
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+
+#include "server.h"
+#include <algorithm>
+#include "icp.h"
+#include <orbsvcs/CosNamingC.h>
+#include <strstream.h>
+
+// #include <iostream.h>
+// #include <fstream.h>
+
+const char * Controller_oid = "Controller";
+
+//----------------------------------------------------------------
+
+template<class T>
+typename T::_ptr_type
+resolve_init(CORBA::ORB_ptr orb, const char * id)
+{
+ CORBA::Object_var obj;
+ try {
+ obj = orb->resolve_initial_references(id);
+ }
+ catch (const CORBA::ORB::InvalidName & e) {
+ throw;
+ }
+ catch (const CORBA::Exception & e) {
+ cerr << "Cannot get initial reference for "
+ << id << ": " << e << endl;
+ throw 0;
+ }
+ assert(!CORBA::is_nil(obj.in()));
+
+ typename T::_var_type ref;
+ try {
+ ref = T::_narrow(obj.in());
+ }
+ catch (const CORBA::Exception & e) {
+ cerr << "Cannot narrow reference for "
+ << id << ": " << e << endl;
+ throw 0;
+ }
+ if (CORBA::is_nil(ref.in())) {
+ cerr << "Incorrect type of reference for "
+ << id << endl;
+ throw 0;
+ }
+ return ref._retn();
+}
+
+//----------------------------------------------------------------
+
+// Generic ostream inserter for exceptions. Inserts the exception
+// name, if available, and the repository ID otherwise.
+
+//#if 0 // This inserter may or may not be needed for your ORB.
+
+static ostream &
+operator<<(ostream & os, const CORBA::Exception & e)
+{
+ CORBA::Any tmp;
+ tmp <<= e;
+
+ CORBA::TypeCode_var tc = tmp.type();
+ const char * p = tc->name();
+ if (*p != '\0')
+ os << p;
+ else
+ os << tc->id();
+ return os;
+}
+
+//#endif
+
+//----------------------------------------------------------------
+
+// Helper function to create object references.
+
+static CCS::Thermometer_ptr
+make_dref(PortableServer::POA_ptr poa, CCS::AssetType anum)
+{
+ // Convert asset number to OID.
+ ostrstream ostr;
+ ostr << anum << ends;
+ char * anum_str = ostr.str();
+ PortableServer::ObjectId_var oid
+ = PortableServer::string_to_ObjectId(anum_str);
+ delete[] anum_str;
+
+ // Look at the model via the network to determine
+ // the repository ID.
+ char buf[32];
+ assert(ICP_get(anum, "model", buf, sizeof(buf)) == 0);
+ const char * rep_id = strcmp(buf, "Sens-A-Temp") == 0
+ ? "IDL:acme.com/CCS/Thermometer:1.0"
+ : "IDL:acme.com/CCS/Thermostat:1.0";
+
+ // Make a new reference.
+ CORBA::Object_var obj
+ = poa->create_reference_with_id(oid.in(), rep_id);
+ return CCS::Thermometer::_narrow(obj.in());
+}
+
+//----------------------------------------------------------------
+
+Controller_impl * Thermometer_impl::m_ctrl; // static member
+
+// Helper function to read the model string from a device.
+
+CCS::ModelType
+Thermometer_impl::
+get_model()
+{
+ char buf[32];
+ assert(ICP_get(m_anum, "model", buf, sizeof(buf)) == 0);
+ return CORBA::string_dup(buf);
+}
+
+// Helper function to read the temperature from a device.
+
+CCS::TempType
+Thermometer_impl::
+get_temp()
+{
+ short temp;
+ assert(ICP_get(m_anum, "temperature", &temp, sizeof(temp)) == 0);
+ return temp;
+}
+
+// Helper function to read the location from a device.
+
+CCS::LocType
+Thermometer_impl::
+get_loc()
+{
+ char buf[32];
+ assert(ICP_get(m_anum, "location", buf, sizeof(buf)) == 0);
+ return CORBA::string_dup(buf);
+}
+
+// Helper function to set the location of a device.
+
+void
+Thermometer_impl::
+set_loc(const char * loc)
+{
+ assert(ICP_set(m_anum, "location", loc) == 0);
+}
+
+// Constructor.
+
+Thermometer_impl::
+Thermometer_impl(CCS::AssetType anum) : m_anum(anum)
+{
+ m_ctrl->add_impl(anum, this); // Add self to controller's set
+}
+
+// Destructor.
+
+Thermometer_impl::
+~Thermometer_impl()
+{
+ if (m_ctrl->exists(m_anum))
+ m_ctrl->add_impl(m_anum, 0); // Clear servant pointer
+}
+
+// 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 remove operation.
+
+void
+Thermometer_impl::
+remove() throw(CORBA::SystemException)
+{
+ m_ctrl->remove_impl(m_anum);
+ assert(ICP_offline(m_anum) == 0);
+ //delete this;
+}
+
+// IDL location attribute modifier.
+
+void
+Thermometer_impl::
+location(const char *loc) throw(CORBA::SystemException)
+{
+ set_loc(loc);
+}
+
+//----------------------------------------------------------------
+
+// Helper function to get a thermostat's nominal temperature.
+
+CCS::TempType
+Thermostat_impl::
+get_nominal_temp()
+{
+ short temp;
+ assert(ICP_get(m_anum, "nominal_temp", &temp, sizeof(temp)) == 0);
+ 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.
+ assert(
+ ICP_get(
+ m_anum, "nominal_temp", &old_temp, sizeof(old_temp)
+ ) == 0
+ );
+
+ // 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.
+
+Thermostat_impl::
+Thermostat_impl(CCS::AssetType anum) : Thermometer_impl(anum)
+{
+ // Intentionally empty.
+}
+
+// Destructor.
+
+Thermostat_impl::
+~Thermostat_impl()
+{
+ // Intentionally empty.
+}
+
+// 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 to add an entry to the asset map.
+
+void
+Controller_impl::
+add_impl(CCS::AssetType anum, Thermometer_impl * tip)
+{
+ m_assets[anum] = tip;
+}
+
+// Helper function to remove an entry from the asset map.
+
+void
+Controller_impl::
+remove_impl(CCS::AssetType anum)
+{
+ m_assets.erase(anum);
+}
+
+// Helper function to locate a servant in the asset map.
+
+bool
+Controller_impl::
+exists(CCS::AssetType anum)
+{
+ return m_assets.find(anum) != m_assets.end();
+}
+
+// Constructor
+
+Controller_impl::
+Controller_impl(
+ PortableServer::POA_ptr poa,
+ const char * asset_file
+) throw(int) : m_poa(PortableServer::POA::_duplicate(poa)),
+ m_asset_file(asset_file)
+{
+ fstream afile(m_asset_file.in(), ios::in|ios::out, 0666);
+ if (!afile) {
+ cerr << "Cannot open " << m_asset_file.in() << endl;
+ throw 0;
+ }
+ CCS::AssetType anum;
+ while (afile >> anum)
+ m_assets[anum] = 0;
+ //afile.close();
+ //if (!afile) {
+ // cerr << "Cannot close " << m_asset_file << endl;
+ // throw 0;
+ //}
+}
+
+// Destructor
+
+Controller_impl::
+~Controller_impl()
+{
+ // Write out the current set of asset numbers
+ // and clean up all servant instances.
+ ofstream afile(m_asset_file.in());
+ if (!afile) {
+ cerr << "Cannot open " << m_asset_file.in() << endl;
+ assert(0);
+ }
+ AssetMap::iterator i;
+ for (i = m_assets.begin(); i != m_assets.end(); i++) {
+ afile << i->first << endl;
+ if (!afile) {
+ cerr << "Cannot update " << m_asset_file.in() << endl;
+ assert(0);
+ }
+ delete i->second;
+ }
+ //afile.close();
+ //if (!afile) {
+ // cerr << "Cannot close " << m_asset_file << endl;
+ // assert(0);
+ //}
+}
+
+CCS::Thermometer_ptr
+Controller_impl::
+create_thermometer(CCS::AssetType anum, const char * loc)
+throw(CORBA::SystemException, CCS::Controller::DuplicateAsset)
+{
+ if (anum % 2 == 0)
+ throw CORBA::BAD_PARAM(); // Thermometers have odd numbers
+ if (exists(anum))
+ throw CCS::Controller::DuplicateAsset();
+
+ assert(ICP_online(anum) == 0);
+ assert(ICP_set(anum, "location", loc) == 0);
+ add_impl(anum, 0);
+ return make_dref(m_poa.in(), anum);
+}
+
+CCS::Thermostat_ptr
+Controller_impl::
+create_thermostat(
+ CCS::AssetType anum,
+ const char* loc,
+ CCS::TempType temp)
+throw(
+ CORBA::SystemException,
+ CCS::Controller::DuplicateAsset,
+ CCS::Thermostat::BadTemp)
+{
+ if (anum % 2 != 0)
+ throw CORBA::BAD_PARAM(); // Thermostats have even numbers
+ if (exists(anum))
+ throw CCS::Controller::DuplicateAsset();
+
+ assert(ICP_online(anum) == 0);
+ assert(ICP_set(anum, "location", loc) == 0);
+ // Set the nominal temperature.
+ if (ICP_set(anum, "nominal_temp", &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(
+ anum, "MIN_TEMP",
+ &btd.min_permitted, sizeof(btd.min_permitted)
+ );
+ ICP_get(
+ anum, "MAX_TEMP",
+ &btd.max_permitted, sizeof(btd.max_permitted)
+ );
+ btd.requested = temp;
+ btd.error_msg = CORBA::string_dup(
+ temp > btd.max_permitted ? "Too hot" : "Too cold"
+ );
+ ICP_offline(anum);
+ throw CCS::Thermostat::BadTemp(btd);
+ }
+
+ add_impl(anum, 0);
+ CORBA::Object_var obj = make_dref(m_poa.in(), anum);
+ return CCS::Thermostat::_narrow(obj.in());
+}
+
+// IDL list operation.
+
+CCS::Controller::ThermometerSeq *
+Controller_impl::
+list() throw(CORBA::SystemException)
+{
+ // 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 set 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++] = make_dref(m_poa.in(), i->first);
+ 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; // Skip nil references
+
+ // 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;
+}
+
+// IDL find operation
+
+void
+Controller_impl::
+find(CCS::Controller::SearchSeq & slist)
+throw(CORBA::SystemException)
+{
+ // Loop over input list and lookup each device.
+ CORBA::ULong listlen = slist.length();
+ for (CORBA::ULong i = 0; i < listlen; i++) {
+
+ AssetMap::iterator where; // Iterator for asset set
+ 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 = make_dref(m_poa.in(), where->first);
+ } 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 = make_dref(m_poa.in(), where->first);
+ } else {
+ // Further matches each append 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 = make_dref(m_poa.in(), where->first);
+ }
+ num_found++;
+
+ // Find next matching device with this key.
+ where = find_if(
+ ++where, m_assets.end(),
+ StrFinder(sc, search_str)
+ );
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------
+
+DeviceLocator_impl::
+DeviceLocator_impl(Controller_impl * ctrl) : m_ctrl(ctrl)
+{
+ // Intentionally empty
+}
+
+PortableServer::Servant
+DeviceLocator_impl::
+preinvoke(
+ const PortableServer::ObjectId & oid,
+ PortableServer::POA_ptr /* poa */,
+ const char * operation,
+ void * & /* cookie */,
+ CORBA_Environment &
+) throw(CORBA::SystemException, PortableServer::ForwardRequest)
+{
+ // Convert object id into asset number.
+ CORBA::String_var oid_string;
+ try {
+ oid_string = PortableServer::ObjectId_to_string(oid);
+ } catch (const CORBA::BAD_PARAM &) {
+ throw CORBA::OBJECT_NOT_EXIST();
+ }
+
+ if (strcmp(oid_string.in(), Controller_oid) == 0)
+ return m_ctrl;
+
+ istrstream istr(oid_string.in());
+ CCS::AssetType anum;
+ istr >> anum;
+ if (istr.fail())
+ throw CORBA::OBJECT_NOT_EXIST();
+
+ // Check whether the device is known.
+ if (!m_ctrl->exists(anum))
+ throw CORBA::OBJECT_NOT_EXIST();
+
+ // Look at the object map to find out whether
+ // we have a servant in memory.
+ Thermometer_impl * servant;
+ ActiveObjectMap::iterator servant_pos = m_aom.find(anum);
+ if (servant_pos == m_aom.end()) {
+ // No servant in memory. If evictor queue is full,
+ // evict servant at head of queue.
+ if (m_eq.size() == MAX_EQ_SIZE) {
+ servant = m_eq.back();
+ m_aom.erase(servant->m_anum);
+ m_eq.pop_back();
+ delete servant;
+ }
+ // Instantiate correct type of servant.
+ char buf[32];
+ assert(ICP_get(anum, "model", buf, sizeof(buf)) == 0);
+ if (strcmp(buf, "Sens-A-Temp") == 0)
+ servant = new Thermometer_impl(anum);
+ else
+ servant = new Thermostat_impl(anum);
+ } else {
+ // Servant already in memory.
+ servant = *(servant_pos->second); // Remember servant
+ m_eq.erase(servant_pos->second); // Remove from queue
+
+ // If operation is "remove", also remove entry from
+ // active object map -- the object is about to be deleted.
+ if (strcmp(operation, "remove") == 0)
+ m_aom.erase(servant_pos);
+ }
+
+ // We found a servant, or just instantiated it.
+ // If the operation is not a remove, move
+ // the servant to the tail of the evictor queue
+ // and update its queue position in the map.
+ if (strcmp(operation, "remove") != 0) {
+ m_eq.push_front(servant);
+ m_aom[anum] = m_eq.begin();
+ }
+
+ return servant;
+}
+
+//----------------------------------------------------------------
+
+int
+main(int argc, char * argv[])
+{
+ CORBA::ORB_var orb;
+
+ try {
+ // Initialize orb
+ 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.in());
+
+ // Get POA manager
+ PortableServer::POAManager_var poa_mgr = poa->the_POAManager();
+
+ // Create a policy list. We use persistent objects with
+ // user-assigned IDs, and explicit activation.
+ CORBA::PolicyList policy_list;
+ policy_list.length(6);
+ policy_list[0] = poa->create_lifespan_policy(
+ PortableServer::TRANSIENT // REVISIT
+ );
+ policy_list[1] = poa->create_id_assignment_policy(
+ PortableServer::USER_ID
+ );
+ policy_list[2] = poa->create_implicit_activation_policy(
+ PortableServer::NO_IMPLICIT_ACTIVATION
+ );
+ policy_list[3] = poa->create_request_processing_policy(
+ PortableServer::USE_SERVANT_MANAGER
+ );
+ policy_list[4] = poa->create_servant_retention_policy(
+ PortableServer::NON_RETAIN
+ );
+ policy_list[5] = poa->create_thread_policy(
+ PortableServer::SINGLE_THREAD_MODEL
+ );
+
+ // Create a POA for all CCS elements.
+ PortableServer::POA_var ccs_poa
+ = poa->create_POA("CCS_POA", poa_mgr.in(), policy_list);
+
+ // Create a controller and set static m_ctrl member
+ // for thermostats and thermometers.
+ Controller_impl ctrl_servant(ccs_poa.in(), "/tmp/CCS_assets");
+ Thermometer_impl::m_ctrl = &ctrl_servant;
+
+ // Create a reference for the controller and
+ // create the corresponding CORBA object.
+ PortableServer::ObjectId_var oid
+ = PortableServer::string_to_ObjectId(Controller_oid);
+ CORBA::Object_var ctrl
+ = ccs_poa->create_reference_with_id(
+ oid.in(), "IDL:acme.com/CCS/Controller:1.0"
+ );
+
+ // Get reference to initial naming context.
+ CosNaming::NamingContext_var inc
+ = resolve_init<CosNaming::NamingContext>(
+ orb.in(), "NameService"
+ );
+
+ // Attempt to create CCS context.
+ CosNaming::Name n;
+ n.length(1);
+ n[0].id = CORBA::string_dup("CCS");
+ try {
+ CosNaming::NamingContext_var nc
+ = inc->bind_new_context(n);
+ } catch (const CosNaming::NamingContext::AlreadyBound &) {
+ // Fine, CCS context already exists.
+ }
+
+ // Force binding of controller reference to make
+ // sure it is always up-to-date.
+ n.length(2);
+ n[1].id = CORBA::string_dup("Controller");
+ inc->rebind(n, ctrl.in());
+
+ // Instantiate the servant locator for devices.
+ DeviceLocator_impl my_locator(&ctrl_servant);
+ PortableServer::ServantManager_var locator
+ = my_locator._this();
+
+ // Set servant locator.
+ ccs_poa->set_servant_manager(locator.in());
+
+ // Activate the POA manager.
+ poa_mgr->activate();
+
+ // Accept requests
+ orb->run();
+ }
+ catch (const CORBA::Exception & e) {
+ cerr << "Uncaught CORBA exception: " << e << endl;
+ return 1;
+ }
+ catch (...) {
+ assert(0); // Uncaught exception, dump core
+ }
+ return 0;
+}
diff --git a/TAO/examples/Advanced/ch_18/server.h b/TAO/examples/Advanced/ch_18/server.h
new file mode 100644
index 00000000000..5eef5fe6300
--- /dev/null
+++ b/TAO/examples/Advanced/ch_18/server.h
@@ -0,0 +1,238 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_18
+//
+// = FILENAME
+// server.h
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+
+#ifndef server_HH_
+#define server_HH_
+
+#include "CCSS.h"
+#include "icp.h"
+#include <map>
+#include <list>
+//#include <assert.h>
+//#include <corba/poaS.h>
+
+
+class Controller_impl;
+
+class Thermometer_impl : public virtual POA_CCS::Thermometer {
+public:
+ // CORBA attributes
+ virtual CCS::ModelType model()
+ throw(CORBA::SystemException);
+ virtual CCS::AssetType asset_num()
+ throw(CORBA::SystemException);
+ virtual CCS::TempType temperature()
+ throw(CORBA::SystemException);
+ virtual CCS::LocType location()
+ throw(CORBA::SystemException);
+ virtual void location(const char *loc)
+ throw(CORBA::SystemException);
+ virtual void remove()
+ throw(CORBA::SystemException);
+
+ // Constructor & destructor
+ Thermometer_impl(CCS::AssetType anum);
+ virtual ~Thermometer_impl();
+
+ static Controller_impl * m_ctrl; // My controller
+ const CCS::AssetType m_anum; // My asset number
+
+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
+ 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);
+ 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::ThermostatSeq & tlist,
+ CORBA::Short delta
+ ) throw(
+ CORBA::SystemException,
+ CCS::Controller::EChange
+ );
+ virtual CCS::Thermometer_ptr
+ create_thermometer(
+ CCS::AssetType anum,
+ const char* loc
+ ) throw(
+ CORBA::SystemException,
+ CCS::Controller::DuplicateAsset
+ );
+ virtual CCS::Thermostat_ptr
+ create_thermostat(
+ CCS::AssetType anum,
+ const char* loc,
+ CCS::TempType temp
+ ) throw(
+ CORBA::SystemException,
+ CCS::Controller::DuplicateAsset,
+ CCS::Thermostat::BadTemp
+ );
+
+ // Constructor and destructor
+ Controller_impl(
+ PortableServer::POA_ptr poa,
+ const char * asset_file
+ ) throw(int);
+ virtual ~Controller_impl();
+
+ // Helper functions to allow access to the object map
+ void add_impl(
+ CCS::AssetType anum,
+ Thermometer_impl * tip
+ );
+ void remove_impl(CCS::AssetType anum);
+ bool exists(CCS::AssetType anum);
+
+private:
+ // Map of existing assets. The servant pointer is null
+ // the corresponding servant is not in memory.
+ typedef map<CCS::AssetType, Thermometer_impl *> AssetMap;
+ AssetMap m_assets;
+
+ // POA for thermometers and thermostats
+ PortableServer::POA_var m_poa;
+
+ // Name of asset number file
+ CORBA::String_var m_asset_file;
+
+ // 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(
+ CCS::Controller::SearchCriterion sc,
+ const char * str
+ ) : m_sc(sc), m_str(str) {}
+ bool operator()(
+ pair<const CCS::AssetType, Thermometer_impl *> & p
+ ) const
+ {
+ char buf[32];
+ switch (m_sc) {
+ case CCS::Controller::LOCATION:
+ ICP_get(p.first, "location", buf, sizeof(buf));
+ break;
+ case CCS::Controller::MODEL:
+ ICP_get(p.first, "model", buf, sizeof(buf));
+ break;
+ default:
+ assert(0); // Precondition violation
+ }
+ return strcmp(buf, m_str) == 0;
+ }
+ private:
+ CCS::Controller::SearchCriterion m_sc;
+ const char * m_str;
+ };
+};
+
+class DeviceLocator_impl :
+ public virtual POA_PortableServer::ServantLocator {
+public:
+ DeviceLocator_impl(Controller_impl * ctrl);
+
+ virtual PortableServer::Servant
+ preinvoke(
+ const PortableServer::ObjectId & oid,
+ PortableServer::POA_ptr poa,
+ const char * operation,
+ void * & cookie,
+ CORBA_Environment &
+ ) throw(
+ CORBA::SystemException,
+ PortableServer::ForwardRequest);
+ virtual void
+ postinvoke(
+ const PortableServer::ObjectId & /* oid */,
+ PortableServer::POA_ptr /* poa */,
+ const char * /* operation */,
+ void * /* cookie */,
+ PortableServer::Servant /* servant */,
+ CORBA_Environment &
+ ) throw(CORBA::SystemException) {}
+
+private:
+ Controller_impl * m_ctrl;
+
+ typedef list<Thermometer_impl *> EvictorQueue;
+ typedef map<CCS::AssetType, EvictorQueue::iterator>
+ ActiveObjectMap;
+
+ static const unsigned int MAX_EQ_SIZE = 100;
+ EvictorQueue m_eq;
+ ActiveObjectMap m_aom;
+
+ // Copy and assignment not supported
+ DeviceLocator_impl(const DeviceLocator_impl &);
+ void operator=(const DeviceLocator_impl &);
+};
+
+#endif
diff --git a/TAO/examples/Advanced/ch_3/CHANGES b/TAO/examples/Advanced/ch_3/CHANGES
new file mode 100644
index 00000000000..4185ef533a8
--- /dev/null
+++ b/TAO/examples/Advanced/ch_3/CHANGES
@@ -0,0 +1,47 @@
+$Id$
+
+Changelog for chapter 3 example in "Advanced CORBA Programming
+with C++" by Michi Henning and Steve Vinoski, Copyright 1999,
+Addison-Wesley, Reading, MA. The following changes have been made
+to the book's source code to make the example work with TAO and
+with various platforms and compilers.
+
+______________________________________________________________________________
+ESSENTIAL CHANGES:
+ 1. changed filenames .cc to .cpp and .hh h, and modified #includes in
+ client.cpp server.cpp and server.h appropriately.
+
+ 2. a) changed #include "time.h" to #include "timeC.h" in client.cpp
+
+ b) Moved standard #includes below local #includes, and commented-out
+ unnecessary #includes to avoid warnings and errors (g++)
+ -client.cpp now reads:
+ #include "timeC.h"
+ #include <iomanip.h>
+ // #include <iostream.h>
+ -server.cpp now reads:
+ #include "server.h"
+ // #include <time.h>
+ // #include <iostream.h>
+
+______________________________________________________________________________
+ADDITIONAL CHANGES:
+ 3. added .in() to _var type parameters
+ -3 times in client.cpp for calls to is_nil() and _narrow()
+ -3 times in main() in server.cpp for calls to _narrow(),
+ object_to_string, and <<
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TAO/examples/Advanced/ch_3/Makefile b/TAO/examples/Advanced/ch_3/Makefile
new file mode 100644
index 00000000000..4fb5a0eb2db
--- /dev/null
+++ b/TAO/examples/Advanced/ch_3/Makefile
@@ -0,0 +1,71 @@
+#----------------------------------------------------------------------------
+#
+# $Id$
+#
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Local macros
+#----------------------------------------------------------------------------
+
+ifndef TAO_ROOT
+ TAO_ROOT = $(ACE_ROOT)/TAO
+endif # ! TAO_ROOT
+
+
+
+LDLIBS = -lTAO
+IDL_SRC = timeC.cpp timeS.cpp
+IDL_HDR = timeC.h timeS.h
+
+PROG_SRCS = \
+ client.cpp \
+ server.cpp \
+
+SRC = $(IDL_SRC) $(PROG_SRCS)
+
+SIMPLE_CLT_OBJS = \
+ timeC.o \
+ timeS.o \
+ client.o
+
+SIMPLE_SVR_OBJS = \
+ timeC.o \
+ timeS.o \
+ server.o
+
+
+BIN = server \
+ client
+BUILD = $(BIN)
+
+#----------------------------------------------------------------------------
+# Include macros and targets
+#----------------------------------------------------------------------------
+
+include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU
+include $(ACE_ROOT)/include/makeinclude/macros.GNU
+include $(TAO_ROOT)/rules.tao.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.common.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.local.GNU
+include $(TAO_ROOT)/taoconfig.mk
+
+#----------------------------------------------------------------------------
+# Local targets
+#----------------------------------------------------------------------------
+.PRECIOUS: timeC.cpp timeC.i timeC.h
+.PRECIOUS: timeS.cpp timeS.i timeS.h
+.PRECIOUS: timeS_T.cpp timeS_T.i timeS_T.h
+
+server: $(addprefix $(VDIR),$(SIMPLE_SVR_OBJS))
+ $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK)
+
+client: $(addprefix $(VDIR),$(SIMPLE_CLT_OBJS))
+ $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK)
+
+realclean: clean
+ -/bin/$(RM) -rf timeC.* timeS.* timeS_T.* time.h
+
+# DO NOT DELETE THIS LINE -- g++dep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
diff --git a/TAO/examples/Advanced/ch_3/README b/TAO/examples/Advanced/ch_3/README
new file mode 100644
index 00000000000..e74eeb9bdf1
--- /dev/null
+++ b/TAO/examples/Advanced/ch_3/README
@@ -0,0 +1,42 @@
+$Id$
+
+Chapter 3 example.
+______________________________________________________________________________
+This example been taken from the book "Advanced CORBA Programming with C++"
+by Michi Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+MA. To make the examples work with TAO, some minor modifications to the
+source code have been made, with permission, by Mike Moran <mm4@cs.wustl.edu>.
+All of these changes are documented in the file CHANGES, in this directory.
+______________________________________________________________________________
+
+
+Summary:
+ This is the simple time server given in chapter 3 of the book.
+ There is a server process which holds a servant object which can return
+ the current Greenwich time, and a client process which can acess this
+ object.
+
+Building:
+ This example must be built with native C++ exceptions, and with an ACE/TAO
+ build with exceptions. Make sure to use TAO_FLAG Ge=0 to ensure
+ that CORBA::Environment variables are not created in the IDL generated
+ stubs and skeletons.
+
+ With GNU make, simply type
+
+ % make exceptions=1
+
+ to create the executable server and client
+
+server:
+ The server takes no parameters nor command line options and returns an
+ IOR to stdout. The server then waits infinitely for clients requests.
+
+client:
+ The client takes an IOR from the command line, prints out the current
+ time, and terminates.
+
+run_test.pl:
+ This is currently a UNIX only script! It starts up the server, redirecting
+ stdout to a file, then passes the file's contents to the command line of
+ the client. After the client terminates, the server is killed.
diff --git a/TAO/examples/Advanced/ch_3/client.cpp b/TAO/examples/Advanced/ch_3/client.cpp
new file mode 100644
index 00000000000..cfeffd08215
--- /dev/null
+++ b/TAO/examples/Advanced/ch_3/client.cpp
@@ -0,0 +1,67 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_3
+//
+// = FILENAME
+// client.cpp
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+#include "timeC.h"
+#include <iomanip.h>
+//#include <iostream.h>
+
+int
+main(int argc, char * argv[])
+{
+ try {
+ // Check arguments
+ if (argc != 2) {
+ cerr << "Usage: client IOR_string" << endl;
+ throw 0;
+ }
+
+ // Initialize orb
+ CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
+
+ // Destringify argv[1]
+ CORBA::Object_var obj = orb->string_to_object(argv[1]);
+ if (CORBA::is_nil(obj.in())) {
+ cerr << "Nil Time reference" << endl;
+ throw 0;
+ }
+
+ // Narrow
+ Time_var tm = Time::_narrow(obj.in());
+ if (CORBA::is_nil(tm.in())) {
+ cerr << "Argument is not a Time reference" << endl;
+ throw 0;
+ }
+
+ // Get time
+ TimeOfDay tod = tm->get_gmt();
+ cout << "Time in Greenwich is "
+ << setw(2) << setfill('0') << tod.hour << ":"
+ << setw(2) << setfill('0') << tod.minute << ":"
+ << setw(2) << setfill('0') << tod.second << endl;
+ }
+ catch (const CORBA::Exception &) {
+ cerr << "Uncaught CORBA exception" << endl;
+ return 1;
+ }
+ catch (...) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/TAO/examples/Advanced/ch_3/run_test.pl b/TAO/examples/Advanced/ch_3/run_test.pl
new file mode 100755
index 00000000000..74c52a910be
--- /dev/null
+++ b/TAO/examples/Advanced/ch_3/run_test.pl
@@ -0,0 +1,54 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib "../../../../bin";
+
+require ACEutils;
+require Process;
+
+$status = 0;
+$iorfile = "chapter_test.ior";
+unlink $iorfile;
+
+
+
+# Hacked call
+$server = Process::Create ("exec ".$EXEPREFIX."server".$EXE_EXT.">$iorfile",
+ "");
+# Proper call
+#$server = Process::Create ($EXEPREFIX."server".$EXE_EXT, ">$iorfile");
+
+if (ACE::waitforfile_timed ($iorfile, 15) == -1) {
+ print STDERR "ERROR: timedout waiting for file <$iorfile>\n";
+ $server->Kill (); $server->TimedWait (1);
+ exit 1;
+}
+
+open(ior_handle, "$iorfile");
+$ior_content = <ior_handle>;
+
+$client = Process::Create($EXEPREFIX."client$EXE_EXT", "$ior_content");
+
+if ($client->TimedWait (60) == -1) {
+ print STDERR "ERROR: client timedout\n";
+ $status = 1;
+ $client->Kill (); $client->TimedWait (1);
+}
+
+
+
+
+$server->Terminate ();
+if ($server->TimedWait (5) == -1) {
+ print STDERR "ERROR: cannot terminate the server\n";
+ $server->Kill (); $server->TimedWait (1);
+ $status = 1;
+}
+
+unlink $iorfile;
+
+exit $status;
diff --git a/TAO/examples/Advanced/ch_3/server.cpp b/TAO/examples/Advanced/ch_3/server.cpp
new file mode 100644
index 00000000000..d095f4e2d88
--- /dev/null
+++ b/TAO/examples/Advanced/ch_3/server.cpp
@@ -0,0 +1,89 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_3
+//
+// = FILENAME
+// server.cpp
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+#include "server.h"
+//#include <time.h>
+//#include <iostream.h>
+
+
+TimeOfDay
+Time_impl::
+get_gmt() throw(CORBA::SystemException)
+{
+ time_t time_now = time(0);
+ struct tm * time_p = gmtime(&time_now);
+
+ TimeOfDay tod;
+ tod.hour = time_p->tm_hour;
+ tod.minute = time_p->tm_min;
+ tod.second = time_p->tm_sec;
+
+ return tod;
+}
+// $Id$
+// Changelog for Henning and Vinoski's chapter 18 example
+// ______________________________________________________
+
+//-----------------------------------------------------------------------------
+
+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.in());
+
+ // Activate POA manager
+ PortableServer::POAManager_var mgr
+ = poa->the_POAManager();
+ mgr->activate();
+
+ // Create an object
+ Time_impl time_servant;
+
+ // Write its stringified reference to stdout
+ Time_var tm = time_servant._this();
+ CORBA::String_var str = orb->object_to_string(tm.in());
+ cout << str.in() << endl;
+
+ // Accept requests
+ orb->run();
+ }
+ catch (const CORBA::Exception &) {
+ cerr << "Uncaught CORBA exception" << endl;
+ return 1;
+ }
+ return 0;
+}
+
+
+
+
+
+
+
+
diff --git a/TAO/examples/Advanced/ch_3/server.h b/TAO/examples/Advanced/ch_3/server.h
new file mode 100644
index 00000000000..e7dfcd309c8
--- /dev/null
+++ b/TAO/examples/Advanced/ch_3/server.h
@@ -0,0 +1,31 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_3
+//
+// = FILENAME
+// server.h
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+#ifndef server_HH_
+#define server_HH_
+
+#include "timeS.h"
+
+class Time_impl : public virtual POA_Time {
+public:
+ virtual TimeOfDay get_gmt() throw(CORBA::SystemException);
+};
+
+#endif
diff --git a/TAO/examples/Advanced/ch_3/time.idl b/TAO/examples/Advanced/ch_3/time.idl
new file mode 100644
index 00000000000..a8e7e7080ac
--- /dev/null
+++ b/TAO/examples/Advanced/ch_3/time.idl
@@ -0,0 +1,31 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_3
+//
+// = FILENAME
+// time.idl
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+struct TimeOfDay {
+ short hour; // 0 - 23
+ short minute; // 0 - 59
+ short second; // 0 - 59
+};
+
+interface Time {
+ TimeOfDay get_gmt();
+};
+
diff --git a/TAO/examples/Advanced/ch_8_and_10/CCS.idl b/TAO/examples/Advanced/ch_8_and_10/CCS.idl
new file mode 100644
index 00000000000..7ab254d6eec
--- /dev/null
+++ b/TAO/examples/Advanced/ch_8_and_10/CCS.idl
@@ -0,0 +1,88 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_8_and_10
+//
+// = FILENAME
+// CCS.idl
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+#pragma prefix "acme.com"
+
+module CCS {
+ typedef unsigned long AssetType;
+ typedef string ModelType;
+ typedef short TempType;
+ typedef string LocType;
+
+ interface Thermometer {
+ readonly attribute ModelType model;
+ readonly attribute AssetType asset_num;
+ readonly attribute TempType temperature;
+ attribute LocType location;
+ };
+
+ interface Thermostat : Thermometer {
+ struct BtData {
+ TempType requested;
+ TempType min_permitted;
+ TempType max_permitted;
+ string error_msg;
+ };
+ exception BadTemp { BtData details; };
+
+ TempType get_nominal();
+ TempType set_nominal(in TempType new_temp)
+ raises(BadTemp);
+ };
+
+ interface Controller {
+ typedef sequence<Thermometer> ThermometerSeq;
+ typedef sequence<Thermostat> ThermostatSeq;
+
+ enum SearchCriterion { ASSET, LOCATION, MODEL };
+
+ union KeyType switch(SearchCriterion) {
+ case ASSET:
+ AssetType asset_num;
+ case LOCATION:
+ LocType loc;
+ case MODEL:
+ ModelType model_desc;
+ };
+
+ struct SearchType {
+ KeyType key;
+ Thermometer device;
+ };
+ typedef sequence<SearchType> SearchSeq;
+
+ struct ErrorDetails {
+ Thermostat tmstat_ref;
+ Thermostat::BtData info;
+ };
+ typedef sequence<ErrorDetails> ErrSeq;
+
+ exception EChange {
+ ErrSeq errors;
+ };
+
+ ThermometerSeq list();
+ void find(inout SearchSeq slist);
+ void change(
+ in ThermostatSeq tlist, in short delta
+ ) raises(EChange);
+ };
+};
diff --git a/TAO/examples/Advanced/ch_8_and_10/CHANGES b/TAO/examples/Advanced/ch_8_and_10/CHANGES
new file mode 100644
index 00000000000..b1454a1983d
--- /dev/null
+++ b/TAO/examples/Advanced/ch_8_and_10/CHANGES
@@ -0,0 +1,51 @@
+$Id$
+
+Changelog for chapter 8 and 10 example in "Advanced CORBA
+Programming with C++" by Michi Henning and Steve Vinoski,
+Copyright 1999, Addison-Wesley, Reading, MA. The following
+changes have been made to the book's source code to make the
+example work with TAO and with various platforms and compilers.
+
+_______________________________________________________________________________
+ESSENTIAL CHANGES:
+ 1. Changed filenames from .cc to .cpp and .hh to.h,
+ and modified #includes appropriatly
+
+ 2. a) Unnecessary standard includes of <iostreams.h> and <assert.h> must
+ be removed or moved to follow the local includes in
+ server.h, server.cpp, client.cpp, and icp.cpp.
+
+ b) The following files may need their includes further rearranged
+ to avoid warnings and errors (g++). The following orderings
+ seem to work fine:
+ -server.cpp: "server.h", <algorithm>, "icp.h"
+ -server.h: "CCSS.h", <map>
+
+ 3. removed if 0 code surrounding
+ operator<<(ostream & os, const CCS::Controller::EChange & ec)
+ definition in server.cpp and client.cpp.
+
+_______________________________________________________________________________
+ADDITIONAL CHANGES:
+ 4. Added .in() to _var parameters wherever needed:
+ -client.cpp:
+ -4 changes in operator<<(ostream & os, CCS::Thermometer_ptr t)
+ -6 changes in main(): 5 calls to is_nil(), 1 call to _narrow
+ -2 additions in main() of .inout() to _var parameters of set_temp().
+ Note: .inout() is functionally the same as .in() in this case
+
+ -server.cpp:
+ 3 changes in main()
+
+_______________________________________________________________________________
+TO DO:
+ -discrepancy in temperatures in my output vs. sample output
+ in book.
+_____________________________________________________
+
+
+
+
+
+
+
diff --git a/TAO/examples/Advanced/ch_8_and_10/Makefile b/TAO/examples/Advanced/ch_8_and_10/Makefile
new file mode 100644
index 00000000000..5557a433044
--- /dev/null
+++ b/TAO/examples/Advanced/ch_8_and_10/Makefile
@@ -0,0 +1,86 @@
+#----------------------------------------------------------------------------
+#
+# $Id$
+#
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Local macros
+#----------------------------------------------------------------------------
+
+ifndef TAO_ROOT
+ TAO_ROOT = $(ACE_ROOT)/TAO
+endif
+
+LDLIBS = -lTAO
+IDL_SRC = CCSC.cpp CCSS.cpp
+IDL_HDR = CCSC.h CCSS.h
+
+PROG_SRCS = \
+ client.cpp \
+ server.cpp \
+ icp.cpp
+
+SRC = $(IDL_SRC) $(PROG_SRCS)
+
+SIMPLE_CLT_OBJS = \
+ CCSC.o \
+ CCSS.o \
+ client.o
+
+SIMPLE_SVR_OBJS = \
+ CCSC.o \
+ CCSS.o \
+ server.o \
+ icp.o
+
+
+BIN = server \
+ client
+BUILD = $(BIN)
+VLDLIBS = $(LDLIBS:%=%$(VAR))
+VBIN = $(BIN:%=%$(VAR))
+
+#----------------------------------------------------------------------------
+# Include macros and targets
+#----------------------------------------------------------------------------
+
+include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU
+include $(ACE_ROOT)/include/makeinclude/macros.GNU
+include $(TAO_ROOT)/rules.tao.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.common.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.local.GNU
+include $(TAO_ROOT)/taoconfig.mk
+
+#----------------------------------------------------------------------------
+# Local targets
+#----------------------------------------------------------------------------
+LDFLAGS += -L$(TAO_ROOT)/orbsvcs/orbsvcs -L$(TAO_ROOT)/tao -L$(TAO_ROOT)/orbsvcs/Naming_Service
+CPPFLAGS += -I$(TAO_ROOT)/orbsvcs
+
+.PRECIOUS: CCSC.cpp CCSC.i CCSC.h
+.PRECIOUS: CCSS.cpp CCSS.i CCSS.h
+.PRECIOUS: CCSS_T.cpp CCSS_T.i CCSS_T.h
+
+override TAO_IDLFLAGS += -hc .hh -hs S.hh -hT S_T.hh \
+ -cs C.cc -ci C.i \
+ -ss S.cc -sT S_T.cc
+CCFLAGS += -fimplicit-templates -frtti -O0
+
+$(IDL_SRC): CCS.idl
+ $(TAO_ROOT)/TAO_IDL/tao_idl CCS.idl -hc .h -hs S.h -hT S_T.h \
+ -cs C.cpp \
+ -ss S.cpp -sT S_T.cpp
+server: $(addprefix $(VDIR),$(SIMPLE_SVR_OBJS))
+ $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK)
+
+client: $(addprefix $(VDIR),$(SIMPLE_CLT_OBJS))
+ $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK)
+
+realclean: clean
+ -/bin/$(RM) -rf CCSC.* CCSS.* CCSS_T.* CCS.h
+
+# DO NOT DELETE THIS LINE -- g++dep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
diff --git a/TAO/examples/Advanced/ch_8_and_10/README b/TAO/examples/Advanced/ch_8_and_10/README
new file mode 100644
index 00000000000..6b44902f1f6
--- /dev/null
+++ b/TAO/examples/Advanced/ch_8_and_10/README
@@ -0,0 +1,40 @@
+$Id$
+
+Chapters 8 and 10 example.
+______________________________________________________________________________
+This example been taken from the book "Advanced CORBA Programming with C++"
+by Michi Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+MA. To make the examples work with TAO, some minor modifications to the
+source code have been made, with permission, by Mike Moran <mm4@cs.wustl.edu>.
+All of these changes are documented in the file CHANGES, in this directory.
+______________________________________________________________________________
+
+
+Summary:
+ This is the most basic version of the climate control system presented
+ throughout the book. The client is presented in chapter 8 and the
+ server in chapter 10.
+
+Building:
+ This example must be built with native C++ exceptions, and with an ACE/TAO
+ build with exceptions. Make sure to use TAO_FLAG Ge=0 to ensure
+ that the IDL generated code uses c++ exceptions rather than creating
+ CORBA_Environment variables.
+
+ With GNU make, simply type
+ % make exceptions=1
+ to create the executable server and client.
+
+server:
+ The server takes no parameters nor command line options and returns an
+ IOR to stdout. The server then waits infinitely for clients requests.
+
+client:
+ The client takes an IOR from the command line, narrows this to a
+ controller reference, makes several remote calls on this controller, and
+ finally terminates.
+
+run_test.pl:
+ This is currently a UNIX only script! It starts up the server, redirecting
+ stdout to a file, then passes the file's contents to the command line of
+ the client. After the client terminates, the server is killed. \ No newline at end of file
diff --git a/TAO/examples/Advanced/ch_8_and_10/client.cpp b/TAO/examples/Advanced/ch_8_and_10/client.cpp
new file mode 100644
index 00000000000..79a848ae226
--- /dev/null
+++ b/TAO/examples/Advanced/ch_8_and_10/client.cpp
@@ -0,0 +1,265 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_8_and_10
+//
+// = FILENAME
+// client.cpp
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+
+#include "CCS.h" // ORB-specific
+//#include <iostream.h>
+
+// Show the details for a thermometer or thermostat.
+static ostream &
+operator<<(ostream & os, CCS::Thermometer_ptr t)
+{
+ // Check for nil.
+ if (CORBA::is_nil(t)) {
+ os << "Cannot show state for nil reference." << endl;
+ return os;
+ }
+
+ // Try to narrow and print what kind of device it is.
+ CCS::Thermostat_var tmstat = CCS::Thermostat::_narrow(t);
+ os << (CORBA::is_nil(tmstat.in()) ? "Thermometer:" : "Thermostat:")
+ << endl;
+
+ // Show attribute values.
+ CCS::ModelType_var model = t->model();
+ CCS::LocType_var location = t->location();
+ os << "\tAsset number: " << t->asset_num() << endl;
+ os << "\tModel : " << model.in() << endl;
+ os << "\tLocation : " << location.in() << endl;
+ os << "\tTemperature : " << t->temperature() << endl;
+
+ // If device is a thermostat, show nominal temperature.
+ if (!CORBA::is_nil(tmstat.in()))
+ os << "\tNominal temp: " << tmstat->get_nominal() << endl;
+ return os;
+}
+
+//----------------------------------------------------------------
+
+// Show the information in a BtData struct.
+
+static ostream &
+operator<<(ostream & os, const CCS::Thermostat::BtData & btd)
+{
+ os << "CCS::Thermostat::BtData details:" << endl;
+ os << "\trequested : " << btd.requested << endl;
+ os << "\tmin_permitted: " << btd.min_permitted << endl;
+ os << "\tmax_permitted: " << btd.max_permitted << endl;
+ os << "\terror_msg : " << btd.error_msg << endl;
+ return os;
+}
+
+//----------------------------------------------------------------
+
+// Loop over the sequence of records in an EChange exception and
+// show the details of each record.
+
+static ostream &
+operator<<(ostream & os, const CCS::Controller::EChange & ec)
+{
+ for (CORBA::ULong i = 0; i < ec.errors.length(); i++) {
+ os << "Change failed:" << endl;
+ os << ec.errors[i].tmstat_ref.in(); // Overloaded <<
+ os << ec.errors[i].info << endl; // Overloaded <<
+ }
+ return os;
+}
+
+//----------------------------------------------------------------
+
+// Generic ostream inserter for exceptions. Inserts the exception
+// name, if available, and the repository ID otherwise.
+
+// #if 0 // This inserter may or may not be needed for your ORB.
+
+static ostream &
+operator<<(ostream & os, const CORBA::Exception & e)
+{
+ CORBA::Any tmp;
+ tmp <<= e;
+
+ CORBA::TypeCode_var tc = tmp.type();
+ const char * p = tc->name();
+ if (*p != '\0')
+ os << p;
+ else
+ os << tc->id();
+ return os;
+}
+
+// #endif
+
+//----------------------------------------------------------------
+
+// Change the temperature of a thermostat.
+
+static void
+set_temp(CCS::Thermostat_ptr tmstat, CCS::TempType new_temp)
+{
+ if (CORBA::is_nil(tmstat)) // Don't call via nil reference
+ return;
+
+ CCS::AssetType anum = tmstat->asset_num();
+ try {
+ cout << "Setting thermostat " << anum
+ << " to " << new_temp << " degrees." << endl;
+ CCS::TempType old_nominal = tmstat->set_nominal(new_temp);
+ cout << "Old nominal temperature was: "
+ << old_nominal << endl;
+ cout << "New nominal temperature is: "
+ << tmstat->get_nominal() << endl;
+ } catch (const CCS::Thermostat::BadTemp & bt) {
+ cerr << "Setting of nominal temperature failed." << endl;
+ cerr << bt.details << endl; // Overloaded <<
+ }
+}
+
+//----------------------------------------------------------------
+
+int
+main(int argc, char * argv[])
+{
+ try {
+ // Initialize the ORB
+ CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
+
+ // Check arguments
+ if (argc != 2) {
+ cerr << "Usage: client IOR_string" << endl;
+ throw 0;
+ }
+
+ // Get controller reference from argv
+ // and convert to object.
+ CORBA::Object_var obj = orb->string_to_object(argv[1]);
+ if (CORBA::is_nil(obj.in())) {
+ cerr << "Nil controller reference" << endl;
+ throw 0;
+ }
+
+ // Try to narrow to CCS::Controller.
+ CCS::Controller_var ctrl;
+ try {
+ ctrl = CCS::Controller::_narrow(obj.in());
+ } catch (const CORBA::SystemException & se) {
+ cerr << "Cannot narrow controller reference: "
+ << se << endl;
+ throw 0;
+ }
+ if (CORBA::is_nil(ctrl.in())) {
+ cerr << "Wrong type for controller ref." << endl;
+ throw 0;
+ }
+
+ // Get list of devices
+ CCS::Controller::ThermometerSeq_var list = ctrl->list();
+
+ // Show number of devices.
+ CORBA::ULong len = list->length();
+ cout << "Controller has " << len << " device";
+ if (len != 1)
+ cout << "s";
+ cout << "." << endl;
+
+ // If there are no devices at all, we are finished.
+ if (len == 0)
+ return 0;
+
+ // Show details for each device.
+ for (CORBA::ULong i = 0; i < list->length(); i++)
+ cout << list[i].in();
+ cout << endl;
+
+ // Change the location of first device in the list
+ CCS::AssetType anum = list[0]->asset_num();
+ cout << "Changing location of device "
+ << anum << "." << endl;
+ list[0]->location("Earth");
+ // Check that the location was updated
+ cout << "New details for device "
+ << anum << " are:" << endl;
+ cout << list[0] << endl;
+
+ // Find first thermostat in list.
+ CCS::Thermostat_var tmstat;
+ for ( CORBA::ULong i = 0;
+ i < list->length() && CORBA::is_nil(tmstat.in());
+ i++) {
+ tmstat = CCS::Thermostat::_narrow(list[i]);
+ }
+
+ // Check that we found a thermostat on the list.
+ if (CORBA::is_nil(tmstat.in())) {
+ cout << "No thermostat devices in list." << endl;
+ } else {
+ // Set temperature of thermostat to
+ // 50 degrees (should work).
+ set_temp(tmstat.inout(), 50);
+ cout << endl;
+
+ // Set temperature of thermostat to
+ // -10 degrees (should fail).
+ set_temp(tmstat.inout(), -10);
+ }
+
+ // Look for device in Rooms Earth and HAL. This must
+ // locate at least one device because we earlier changed
+ // the location of the first device to Room Earth.
+ cout << "Looking for devices in Earth and HAL." << endl;
+ CCS::Controller::SearchSeq ss;
+ ss.length(2);
+ ss[0].key.loc(CORBA::string_dup("Earth"));
+ ss[1].key.loc(CORBA::string_dup("HAL"));
+ ctrl->find(ss);
+
+ // Show the devices found in that room.
+ for (CORBA::ULong i = 0; i < ss.length(); i++)
+ cout << ss[i].device.in(); // Overloaded <<
+ cout << endl;
+
+ // Increase the temperature of all thermostats
+ // by 40 degrees. First, make a new list (tss)
+ // containing only thermostats.
+ cout << "Increasing thermostats by 40 degrees." << endl;
+ CCS::Controller::ThermostatSeq tss;
+ for (CORBA::ULong i = 0; i < list->length(); i++) {
+ tmstat = CCS::Thermostat::_narrow(list[i]);
+ if (CORBA::is_nil(tmstat.in()))
+ continue; // Skip thermometers
+ len = tss.length();
+ tss.length(len + 1);
+ tss[len] = tmstat;
+ }
+
+ // Try to change all thermostats.
+ try {
+ ctrl->change(tss, 40);
+ } catch (const CCS::Controller::EChange & ec) {
+ cerr << ec; // Overloaded <<
+ }
+ } catch (const CORBA::Exception & e) {
+ cerr << "Uncaught CORBA exception: " << e << endl;
+ return 1;
+ } catch (...) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/TAO/examples/Advanced/ch_8_and_10/icp.cpp b/TAO/examples/Advanced/ch_8_and_10/icp.cpp
new file mode 100644
index 00000000000..968190249c7
--- /dev/null
+++ b/TAO/examples/Advanced/ch_8_and_10/icp.cpp
@@ -0,0 +1,300 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_8_and_10
+//
+// = FILENAME
+// icp.cpp
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+
+#include <string>
+#include <map>
+#include <algorithm>
+//#include <stdlib.h>
+#include "icp.h"
+
+//----------------------------------------------------------------
+
+enum DeviceType { thermometer, thermostat };
+
+struct DeviceState { // State for a device
+ DeviceType type;
+ const char * model;
+ string location;
+ short nominal_temp; // For thermostats only
+};
+typedef map<unsigned long, DeviceState> StateMap;
+
+//----------------------------------------------------------------
+
+const size_t MAXSTR = 32; // Max len of string including NUL
+
+const short MIN_TEMP = 40; // 40 F == 4.44 C
+const short MAX_TEMP = 90; // 90 F == 32.22 C
+const short DFLT_TEMP = 68; // 68 F == 20.00 C
+
+static StateMap dstate; // Map of known devices
+
+//----------------------------------------------------------------
+
+// ICP_online() simulates adding a new device to the network by
+// adding it to the dstate map.
+//
+// For this simple simulation, devices with odd asset numbers
+// are thermometers and devices with even asset numbers
+// are thermostats.
+//
+// Thermostats get an initial nominal temperature of DFLT_TEMP.
+// The location string is intentionally left blank because it
+// must be programmed by the controller after putting the device
+// on-line (as should be the nominal temperature).
+//
+// If a device with the specified ID is already on-line, the
+// return value is -1. A zero return value indicates success.
+
+extern "C"
+int
+ICP_online(unsigned long id)
+{
+ // Look for id in state map.
+ StateMap::iterator pos = dstate.find(id);
+ if (pos != dstate.end())
+ return -1; // Already exists
+
+ // Fill in state.
+ DeviceState ds;
+ ds.type = (id % 2) ? thermometer : thermostat;
+ ds.model = (ds.type == thermometer)
+ ? "Sens-A-Temp" : "Select-A-Temp";
+ ds.nominal_temp = DFLT_TEMP;
+
+ // Insert new device into map
+ dstate[id] = ds;
+
+ return 0;
+}
+
+//----------------------------------------------------------------
+
+// ICP_offline() simulates removing a device from the network by
+// removing it from the dstate map. If the device isn't known, the
+// return value is -1. A zero return value indicates success.
+
+extern "C"
+int
+ICP_offline(unsigned long id)
+{
+ // Look for id in state map
+ StateMap::iterator pos = dstate.find(id);
+ if (pos == dstate.end())
+ return -1; // No such device
+ dstate.erase(id);
+ return 0;
+}
+
+//----------------------------------------------------------------
+
+// vary_temp() simulates the variation in actual temperature
+// around a thermostat. The function randomly varies the
+// temperature as a percentage of calls as follows:
+//
+// 3 degrees too cold: 5%
+// 3 degrees too hot: 5%
+// 2 degrees too cold: 10%
+// 2 degrees too hot: 10%
+// 1 degree too cold: 15%
+// 1 degree too hot: 15%
+// exact temperature: 40%
+
+static
+short
+vary_temp(short temp)
+{
+ long r = lrand48() % 50;
+ long delta;
+ if (r < 5)
+ delta = 3;
+ else if (r < 15)
+ delta = 2;
+ else if (r < 30)
+ delta = 1;
+ else
+ delta = 0;
+ if (lrand48() % 2)
+ delta = -delta;
+ return temp + delta;
+}
+
+//----------------------------------------------------------------
+
+// Function object. Locates a thermostat that is in the same room
+// as the device at position pos.
+
+class ThermostatInSameRoom {
+public:
+ ThermostatInSameRoom(
+ const StateMap::iterator & pos
+ ) : m_pos(pos) {}
+ bool operator()(
+ pair<const unsigned long, DeviceState> & p
+ ) const
+ {
+ return(
+ p.second.type == thermostat
+ && p.second.location
+ == m_pos->second.location
+ );
+ }
+private:
+ const StateMap::iterator & m_pos;
+};
+
+//----------------------------------------------------------------
+
+// actual_temp() is a helper function to determine the actual
+// temperature returned by a particular thermometer or thermostat.
+// The pos argument indicates the device.
+//
+// The function locates all thermostats that are in the same room
+// as the device denoted by pos and computes the average of all
+// the thermostats' nominal temperatures. (If no thermostats are
+// in the same room as the device, the function assumes that the
+// average of the nominal temperatures is DFLT_TEMP.)
+//
+// The returned temperature varies from the average as
+// determined by vary_temp().
+
+static
+short
+actual_temp(const StateMap::iterator & pos)
+{
+ long sum = 0;
+ long count = 0;
+ StateMap::iterator where = find_if(
+ dstate.begin(), dstate.end(),
+ ThermostatInSameRoom(pos)
+ );
+ while (where != dstate.end()) {
+ count++;
+ sum += where->second.nominal_temp;
+ where = find_if(
+ ++where, dstate.end(),
+ ThermostatInSameRoom(pos)
+ );
+ }
+ return vary_temp(count == 0 ? DFLT_TEMP : sum / count);
+}
+
+//----------------------------------------------------------------
+
+// ICP_get() returns an attribute value of the device with the
+// given id. The attribute is named by the attr parameter. The
+// value is copied into the buffer pointed to by the value
+// pointer. The len parameter is the size of the passed buffer,
+// so ICP_get can avoid overrunning the buffer.
+//
+// By default, thermometers report a temperature that varies
+// somewhat around DFLT_TEMP. However, if there is another
+// thermostat in the same room as the thermometer, the
+// thermometer reports a temperature that varies around that
+// thermostat's temperature. For several thermostats that are in
+// the same room, the thermometer reports a temperature that
+// varies around the average nominal temperature of all the
+// thermostats.
+//
+// Attempts to read from a non-existent device or to read a
+// non-existent attribute return -1. A return value of zero
+// indicates success. If the supplied buffer is too short to hold
+// a value, ICP_get() silently truncates the value and
+// returns success.
+
+extern "C"
+int
+ICP_get(
+ unsigned long id,
+ const char * attr,
+ void * value,
+ size_t len)
+{
+ // Look for id in state map
+ StateMap::iterator pos = dstate.find(id);
+ if (pos == dstate.end())
+ return -1; // No such device
+
+ // Depending on the attribute, return the
+ // corresponding piece of state.
+ if (strcmp(attr, "model") == 0) {
+ strncpy((char *)value, pos->second.model, len);
+ } else if (strcmp(attr, "location") == 0) {
+ strncpy((char *)value, pos->second.location.c_str(), len);
+ } else if (strcmp(attr, "nominal_temp") == 0) {
+ if (pos->second.type != thermostat)
+ return -1; // Must be thermostat
+ memcpy(
+ value, &pos->second.nominal_temp,
+ min(len, sizeof(pos->second.nominal_temp))
+ );
+ } else if (strcmp(attr, "temperature") == 0) {
+ short temp = actual_temp(pos);
+ memcpy(value, &temp, min(len, sizeof(temp)));
+ } else if (strcmp(attr, "MIN_TEMP") == 0) {
+ memcpy(value, &MIN_TEMP, min(len, sizeof(MIN_TEMP)));
+ } else if (strcmp(attr, "MAX_TEMP") == 0) {
+ memcpy(value, &MAX_TEMP, min(len, sizeof(MAX_TEMP)));
+ } else {
+ return -1; // No such attribute
+ }
+ return 0; // OK
+}
+
+//----------------------------------------------------------------
+
+// ICP_set() sets the attribute specified by attr to the
+// value specified by value for the device with ID id. Attempts to
+// write a string longer than MAXSTR bytes (including the
+// terminating NUL) result in silent truncation of the string.
+// Attempts to access a non-existent device or attribute
+// return -1. Attempts to set a nominal temperature outside the
+// legal range also return -1. A zero return value
+// indicates success.
+
+extern "C"
+int
+ICP_set(unsigned long id, const char * attr, const void * value)
+{
+ // Look for id in state map
+ StateMap::iterator pos = dstate.find(id);
+ if (pos == dstate.end())
+ return -1; // No such device
+
+ // Change either location or nominal temp, depending on attr.
+ if (strcmp(attr, "location") == 0) {
+ pos->second.location.assign(
+ (const char *)value, MAXSTR - 1
+ );
+ } else if (strcmp(attr, "nominal_temp") == 0) {
+ if (pos->second.type != thermostat)
+ return -1; // Must be thermostat
+ short temp;
+ memcpy(&temp, value, sizeof(temp));
+ if (temp < MIN_TEMP || temp > MAX_TEMP)
+ return -1;
+ pos->second.nominal_temp = temp;
+ } else {
+ return -1; // No such attribute
+ }
+ return 0; // OK
+}
diff --git a/TAO/examples/Advanced/ch_8_and_10/icp.h b/TAO/examples/Advanced/ch_8_and_10/icp.h
new file mode 100644
index 00000000000..334a6416a77
--- /dev/null
+++ b/TAO/examples/Advanced/ch_8_and_10/icp.h
@@ -0,0 +1,41 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_8_and_10
+//
+// = FILENAME
+// icp.h
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+#ifndef _ICP_H
+#define _ICP_H
+
+extern "C" {
+ int ICP_online(unsigned long id); // Add device
+ int ICP_offline(unsigned long id); // Remove device
+ int ICP_get( // Get attribute
+ unsigned long id,
+ const char * attr,
+ void * value,
+ size_t len
+ );
+ int ICP_set( // Set attribute
+ unsigned long id,
+ const char * attr,
+ const void * value
+ );
+}
+
+#endif /* _ICP_H */
diff --git a/TAO/examples/Advanced/ch_8_and_10/run_test.pl b/TAO/examples/Advanced/ch_8_and_10/run_test.pl
new file mode 100755
index 00000000000..74c52a910be
--- /dev/null
+++ b/TAO/examples/Advanced/ch_8_and_10/run_test.pl
@@ -0,0 +1,54 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib "../../../../bin";
+
+require ACEutils;
+require Process;
+
+$status = 0;
+$iorfile = "chapter_test.ior";
+unlink $iorfile;
+
+
+
+# Hacked call
+$server = Process::Create ("exec ".$EXEPREFIX."server".$EXE_EXT.">$iorfile",
+ "");
+# Proper call
+#$server = Process::Create ($EXEPREFIX."server".$EXE_EXT, ">$iorfile");
+
+if (ACE::waitforfile_timed ($iorfile, 15) == -1) {
+ print STDERR "ERROR: timedout waiting for file <$iorfile>\n";
+ $server->Kill (); $server->TimedWait (1);
+ exit 1;
+}
+
+open(ior_handle, "$iorfile");
+$ior_content = <ior_handle>;
+
+$client = Process::Create($EXEPREFIX."client$EXE_EXT", "$ior_content");
+
+if ($client->TimedWait (60) == -1) {
+ print STDERR "ERROR: client timedout\n";
+ $status = 1;
+ $client->Kill (); $client->TimedWait (1);
+}
+
+
+
+
+$server->Terminate ();
+if ($server->TimedWait (5) == -1) {
+ print STDERR "ERROR: cannot terminate the server\n";
+ $server->Kill (); $server->TimedWait (1);
+ $status = 1;
+}
+
+unlink $iorfile;
+
+exit $status;
diff --git a/TAO/examples/Advanced/ch_8_and_10/server.cpp b/TAO/examples/Advanced/ch_8_and_10/server.cpp
new file mode 100644
index 00000000000..8e600dc794a
--- /dev/null
+++ b/TAO/examples/Advanced/ch_8_and_10/server.cpp
@@ -0,0 +1,464 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_8_and_10
+//
+// = FILENAME
+// server.cpp
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+#include "server.h"
+#include <algorithm>
+#include "icp.h"
+//#include <iostream.h>
+//#include <assert.h>
+//----------------------------------------------------------------
+
+
+// Generic ostream inserter for exceptions. Inserts the exception
+// name, if available, and the repository ID otherwise.
+
+// #if 0 This inserter may or may not be needed for your ORB.
+
+static ostream &
+operator<<(ostream & os, const CORBA::Exception & e)
+{
+ CORBA::Any tmp;
+ tmp <<= e;
+ CORBA::TypeCode_var tc = tmp.type();
+ const char * p = tc->name();
+ if (*p != '\0')
+ os << p;
+ else
+ os << tc->id();
+ return os;
+}
+
+// #endif
+
+//----------------------------------------------------------------
+
+Controller_impl * Thermometer_impl::m_ctrl; // static member
+
+// Helper function to read the model string from a device.
+
+CCS::ModelType
+Thermometer_impl::
+get_model()
+{
+ char buf[32];
+ assert(ICP_get(m_anum, "model", buf, sizeof(buf)) == 0);
+ return CORBA::string_dup(buf);
+}
+
+// Helper function to read the temperature from a device.
+
+CCS::TempType
+Thermometer_impl::
+get_temp()
+{
+ short temp;
+ assert(
+ ICP_get(m_anum, "temperature", &temp, sizeof(temp)
+ ) == 0);
+ return temp;
+}
+
+// Helper function to read the location from a device.
+
+CCS::LocType
+Thermometer_impl::
+get_loc()
+{
+ char buf[32];
+ assert(ICP_get(m_anum, "location", buf, sizeof(buf)) == 0);
+ return CORBA::string_dup(buf);
+}
+
+// Helper function to set the location of a device.
+
+void
+Thermometer_impl::
+set_loc(const char * loc)
+{
+ assert(ICP_set(m_anum, "location", loc) == 0);
+}
+
+// Constructor.
+
+Thermometer_impl::
+Thermometer_impl(
+ CCS::AssetType anum,
+ const char * location
+) : m_anum(anum)
+{
+ assert(ICP_online(anum) == 0); // Mark device as on-line
+ set_loc(location);
+ 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 (...) {
+ assert(0); // Prevent exceptions from escaping
+ }
+}
+
+// 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);
+}
+
+//----------------------------------------------------------------
+
+// Helper function to get a thermostat's nominal temperature.
+
+CCS::TempType
+Thermostat_impl::
+get_nominal_temp()
+{
+ short temp;
+ assert(
+ ICP_get(m_anum, "nominal_temp", &temp, sizeof(temp)
+ ) == 0);
+ 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.
+ assert(ICP_get(
+ m_anum, "nominal_temp",
+ &old_temp, sizeof(old_temp)
+ ) == 0
+ );
+
+ // 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.
+
+Thermostat_impl::
+Thermostat_impl(
+ CCS::AssetType anum,
+ 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)
+{
+ // 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; // Skip nil references
+
+ // 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;
+}
+
+// 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.
+ where = find_if(
+ ++where, m_assets.end(),
+ StrFinder(sc, search_str)
+ );
+ }
+ }
+ }
+ cerr << "end" << endl;
+}
+
+//----------------------------------------------------------------
+
+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.in());
+
+ // 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.in());
+ cout << str.in() << 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 (...) {
+ assert(0); // Unexpected exception, dump core
+ }
+ return 0;
+}
diff --git a/TAO/examples/Advanced/ch_8_and_10/server.h b/TAO/examples/Advanced/ch_8_and_10/server.h
new file mode 100644
index 00000000000..b94cb6e5d92
--- /dev/null
+++ b/TAO/examples/Advanced/ch_8_and_10/server.h
@@ -0,0 +1,167 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// TAO/examples/Advanced/ch_8_and_10
+//
+// = FILENAME
+// server.h
+//
+// = AUTHORS
+// Source code used in TAO has been modified and adapted from the code
+// provided in the book, "Advanced CORBA Programming with C++" by Michi
+// Henning and Steve Vinoski. Copyright 1999. Addison-Wesley, Reading,
+// MA.
+//
+// Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
+//
+// ============================================================================
+
+
+
+
+#ifndef server_HH_
+#define server_HH_
+
+#include "CCSS.h"
+#include <map>
+//#include <assert.h>
+
+
+class Controller_impl;
+
+class Thermometer_impl : public virtual POA_CCS::Thermometer {
+public:
+ // CORBA attributes
+ virtual CCS::ModelType model()
+ throw(CORBA::SystemException);
+ virtual CCS::AssetType asset_num()
+ throw(CORBA::SystemException);
+ virtual CCS::TempType temperature()
+ throw(CORBA::SystemException);
+ virtual CCS::LocType location()
+ throw(CORBA::SystemException);
+ virtual void 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:
+ const CCS::AssetType m_anum; // My asset number
+
+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
+ 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::ThermostatSeq & tlist,
+ CORBA::Short delta
+ ) throw(
+ CORBA::SystemException,
+ CCS::Controller::EChange
+ );
+
+ // Constructor and destructor
+ Controller_impl() {}
+ virtual ~Controller_impl() {}
+
+ // 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(
+ CCS::Controller::SearchCriterion sc,
+ 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:
+ assert(0); // Precondition violation
+ }
+ return 0; // Stops compiler warning
+ }
+ private:
+ CCS::Controller::SearchCriterion m_sc;
+ const char * m_str;
+ };
+};
+
+#endif
diff --git a/TAO/examples/Advanced/run_test.pl b/TAO/examples/Advanced/run_test.pl
new file mode 100755
index 00000000000..cab8085049f
--- /dev/null
+++ b/TAO/examples/Advanced/run_test.pl
@@ -0,0 +1,62 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib "../../../bin";
+require ACEutils;
+require Process;
+
+$status = 0;
+
+
+sub run_test_from_current_directory{
+ announce_test();
+ $test = Process::Create($EXEPREFIX."run_test.pl","");
+ wait_for_test_to_finish();
+}
+
+sub announce_test{
+ use Cwd;
+ $dir = cwd();
+ print STDOUT "__________________________________________________________ \n";
+ print STDOUT "**running test in $dir : \n";
+}
+
+sub wait_for_test_to_finish {
+ if ($test->TimedWait (60) == -1) {
+ print STDERR "ERROR: run_test.pl timedout\n";
+ $status = 1;
+ $test->Kill (); $test->TimedWait (1);
+ }
+}
+
+
+
+
+# change to each example's directory, and run their test
+chdir "ch_3" or die "can't cd to ch_3 $!\n";
+run_test_from_current_directory();
+
+chdir "../ch_8_and_10" or die "can't cd to ch_8_and_10 $!\n";
+run_test_from_current_directory();
+
+chdir "../ch_12" or die "can't cd to ch_12 $!\n";
+run_test_from_current_directory();
+
+chdir "../ch_18" or die "can't cd to ch_18 $!\n";
+run_test_from_current_directory();
+
+#chdir "../ch_19" or die "can't cd to ch_19 $!\n";
+#run_test_from_current_directory();
+
+#chdir "../ch_21" or die "can't cd to ch_21 $!\n";
+#run_test_from_current_directory();
+
+exit $status;
+
+
+
+