Changes to attempt to silence bcc64x
[ACE_TAO.git] / TAO / orbsvcs / tests / FT_App / FT_ReplicaFactory_i.cpp
blob72a0a959298d8285639a745e0b3ca7da69236cd2
1 /* -*- C++ -*- */
2 //=============================================================================
3 /**
4 * @file FT_ReplicaFactory_i.cpp
6 * This file is part of Fault Tolerant CORBA.
8 * @author Dale Wilson <wilson_d@ociweb.com>
9 */
10 //=============================================================================
11 #include "FT_ReplicaFactory_i.h"
12 #include "FT_TestReplica_i.h"
13 #include "ace/Get_Opt.h"
14 #include "ace/OS_NS_unistd.h"
15 #include "orbsvcs/CosNamingC.h"
16 #include "orbsvcs/PortableGroupC.h"
17 #include "orbsvcs/PortableGroup/PG_Property_Set.h"
19 // Use this macro at the beginning of CORBA methods
20 // to aid in debugging.
21 #define METHOD_ENTRY(name) \
22 ACE_DEBUG (( LM_DEBUG, \
23 "Enter %s\n", #name \
26 // Use this macro to return from CORBA methods
27 // to aid in debugging. Note that you can specify
28 // the return value after the macro, for example:
29 // METHOD_RETURN(Plugh::plover) xyzzy; is equivalent
30 // to return xyzzy;
31 // METHOD_RETURN(Plugh::troll); is equivalent to
32 // return;
33 // WARNING: THIS GENERATES TWO STATEMENTS!!! THE FOLLOWING
34 // will not do what you want it to:
35 // if (cave_is_closing) METHOD_RETURN(Plugh::pirate) aarrggh;
36 // Moral: Always use braces.
37 #define METHOD_RETURN(name) \
38 ACE_DEBUG (( LM_DEBUG, \
39 "Leave %s\n", #name \
40 )); \
41 return /* value goes here */
44 static const char * criterion_initial_value = "INITIAL_VALUE";
46 //////////////////////////////////////////////////////
47 // FT_ReplicaFactory_i Construction/destruction
49 FT_ReplicaFactory_i::FT_ReplicaFactory_i ()
50 : internals_ ()
51 , orb_ (CORBA::ORB::_nil ())
52 , poa_ (PortableServer::POA::_nil ())
53 , object_id_ ()
54 , ior_ ()
55 , ior_output_file_ (0)
56 , identity_ ()
57 , have_replication_manager_(0)
58 , replication_manager_(0)
59 , factory_registry_ior_(0)
60 , factory_registry_ (0)
61 , registered_(0)
62 , test_output_file_(0)
63 , ns_name_("")
64 , naming_context_ (CosNaming::NamingContext::_nil ())
65 , this_name_ ()
66 , roles_ ()
67 , location_ ("unknown")
68 , quit_on_idle_ (0)
69 , unregister_by_location_ (0)
70 , replicas_ ()
71 , empty_slots_(0)
72 , quit_requested_(0)
73 , name_persistent_file_(ACE_TEXT(""))
75 char const * repo_id =
76 FT_TEST::_tc_TestReplica->id ();
78 ACE_DEBUG ((LM_DEBUG,
79 "TestReplica type_id: %s\n",
80 repo_id));
82 // ACE_DEBUG((LM_DEBUG, "Hobbit type_id: %s\n", FT_TEST::_tc_Hobbit->id() ));
83 // ACE_DEBUG((LM_DEBUG, "Elf type_id: %s\n", FT_TEST::_tc_Elf->id() ));
84 // ACE_DEBUG((LM_DEBUG, "Human type_id: %s\n", FT_TEST::_tc_Human->id() ));
88 FT_ReplicaFactory_i::~FT_ReplicaFactory_i ()
91 ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
93 // be sure all replicas are gone
94 // before this object disappears
95 shutdown_i ();
99 ////////////////////////////////////////////
100 // FT_ReplicaFactory_i private methods
102 CORBA::ULong FT_ReplicaFactory_i::allocate_id()
104 // assume mutex is locked
105 CORBA::ULong id = this->replicas_.size();
106 if (this->empty_slots_ != 0)
108 for(CORBA::ULong pos = 0; pos < id; ++pos)
110 if (this->replicas_[pos] == 0)
112 id = pos;
116 else
118 this->replicas_.push_back(0);
119 this->empty_slots_ += 1;
121 return id;
124 void FT_ReplicaFactory_i::shutdown_i()
126 // assume mutex is locked
127 for (size_t nReplica = 0; nReplica < this->replicas_.size(); ++nReplica)
129 FT_TestReplica_i * replica = this->replicas_[nReplica];
130 if (replica != 0)
132 replica->request_quit();
137 int FT_ReplicaFactory_i::write_ior(const ACE_TCHAR * outputFile, const char * ior)
139 int result = -1;
140 FILE* out = ACE_OS::fopen (outputFile, "w");
141 if (out)
143 ACE_OS::fprintf (out, "%s", ior);
144 ACE_OS::fclose (out);
145 result = 0;
147 else
149 ACE_ERROR ((LM_ERROR,
150 "Open failed for %s\n", outputFile
153 return result;
156 //////////////////////////////////////////////////////
157 // FT_ReplicaFactory_i public, non-CORBA methods
159 int FT_ReplicaFactory_i::parse_args (int argc, ACE_TCHAR * argv[])
161 ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("o:n:f:i:l:t:p:qu"));
162 int c;
164 while ((c = get_opts ()) != -1)
166 switch (c)
168 case 'o':
170 this->ior_output_file_ = get_opts.opt_arg ();
171 break;
173 case 'n':
175 this->ns_name_ = ACE_TEXT_ALWAYS_CHAR(get_opts.opt_arg ());
176 break;
178 case 'f':
180 this->factory_registry_ior_ = get_opts.opt_arg ();
181 break;
183 case 'i':
185 this->roles_.push_back(ACE_TEXT_ALWAYS_CHAR(get_opts.opt_arg ()));
186 break;
188 case 'l':
190 this->location_ = ACE_TEXT_ALWAYS_CHAR(get_opts.opt_arg ());
191 break;
193 case 'q':
195 this->quit_on_idle_ = 1;
196 break;
198 case 'u':
200 this->unregister_by_location_ = 1;
201 break;
204 case 't':
206 this->test_output_file_ = get_opts.opt_arg ();
207 break;
209 case 'p':
211 this->name_persistent_file_ = get_opts.opt_arg ();
212 break;
215 case '?':
216 // fall thru
217 default:
218 ACE_ERROR_RETURN ((LM_ERROR,
219 "usage: %s\n"
220 " -o <factory ior file>\n"
221 " -n <naming service registration name>\n"
222 " -f <factory registry ior file>\n"
223 " -i <registration: role>\n"
224 " -l <registration: location>\n"
225 " -t <test replica ior file>\n"
226 " -p <name presistent file>\n"
227 " -u{nregister by location}\n"
228 " -q{uit on idle}\n",
229 argv [0]),
230 -1);
231 break;
234 // Indicates successful parsing of the command line
235 return 0;
238 const char * FT_ReplicaFactory_i::location () const
240 return this->location_.c_str ();
243 const ACE_TCHAR * FT_ReplicaFactory_i::identity () const
245 return this->identity_.c_str();
248 int FT_ReplicaFactory_i::idle (int & result)
250 result = 0;
251 size_t replicaCount = this->replicas_.size();
252 if (replicaCount != this->empty_slots_)
254 for (size_t nReplica = 0; result == 0 && nReplica < replicaCount; ++nReplica)
256 FT_TestReplica_i * replica = this->replicas_[nReplica];
257 if (replica != 0)
259 // give the replica's idle processing a change
260 // ignore the return status (the replica should shut itself down
261 // unless result is non-zero.
262 // non-zero result means panic.
263 replica->idle(result);
268 int quit = (this->quit_requested_ || result != 0);
269 if (!quit && this->replicas_.size() == this->empty_slots_)
271 /* if you re-enable this, add some kind of throttle to avoid noise.
272 ACE_ERROR (( LM_ERROR,
273 "ReplicaFactory is idle.\n"
276 if (this->quit_on_idle_ && this->empty_slots_ != 0)
278 ACE_ERROR (( LM_ERROR,
279 "%s exits due to quit on idle option.\n",
280 identity()
282 quit = 1;
286 return quit;
290 int FT_ReplicaFactory_i::init (CORBA::ORB_ptr orb)
292 int result = 0;
294 this->orb_ = CORBA::ORB::_duplicate (orb);
296 // Use the ROOT POA for now
297 CORBA::Object_var poa_object =
298 this->orb_->resolve_initial_references (TAO_OBJID_ROOTPOA);
300 if (CORBA::is_nil (poa_object.in ()))
302 ACE_ERROR_RETURN ((LM_ERROR,
303 ACE_TEXT (" (%P|%t) Unable to initialize the POA.\n")),
304 -1);
307 // Get the POA object.
308 this->poa_ =
309 PortableServer::POA::_narrow (poa_object.in ());
311 if (CORBA::is_nil(this->poa_.in ()))
313 ACE_ERROR_RETURN ((LM_ERROR,
314 ACE_TEXT (" (%P|%t) Unable to narrow the POA.\n")),
315 -1);
318 PortableServer::POAManager_var poa_manager =
319 this->poa_->the_POAManager ();
321 poa_manager->activate ();
323 // Register with the POA.
325 this->object_id_ = this->poa_->activate_object (this);
327 CORBA::Object_var this_obj =
328 this->poa_->id_to_reference (object_id_.in ());
330 this->ior_ = this->orb_->object_to_string (this_obj.in ());
332 if (this->factory_registry_ior_ != 0)
334 if (ACE_OS::strcmp (this->factory_registry_ior_, ACE_TEXT("none")) != 0)
336 CORBA::Object_var reg_obj = this->orb_->string_to_object(factory_registry_ior_);
337 this->factory_registry_ = ::PortableGroup::FactoryRegistry::_narrow(reg_obj.in ());
338 if (CORBA::is_nil(this->factory_registry_.in ()))
340 ACE_ERROR (( LM_ERROR,
341 "Can't resolve Factory Registry IOR %s\n",
342 this->factory_registry_ior_
344 result = -1;
348 else // no -f option. Try RIR(RM)
350 ///////////////////////////////
351 // Find the ReplicationManager
354 CORBA::Object_var rm_obj = orb->resolve_initial_references("ReplicationManager");
355 this->replication_manager_ = ::FT::ReplicationManager::_narrow(rm_obj.in());
356 if (!CORBA::is_nil (replication_manager_.in ()))
358 this->have_replication_manager_ = 1;
359 // empty criteria
360 ::PortableGroup::Criteria criteria;
361 this->factory_registry_ = this->replication_manager_->get_factory_registry(criteria);
362 if (CORBA::is_nil (this->factory_registry_.in ()))
364 ACE_ERROR ((LM_ERROR,"ReplicaFactory: ReplicationManager failed to return FactoryRegistry. Factory will not be registered.\n" ));
367 else
369 this->factory_registry_ = ::PortableGroup::FactoryRegistry::_narrow(rm_obj.in());
370 if (!CORBA::is_nil(this->factory_registry_.in ()))
372 ACE_DEBUG ((LM_DEBUG,"Found a FactoryRegistry DBA ReplicationManager\n" ));
374 else
376 ACE_ERROR ((LM_ERROR,"ReplicaFactory: Can't resolve ReplicationManager.\n" ));
380 catch (const CORBA::Exception& ex)
382 if (this->test_output_file_ == 0) // ignore if this is a test run
384 ex._tao_print_exception (
385 "ReplicaFactory: Exception resolving ReplicationManager. Factory will not be registered.\n");
391 if ( ! CORBA::is_nil (this->factory_registry_.in ()))
393 size_t roleCount = roles_.size();
394 for (size_t nRole = 0; nRole < roleCount; ++nRole)
396 const char * roleName = this->roles_[nRole].c_str();
398 PortableGroup::FactoryInfo info;
399 info.the_factory = ::PortableGroup::GenericFactory::_narrow(this_obj.in ());
400 info.the_location.length(1);
401 info.the_location[0].id = CORBA::string_dup(this->location_.c_str ());
402 info.the_criteria.length(1);
403 info.the_criteria[0].nam.length(1);
404 info.the_criteria[0].nam[0].id = CORBA::string_dup(PortableGroup::role_criterion);
405 info.the_criteria[0].val <<= CORBA::string_dup(roleName);
407 ACE_ERROR (( LM_INFO,
408 "Factory: %s@%C registering with factory registry\n",
409 roleName,
410 location_.c_str ()
413 char const * replica_repository_id =
414 FT_TEST::_tc_TestReplica->id ();
416 this->factory_registry_->register_factory(
417 roleName,
418 replica_repository_id,
419 info);
421 this->registered_ = 1;
424 int identified = 0; // bool
426 if (this->roles_.size() > 0)
428 this->identity_ = ACE_TEXT("Factory");
429 if (this->location_.length () != 0)
431 this->identity_ += ACE_TEXT("@");
432 this->identity_ += ACE_TEXT_CHAR_TO_TCHAR(this->location_.c_str ());
434 identified = 1;
437 if (this->ior_output_file_ != 0)
439 if (!identified)
441 this->identity_ = ACE_TEXT("file:");
442 this->identity_ += this->ior_output_file_;
443 // note: don't set identified--ns identity overrides file identitiy
445 result = write_ior (this->ior_output_file_, this->ior_. in ());
447 else
449 if (this->registered_)
451 // if we didn't register with a FactoryRegistry
452 // and no IOR file specified,
453 // then always try to register with name service
454 this->ns_name_ = "FT_ReplicaFactory";
458 if (this->ns_name_.length () != 0)
460 if (!identified)
462 this->identity_ = ACE_TEXT("name:");
463 this->identity_ += ACE_TEXT_CHAR_TO_TCHAR(this->ns_name_.c_str ());
466 CORBA::Object_var naming_obj =
467 this->orb_->resolve_initial_references ("NameService");
469 if (CORBA::is_nil(naming_obj.in ())){
470 ACE_ERROR_RETURN ((LM_ERROR,
471 "%T %n (%P|%t) Unable to find the Naming Service\n"),
475 this->naming_context_ =
476 CosNaming::NamingContext::_narrow (naming_obj.in ());
478 this->this_name_.length (1);
479 this->this_name_[0].id = CORBA::string_dup (this->ns_name_.c_str ());
481 this->naming_context_->rebind (this->this_name_, this_obj.in());
484 // if we're testing. Create a replica at startup time
485 if (this->test_output_file_ != 0)
487 // shouldn't be necessary, but create_replica assumes this
488 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->internals_, 1);
489 FT_TestReplica_i * replica = create_replica ("test");
491 PortableServer::POA_var poa = replica->_default_POA ();
492 ::CORBA::Object_var replica_obj = poa->servant_to_reference(replica);
493 ::CORBA::String_var replicaIOR = this->orb_->object_to_string(replica_obj.in ());
494 write_ior (this->test_output_file_, replicaIOR.in ());
497 return result;
500 int FT_ReplicaFactory_i::fini ()
502 if (this->ior_output_file_ != 0)
504 ACE_OS::unlink (this->ior_output_file_);
505 this->ior_output_file_ = 0;
507 if (this->ns_name_.length () != 0)
509 this->naming_context_->unbind (this_name_);
510 this->ns_name_.clear ();
513 if (registered_)
515 registered_ = 0;
517 if (this->unregister_by_location_)
519 ACE_ERROR (( LM_INFO,
520 "%s: unregistering all factories at %C\n",
521 identity(),
522 location_.c_str ()
525 PortableGroup::Location location(1);
526 location.length(1);
527 location[0].id = CORBA::string_dup(location_.c_str ());
528 this->factory_registry_->unregister_factory_by_location (
529 location);
531 else
533 size_t roleCount = roles_.size();
534 for (size_t nRole = 0; nRole < roleCount; ++nRole)
536 const char * roleName = this->roles_[nRole].c_str();
537 ACE_ERROR (( LM_INFO,
538 "Factory for: %s@%C unregistering from factory registry\n",
539 roleName,
540 location_.c_str ()
543 PortableGroup::Location location(1);
544 location.length(1);
545 location[0].id = CORBA::string_dup(location_.c_str ());
546 this->factory_registry_->unregister_factory (
547 roleName,
548 location);
553 return 0;
557 void FT_ReplicaFactory_i::remove_replica(CORBA::ULong id, FT_TestReplica_i * replica)
559 ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
560 if (id < this->replicas_.size())
562 if(this->replicas_[id] == replica)
564 replica->fini();
565 delete replica;
566 this->replicas_[id] = 0;
567 this->empty_slots_ += 1;
569 else
571 ACE_ERROR (( LM_ERROR,
572 "Remove replica %d mismatch.\n",
573 static_cast<int> (id)
577 else
579 ACE_ERROR (( LM_ERROR,
580 "Attempt to remove invalid replica %d. Limit %d.\n",
581 static_cast<int> (id),
582 static_cast<int> (this->replicas_.size())
587 //////////////////////////////////////////
588 // FT_ReplicaFactory_i CORBA methods
590 CORBA::Object_ptr FT_ReplicaFactory_i::create_object (
591 const char * type_id,
592 const PortableGroup::Criteria & the_criteria,
593 PortableGroup::GenericFactory::FactoryCreationId_out factory_creation_id)
595 METHOD_ENTRY(FT_ReplicaFactory_i::create_object);
596 ACE_UNUSED_ARG (type_id);
597 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->internals_, CORBA::Object::_nil ());
599 ::TAO::PG_Property_Set decoder (the_criteria);
601 // boolean, becomes true if a required parameter is missing
602 int missingParameter = 0;
603 const char * missingParameterName = 0;
605 CORBA::Long initialValue = 0;
606 if (! ::TAO::find (decoder, criterion_initial_value, initialValue) )
608 // not required. Otherwise:
609 // missingParameter = 1;
610 // missingParameterName = criterion_initial_value;
613 const char * role = "replica";
614 if (! ::TAO::find (decoder, PortableGroup::role_criterion, role) )
616 ACE_ERROR((LM_INFO,
617 "Property \"%s\" not found?\n", PortableGroup::role_criterion
619 // not required. Otherwise:
620 // missingParameter = 1;
621 // missingParameterName = PortableGroup::role_criterion;
624 if (missingParameter)
626 ACE_ERROR ((LM_ERROR,
627 "Throwing 'InvalidCriteria' due to missing %s\n",
628 missingParameterName
630 throw PortableGroup::InvalidCriteria();
633 FT_TestReplica_i * replica = create_replica(role);
634 if (replica == 0)
636 ACE_ERROR ((LM_ERROR,
637 "New Replica_i returned NULL. Throwing ObjectNotCreated.\n"
639 throw PortableGroup::ObjectNotCreated();
642 ACE_NEW_THROW_EX ( factory_creation_id,
643 PortableGroup::GenericFactory::FactoryCreationId,
644 PortableGroup::ObjectNotCreated());
645 CORBA::ULong factory_id = replica->factory_id();
646 (*factory_creation_id) <<= factory_id;
648 ACE_ERROR ((LM_INFO,
649 "Created %s@%C#%d.\n", role, this->location_.c_str (), static_cast<int> (factory_id)
653 ::CORBA::Object_ptr replica_obj =
654 replica->_default_POA()->servant_to_reference(replica);
655 METHOD_RETURN(FT_ReplicaFactory_i::create_object) replica_obj->_duplicate(replica_obj);
658 FT_TestReplica_i * FT_ReplicaFactory_i::create_replica(const char * name)
660 // assume mutex is locked
661 CORBA::ULong factoryId = allocate_id();
663 FT_TestReplica_i * pFTReplica = 0;
665 ACE_NEW_NORETURN(pFTReplica, FT_TestReplica_i(
666 this,
667 name,
668 factoryId
671 this->replicas_[factoryId] = pFTReplica;
672 this->empty_slots_ -= 1;
674 pFTReplica->init (this->orb_, this->name_persistent_file_);
675 return pFTReplica;
678 void FT_ReplicaFactory_i::delete_object (
679 const PortableGroup::GenericFactory::FactoryCreationId & factory_creation_id)
681 METHOD_ENTRY(FT_ReplicaFactory_i::delete_object);
683 ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
685 CORBA::ULong factoryId;
686 factory_creation_id >>= factoryId;
687 if (factoryId < this->replicas_.size())
689 if(this->replicas_[factoryId] != 0)
691 this->replicas_[factoryId]->request_quit();
693 else
695 throw ::PortableGroup::ObjectNotFound();
698 else
700 throw ::PortableGroup::ObjectNotFound();
702 METHOD_RETURN(FT_ReplicaFactory_i::delete_object);
705 CORBA::Boolean FT_ReplicaFactory_i::is_alive ()
707 METHOD_RETURN(FT_ReplicaFactory_i::is_alive)
708 true;
711 void FT_ReplicaFactory_i::shutdown ()
713 METHOD_ENTRY(FT_FaultDetectorFactory_i::shutdown);
714 ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
715 shutdown_i ();
716 this->quit_requested_ = 1;
717 METHOD_RETURN(FT_FaultDetectorFactory_i::shutdown);