#include <Leader_Follower.h>

Public Member Functions | |
| TAO_Leader_Follower (TAO_ORB_Core *orb_core, TAO_New_Leader_Generator *new_leader_generator=0) | |
| Constructor. | |
| ~TAO_Leader_Follower (void) | |
| Destructor. | |
| int | set_event_loop_thread (ACE_Time_Value *max_wait_time) |
| void | reset_event_loop_thread (void) |
| void | set_upcall_thread (void) |
| int | leader_available (void) const |
| Is there any thread running as a leader? | |
| void | set_client_thread (void) |
| A server thread is making a request. | |
| void | reset_client_thread (void) |
| A server thread has finished is making a request. | |
| int | wait_for_event (TAO_LF_Event *event, TAO_Transport *transport, ACE_Time_Value *max_wait_time) |
| Wait on the Leader/Followers loop until one event happens. | |
| void | set_client_leader_thread (void) |
| void | reset_client_leader_thread (void) |
| void | set_client_leader_thread (ACE_thread_t thread_ID) |
| int | is_client_leader_thread (void) const |
| checks if we are a leader thread | |
| int | elect_new_leader (void) |
| TAO_SYNCH_MUTEX & | lock (void) |
| Get a reference to the underlying mutex. | |
| ACE_Reverse_Lock < TAO_SYNCH_MUTEX > & | reverse_lock (void) |
| int | has_clients (void) const |
| Check if there are any client threads running. | |
| ACE_Reactor * | reactor (void) |
| Accesor to the reactor. | |
| void | no_leaders_available (void) |
| Called when we are out of leaders. | |
| void | set_new_leader_generator (TAO_New_Leader_Generator *new_leader_generator) |
| Set the new leader generator. | |
Follower creation/destructions | |
The Leader/Followers set acts as a factory for the Follower objects. Followers are used to represent a thread blocked waiting in the Follower set. The Leader/Followers abstraction keeps a list of the waiting followers, so it can wake up one when the leader thread stops handling events. For performance reasons the Leader/Followers set uses a pool (or free-list) to keep Follower objects unattached to any thread. It could be tempting to use TSS to keep such followers, after all a thread can only need one such Follower object, however, that does not work with multiple Leader/Followers sets, consult this bug report for more details: | |
| TAO_LF_Follower * | allocate_follower (void) |
| Allocate a new follower to the caller. | |
| void | release_follower (TAO_LF_Follower *) |
| The caller has finished using a follower. | |
Private Types | |
| typedef ACE_Intrusive_List < TAO_LF_Follower > | Follower_Set |
| Implement the Leader/Followers set using an intrusive list. | |
Private Member Functions | |
| TAO_ORB_Core_TSS_Resources * | get_tss_resources (void) const |
| Shortcut to obtain the TSS resources of the orb core. | |
| int | wait_for_client_leader_to_complete (ACE_Time_Value *max_wait_time) |
| Wait for the client leader to complete. | |
| void | reset_event_loop_thread_i (TAO_ORB_Core_TSS_Resources *tss) |
Private Attributes | |
| TAO_ORB_Core * | orb_core_ |
| The orb core. | |
| TAO_SYNCH_MUTEX | lock_ |
| To synchronize access to the members. | |
| ACE_Reverse_Lock< TAO_SYNCH_MUTEX > | reverse_lock_ |
| Do protect the access to the following three members. | |
| Follower_Set | follower_set_ |
| Follower_Set | follower_free_list_ |
| Use a free list to allocate and release Follower objects. | |
| int | leaders_ |
| int | clients_ |
| ACE_Reactor * | reactor_ |
| The reactor. | |
| int | client_thread_is_leader_ |
| Is a client thread the current leader? | |
| int | event_loop_threads_waiting_ |
| Are server threads waiting for the client leader to complete? | |
| TAO_SYNCH_CONDITION | event_loop_threads_condition_ |
| TAO_New_Leader_Generator * | new_leader_generator_ |
Follower Set Operations | |
|
| |
| void | add_follower (TAO_LF_Follower *follower) |
| Add a new follower to the set. | |
| void | remove_follower (TAO_LF_Follower *follower) |
| Removes a follower from the leader-follower set. | |
| int | follower_available (void) const |
| Checks if there are any followers available. | |
| int | elect_new_leader_i (void) |
Definition at line 49 of file Leader_Follower.h.
typedef ACE_Intrusive_List<TAO_LF_Follower> TAO_Leader_Follower::Follower_Set [private] |
Implement the Leader/Followers set using an intrusive list.
Definition at line 230 of file Leader_Follower.h.
| TAO_Leader_Follower::TAO_Leader_Follower | ( | TAO_ORB_Core * | orb_core, | |
| TAO_New_Leader_Generator * | new_leader_generator = 0 | |||
| ) |
Constructor.
Definition at line 13 of file Leader_Follower.inl.
: orb_core_ (orb_core), reverse_lock_ (lock_), leaders_ (0), clients_ (0), reactor_ (0), client_thread_is_leader_ (0), event_loop_threads_waiting_ (0), event_loop_threads_condition_ (lock_), new_leader_generator_ (new_leader_generator) { }
| TAO_Leader_Follower::~TAO_Leader_Follower | ( | void | ) |
Destructor.
Definition at line 27 of file Leader_Follower.cpp.
{
while (!this->follower_free_list_.empty ())
{
TAO_LF_Follower *follower = this->follower_free_list_.pop_front ();
delete follower;
}
// Hand the reactor back to the resource factory.
// use GUI reactor factory if available
if ( this->orb_core_->gui_resource_factory () )
this->orb_core_->gui_resource_factory ()->reclaim_reactor (this->reactor_);
else
this->orb_core_->resource_factory ()->reclaim_reactor (this->reactor_);
this->reactor_ = 0;
}
| void TAO_Leader_Follower::add_follower | ( | TAO_LF_Follower * | follower | ) |
Add a new follower to the set.
Definition at line 176 of file Leader_Follower.inl.
{
this->follower_set_.push_back (follower);
}
| TAO_LF_Follower * TAO_Leader_Follower::allocate_follower | ( | void | ) |
Allocate a new follower to the caller.
Definition at line 45 of file Leader_Follower.cpp.
{
if (!this->follower_free_list_.empty ())
return this->follower_free_list_.pop_front ();
TAO_LF_Follower* ptr = 0;
ACE_NEW_RETURN (ptr,
TAO_LF_Follower (*this),
0);
return ptr;
}
| int TAO_Leader_Follower::elect_new_leader | ( | void | ) |
A leader thread is relinquishing its role, unless there are more leader threads running pick up a follower (if there is any) to play the leader role.
Definition at line 47 of file Leader_Follower.inl.
{
if (this->leaders_ == 0)
{
if (this->event_loop_threads_waiting_)
{
return this->event_loop_threads_condition_.broadcast ();
}
else if (this->follower_available ())
{
return this->elect_new_leader_i ();
}
else
{
this->no_leaders_available ();
}
}
return 0;
}
| int TAO_Leader_Follower::elect_new_leader_i | ( | void | ) | [private] |
Remote a follower from the Followers set and promote it to the leader role. This is a helper routine for elect_new_leader(), after verifying that all the pre-conditions are satisfied the Follower set is changed and the promoted Follower is signaled.
Definition at line 64 of file Leader_Follower.cpp.
{
TAO_LF_Follower* const follower = this->follower_set_.head ();
#if defined (TAO_DEBUG_LEADER_FOLLOWER)
ACE_DEBUG ((LM_DEBUG,
"TAO (%P|%t) LF::elect_new_leader_i - "
"follower is %x\n",
follower));
#endif /* TAO_DEBUG_LEADER_FOLLOWER */
return follower->signal ();
}
| int TAO_Leader_Follower::follower_available | ( | void | ) | const |
Checks if there are any followers available.
Definition at line 34 of file Leader_Follower.inl.
{
return !this->follower_set_.empty ();
}
| TAO_ORB_Core_TSS_Resources * TAO_Leader_Follower::get_tss_resources | ( | void | ) | const [private] |
Shortcut to obtain the TSS resources of the orb core.
Definition at line 28 of file Leader_Follower.inl.
{
return this->orb_core_->get_tss_resources ();
}
| int TAO_Leader_Follower::has_clients | ( | void | ) | const |
Check if there are any client threads running.
Definition at line 194 of file Leader_Follower.inl.
{
return this->clients_;
}
| int TAO_Leader_Follower::is_client_leader_thread | ( | void | ) | const |
checks if we are a leader thread
Definition at line 169 of file Leader_Follower.inl.
{
TAO_ORB_Core_TSS_Resources *tss = this->get_tss_resources ();
return tss->client_leader_thread_ != 0;
}
| int TAO_Leader_Follower::leader_available | ( | void | ) | const |
Is there any thread running as a leader?
Definition at line 145 of file Leader_Follower.inl.
{
return this->leaders_ != 0;
}
| TAO_SYNCH_MUTEX & TAO_Leader_Follower::lock | ( | void | ) |
Get a reference to the underlying mutex.
Definition at line 125 of file Leader_Follower.inl.
{
return this->lock_;
}
| void TAO_Leader_Follower::no_leaders_available | ( | void | ) |
Called when we are out of leaders.
Definition at line 40 of file Leader_Follower.inl.
{
if (this->new_leader_generator_)
this->new_leader_generator_->no_leaders_available ();
}
| ACE_Reactor * TAO_Leader_Follower::reactor | ( | void | ) |
Accesor to the reactor.
Definition at line 126 of file Leader_Follower.cpp.
{
if (this->reactor_ == 0)
{
ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ace_mon, this->lock (), 0);
if (this->reactor_ == 0)
{
// use GUI reactor factory if available
if ( this->orb_core_->gui_resource_factory () )
this->reactor_ =
this->orb_core_->gui_resource_factory ()->get_reactor ();
else
this->reactor_ =
this->orb_core_->resource_factory ()->get_reactor ();
}
}
return this->reactor_;
}
| void TAO_Leader_Follower::release_follower | ( | TAO_LF_Follower * | follower | ) |
The caller has finished using a follower.
Definition at line 58 of file Leader_Follower.cpp.
{
this->follower_free_list_.push_front (follower);
}
| void TAO_Leader_Follower::remove_follower | ( | TAO_LF_Follower * | follower | ) |
Removes a follower from the leader-follower set.
Definition at line 182 of file Leader_Follower.inl.
{
this->follower_set_.remove (follower);
}
| void TAO_Leader_Follower::reset_client_leader_thread | ( | void | ) |
The current thread is no longer the leader thread in the client side leader-follower set.
Definition at line 160 of file Leader_Follower.inl.
{
TAO_ORB_Core_TSS_Resources *tss = this->get_tss_resources ();
--tss->client_leader_thread_;
--this->leaders_;
--this->client_thread_is_leader_;
}
| void TAO_Leader_Follower::reset_client_thread | ( | void | ) |
A server thread has finished is making a request.
Definition at line 170 of file Leader_Follower.cpp.
{
// If we were a leader thread or an event loop thread, take back
// leadership.
TAO_ORB_Core_TSS_Resources *tss = this->get_tss_resources ();
if (tss->event_loop_thread_ ||
tss->client_leader_thread_)
{
++this->leaders_;
}
--this->clients_;
if (this->clients_ == 0 &&
this->orb_core_->has_shutdown ())
{
// The ORB has shutdown and we are the last client thread, we
// must stop the reactor to ensure that any server threads go
// away.
this->orb_core_->reactor ()->end_reactor_event_loop ();
}
}
| void TAO_Leader_Follower::reset_event_loop_thread | ( | void | ) |
The current thread is not a server thread anymore, reset any flags and counters.
Definition at line 117 of file Leader_Follower.inl.
{
TAO_ORB_Core_TSS_Resources *tss = this->get_tss_resources ();
if (tss->event_loop_thread_ > 0)
this->reset_event_loop_thread_i (tss);
}
| void TAO_Leader_Follower::reset_event_loop_thread_i | ( | TAO_ORB_Core_TSS_Resources * | tss | ) | [private] |
Implement the reset_event_loop_thread() method, once the TSS resources have been acquired. Also used in the set_upcall_thread.
Definition at line 101 of file Leader_Follower.inl.
{
// Always decrement <event_loop_thread_>. If <event_loop_thread_>
// reaches 0 and we are not a client leader, we are done with our
// duties of running the event loop. Therefore, decrement the
// leaders. Otherwise, we just got done with a nested call to the
// event loop or a call to the event loop when we were the client
// leader.
--tss->event_loop_thread_;
if (tss->event_loop_thread_ == 0 &&
tss->client_leader_thread_ == 0)
--this->leaders_;
}
| ACE_Reverse_Lock< TAO_SYNCH_MUTEX > & TAO_Leader_Follower::reverse_lock | ( | void | ) |
Provide a pre-initialized reverse lock for the Leader/Followers set. The Leader/Followers set mutex must be release during some long running operations. This helper class simplifies the process of releasing and reacquiring said mutex.
Definition at line 188 of file Leader_Follower.inl.
{
return this->reverse_lock_;
}
| void TAO_Leader_Follower::set_client_leader_thread | ( | void | ) |
The current thread has become the leader thread in the client side leader-follower set.
Definition at line 151 of file Leader_Follower.inl.
{
TAO_ORB_Core_TSS_Resources *tss = this->get_tss_resources ();
++this->leaders_;
++this->client_thread_is_leader_;
++tss->client_leader_thread_;
}
| void TAO_Leader_Follower::set_client_leader_thread | ( | ACE_thread_t | thread_ID | ) |
sets the thread ID of the leader thread in the leader-follower model
| void TAO_Leader_Follower::set_client_thread | ( | void | ) |
A server thread is making a request.
Definition at line 146 of file Leader_Follower.cpp.
{
// If we were a leader thread or an event loop thread, give up
// leadership.
TAO_ORB_Core_TSS_Resources *tss = this->get_tss_resources ();
if (tss->event_loop_thread_ ||
tss->client_leader_thread_)
{
--this->leaders_;
}
if (this->clients_ == 0 &&
this->orb_core_->has_shutdown () &&
!this->orb_core_->resource_factory ()->drop_replies_during_shutdown ())
{
// The ORB has shutdown and we are the first client after
// that. This means that the reactor is disabled, we must
// re-enable it if we want to receive any replys...
this->orb_core_->reactor ()->reset_reactor_event_loop ();
}
++this->clients_;
}
| int TAO_Leader_Follower::set_event_loop_thread | ( | ACE_Time_Value * | max_wait_time | ) |
The current thread has become a server thread (i.e. called ORB::run), update any flags and counters.
Definition at line 68 of file Leader_Follower.inl.
{
TAO_ORB_Core_TSS_Resources *tss = this->get_tss_resources ();
// Make sure that there is no other client thread run the show. If
// we are the client thread running the show, then it is ok.
if (this->client_thread_is_leader_ &&
tss->client_leader_thread_ == 0)
{
int result =
this->wait_for_client_leader_to_complete (max_wait_time);
if (result != 0)
return result;
}
// If <event_loop_thread_> == 0 and <client_leader_thread_> == 0, we
// are running the event loop for the first time. Therefore,
// increment the leaders. Otherwise, simply increment
// <event_loop_thread_> since either (a) if <event_loop_thread_> !=
// 0 this is a nested call to the event loop, or (b)
// <client_leader_thread_> != 0 this is a call to the event loop
// while we are a client leader.
if (tss->event_loop_thread_ == 0 &&
tss->client_leader_thread_ == 0)
++this->leaders_;
++tss->event_loop_thread_;
return 0;
}
| void TAO_Leader_Follower::set_new_leader_generator | ( | TAO_New_Leader_Generator * | new_leader_generator | ) |
Set the new leader generator.
Definition at line 200 of file Leader_Follower.inl.
{
this->new_leader_generator_ = new_leader_generator;
}
| void TAO_Leader_Follower::set_upcall_thread | ( | void | ) |
This thread is going to perform an upcall, it will no longer be an event loop thread.
Definition at line 131 of file Leader_Follower.inl.
{
TAO_ORB_Core_TSS_Resources *tss = this->get_tss_resources ();
if (tss->event_loop_thread_ > 0)
{
ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->lock ());
this->reset_event_loop_thread_i (tss);
this->elect_new_leader ();
}
}
| int TAO_Leader_Follower::wait_for_client_leader_to_complete | ( | ACE_Time_Value * | max_wait_time | ) | [private] |
Wait for the client leader to complete.
Definition at line 79 of file Leader_Follower.cpp.
{
int result = 0;
ACE_Countdown_Time countdown (max_wait_time);
// Note that we are waiting.
++this->event_loop_threads_waiting_;
while (this->client_thread_is_leader_ && result != -1)
{
if (max_wait_time == 0)
{
if (this->event_loop_threads_condition_.wait () == -1)
{
ACE_ERROR ((LM_ERROR,
ACE_TEXT ("TAO (%P|%t): TAO_Leader_Follower::")
ACE_TEXT ("wait_for_client_leader_to_complete - ")
ACE_TEXT ("Condition variable wait failed\n")));
result = -1;
}
}
else
{
countdown.update ();
ACE_Time_Value tv = ACE_OS::gettimeofday ();
tv += *max_wait_time;
if (this->event_loop_threads_condition_.wait (&tv) == -1)
{
if (errno != ETIME)
ACE_ERROR ((LM_ERROR,
ACE_TEXT ("TAO (%P|%t): TAO_Leader_Follower::")
ACE_TEXT ("wait_for_client_leader_to_complete - ")
ACE_TEXT ("Condition variable wait failed\n")));
result = -1;
}
}
}
// Reset waiting state.
--this->event_loop_threads_waiting_;
return result;
}
| int TAO_Leader_Follower::wait_for_event | ( | TAO_LF_Event * | event, | |
| TAO_Transport * | transport, | |||
| ACE_Time_Value * | max_wait_time | |||
| ) |
Wait on the Leader/Followers loop until one event happens.
| event | The event we wait for, the loop iterates until the event is sucessful, or it fails due to timeout, and error or a connection closed. | |
| transport | The transport attached to the event | |
| max_wait_time | Limit the time spent on the loop |
There should be no reason to reset the value of result here. If there was an error in handle_events () that the leader saw, I (Bala) beleave it should be propogated to the clients. result = 0;
Definition at line 193 of file Leader_Follower.cpp.
{
// Obtain the lock.
ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ace_mon, this->lock (), -1);
ACE_Countdown_Time countdown (max_wait_time);
// Optmize the first iteration [no access to errno]
int result = 1;
// For some cases the transport may dissappear like when waiting for
// connection to be initiated or closed. So cache the id.
// @@ NOTE: This is not completely safe either. We will be fine for
// cases that dont access the id ie. when debug level is off but
// with debugging level on we are on a sticky wicket. Hopefully none
// of our users should run TAO with debugging enabled like they did
// in PathFinder
size_t t_id = 0;
if (TAO_debug_level && transport != 0)
{
t_id = transport->id ();
}
{
// Calls this->set_client_thread () on construction and
// this->reset_client_thread () on destruction.
TAO_LF_Client_Thread_Helper client_thread_helper (*this);
ACE_UNUSED_ARG (client_thread_helper);
// Check if there is a leader. Note that it cannot be us since we
// gave up our leadership when we became a client.
if (this->leader_available ())
{
// = Wait as a follower.
// Grab a follower:
TAO_LF_Follower_Auto_Ptr follower (*this);
if (follower.get () == 0)
return -1;
if (TAO_debug_level >= 5)
ACE_DEBUG ((LM_DEBUG,
"TAO (%P|%t) - Leader_Follower[%d]::wait_for_event,"
" (follower), cond <%x>\n",
t_id, follower.get ()));
// Bound the follower and the LF_Event, this is important to
// get a signal when the event terminates
TAO_LF_Event_Binder event_binder (event, follower.get ());
while (event->keep_waiting () &&
this->leader_available ())
{
// Add ourselves to the list, do it everytime we wake up
// from the CV loop. Because:
//
// - The leader thread could have elected us as the new
// leader.
// - Before we can assume the role another thread becomes
// the leader
// - But our condition variable could have been removed
// already, if we don't add it again we will never wake
// up.
//
// Notice that we can have spurious wake ups, in that case
// adding the leader results in an error, that must be
// ignored.
// You may be thinking of not removing the condition
// variable in the code that sends the signal, but
// removing it here, that does not work either, in that
// case the condition variable may be used twice:
//
// - Wake up because its reply arrived
// - Wake up because it must become the leader
//
// but only the first one has any effect, so the leader is
// lost.
//
TAO_LF_Follower_Auto_Adder auto_adder (*this, follower);
if (max_wait_time == 0)
{
if (follower->wait (max_wait_time) == -1)
{
if (TAO_debug_level >= 5)
ACE_DEBUG ((LM_DEBUG,
"TAO (%P|%t) - Leader_Follower[%d]::wait_for_event, "
" (follower) [no timer, cond failed]\n",
t_id));
// @@ Michael: What is our error handling in this case?
// We could be elected as leader and
// no leader would come in?
return -1;
}
}
else
{
countdown.update ();
ACE_Time_Value tv = ACE_OS::gettimeofday ();
tv += *max_wait_time;
if (follower->wait (&tv) == -1)
{
if (TAO_debug_level >= 5)
ACE_DEBUG ((LM_DEBUG,
"TAO (%P|%t) - Leader_Follower[%d]::wait, "
"(follower) [has timer, follower failed]\n",
t_id ));
// If we have timedout set the state in the
// LF_Event. We call the non-locking,
// no-signalling method on LF_Event.
if (errno == ETIME)
// We have timedout
event->set_state (TAO_LF_Event::LFS_TIMEOUT);
if (!event->successful ())
{
// Remove follower can fail because either
// 1) the condition was satisfied (i.e. reply
// received or queue drained), or
// 2) somebody elected us as leader, or
// 3) the connection got closed.
//
// Therefore:
// If remove_follower fails and the condition
// was not satisfied, we know that we got
// elected as a leader.
// But we got a timeout, so we cannot become
// the leader, therefore, we have to select a
// new leader.
//
if (this->elect_new_leader () == -1
&& TAO_debug_level > 0)
{
ACE_ERROR ((LM_ERROR,
"TAO (%P|%t) - Leader_Follower[%d]::wait_for_event, "
"elect_new_leader failed\n",
t_id ));
}
}
return -1;
}
}
}
countdown.update ();
// @@ Michael: This is an old comment why we do not want to
// remove the follower here.
// We should not remove the follower here, we *must* remove it when
// we signal it so the same condition is not signalled for
// both wake up as a follower and as the next leader.
if (TAO_debug_level >= 5)
ACE_DEBUG ((LM_DEBUG,
"TAO (%P|%t) - Leader_Follower[%d]::wait_for_event,"
" done (follower), successful %d\n",
t_id,
event->successful ()));
// Now somebody woke us up to become a leader or to handle our
// input. We are already removed from the follower queue.
if (event->successful ())
return 0;
if (event->error_detected ())
return -1;
// FALLTHROUGH
// We only get here if we woke up but the reply is not
// complete yet, time to assume the leader role....
// i.e. ACE_ASSERT (event->successful () == 0);
}
// = Leader Code.
// The only way to reach this point is if we must become the
// leader, because there is no leader or we have to update to a
// leader or we are doing nested upcalls in this case we do
// increase the refcount on the leader in TAO_ORB_Core.
// Calls this->set_client_leader_thread () on
// construction and this->reset_client_leader_thread ()
// on destruction. Note that this may increase the refcount of
// the leader.
TAO_LF_Client_Leader_Thread_Helper client_leader_thread_helper (*this);
ACE_UNUSED_ARG (client_leader_thread_helper);
{
ACE_GUARD_RETURN (ACE_Reverse_Lock<TAO_SYNCH_MUTEX>, rev_mon,
this->reverse_lock (), -1);
// Become owner of the reactor.
ACE_Reactor *reactor = this->reactor_;
reactor->owner (ACE_Thread::self ());
// Run the reactor event loop.
if (TAO_debug_level >= 5)
ACE_DEBUG ((LM_DEBUG,
"TAO (%P|%t) - Leader_Follower[%d]::wait_for_event,"
" (leader) enter reactor event loop\n",
t_id));
// If we got our event, no need to run the event loop any
// further.
while (event->keep_waiting ())
{
// Run the event loop.
result = reactor->handle_events (max_wait_time);
// Did we timeout? If so, stop running the loop.
if (result == 0 &&
max_wait_time != 0 &&
*max_wait_time == ACE_Time_Value::zero)
break;
// Other errors? If so, stop running the loop.
if (result == -1)
break;
// Otherwise, keep going...
}
if (TAO_debug_level >= 5)
ACE_DEBUG ((LM_DEBUG,
"TAO (%P|%t) - Leader_Follower[%d]::wait_for_event,"
" (leader) exit reactor event loop\n",
t_id));
}
}
//
// End artificial scope for auto_ptr like helpers calling:
// this->reset_client_thread () and (maybe)
// this->reset_client_leader_thread ().
//
// Wake up the next leader, we cannot do that in handle_input,
// because the woken up thread would try to get into handle_events,
// which is at the time in handle_input still occupied. But do it
// before checking the error in <result>, even if there is an error
// in our input we should continue running the loop in another
// thread.
if (this->elect_new_leader () == -1)
ACE_ERROR_RETURN ((LM_ERROR,
"TAO (%P|%t) - Leader_Follower[%d]::wait_for_event,"
" failed to elect new leader\n",
t_id),
-1);
if (result == -1 && !this->reactor_->reactor_event_loop_done ())
ACE_ERROR_RETURN ((LM_ERROR,
"TAO (%P|%t) - Leader_Follower[%d]::wait_for_event,"
" handle_events failed\n",
t_id),
-1);
// Return an error if there was a problem receiving the reply...
if (max_wait_time != 0)
{
if (!event->successful ()
&& *max_wait_time == ACE_Time_Value::zero)
{
result = -1;
errno = ETIME;
}
else if (event->error_detected ())
{
// If the time did not expire yet, but we get a failure,
// e.g. the connections closed, we should still return an error.
result = -1;
}
}
else
{
/**
* There should be no reason to reset the value of result
* here. If there was an error in handle_events () that the
* leader saw, I (Bala) beleave it should be propogated to the
* clients.
* result = 0;
*/
if (event->error_detected ())
{
result = -1;
}
}
return result;
}
int TAO_Leader_Follower::client_thread_is_leader_ [private] |
Is a client thread the current leader?
Definition at line 252 of file Leader_Follower.h.
int TAO_Leader_Follower::clients_ [private] |
Count the number of active clients, this is useful to know when to deactivate the reactor
Definition at line 246 of file Leader_Follower.h.
TAO_SYNCH_CONDITION TAO_Leader_Follower::event_loop_threads_condition_ [private] |
Condition variable for server threads waiting for the client leader to complete.
Definition at line 259 of file Leader_Follower.h.
int TAO_Leader_Follower::event_loop_threads_waiting_ [private] |
Are server threads waiting for the client leader to complete?
Definition at line 255 of file Leader_Follower.h.
Use a free list to allocate and release Follower objects.
Definition at line 234 of file Leader_Follower.h.
Definition at line 231 of file Leader_Follower.h.
int TAO_Leader_Follower::leaders_ [private] |
Count the number of active leaders. There could be many leaders in the thread pool (i.e. calling ORB::run), and the same leader could show up multiple times as it receives nested upcalls and sends more requests.
Definition at line 242 of file Leader_Follower.h.
TAO_SYNCH_MUTEX TAO_Leader_Follower::lock_ [private] |
To synchronize access to the members.
Definition at line 224 of file Leader_Follower.h.
Leader/Follower class uses this method to notify the system that we are out of leaders.
Definition at line 263 of file Leader_Follower.h.
TAO_ORB_Core* TAO_Leader_Follower::orb_core_ [private] |
The orb core.
Definition at line 221 of file Leader_Follower.h.
ACE_Reactor* TAO_Leader_Follower::reactor_ [private] |
The reactor.
Definition at line 249 of file Leader_Follower.h.
ACE_Reverse_Lock<TAO_SYNCH_MUTEX> TAO_Leader_Follower::reverse_lock_ [private] |
Do protect the access to the following three members.
Definition at line 227 of file Leader_Follower.h.
1.7.0