Merge pull request #1551 from DOCGroup/plm_jira_333
[ACE_TAO.git] / TAO / orbsvcs / tests / FT_App / FT_TestReplica_i.cpp
blob1fcbb23dda101f02347b245e82d898179138101f
1 /* -*- C++ -*- */
2 //=============================================================================
3 /**
4 * @file FT_TestReplica_i.cpp
6 * Implements CORBA interface TestReplica.
8 * @author Dale Wilson <wilson_d@ociweb.com>
9 */
10 //=============================================================================
13 #include "FT_TestReplica_i.h"
14 #include "FT_ReplicaFactory_i.h"
15 #include "tao/ORB_Constants.h"
16 #include "FT_TestReplicaC.h"
17 // FUZZ: disable check_for_streams_include
18 #include "ace/streams.h"
19 #include "ace/OS_NS_stdio.h"
21 //////////////////
22 // TestReplica_i
24 namespace
26 /**
27 * Endian neutral store of long into indexable object.
28 * BUFFER can be sequence of Octet, unsigned char[], etc.
30 * TODO: Find this a good home.
32 * @param state an object that supports char & operator[] (size_t index);
33 * @param offset is the position within state where the first character should be stored.
34 * @param value is the data to be inserted into state.
36 template<typename BUFFER>
37 void storeLong(BUFFER & state, size_t offset, long value)
39 state[offset ] = static_cast<unsigned char> (value >> 24);
40 state[offset + 1] = static_cast<unsigned char> (value >> 16);
41 state[offset + 2] = static_cast<unsigned char> (value >> 8);
42 state[offset + 3] = static_cast<unsigned char> (value );
45 /**
46 * Endian neutral load of long from indexable object.
47 * BUFFER can be sequence of Octet, unsigned char[], etc.
49 * TODO: Find this a good home.
51 * @param state an object that supports const char & operator[] (size_t index) const;
52 * @param offset is the position within state where the first character can be found
53 * @returns value is the data loaded from state.
55 template<typename BUFFER>
56 long loadLong(const BUFFER & state, size_t offset)
58 long result
59 = ((state[offset ] & 0xFF) << 24)
60 | ((state[offset + 1] & 0xFF) << 16)
61 | ((state[offset + 2] & 0xFF) << 8)
62 | ((state[offset + 3] & 0xFF) );
63 return result;
67 // NO_RESPONSE ->no reinvocation
69 #define FAULT_CODE CORBA::TRANSIENT
71 // Macros to simplify suicide.
72 #define KEVORKIAN(value, method) \
73 if (this->death_pending_ == (FT_TEST::TestReplica::value)){ \
74 suicide (#value " in method " #method); \
75 throw FAULT_CODE ( \
76 CORBA::SystemException::_tao_minor_code ( \
77 TAO::VMCID, \
78 EFAULT), \
79 CORBA::COMPLETED_NO); \
82 #define KEVORKIAN_DURING(method) \
83 if (this->death_pending_ == FT_TEST::TestReplica::BEFORE_REPLY ){\
84 suicide ("read-only method " #method); \
85 throw FAULT_CODE ( \
86 CORBA::SystemException::_tao_minor_code ( \
87 TAO::VMCID, \
88 EFAULT), \
89 CORBA::COMPLETED_NO); \
92 #define KEVORKIAN_RETURN(value, method, result) \
93 if (this->death_pending_ == (FT_TEST::TestReplica::value)){ \
94 suicide (#value " in method " #method); \
95 throw FAULT_CODE ( \
96 CORBA::SystemException::_tao_minor_code ( \
97 TAO::VMCID, \
98 EFAULT), \
99 CORBA::COMPLETED_NO); \
102 #define KEVORKIAN_DURING_RETURN(method, result) \
103 if (this->death_pending_ == FT_TEST::TestReplica::BEFORE_REPLY ){\
104 suicide ("read-only method " #method); \
105 throw FAULT_CODE ( \
106 CORBA::SystemException::_tao_minor_code ( \
107 TAO::VMCID, \
108 EFAULT), \
109 CORBA::COMPLETED_NO); \
113 //////////////////////////////////////////////////
114 // class FT_TestReplica_i construction/destruction
116 FT_TestReplica_i::FT_TestReplica_i (FT_ReplicaFactory_i * factory, const char * name, unsigned long factory_id)
117 : death_pending_ (FT_TEST::TestReplica::NOT_YET)
118 , verbose_ (1)
119 , name_ (name)
120 , factory_id_ (factory_id)
121 , factory_ (factory)
122 , orb_ (0)
123 , poa_ (0)
124 , object_id_ (0)
125 , name_persistent_storage (0)
127 // cout << name_.c_str() << '@' << this->factory_->location() << '#' << this->factory_id_ << " Construct" << endl;
130 FT_TestReplica_i::~FT_TestReplica_i ()
132 // cout << name_.c_str() << '@' << this->factory_->location() << '#' << this->factory_id_ << " Destruct" << endl;
136 void FT_TestReplica_i::suicide(const char * note)
138 ACE_OS::fprintf (stdout, "%s@%s#%lu Simulate FAULT_CODE fault: %s\n",
139 name_.c_str(), this->factory_->location(), this->factory_id_, note);
141 // Tell the poa we aren't accepting future calls
142 this->poa_->deactivate_object (this->object_id_.in ());
145 /////////////////////////////////////////////////////
146 // class FT_TestReplica_i public, non-CORBA interface
150 //static
151 const char * FT_TestReplica_i::repository_id()
154 const char * id =
155 FT_TEST::_tc_TestReplica->id();
157 return id;
161 FT_TestReplica_i::parse_args (int argc, ACE_TCHAR *argv[])
163 ACE_UNUSED_ARG (argc);
164 ACE_UNUSED_ARG (argv);
165 return 0;
168 //static
169 const char *
170 FT_TestReplica_i::usage_options()
172 return "";
175 unsigned long FT_TestReplica_i::factory_id()const
177 return this->factory_id_;
180 ::PortableServer::POA_ptr FT_TestReplica_i::_default_POA (void)
182 return ::PortableServer::POA::_duplicate(this->poa_.in ());
185 PortableServer::ObjectId FT_TestReplica_i::object_id()const
187 return this->object_id_.in();
192 * Initialize this object.
193 * @param orbManager our ORB -- we keep var to it.
194 * @return zero for success; nonzero is process return code for failure.
196 int FT_TestReplica_i::init (CORBA::ORB_var & orb, const ACE_TCHAR* file_persistent)
198 this->orb_ = orb;
200 this->name_persistent_storage = file_persistent;
202 // Use the ROOT POA for now
203 CORBA::Object_var poa_object =
204 this->orb_->resolve_initial_references (TAO_OBJID_ROOTPOA);
206 if (CORBA::is_nil (poa_object.in ()))
207 ACE_ERROR_RETURN ((LM_ERROR,
208 ACE_TEXT (" (%P|%t) Unable to initialize the POA.\n")),
209 -1);
211 // Get the POA object.
212 this->poa_ =
213 PortableServer::POA::_narrow (poa_object.in ());
216 if (CORBA::is_nil(this->poa_.in ()))
218 ACE_ERROR_RETURN ((LM_ERROR,
219 ACE_TEXT (" (%P|%t) Unable to narrow the POA.\n")),
220 -1);
223 PortableServer::POAManager_var poa_manager =
224 this->poa_->the_POAManager ();
226 poa_manager->activate ();
229 // Register with the POA.
231 this->object_id_ = this->poa_->activate_object (this);
233 return 0;
236 void FT_TestReplica_i::_remove_ref (void)
238 //////////////////////////////////////////////////
239 // WARNING: The following call invokes fini then deletes this object
240 this->factory_->remove_replica(this->factory_id_, this);
243 int FT_TestReplica_i::fini (void)
245 return 0;
250 /////////////////////////////////////////////////////
251 // class FT_TestReplica_i: PullMonitorable interface
252 CORBA::Boolean FT_TestReplica_i::is_alive (void)
254 KEVORKIAN_RETURN(DURING_IS_ALIVE, is_alive, 0)
255 ACE_ERROR ((LM_ERROR,
256 "%s@%s#%d: is_alive: %d\n",
257 this->name_.c_str(),
258 this->factory_->location(),
259 this->factory_id_,
260 (this->death_pending_ != FT_TEST::TestReplica::DENY_IS_ALIVE)
263 return this->death_pending_ != FT_TEST::TestReplica::DENY_IS_ALIVE;
266 /////////////////////////////////////////////////////
267 // class FT_TestReplica_i: Updateable interface
268 FT::State * FT_TestReplica_i::get_update (void)
270 KEVORKIAN_RETURN(DURING_GET_UPDATE, get_update, 0)
271 long counter = load();
272 ::FT::State_var vState = new ::FT::State;
273 vState->length(sizeof(counter));
274 storeLong(vState, 0, counter);
275 return vState._retn();
278 void FT_TestReplica_i::set_update (const FT::State & s)
280 #if defined(FT_TEST_LACKS_UPDATE)
281 throw FT::InvalidUpdate ();
282 #else // FT_TEST_LACKS_UPDATE
283 KEVORKIAN(BEFORE_SET_UPDATE, set_update)
284 long counter = loadLong<FT::State>(s, 0);
285 store(counter);
286 KEVORKIAN(AFTER_SET_UPDATE, set_update)
287 #endif // FT_TEST_LACKS_UPDATE
290 /////////////////////////////////////////////////////
291 // class FT_TestReplica_i: Checkpointable interface
292 ::FT::State * FT_TestReplica_i::get_state (void)
294 #if defined(FT_TEST_LACKS_STATE)
295 throw FT::NoStateAvailable ();
296 #else // FT_TEST_LACKS_STATE
297 KEVORKIAN_RETURN(DURING_GET_STATE, get_state, 0)
298 long counter = load();
299 ::FT::State_var vState = new ::FT::State;
300 vState->length(sizeof(counter));
301 storeLong(vState, 0, counter);
302 return vState._retn();
303 #endif // FT_TEST_LACKS_STATE
306 void FT_TestReplica_i::set_state (const FT::State & s)
308 #if defined(FT_TEST_LACKS_STATE)
309 throw FT::InvalidState ();
310 #else // FT_TEST_LACKS_STATE
311 KEVORKIAN(BEFORE_SET_STATE, set_state)
312 long counter = loadLong<FT::State>(s, 0);
313 store(counter);
314 KEVORKIAN(AFTER_SET_STATE, set_state)
315 #endif // FT_TEST_LACKS_STATE
318 void FT_TestReplica_i::tao_update_object_group (
319 const char * iogr,
320 PortableGroup::ObjectGroupRefVersion version,
321 CORBA::Boolean is_primary
324 ACE_UNUSED_ARG (iogr);
325 ACE_UNUSED_ARG (version);
326 ACE_UNUSED_ARG (is_primary);
328 throw CORBA::NO_IMPLEMENT();
331 //////////////////////////////
332 // implement FT_TEST::Replica
334 void FT_TestReplica_i::set (CORBA::Long value)
336 KEVORKIAN(BEFORE_STATE_CHANGE, set)
337 long counter = value;
338 store(counter);
339 KEVORKIAN(BEFORE_REPLY, set)
342 CORBA::Long FT_TestReplica_i::increment (CORBA::Long delta)
344 KEVORKIAN_RETURN(BEFORE_STATE_CHANGE, increment, 0)
345 long counter = load ();
346 counter += delta;
347 store (counter);
348 KEVORKIAN_RETURN(BEFORE_REPLY, increment, 0)
349 return counter;
352 CORBA::Long FT_TestReplica_i::get (void)
354 KEVORKIAN_DURING_RETURN(get, 0)
355 long counter = load ();
356 return counter;
359 CORBA::Long FT_TestReplica_i::counter (void)
361 KEVORKIAN_DURING_RETURN([get]counter, 0)
362 long counter = load ();
363 return counter;
366 void FT_TestReplica_i::counter (CORBA::Long counter)
368 KEVORKIAN(BEFORE_STATE_CHANGE, [set]counter)
369 store (counter);
370 KEVORKIAN(BEFORE_REPLY, [set]counter)
373 void FT_TestReplica_i::die (FT_TEST::TestReplica::Bane when)
375 ACE_OS::fprintf (stdout, "%s@%s#%lu Received death threat: %d\n",
376 name_.c_str(), this->factory_->location(), this->factory_id_, when);
378 this->death_pending_ = when;
379 KEVORKIAN(RIGHT_NOW, die)
382 void FT_TestReplica_i::shutdown (void)
384 ACE_OS::fprintf (stdout, "%s@%s#%lu Shut down requested\n",
385 name_.c_str(), this->factory_->location(), this->factory_id_);
386 this->death_pending_ = FT_TEST::TestReplica::CLEAN_EXIT;
389 //////////////////////////////////////////////
390 // FT_TestReplica_i public non-CORBA interface
391 int FT_TestReplica_i::idle (int & result)
393 int quit = 0;
394 if (this->death_pending_ == FT_TEST::TestReplica::WHILE_IDLE)
396 ACE_ERROR ((LM_ERROR,
397 "%s@%s#%d: Simulated fault WHILE_IDLE",
398 this->name_.c_str(),
399 this->factory_->location(),
400 static_cast<int> (this->factory_id_ )
402 this->poa_->deactivate_object (this->object_id_.in ());
403 result = 0;
404 quit = 1;
406 else if (this->death_pending_ == FT_TEST::TestReplica::CLEAN_EXIT)
408 this->poa_->deactivate_object (this->object_id_.in ());
409 result = 0;
410 quit = 1;
412 return quit;
415 void FT_TestReplica_i::request_quit()
417 this->death_pending_ = FT_TEST::TestReplica::WHILE_IDLE;
421 void FT_TestReplica_i::store(long counter)
423 FILE * f = ACE_OS::fopen(this->name_persistent_storage, "w");
424 if(f != 0)
426 unsigned char* buffer = 0;
427 ACE_NEW (buffer, unsigned char [sizeof(long)]);
428 storeLong(buffer, 0, counter);
429 ACE_OS::fwrite(buffer, 1, sizeof(long), f);
430 ACE_OS::fclose(f);
431 if (this->verbose_)
433 ACE_OS::fprintf (stdout, "%s@%s#%lu :%ld\n",
434 name_.c_str(), this->factory_->location(), this->factory_id_, counter);
436 delete[] buffer;
437 buffer = 0;
441 long FT_TestReplica_i::load ()
443 long counter = 0;
444 FILE * f = ACE_OS::fopen(this->name_persistent_storage,"r");
445 if(f != 0)
447 unsigned char buffer[sizeof(long)];
448 ACE_OS::fread(buffer, 1, sizeof(long), f);
449 ACE_OS::fclose(f);
450 counter = loadLong<unsigned char *>(buffer, 0);
452 return counter;