// -*- C++ -*- #include "AsyncListManager.h" #include "Iterator.h" #include "Locator_Repository.h" #include "ImR_Locator_i.h" #include "orbsvcs/Log_Macros.h" //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- AsyncListManager::AsyncListManager (const Locator_Repository *repo, PortableServer::POA_ptr poa, LiveCheck *pinger) :repo_ (repo), poa_ (PortableServer::POA::_duplicate (poa)), primary_ (ImplementationRepository::AMH_AdministrationResponseHandler::_nil ()), secondary_ (ImplementationRepository::AMH_ServerInformationIteratorResponseHandler::_nil ()), pinger_ (pinger), server_list_ (0), first_ (0), how_many_ (0), waiters_ (0), refcount_ (1), lock_ () { } AsyncListManager::~AsyncListManager (void) { if (ImR_Locator_i::debug() > 4) { ORBSVCS_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) AsyncListManager(%@)::dtor\n"), this)); } } PortableServer::POA_ptr AsyncListManager::poa (void) { return PortableServer::POA::_duplicate (this->poa_.in()); } void AsyncListManager::init_list (void) { CORBA::ULong len = static_cast (this->repo_->servers ().current_size ()); Locator_Repository::SIMap::ENTRY* entry = 0; Locator_Repository::SIMap::CONST_ITERATOR it (this->repo_->servers ()); this->server_list_.length (len); this->waiters_ = 0; for (CORBA::ULong i = 0; i < len; i++) { it.next (entry); it.advance (); Server_Info_Ptr info = entry->int_id_; info->setImRInfo (&this->server_list_[i]); if (this->pinger_ != 0) { ListLiveListener *l = 0; ACE_NEW (l, ListLiveListener (info->ping_id (), info->pid, i, this, *this->pinger_)); LiveListener_ptr llp (l); if (!l->start ()) { this->server_list_[i].activeStatus = ImplementationRepository::ACTIVE_NO; l->cancel (); } else { if (!evaluate_status (i, l->status(), info->pid)) { this->waiters_++; } else { l->cancel (); } } } } if (ImR_Locator_i::debug() > 4) { ORBSVCS_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) AsyncListManager(%@)::init_list, <%d> waiters") ACE_TEXT (" out of <%d> registered servers\n"), this, this->waiters_, len)); } } bool AsyncListManager::make_iterator (ImplementationRepository::ServerInformationIterator_out si, CORBA::ULong start) { si = ImplementationRepository::ServerInformationIterator::_nil (); try { ImR_AsyncIterator* imr_iter = 0; ACE_NEW_THROW_EX (imr_iter, ImR_AsyncIterator (start, this), CORBA::NO_MEMORY ()); PortableServer::ServantBase_var tmp (imr_iter); PortableServer::ObjectId_var id = this->poa_->activate_object (imr_iter); CORBA::Object_var obj = this->poa_->id_to_reference (id.in ()); si = ImplementationRepository:: ServerInformationIterator::_unchecked_narrow (obj.in ()); return true; } catch (const CORBA::SystemException& ex) { ex._tao_print_exception ("AsyncListManager:final state constructing iterator\n"); ImplementationRepository::AMH_AdministrationExceptionHolder h (ex._tao_duplicate()); try { this->primary_->list_excep (&h); } catch (const CORBA::Exception& ex2) { ex2._tao_print_exception ("AsyncListManager:final calling list_excep\n"); } } catch (const CORBA::UserException& ex) { ex._tao_print_exception ("AsyncListManager:final state constructing iterator\n"); ImplementationRepository::AMH_AdministrationExceptionHolder h (new CORBA::INTERNAL); try { this->primary_->list_excep (&h); } catch (const CORBA::Exception& ex2) { ex2._tao_print_exception ("AsyncListManager:final calling list_excep\n"); } } return false; } void AsyncListManager::final_state (void) { if (ImR_Locator_i::debug() > 4) { ORBSVCS_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) AsyncListManager(%@)::final_state, ") ACE_TEXT ("waiters count = %d, has pinger? %d\n"), this, this->waiters_, (this->pinger_ != 0))); } if (this->pinger_ != 0 && this->waiters_ > 0) { return; } bool excepted = false; CORBA::ULong const len = this->server_list_.length (); ImplementationRepository::ServerInformationList alt_list (this->how_many_); ImplementationRepository::ServerInformationList *sil = &this->server_list_; if (this->first_ > 0 || this->how_many_ < len) { alt_list.length (this->how_many_); for (CORBA::ULong i = 0; i < this->how_many_; i++) { alt_list[i] = this->server_list_[i + this->first_]; } sil = &alt_list; } if (!CORBA::is_nil (this->primary_.in ())) { ImplementationRepository::ServerInformationIterator_var server_iterator; if (sil != &this->server_list_) { excepted = !this->make_iterator (server_iterator.out(), this->how_many_); } else { server_iterator = ImplementationRepository::ServerInformationIterator::_nil (); } if (!excepted) { try { this->primary_->list (*sil, server_iterator.in ()); } catch (const CORBA::Exception &ex) { ex._tao_print_exception ("AsyncListManager:final state sending list\n"); ImplementationRepository::AMH_AdministrationExceptionHolder h (ex._tao_duplicate()); this->primary_->list_excep (&h); } } this->primary_ = ImplementationRepository::AMH_AdministrationResponseHandler::_nil (); } else if (!CORBA::is_nil (this->secondary_.in())) { CORBA::Boolean done = this->first_ + sil->length() == len; try { this->secondary_->next_n (done, *sil); } catch (const CORBA::Exception &ex) { ex._tao_print_exception ("AsyncListManager:final state sending secondary list\n"); ImplementationRepository::AMH_ServerInformationIteratorExceptionHolder h (ex._tao_duplicate()); this->secondary_->next_n_excep (&h); } this->secondary_ = ImplementationRepository::AMH_ServerInformationIteratorResponseHandler::_nil (); } } CORBA::ULong AsyncListManager::list (ImplementationRepository::AMH_ServerInformationIteratorResponseHandler_ptr _tao_rh, CORBA::ULong start, CORBA::ULong count) { this->secondary_ = ImplementationRepository::AMH_ServerInformationIteratorResponseHandler::_duplicate (_tao_rh); this->list_i (start, count); return this->first_ + this->how_many_; } void AsyncListManager::list (ImplementationRepository::AMH_AdministrationResponseHandler_ptr _tao_rh, CORBA::ULong count) { this->primary_ = ImplementationRepository::AMH_AdministrationResponseHandler::_duplicate (_tao_rh); this->list_i (0, count); } void AsyncListManager::list_i (CORBA::ULong start, CORBA::ULong count) { if (this->server_list_.length () == 0) { this->init_list (); } this->first_ = start; this->how_many_ = this->server_list_.length () - start; if (start > 0 || (count > 0 && count < this->how_many_)) { if (count > 0 && count < this->how_many_) { this->how_many_ = count; } } if (this->waiters_ == 0) { this->final_state (); } } bool AsyncListManager::evaluate_status (CORBA::ULong index, LiveStatus status, int pid) { bool is_final = true; switch (status) { case LS_ALIVE: case LS_LAST_TRANSIENT: this->server_list_[index].activeStatus = ImplementationRepository::ACTIVE_YES; break; case LS_TIMEDOUT: this->server_list_[index].activeStatus = ImplementationRepository::ACTIVE_MAYBE; break; case LS_DEAD: this->server_list_[index].activeStatus = (pid == 0) ? ImplementationRepository::ACTIVE_NO : ImplementationRepository::ACTIVE_MAYBE; break; default: is_final = false; } return is_final; } void AsyncListManager::ping_replied (CORBA::ULong index, LiveStatus status, int pid) { if (ImR_Locator_i::debug() > 4) { ORBSVCS_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) AsyncListManager(%@)::ping_replied, index <%d> ") ACE_TEXT ("status <%C> server pid <%d> waiters <%d>\n"), this,index, LiveEntry::status_name (status), pid, this->waiters_)); } if (evaluate_status (index, status, pid)) { if (--this->waiters_ == 0) { this->final_state (); } return; } } AsyncListManager * AsyncListManager::_add_ref (void) { ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, mon, this->lock_, 0); ++this->refcount_; return this; } void AsyncListManager::_remove_ref (void) { int count = 0; { ACE_GUARD (TAO_SYNCH_MUTEX, mon, this->lock_); count = --this->refcount_; } if (count == 0) { delete this; } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- ListLiveListener::ListLiveListener (const char *server, int pid, CORBA::ULong index, AsyncListManager *owner, LiveCheck &pinger) :LiveListener (server), owner_ (owner->_add_ref ()), pinger_ (pinger), status_ (LS_UNKNOWN), index_ (index), started_ (false), pid_ (pid) { } ListLiveListener::~ListLiveListener (void) { } bool ListLiveListener::start (void) { bool rtn = this->pinger_.add_poll_listener (this); this->started_ = true; return rtn; } LiveStatus ListLiveListener::status (void) { return this->status_; } void ListLiveListener::cancel (void) { this->pinger_.remove_listener (this); } bool ListLiveListener::status_changed (LiveStatus status) { this->status_ = status; if (status == LS_TRANSIENT) { return false; } else { if (this->started_) this->owner_->ping_replied (this->index_, status, this->pid_); } return true; }