Merge pull request #1844 from jrw972/monterey
[ACE_TAO.git] / TAO / orbsvcs / ImplRepo_Service / LiveCheck.cpp
blob310e331b8a5c60e91e029b0d2aab1769aacdf977
1 // -*- C++ -*-
2 #include "LiveCheck.h"
3 #include "ImR_Locator_i.h"
5 #include "orbsvcs/Log_Macros.h"
7 #include "tao/ORB_Core.h"
8 #include "ace/Reactor.h"
9 #include "ace/OS_NS_sys_time.h"
10 #include "ace/Timer_Queue.h"
11 #include "ace/Timer_Queue_Iterator.h"
13 LiveListener::LiveListener (const char *server)
14 : server_ (server),
15 refcount_ (1)
19 LiveListener::~LiveListener (void)
23 const char *
24 LiveListener::server (void) const
26 return this->server_.c_str ();
29 LiveListener *
30 LiveListener::_add_ref (void)
32 int const refcount = ++this->refcount_;
33 if (ImR_Locator_i::debug () > 5)
35 ORBSVCS_DEBUG ((LM_DEBUG,
36 ACE_TEXT ("(%P|%t) LiveListener::add_ref <%C> count <%d>\n"),
37 server_.c_str(), refcount));
39 return this;
42 void
43 LiveListener::_remove_ref (void)
45 int const count = --this->refcount_;
46 if (ImR_Locator_i::debug () > 5)
48 ORBSVCS_DEBUG ((LM_DEBUG,
49 ACE_TEXT ("(%P|%t) LiveListener::remove_ref <%C> count <%d>\n"),
50 server_.c_str(), count));
52 if (count == 0)
54 delete this;
58 //---------------------------------------------------------------------------
59 //---------------------------------------------------------------------------
61 const int LiveEntry::reping_msec_[] = {10, 100, 500, 1000, 1000, 2000, 2000, 5000, 5000};
62 int LiveEntry::reping_limit_ = sizeof (LiveEntry::reping_msec_) / sizeof (int);
64 const char *
65 LiveEntry::status_name (LiveStatus s)
67 switch (s)
69 case LS_INIT:
70 return "INIT";
71 case LS_UNKNOWN:
72 return "UNKNOWN";
73 case LS_PING_AWAY:
74 return "PING_AWAY";
75 case LS_DEAD:
76 return "DEAD";
77 case LS_ALIVE:
78 return "ALIVE";
79 case LS_TRANSIENT:
80 return "TRANSIENT";
81 case LS_LAST_TRANSIENT:
82 return "LAST_TRANSIENT";
83 case LS_TIMEDOUT:
84 return "TIMEDOUT";
85 case LS_CANCELED:
86 return "CANCELED";
88 return "<undefined status>";
91 void
92 LiveEntry::set_reping_limit (int max)
94 int array_max = sizeof (LiveEntry::reping_msec_) / sizeof (int);
95 LiveEntry::reping_limit_ = max < array_max && max >= 0 ? max : array_max;
98 bool
99 LiveEntry::reping_available (void) const
101 return this->repings_ < this->max_retry_;
105 LiveEntry::next_reping (void)
107 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, mon, this->lock_, -1);
108 return this->reping_available() ? LiveEntry::reping_msec_[this->repings_++] : -1;
111 void
112 LiveEntry::max_retry_msec (int msec)
114 ACE_GUARD (TAO_SYNCH_MUTEX, mon, this->lock_);
115 for (this->max_retry_ = 0;
116 this->max_retry_ < LiveEntry::reping_limit_ && msec > 0;
117 ++this->max_retry_)
119 msec -= LiveEntry::reping_msec_[this->repings_];
123 LiveEntry::LiveEntry (LiveCheck *owner,
124 const char *server,
125 bool may_ping,
126 ImplementationRepository::ServerObject_ptr ref,
127 int pid)
128 : owner_ (owner),
129 server_ (server),
130 ref_ (ImplementationRepository::ServerObject::_duplicate (ref)),
131 liveliness_ (LS_INIT),
132 next_check_ (ACE_OS::gettimeofday()),
133 repings_ (0),
134 max_retry_ (LiveEntry::reping_limit_),
135 may_ping_ (may_ping),
136 listeners_ (),
137 lock_ (),
138 callback_ (0),
139 pid_ (pid)
141 if (ImR_Locator_i::debug () > 4)
143 ORBSVCS_DEBUG ((LM_DEBUG,
144 ACE_TEXT ("(%P|%t) LiveEntry::ctor server <%C> status <%C> may_ping <%d> pid <%d>\n"),
145 server, status_name (this->liveliness_), may_ping, pid));
149 LiveEntry::~LiveEntry (void)
151 if (this->callback_.in () != 0)
153 PingReceiver *rec = dynamic_cast<PingReceiver *>(this->callback_.in());
154 if (rec != 0)
156 rec->cancel ();
161 void
162 LiveEntry::release_callback (void)
164 this->callback_ = 0;
167 void
168 LiveEntry::add_listener (LiveListener *ll)
170 ACE_GUARD (TAO_SYNCH_MUTEX, mon, this->lock_);
171 LiveListener_ptr llp(ll->_add_ref());
172 int const result = this->listeners_.insert (llp);
173 if (ImR_Locator_i::debug() > 4)
175 ORBSVCS_DEBUG ((LM_DEBUG,
176 ACE_TEXT ("(%P|%t) LiveEntry::add_listener server <%C> result <%d>\n"),
177 this->server_.c_str(),
178 result));
182 void
183 LiveEntry::remove_listener (LiveListener *ll)
185 ACE_GUARD (TAO_SYNCH_MUTEX, mon, this->lock_);
186 LiveListener_ptr llp(ll->_add_ref());
187 int const result = this->listeners_.remove (llp);
188 if (ImR_Locator_i::debug() > 4)
190 ORBSVCS_DEBUG ((LM_DEBUG,
191 ACE_TEXT ("(%P|%t) LiveEntry::remove_listener server <%C> result <%d>\n"),
192 this->server_.c_str(),
193 result));
197 void
198 LiveEntry::reset_status (void)
200 ACE_GUARD (TAO_SYNCH_MUTEX, mon, this->lock_);
201 if ( this->liveliness_ == LS_ALIVE ||
202 this->liveliness_ == LS_LAST_TRANSIENT ||
203 this->liveliness_ == LS_TIMEDOUT)
205 this->liveliness_ = LS_UNKNOWN;
206 this->repings_ = 0;
207 this->next_check_ = ACE_OS::gettimeofday();
209 if (ImR_Locator_i::debug () > 2)
211 ORBSVCS_DEBUG ((LM_DEBUG,
212 ACE_TEXT ("(%P|%t) LiveEntry::reset_status this <%x> ")
213 ACE_TEXT ("server <%C> status <%C>\n"),
214 this, this->server_.c_str(),
215 status_name (this->liveliness_)));
220 LiveStatus
221 LiveEntry::status (void) const
223 if (!this->may_ping_)
225 return LS_ALIVE;
228 if (this->liveliness_ == LS_ALIVE &&
229 this->owner_->ping_interval() != ACE_Time_Value::zero)
231 ACE_Time_Value now (ACE_OS::gettimeofday());
232 if (now >= this->next_check_)
234 return LS_UNKNOWN;
237 return this->liveliness_;
240 void
241 LiveEntry::update_listeners (void)
243 Listen_Set remove;
244 for (Listen_Set::ITERATOR i(this->listeners_);
245 !i.done();
246 i.advance ())
249 if ((*i)->status_changed (this->liveliness_))
251 remove.insert (*i);
255 ACE_GUARD (TAO_SYNCH_MUTEX, mon, this->lock_);
256 for (Listen_Set::ITERATOR i (remove);
257 !i.done();
258 i.advance ())
260 LiveListener_ptr llp (*i);
261 int const result = this->listeners_.remove (llp);
262 if (result == -1)
266 LiveListener_ptr dummy;
267 this->listeners_.remove (dummy);
271 void
272 LiveEntry::status (LiveStatus l)
275 ACE_GUARD (TAO_SYNCH_MUTEX, mon, this->lock_);
276 this->liveliness_ = l;
277 if (l == LS_ALIVE)
279 ACE_Time_Value now (ACE_OS::gettimeofday());
280 this->next_check_ = now + owner_->ping_interval();
282 if (l == LS_TRANSIENT && !this->reping_available())
284 this->liveliness_ = LS_LAST_TRANSIENT;
287 this->update_listeners ();
289 if (!this->listeners_.is_empty ())
291 if (ImR_Locator_i::debug () > 2)
293 ORBSVCS_DEBUG ((LM_DEBUG,
294 ACE_TEXT ("(%P|%t) LiveEntry::status change, ")
295 ACE_TEXT ("server <%C> status <%C>\n"),
296 this->server_.c_str(),
297 status_name (this->liveliness_)));
299 this->owner_->schedule_ping (this);
301 else
303 if (this->owner_->remove_per_client_entry (this))
305 delete (this);
310 const ACE_Time_Value &
311 LiveEntry::next_check (void) const
313 return this->next_check_;
316 const char *
317 LiveEntry::server_name (void) const
319 return this->server_.c_str();
322 void
323 LiveEntry::set_pid (int pid)
325 this->pid_ = pid;
329 LiveEntry::pid (void) const
331 return this->pid_;
334 bool
335 LiveEntry::may_ping (void) const
337 return this->may_ping_;
340 bool
341 LiveEntry::has_pid (int pid) const
343 return this->pid_ == 0 || pid == 0 || pid == this->pid_;
346 bool
347 LiveEntry::validate_ping (bool &want_reping, ACE_Time_Value& next)
349 if (ImR_Locator_i::debug () > 4)
351 ORBSVCS_DEBUG ((LM_DEBUG,
352 ACE_TEXT ("(%P|%t) LiveEntry::validate_ping, status ")
353 ACE_TEXT ("<%C> listeners <%d> server <%C> pid <%d> want_reping <%d> may_ping <%d>\n"),
354 status_name (this->liveliness_), this->listeners_.size (),
355 this->server_.c_str(), this->pid_, want_reping, this->may_ping_));
358 if (this->liveliness_ == LS_PING_AWAY ||
359 this->liveliness_ == LS_DEAD ||
360 this->listeners_.is_empty ())
362 return false;
364 ACE_Time_Value const now (ACE_OS::gettimeofday());
365 ACE_Time_Value const diff = this->next_check_ - now;
366 long const msec = diff.msec();
367 if (msec > 0)
369 if (!want_reping || this->next_check_ < next)
371 want_reping = true;
372 next = this->next_check_;
374 if (ImR_Locator_i::debug () > 2)
376 ORBSVCS_DEBUG ((LM_DEBUG,
377 ACE_TEXT ("(%P|%t) LiveEntry::validate_ping, ")
378 ACE_TEXT ("status <%C> listeners <%d> ")
379 ACE_TEXT ("msec <%d> server <%C> pid <%d>\n"),
380 status_name (this->liveliness_), this->listeners_.size (),
381 msec, this->server_.c_str(), this->pid_));
383 return false;
385 switch (this->liveliness_)
387 case LS_UNKNOWN:
388 case LS_INIT:
389 break;
390 case LS_ALIVE:
391 case LS_TIMEDOUT:
393 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, mon, this->lock_, false);
394 this->next_check_ = now + owner_->ping_interval();
396 break;
397 case LS_TRANSIENT:
398 case LS_LAST_TRANSIENT:
400 int const ms = this->next_reping ();
401 if (ms != -1)
403 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, mon, this->lock_, false);
404 if (this->liveliness_ == LS_LAST_TRANSIENT)
406 this->liveliness_ = LS_TRANSIENT;
408 ACE_Time_Value const next (ms / 1000, (ms % 1000) * 1000);
409 this->next_check_ = now + next;
410 if (ImR_Locator_i::debug () > 4)
412 ORBSVCS_DEBUG ((LM_DEBUG,
413 ACE_TEXT ("(%P|%t) LiveEntry::validate_ping, ")
414 ACE_TEXT ("transient, reping in <%d> ms, ")
415 ACE_TEXT ("server <%C> pid <%d>\n"),
416 ms, this->server_.c_str(), this->pid_));
419 else
421 if (this->liveliness_ == LS_TRANSIENT)
423 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, mon, this->lock_, false);
424 this->liveliness_ = LS_LAST_TRANSIENT;
426 if (ImR_Locator_i::debug () > 2)
428 ORBSVCS_DEBUG ((LM_DEBUG,
429 ACE_TEXT ("(%P|%t) LiveEntry::validate_ping, ")
430 ACE_TEXT ("transient, no more repings, ")
431 ACE_TEXT ("server <%C> pid <%d>\n"),
432 this->server_.c_str(), this->pid_));
434 if (!this->listeners_.is_empty ())
436 this->update_listeners ();
438 return false;
441 break;
442 default:;
444 return true;
447 void
448 LiveEntry::do_ping (PortableServer::POA_ptr poa)
450 this->callback_ = new PingReceiver (this, poa);
451 PortableServer::ObjectId_var oid = poa->activate_object (this->callback_.in());
452 CORBA::Object_var obj = poa->id_to_reference (oid.in());
453 ImplementationRepository::AMI_ServerObjectHandler_var cb =
454 ImplementationRepository::AMI_ServerObjectHandler::_narrow (obj.in());
456 ACE_GUARD (TAO_SYNCH_MUTEX, mon, this->lock_);
457 this->liveliness_ = LS_PING_AWAY;
461 if (ImR_Locator_i::debug () > 3)
463 ORBSVCS_DEBUG ((LM_DEBUG,
464 ACE_TEXT ("(%P|%t) LiveEntry::do_ping, ")
465 ACE_TEXT ("starting sendc_ping for server <%C>\n"),
466 this->server_.c_str()));
468 this->ref_->sendc_ping (cb.in());
469 if (ImR_Locator_i::debug () > 3)
471 ORBSVCS_DEBUG ((LM_DEBUG,
472 ACE_TEXT ("(%P|%t) LiveEntry::do_ping, ")
473 ACE_TEXT ("sendc_ping for server <%C> returned OK\n"),
474 this->server_.c_str()));
477 catch (const CORBA::Exception &ex)
479 if (ImR_Locator_i::debug () > 3)
481 ORBSVCS_DEBUG ((LM_DEBUG,
482 ACE_TEXT ("(%P|%t) LiveEntry::do_ping, ")
483 ACE_TEXT ("sendc_ping for server <%C> threw <%C> marking as dead\n"),
484 this->server_.c_str(), ex._info ().c_str ()));
486 this->release_callback ();
487 this->status (LS_DEAD);
491 //---------------------------------------------------------------------------
492 PingReceiver::PingReceiver (LiveEntry *entry, PortableServer::POA_ptr poa)
493 :poa_ (PortableServer::POA::_duplicate(poa)),
494 entry_ (entry)
498 PingReceiver::~PingReceiver (void)
502 void
503 PingReceiver::cancel (void)
505 if (ImR_Locator_i::debug () > 4)
507 const char *server = "not available";
508 if (this->entry_ != 0)
510 server = this->entry_->server_name ();
512 ORBSVCS_DEBUG ((LM_DEBUG,
513 ACE_TEXT ("(%P|%t) PingReceiver::cancel server <%C>\n"),
514 server));
517 this->entry_ = 0;
520 PortableServer::ObjectId_var oid = this->poa_->servant_to_id (this);
521 poa_->deactivate_object (oid.in());
523 catch (const CORBA::Exception &ex)
525 if (ImR_Locator_i::debug () > 4)
527 ORBSVCS_DEBUG ((LM_DEBUG,
528 ACE_TEXT ("(%P|%t) PingReceiver::cancel caught <%C>\n"),
529 ex._info ().c_str ()));
534 void
535 PingReceiver::ping (void)
537 if (this->entry_ != 0)
539 if (ImR_Locator_i::debug () > 5)
541 ORBSVCS_DEBUG ((LM_DEBUG,
542 ACE_TEXT ("(%P|%t) PingReceiver::ping received from <%C>\n"),
543 this->entry_->server_name ()));
545 this->entry_->release_callback ();
546 this->entry_->status (LS_ALIVE);
548 PortableServer::ObjectId_var oid = this->poa_->servant_to_id (this);
549 poa_->deactivate_object (oid.in());
552 void
553 PingReceiver::ping_excep (Messaging::ExceptionHolder * excep_holder)
555 const CORBA::ULong TAO_MINOR_MASK = 0x00000f80;
558 if (ImR_Locator_i::debug () > 5)
560 ORBSVCS_DEBUG ((LM_DEBUG,
561 ACE_TEXT ("(%P|%t) PingReceiver::ping_excep received from <%C>\n"),
562 this->entry_->server_name ()));
564 excep_holder->raise_exception ();
566 catch (const CORBA::TRANSIENT &ex)
568 switch (ex.minor () & TAO_MINOR_MASK)
570 case TAO_POA_DISCARDING:
571 case TAO_POA_HOLDING:
573 if (this->entry_ != 0)
575 this->entry_->release_callback ();
576 this->entry_->status (LS_TRANSIENT);
578 break;
580 default: //case TAO_INVOCATION_SEND_REQUEST_MINOR_CODE:
582 if (this->entry_ != 0)
584 this->entry_->release_callback ();
585 this->entry_->status (LS_DEAD);
590 catch (const CORBA::TIMEOUT &ex)
592 if (this->entry_ != 0)
594 this->entry_->release_callback ();
595 if ((ex.minor () & TAO_MINOR_MASK) == TAO_TIMEOUT_CONNECT_MINOR_CODE)
597 this->entry_->status (LS_DEAD);
599 else
601 this->entry_->status (LS_TIMEDOUT);
605 catch (const CORBA::Exception &)
607 if (this->entry_ != 0)
609 this->entry_->release_callback ();
610 this->entry_->status (LS_DEAD);
614 PortableServer::ObjectId_var oid = this->poa_->servant_to_id (this);
615 poa_->deactivate_object (oid.in());
618 //---------------------------------------------------------------------------
619 //---------------------------------------------------------------------------
621 LC_TimeoutGuard::LC_TimeoutGuard (LiveCheck *owner, LC_token_type token)
622 :owner_ (owner),
623 token_ (token),
624 blocked_ (owner->in_handle_timeout ())
626 if (ImR_Locator_i::debug () > 3)
628 ORBSVCS_DEBUG ((LM_DEBUG,
629 ACE_TEXT ("(%P|%t) LC_TimeoutGuard(%d)::ctor, ")
630 ACE_TEXT ("blocked <%d>\n"),
631 this->token_, this->blocked_));
633 owner_->enter_handle_timeout ();
636 LC_TimeoutGuard::~LC_TimeoutGuard (void)
638 owner_->exit_handle_timeout ();
640 if (blocked_)
642 if (ImR_Locator_i::debug () > 3)
644 ORBSVCS_DEBUG ((LM_DEBUG,
645 ACE_TEXT ("(%P|%t) LC_TimeoutGuard(%d)::dtor, ")
646 ACE_TEXT ("doing nothing because our owner is blocked\n"),
647 this->token_));
649 return;
652 owner_->remove_deferred_servers ();
654 if (owner_->want_timeout_)
656 ACE_Time_Value delay = ACE_Time_Value::zero;
657 if (owner_->deferred_timeout_ != ACE_Time_Value::zero)
659 ACE_Time_Value const now (ACE_OS::gettimeofday());
660 if (owner_->deferred_timeout_ > now)
661 delay = owner_->deferred_timeout_ - now;
663 ++owner_->token_;
664 if (ImR_Locator_i::debug () > 2)
666 ORBSVCS_DEBUG ((LM_DEBUG,
667 ACE_TEXT ("(%P|%t) LC_TimeoutGuard(%d)::dtor, ")
668 ACE_TEXT ("scheduling new timeout(%d), delay = %d,%d\n"),
669 this->token_, owner_->token_, delay.sec(), delay.usec()));
671 owner_->reactor()->schedule_timer (owner_,
672 reinterpret_cast<void *>(owner_->token_),
673 delay);
674 owner_->want_timeout_ = false;
676 else
678 if (ImR_Locator_i::debug () > 3)
680 ORBSVCS_DEBUG ((LM_DEBUG,
681 ACE_TEXT ("(%P|%t) LC_TimeoutGuard(%d)::dtor, ")
682 ACE_TEXT ("no pending timeouts requested\n"),
683 this->token_));
688 bool LC_TimeoutGuard::blocked (void) const
690 return this->blocked_;
693 //---------------------------------------------------------------------------
694 //---------------------------------------------------------------------------
696 LiveCheck::LiveCheck ()
697 :ping_interval_(),
698 running_ (false),
699 token_ (100),
700 handle_timeout_busy_ (0),
701 want_timeout_ (false),
702 deferred_timeout_ (ACE_Time_Value::zero)
706 LiveCheck::~LiveCheck (void)
708 for (LiveEntryMap::iterator em (this->entry_map_); !em.done(); em++)
710 delete em->int_id_;
712 this->entry_map_.unbind_all();
714 for (PerClientStack::iterator pc (this->per_client_); !pc.done(); pc++)
716 delete *pc;
718 this->per_client_.reset ();
719 this->removed_entries_.reset ();
722 void
723 LiveCheck::enter_handle_timeout (void)
725 ++this->handle_timeout_busy_;
728 void
729 LiveCheck::exit_handle_timeout (void)
731 --this->handle_timeout_busy_;
734 bool
735 LiveCheck::in_handle_timeout (void)
737 return this->handle_timeout_busy_ != 0;
740 void
741 LiveCheck::init (CORBA::ORB_ptr orb,
742 const ACE_Time_Value &pi)
744 this->ping_interval_ = pi;
745 ACE_Reactor *r = orb->orb_core()->reactor();
746 this->reactor (r);
747 CORBA::Object_var obj = orb->resolve_initial_references ("RootPOA");
748 this->poa_ = PortableServer::POA::_narrow (obj.in());
749 this->running_ = true;
752 void
753 LiveCheck::shutdown (void)
755 this->running_ = false;
756 this->reactor()->cancel_timer (this);
759 const ACE_Time_Value &
760 LiveCheck::ping_interval (void) const
762 return this->ping_interval_;
766 LiveCheck::handle_timeout (const ACE_Time_Value &,
767 const void * tok)
769 LC_token_type token = reinterpret_cast<LC_token_type>(tok);
770 if (ImR_Locator_i::debug () > 2)
772 ORBSVCS_DEBUG ((LM_DEBUG,
773 ACE_TEXT ("(%P|%t) LiveCheck::handle_timeout(%d), ")
774 ACE_TEXT ("running <%d>\n"),
775 token, this->running_));
777 if (!this->running_)
778 return -1;
780 LC_TimeoutGuard tg (this, token);
781 if (tg.blocked ())
782 return 0;
784 LiveEntryMap::iterator le_end = this->entry_map_.end();
785 for (LiveEntryMap::iterator le = this->entry_map_.begin();
786 le != le_end;
787 ++le)
789 LiveEntry *entry = le->item ();
790 if (entry->validate_ping (this->want_timeout_, this->deferred_timeout_))
792 entry->do_ping (poa_.in ());
793 if (ImR_Locator_i::debug () > 2)
795 ORBSVCS_DEBUG ((LM_DEBUG,
796 ACE_TEXT ("(%P|%t) LiveCheck::handle_timeout(%d)")
797 ACE_TEXT (", ping sent to server <%C>\n"),
798 token, entry->server_name ()));
801 else
803 if (ImR_Locator_i::debug () > 4)
805 ORBSVCS_DEBUG ((LM_DEBUG,
806 ACE_TEXT ("(%P|%t) LiveCheck::handle_timeout(%d)")
807 ACE_TEXT (", ping skipped for server <%C> may_ping <%d>\n"),
808 token, entry->server_name (), entry->may_ping ()));
813 PerClientStack::iterator pe_end = this->per_client_.end();
814 for (PerClientStack::iterator pe = this->per_client_.begin();
815 pe != pe_end;
816 ++pe)
818 LiveEntry *entry = *pe;
819 if (entry != 0)
821 if (entry->validate_ping (this->want_timeout_, this->deferred_timeout_))
823 entry->do_ping (poa_.in ());
825 LiveStatus const status = entry->status ();
826 if (status != LS_PING_AWAY && status != LS_TRANSIENT)
828 this->per_client_.remove (entry);
829 delete entry;
834 return 0;
837 bool
838 LiveCheck::has_server (const char *server)
840 ACE_CString s (server);
841 LiveEntry *entry = 0;
842 int const result = entry_map_.find (s, entry);
843 return (result == 0 && entry != 0);
846 void
847 LiveCheck::add_server (const char *server,
848 bool may_ping,
849 ImplementationRepository::ServerObject_ptr ref,
850 int pid)
852 if (ImR_Locator_i::debug () > 2)
854 ORBSVCS_DEBUG ((LM_DEBUG,
855 ACE_TEXT ("(%P|%t) LiveCheck::add_server <%C> ")
856 ACE_TEXT ("may_ping <%d> running <%d> pid <%d>\n"),
857 server, may_ping, this->running_, pid));
860 if (!this->running_)
861 return;
863 ACE_CString s (server);
864 LiveEntry *entry = 0;
865 ACE_NEW (entry, LiveEntry (this, server, may_ping, ref, pid));
866 int result = entry_map_.bind (s, entry);
867 if (result != 0)
869 LiveEntry *old = 0;
870 result = entry_map_.rebind (s, entry, old);
871 if (old)
873 old->status (LS_CANCELED);
875 delete old;
879 void
880 LiveCheck::set_pid (const char *server, int pid)
882 if (ImR_Locator_i::debug () > 0)
884 ORBSVCS_DEBUG ((LM_DEBUG,
885 ACE_TEXT ("(%P|%t) LiveCheck::set_pid <%C> pid <%d>\n"),
886 server, pid));
888 ACE_CString s(server);
889 LiveEntry *entry = 0;
890 int const result = entry_map_.find (s, entry);
891 if (result != -1 && entry != 0)
893 entry->set_pid (pid);
895 else
897 if (ImR_Locator_i::debug () > 0)
899 ORBSVCS_DEBUG ((LM_DEBUG,
900 ACE_TEXT ("(%P|%t) LiveCheck::set_pid <%C> pid <%d> cannot find entry\n"),
901 server, pid));
906 void
907 LiveCheck::remove_server (const char *server, int pid)
909 if (ImR_Locator_i::debug () > 0)
911 ORBSVCS_DEBUG ((LM_DEBUG,
912 ACE_TEXT ("(%P|%t) LiveCheck::remove_server <%C> pid <%d>\n"),
913 server, pid));
915 ACE_CString s(server);
916 LiveEntry *entry = 0;
917 int const result = entry_map_.find (s, entry);
918 if (result != -1 && entry != 0 && entry->has_pid (pid))
920 if (!this->in_handle_timeout ())
922 if (ImR_Locator_i::debug () > 0)
924 ORBSVCS_DEBUG ((LM_DEBUG,
925 ACE_TEXT ("(%P|%t) LiveCheck::remove_server removing <%C> pid <%d> entry pid <%d> status <%C>\n"),
926 server, pid, entry->pid (), LiveEntry::status_name (entry->status ())));
928 if (entry_map_.unbind (s, entry) == 0)
930 delete entry;
933 else
935 // We got a request to remove the server but we are in handle timeout, so we have to postpone
936 // the remove. We do set the status to dead so that we make sure that we only remove later
937 // on the dead server and not a possible restart
938 entry->status (LS_DEAD);
940 if (ImR_Locator_i::debug () > 0)
942 ORBSVCS_DEBUG ((LM_DEBUG,
943 ACE_TEXT ("(%P|%t) LiveCheck::remove_server <%C> pid <%d> entry pid <%d> status <%C> ")
944 ACE_TEXT ("called during handle_timeout\n"), server, pid, entry->pid (), LiveEntry::status_name (entry->status ())));
946 this->removed_entries_.insert_tail (std::make_pair (s, pid));
949 else
951 if (ImR_Locator_i::debug () > 0)
953 if (entry == 0)
955 ORBSVCS_DEBUG ((LM_DEBUG,
956 ACE_TEXT ("(%P|%t) LiveCheck::remove_server <%C> ")
957 ACE_TEXT ("Can't find server entry, server probably already removed earlier\n"),
958 server));
960 else
962 ORBSVCS_DEBUG ((LM_DEBUG,
963 ACE_TEXT ("(%P|%t) LiveCheck::remove_server <%C> ")
964 ACE_TEXT ("pid <%d> does not match entry pid <%d>\n"),
965 server, pid, entry->pid ()));
971 void
972 LiveCheck::remove_deferred_servers (void)
974 if (!this->removed_entries_.is_empty ())
976 // When we are in handle_timeout we can't remove deferred servers
977 if (!this->in_handle_timeout ())
979 NamePidStack::iterator re_end = this->removed_entries_.end();
980 for (NamePidStack::iterator re = this->removed_entries_.begin();
981 re != re_end;
982 ++re)
984 NamePidPair const & name_pid_pair = (*re);
985 if (ImR_Locator_i::debug () > 4)
987 ORBSVCS_DEBUG ((LM_DEBUG,
988 ACE_TEXT ("(%P|%t) LiveCheck::remove_deferred_servers ")
989 ACE_TEXT ("removing <%C> pid <%d>\n"),
990 name_pid_pair.first.c_str(), name_pid_pair.second));
992 // Now try to remove the server, we have to make sure
993 // that we only remove the server when the
994 // name and pid match. These could potentially not
995 // match when the server has already been restarted between the
996 // moment it got in the removed_entries_ stack and this point
997 // where we remove it from the internal administration
998 LiveEntry *entry = 0;
999 int const result = entry_map_.find (name_pid_pair.first, entry);
1000 if (result != -1 && entry != 0)
1002 if (entry->pid () == name_pid_pair.second)
1004 if (entry->status () == LS_DEAD)
1006 // We have a matched process id
1007 if (ImR_Locator_i::debug () > 4)
1009 ORBSVCS_DEBUG ((LM_DEBUG,
1010 ACE_TEXT ("(%P|%t) LiveCheck::remove_deferred_servers <%C> ")
1011 ACE_TEXT ("removing dead server using matched pid <%d>\n"),
1012 name_pid_pair.first.c_str(), name_pid_pair.second));
1014 if (entry_map_.unbind (name_pid_pair.first, entry) == 0)
1016 delete entry;
1019 else
1021 ORBSVCS_DEBUG ((LM_DEBUG,
1022 ACE_TEXT ("(%P|%t) LiveCheck::remove_deferred_servers <%C> ")
1023 ACE_TEXT ("matched pid <%d> but is not dead but <%C>\n"),
1024 name_pid_pair.first.c_str(), name_pid_pair.second, LiveEntry::status_name (entry->status ())));
1027 else
1029 ORBSVCS_DEBUG ((LM_DEBUG,
1030 ACE_TEXT ("(%P|%t) LiveCheck::remove_deferred_servers <%C> ")
1031 ACE_TEXT ("pid <%d> does not match entry pid <%d>\n"),
1032 name_pid_pair.first.c_str(), name_pid_pair.second, entry->pid ()));
1035 else
1037 if (ImR_Locator_i::debug () > 0)
1039 ORBSVCS_DEBUG ((LM_DEBUG,
1040 ACE_TEXT ("(%P|%t) LiveCheck::remove_deferred_servers <%C> ")
1041 ACE_TEXT ("Can't find server entry, server probably already removed earlier\n"),
1042 name_pid_pair.first.c_str()));
1046 this->removed_entries_.reset ();
1048 else
1050 if (ImR_Locator_i::debug () > 0)
1052 ORBSVCS_DEBUG ((LM_DEBUG,
1053 ACE_TEXT ("(%P|%t) LiveCheck::remove_deferred_servers ")
1054 ACE_TEXT ("Can't remove <%d> servers because we are still in handle timeout\n"),
1055 this->removed_entries_.size ()));
1061 bool
1062 LiveCheck::remove_per_client_entry (LiveEntry *e)
1064 return (this->per_client_.remove (e) == 0);
1067 bool
1068 LiveCheck::add_per_client_listener (LiveListener *l,
1069 ImplementationRepository::ServerObject_ptr ref)
1071 if (!this->running_)
1072 return false;
1074 LiveEntry *entry = 0;
1075 ACE_NEW_RETURN (entry, LiveEntry (this, l->server (), true, ref, 0), false);
1077 if (this->per_client_.insert_tail(entry) == 0)
1079 entry->add_listener (l);
1081 if (!this->in_handle_timeout ())
1083 ++this->token_;
1084 this->reactor()->schedule_timer (this,
1085 reinterpret_cast<void *>(this->token_),
1086 ACE_Time_Value::zero);
1088 else
1090 this->want_timeout_ = true;
1091 this->deferred_timeout_ = ACE_Time_Value::zero;
1093 return true;
1095 return false;
1098 bool
1099 LiveCheck::add_poll_listener (LiveListener *l)
1101 if (!this->running_)
1102 return false;
1104 LiveEntry *entry = 0;
1105 ACE_CString key (l->server());
1106 int const result = entry_map_.find (key, entry);
1107 if (result == -1 || entry == 0)
1109 return false;
1112 entry->add_listener (l);
1113 entry->reset_status ();
1114 l->status_changed (entry->status());
1115 return this->schedule_ping (entry);
1118 bool
1119 LiveCheck::add_listener (LiveListener *l)
1121 if (!this->running_)
1122 return false;
1124 LiveEntry *entry = 0;
1125 ACE_CString key (l->server());
1126 int const result = entry_map_.find (key, entry);
1127 if (result == -1 || entry == 0)
1129 return false;
1132 entry->add_listener (l);
1133 return this->schedule_ping (entry);
1136 void
1137 LiveCheck::remove_listener (LiveListener *l)
1139 if (!this->running_)
1140 return;
1142 LiveEntry *entry = 0;
1143 ACE_CString key (l->server());
1144 int const result = entry_map_.find (key, entry);
1145 if (result != -1 && entry != 0)
1147 entry->remove_listener (l);
1151 bool
1152 LiveCheck::schedule_ping (LiveEntry *entry)
1154 if (!this->running_)
1155 return false;
1157 LiveStatus const status = entry->status();
1158 if (status == LS_PING_AWAY || status == LS_DEAD)
1160 return status != LS_DEAD;
1163 ACE_Time_Value const now (ACE_OS::gettimeofday());
1164 ACE_Time_Value const next = entry->next_check ();
1166 if (!this->in_handle_timeout ())
1168 ACE_Time_Value delay = ACE_Time_Value::zero;
1169 if (next > now)
1171 delay = next - now;
1174 ACE_Timer_Queue *tq = this->reactor ()->timer_queue ();
1175 if (!tq->is_empty ())
1177 for (ACE_Timer_Queue_Iterator_T<ACE_Event_Handler*> &i = tq->iter ();
1178 !i.isdone (); i.next())
1180 if (i.item ()->get_type () == this)
1182 if (next >= tq->earliest_time ())
1184 if (ImR_Locator_i::debug () > 2)
1186 ORBSVCS_DEBUG ((LM_DEBUG,
1187 ACE_TEXT ("(%P|%t) LiveCheck::schedule_ping ")
1188 ACE_TEXT ("already scheduled\n")));
1190 return true;
1192 break;
1196 ++this->token_;
1197 if (ImR_Locator_i::debug () > 2)
1199 ORBSVCS_DEBUG ((LM_DEBUG,
1200 ACE_TEXT ("(%P|%t) LiveCheck::schedule_ping (%d),")
1201 ACE_TEXT (" delay <%d,%d>\n"),
1202 this->token_, delay.sec(), delay.usec()));
1204 this->reactor()->schedule_timer (this,
1205 reinterpret_cast<void *>(this->token_),
1206 delay);
1208 else
1210 if (ImR_Locator_i::debug () > 2)
1212 ORBSVCS_DEBUG ((LM_DEBUG,
1213 ACE_TEXT ("(%P|%t) LiveCheck::schedule_ping deferred because we are in handle timeout\n")));
1215 if (!this->want_timeout_ || next < this->deferred_timeout_)
1217 this->want_timeout_ = true;
1218 this->deferred_timeout_ = next;
1221 return true;
1224 LiveStatus
1225 LiveCheck::is_alive (const char *server)
1227 if (!this->running_)
1228 return LS_DEAD;
1230 if (this->ping_interval_ == ACE_Time_Value::zero)
1232 return LS_ALIVE;
1235 ACE_CString s(server);
1236 LiveEntry *entry = 0;
1237 int const result = entry_map_.find (s, entry);
1238 if (result == 0 && entry != 0)
1240 return entry->status ();
1242 return LS_DEAD;