Public Member Functions | Private Types | Private Member Functions | Private Attributes

TAO_Leader_Follower Class Reference

TAO_Leader_Follower. More...

#include <Leader_Follower.h>

Collaboration diagram for TAO_Leader_Follower:
Collaboration graph
[legend]

List of all members.

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_Reactorreactor (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:

http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=296

TAO_LF_Followerallocate_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_Resourcesget_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_Coreorb_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_Reactorreactor_
 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_Generatornew_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)

Detailed Description

TAO_Leader_Follower.

TAO_Leader_Follower

Definition at line 49 of file Leader_Follower.h.


Member Typedef Documentation

Implement the Leader/Followers set using an intrusive list.

Definition at line 230 of file Leader_Follower.h.


Constructor & Destructor Documentation

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.

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;
}


Member Function Documentation

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.

Returns:
1 if there follower set is not empty

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.

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.

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.

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.

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.

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.

Parameters:
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
Returns:
Returns -1 on error, 0 or non-zero value otherwise.
Todo:
Document this better, split the Follower code to the TAO_LF_Follower class, we probably don't need the transport object.

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;
}


Member Data Documentation

Is a client thread the current leader?

Definition at line 252 of file Leader_Follower.h.

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.

Condition variable for server threads waiting for the client leader to complete.

Definition at line 259 of file Leader_Follower.h.

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.

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.

The orb core.

Definition at line 221 of file Leader_Follower.h.

The reactor.

Definition at line 249 of file Leader_Follower.h.

Do protect the access to the following three members.

Definition at line 227 of file Leader_Follower.h.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines