Changes to attempt to silence bcc64x
[ACE_TAO.git] / TAO / examples / Advanced / ch_12 / icp.cpp
blob25fa92c8557c54b9e21f096b9aa6bed9c0cedf3e
2 //=============================================================================
3 /**
4 * @file icp.cpp
6 * @author Source code used in TAO has been modified and adapted from thecode provided in the book
7 * @author "Advanced CORBA Programming with C++"by Michi Henning and Steve Vinoski. Copyright1999. Addison-Wesley
8 * @author Reading
9 * @author MA. Used with permission ofAddison-Wesley.Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
11 //=============================================================================
14 #include <string>
15 #include <map>
16 #include <algorithm>
17 #include <iostream>
18 #include "icp.h"
20 using namespace std;
22 // The following header is #included automatically by ACE+TAO.
23 // Therefore, they don't need to be included explicitly.
24 //#include <stdlib.h>
26 enum DeviceType { thermometer, thermostat };
28 struct DeviceState
29 { // State for a device
30 DeviceType type;
31 const char *model;
32 string location;
33 short nominal_temp; // For thermostats only
36 typedef map<unsigned long, DeviceState> StateMap;
38 const size_t MAXSTR = 32; // Max len of string including NUL
40 const long MIN_TEMP = 40; // 40 F == 4.44 C
41 const long MAX_TEMP = 90; // 90 F == 32.22 C
42 const long DFLT_TEMP = 68; // 68 F == 20.00 C
44 static StateMap dstate; // Map of known devices
46 // ICP_online () simulates adding a new device to the network by
47 // adding it to the dstate map.
49 // For this simple simulation, devices with odd asset numbers
50 // are thermometers and devices with even asset numbers
51 // are thermostats.
53 // Thermostats get an initial nominal temperature of DFLT_TEMP.
54 // The location string is intentionally left blank because it
55 // must be programmed by the controller after putting the device
56 // on-line (as should be the nominal temperature).
58 // If a device with the specified ID is already on-line, the
59 // return value is -1. A zero return value indicates success.
61 extern "C"
62 int
63 ICP_online (unsigned long id)
65 // Look for id in state map.
66 StateMap::iterator pos = dstate.find (id);
67 if (pos != dstate.end ())
68 return -1; // Already exists
70 // Fill in state.
71 DeviceState ds;
72 ds.type = (id % 2) ? thermometer : thermostat;
73 ds.model = (ds.type == thermometer)
74 ? "Sens-A-Temp" : "Select-A-Temp";
75 ds.nominal_temp = DFLT_TEMP;
77 // Insert new device into map
78 dstate[id] = ds;
80 return 0;
83 // ICP_offline () simulates removing a device from the network by
84 // removing it from the dstate map. If the device isn't known, the
85 // return value is -1. A zero return value indicates success.
87 extern "C"
88 int
89 ICP_offline (unsigned long id)
91 // Look for id in state map
92 StateMap::iterator pos = dstate.find (id);
94 if (pos == dstate.end ())
95 return -1; // No such device
96 dstate.erase (id);
97 return 0;
100 // vary_temp () simulates the variation in actual temperature around a
101 // thermostat.The function randomly varies the temperature as a
102 // percentage of calls as follows:
104 // 3 degrees too cold: 5%
105 // 3 degrees too hot: 5%
106 // 2 degrees too cold: 10%
107 // 2 degrees too hot: 10%
108 // 1 degree too cold: 15%
109 // 1 degree too hot: 15%
110 // exact temperature: 40%
112 static
113 long
114 vary_temp (long temp)
116 long r = ACE_OS::rand() % 50;
117 long delta;
118 if (r < 5)
119 delta = 3;
120 else if (r < 15)
121 delta = 2;
122 else if (r < 30)
123 delta = 1;
124 else
125 delta = 0;
127 if (ACE_OS::rand() % 2)
128 delta = -delta;
129 return temp + delta;
132 // Function object. Locates a thermostat that is in the same room as
133 // the device at position pos.
135 class ThermostatInSameRoom
137 public:
138 ThermostatInSameRoom (const StateMap::iterator &pos):
139 m_pos (pos) {}
140 bool operator () (pair<const unsigned long, DeviceState> &p) const
142 return p.second.type == thermostat
143 && p.second.location == m_pos->second.location;
145 private:
146 const StateMap::iterator & m_pos;
149 // actual_temp () is a helper function to determine the actual
150 // temperature returned by a particular thermometer or thermostat.
151 // The pos argument indicates the device.
153 // The function locates all thermostats that are in the same room
154 // as the device denoted by pos and computes the average of all
155 // the thermostats' nominal temperatures. (If no thermostats are
156 // in the same room as the device, the function assumes that the
157 // average of the nominal temperatures is DFLT_TEMP.)
159 // The returned temperature varies from the average as
160 // determined by vary_temp ().
162 static
163 long
164 actual_temp (const StateMap::iterator & pos)
166 long sum = 0;
167 long count = 0;
168 StateMap::iterator where = std::find_if (dstate.begin (), dstate.end (),
169 ThermostatInSameRoom (pos));
170 while (where != dstate.end ())
172 count++;
173 sum += where->second.nominal_temp;
174 where = std::find_if (++where, dstate.end (),
175 ThermostatInSameRoom (pos));
178 return vary_temp (count == 0 ? DFLT_TEMP : sum / count);
181 //---------------------------------------------------------------
183 // ICP_get () returns an attribute value of the device with the given
184 // id. The attribute is named by the attr parameter. The value is
185 // copied into the buffer pointed to by the value pointer. The len
186 // parameter is the size of the passed buffer, so ICP_get can avoid
187 // overrunning the buffer.
189 // By default, thermometers report a temperature that varies somewhat
190 // around DFLT_TEMP. However, if there is another thermostat in the
191 // same room as the the thermometer, the thermometer reports a
192 // temperature that varies around that thermostat's temperature. For
193 // several thermostats that are in the same room, the thermometer
194 // reports around the average nominal temperature of all the
195 // thermostats.
197 // Attempts to read from a non-existent device or to read a
198 // non-existent attribute return -1. A return value of zero indicates
199 // success. If the supplied buffer is too short to hold a value,
200 // ICP_get () silently truncates the value and returns success.
202 extern "C"
204 ICP_get (unsigned long id,
205 const char * attr,
206 void *value,
207 size_t len)
209 // Look for id in state map
210 StateMap::iterator pos = dstate.find (id);
211 if (pos == dstate.end ())
212 return -1; // No such device
214 // Depending on the attribute, return the
215 // corresponding piece of state.
216 if (ACE_OS::strcmp (attr, "model") == 0)
218 ACE_OS::strncpy ( (char *)value, pos->second.model, len);
220 else if (ACE_OS::strcmp (attr, "location") == 0)
222 ACE_OS::strncpy ( (char *)value, pos->second.location.c_str (), len);
224 else if (ACE_OS::strcmp (attr, "nominal_temp") == 0)
226 if (pos->second.type != thermostat)
227 return -1; // Must be thermostat
228 ACE_OS::memcpy (value, &pos->second.nominal_temp,
229 ace_min (len, sizeof (pos->second.nominal_temp)));
231 else if (ACE_OS::strcmp (attr, "temperature") == 0)
233 long temp = actual_temp (pos);
234 ACE_OS::memcpy (value, &temp, ace_min (len, sizeof (temp)));
236 else if (ACE_OS::strcmp (attr, "MIN_TEMP") == 0)
238 ACE_OS::memcpy (value, &MIN_TEMP, ace_min (len, sizeof (MIN_TEMP)));
240 else if (ACE_OS::strcmp (attr, "MAX_TEMP") == 0)
242 ACE_OS::memcpy (value, &MAX_TEMP, ace_min (len, sizeof (MAX_TEMP)));
244 else
246 return -1; // No such attribute
248 return 0; // OK
251 // ICP_set () sets the the attributed specified by attr to the value
252 // specified by value for the device with ID id. Attempts to write a
253 // string longer than MAXSTR bytes (including the terminating NUL)
254 // result in silent truncation of the string. Attempts to access a
255 // non-existent device or attribute return -1. Attempts to set a
256 // nominal temperature outside the legal range also return -1. A zero
257 // return value indicates success.
259 extern "C"
261 ICP_set (unsigned long id, const char * attr, const void * value)
263 // Look for id in state map
264 StateMap::iterator pos = dstate.find (id);
265 if (pos == dstate.end ())
266 return -1; // No such device
268 // Change either location or nominal temp, depending on attr.
269 if (ACE_OS::strcmp (attr, "location") == 0)
271 pos->second.location.assign ((const char *)value, MAXSTR - 1);
273 else if (ACE_OS::strcmp (attr, "nominal_temp") == 0)
275 if (pos->second.type != thermostat)
276 return -1; // Must be thermostat
277 short temp;
278 ACE_OS::memcpy (&temp, value, sizeof (temp));
279 if (temp < MIN_TEMP || temp > MAX_TEMP)
280 return -1;
281 pos->second.nominal_temp = temp;
283 else
285 return -1; // No such attribute
287 return 0; // OK
290 #include <fstream>
292 class ICP_Persist
294 public:
295 ICP_Persist (const char *file);
296 ~ICP_Persist ();
297 private:
298 string m_filename;
301 // Read device state from a file and initialize the dstate map.
303 ICP_Persist::
304 ICP_Persist (const char *file)
305 : m_filename (file)
307 // Open input file, creating it if necessary.
308 std::ifstream db (m_filename.c_str (), std::ios::in|std::ios::out);//, 0666);
309 if (!db)
311 std::cerr << "Error opening " << m_filename << std::endl;
312 ACE_OS::exit (1);
315 // Read device details, one attribute per line.
316 DeviceState ds;
317 unsigned long id;
318 while (db >> id)
320 // Read device type and set model string accordingly.
321 int dtype;
322 db >> dtype;
323 ds.type = dtype == thermometer
324 ? thermometer : thermostat;
325 ds.model = dtype == thermometer
326 ? "Sens-A-Temp" : "Select-A-Temp";
327 char loc[MAXSTR];
328 db.get (loc[0]); // Skip newline
329 db.getline (loc, sizeof (loc)); // Read location
330 ds.location = loc;
331 if (ds.type == thermostat)
332 db >> ds.nominal_temp; // Read temperature
333 dstate[id] = ds; // Add entry to map
336 //db.close ();
337 //if (!db) {
338 // cerr << "Error closing " << m_filename << endl;
339 // exit (1);
343 // Write device state to the file.
345 ICP_Persist::
346 ~ICP_Persist ()
348 std::cout<<"~ICP_Persist"<<std::endl;///////////////////////
349 // Open input file, truncating it.
350 ofstream db (m_filename.c_str ());
351 if (!db)
353 std::cerr << "Error opening " << m_filename << std::endl;
354 ACE_OS::exit (1);
357 // Write the state details for each device.
358 StateMap::iterator i;
359 for (i = dstate.begin (); i != dstate.end (); i++)
361 db << i->first << std::endl;
362 db << (unsigned long) (i->second.type) << std::endl;
363 db << i->second.location << std::endl;
364 if (i->second.type == thermostat)
365 db << i->second.nominal_temp << std::endl;
367 if (!db)
369 std::cerr << "Error writing " << m_filename << std::endl;
370 ACE_OS::exit (1);
373 db.close ();
374 if (!db)
376 std::cerr << "Error closing " << m_filename << std::endl;
377 ACE_OS::exit (1);
381 // Instantiate a single global instance of the class.
382 static ICP_Persist mydb ("/tmp/CCS_DB");