Public Member Functions | Protected Member Functions | Protected Attributes | Private Attributes

TAO_Connector Class Reference

Generic Connector interface definitions. More...

#include <Transport_Connector.h>

Inheritance diagram for TAO_Connector:
Inheritance graph
[legend]
Collaboration diagram for TAO_Connector:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 TAO_Connector (CORBA::ULong tag)
 Default constructor.
virtual ~TAO_Connector (void)
 The destructor.
CORBA::ULong tag (void) const
int make_mprofile (const char *ior, TAO_MProfile &mprofile)
virtual TAO_Profilecorbaloc_scan (const char *ior, size_t &len)
virtual int open (TAO_ORB_Core *orb_core)=0
 Initialize object and register with reactor.
virtual int close (void)=0
 Shutdown Connector bridge and concrete Connector.
virtual TAO_Transportconnect (TAO::Profile_Transport_Resolver *r, TAO_Transport_Descriptor_Interface *desc, ACE_Time_Value *timeout)
virtual TAO_Transportparallel_connect (TAO::Profile_Transport_Resolver *r, TAO_Transport_Descriptor_Interface *desc, ACE_Time_Value *timeout)
virtual TAO_Profilecreate_profile (TAO_InputCDR &cdr)=0
virtual int check_prefix (const char *endpoint)=0
virtual char object_key_delimiter (void) const =0
 Return the object key delimiter to use or expect.

Protected Member Functions

virtual int supports_parallel_connects (void) const
virtual TAO_Profilemake_profile (void)=0
 Create a profile with a given endpoint.
virtual int set_validate_endpoint (TAO_Endpoint *endpoint)=0
virtual TAO_Transportmake_connection (TAO::Profile_Transport_Resolver *r, TAO_Transport_Descriptor_Interface &desc, ACE_Time_Value *timeout)=0
 Make a connection.
virtual TAO_Transportmake_parallel_connection (TAO::Profile_Transport_Resolver *r, TAO_Transport_Descriptor_Interface &desc, ACE_Time_Value *timeout)
virtual int cancel_svc_handler (TAO_Connection_Handler *svc_handler)=0
 Cancel the passed cvs handler from the connector.
virtual int check_connection_closure (TAO_Connection_Handler *connection_handler)
 Check whether the connection is not closed.
virtual bool wait_for_connection_completion (TAO::Profile_Transport_Resolver *r, TAO_Transport_Descriptor_Interface &desc, TAO_Transport *&transport, ACE_Time_Value *timeout)
virtual bool wait_for_connection_completion (TAO::Profile_Transport_Resolver *r, TAO_Transport *&the_winner, TAO_Transport **transport, unsigned int count, TAO_LF_Multi_Event *mev, ACE_Time_Value *timeout)
bool new_connection_is_ok (size_t busy_count)
 See if a new connection is allowed.
bool wait_for_transport (TAO::Profile_Transport_Resolver *r, TAO_Transport *base_transport, ACE_Time_Value *timeout, bool force_wait)
void orb_core (TAO_ORB_Core *orb_core)
 Set the ORB Core pointer.
int create_connect_strategy (void)
 Create a connect strategy.
TAO_ORB_Coreorb_core (void)
 Return the TAO_ORB_Core pointer.

Protected Attributes

TAO_Connect_Strategyactive_connect_strategy_
 The (a)synch connect strategy.

Private Attributes

CORBA::ULong const tag_
 IOP protocol tag.
TAO_ORB_Coreorb_core_
 Pointer to our ORB core.

Detailed Description

Generic Connector interface definitions.

Base class for connector bridge object.

Todo:
Need to rename the class as TAO_Transport_Connector.

Definition at line 65 of file Transport_Connector.h.


Constructor & Destructor Documentation

TAO_Connector::TAO_Connector ( CORBA::ULong  tag  ) 

Default constructor.

Definition at line 72 of file Transport_Connector.cpp.

TAO_Connector::~TAO_Connector ( void   )  [virtual]

The destructor.

Definition at line 79 of file Transport_Connector.cpp.

{
  delete this->active_connect_strategy_;
}


Member Function Documentation

virtual int TAO_Connector::cancel_svc_handler ( TAO_Connection_Handler svc_handler  )  [protected, pure virtual]

Cancel the passed cvs handler from the connector.

Implemented in TAO_IIOP_Connector, TAO_DIOP_Connector, and TAO_UIOP_Connector.

int TAO_Connector::check_connection_closure ( TAO_Connection_Handler connection_handler  )  [protected, virtual]

Check whether the connection is not closed.

Return values:
0 The connection happens to be not closed, but is now open because an other thread managed to open the handler
-1 The connection is closed

Definition at line 1031 of file Transport_Connector.cpp.

{
  int result = -1;

  // Check if the handler has been closed.
  bool closed = connection_handler->is_closed ();

  // In case of failures and close() has not be called.
  if (!closed)
    {
      // First, cancel from connector.
      if (this->cancel_svc_handler (connection_handler) == -1)
        return -1;

      // Double check to make sure the handler has not been closed
      // yet.  This double check is required to ensure that the
      // connection handler was not closed yet by some other
      // thread since it was still registered with the connector.
      // Once connector.cancel() has been processed, we are
      // assured that the connector will no longer open/close this
      // handler.
      closed = connection_handler->is_closed ();

      // If closed, there is nothing to do here.  If not closed,
      // it was either opened or is still pending.
      if (!closed)
        {
          // Check if the handler has been opened.
          const bool open = connection_handler->is_open ();

          // Some other thread was able to open the handler even
          // though wait failed for this thread.
          if (open)
            {
              // Set the result to 0, we have an open connection
              result = 0;
            }
          else
            {
              // Assert that it is still connecting.
              ACE_ASSERT (connection_handler->is_connecting ());

              // Force close the handler now.
              connection_handler->close_handler ();
            }
        }
    }

  return result;
}

virtual int TAO_Connector::check_prefix ( const char *  endpoint  )  [pure virtual]

Check that the prefix of the provided endpoint is valid for use with a given pluggable protocol.

Implemented in TAO_IIOP_Connector, TAO_DIOP_Connector, and TAO_UIOP_Connector.

virtual int TAO_Connector::close ( void   )  [pure virtual]

Shutdown Connector bridge and concrete Connector.

Implemented in TAO_IIOP_Connector, TAO_DIOP_Connector, and TAO_UIOP_Connector.

TAO_Transport * TAO_Connector::connect ( TAO::Profile_Transport_Resolver *  r,
TAO_Transport_Descriptor_Interface desc,
ACE_Time_Value timeout 
) [virtual]

To support pluggable we need to abstract away the details of the connect () method so it can be called from the invocation code independent of the actual transport protocol in use.

Definition at line 484 of file Transport_Connector.cpp.

{
  TAO::Transport_Cache_Manager &tcm =
    this->orb_core ()->lane_resources ().transport_cache ();

  // Stay in this loop until we find:
  // a usable connection, or a timeout happens
  while (true)
    {
      // Find a connection in the cache
      // If transport found, reference count is incremented on assignment
      TAO_Transport *base_transport = 0;
      size_t busy_count = 0;
      TAO::Transport_Cache_Manager::Find_Result found =
          tcm.find_transport (desc,
                              base_transport,
                              busy_count);

      if (found == TAO::Transport_Cache_Manager::CACHE_FOUND_AVAILABLE)
        {
          TAO_Connection_Handler *ch = base_transport->connection_handler ();
          // one last check before using the cached connection
          if (ch->error_detected ())
            {
              if (TAO_debug_level > 0)
                {
                  ACE_DEBUG ((LM_DEBUG,
                    ACE_TEXT("TAO (%P|%t) Transport_Connector::connect, ")
                    ACE_TEXT("error in transport from cache\n")));
                }
              (void) base_transport->close_connection ();
              (void) base_transport->purge_entry ();
              base_transport->remove_reference ();
            }
          else if (ch->is_closed ())
            {
              if (TAO_debug_level > 0)
                {
                  ACE_DEBUG ((LM_DEBUG,
                    ACE_TEXT("TAO (%P|%t) Transport_Connector::connect, ")
                    ACE_TEXT("closed transport from cache\n")));
                }
              (void) base_transport->purge_entry ();
              base_transport->remove_reference ();
            }
          else
            {
              if (TAO_debug_level > 4)
                {
                  TAO::Connection_Role cr = base_transport->opened_as ();

                  ACE_DEBUG ((LM_DEBUG,
                              ACE_TEXT("TAO (%P|%t) - Transport_Connector::connect, ")
                              ACE_TEXT("got an existing %C Transport[%d] in role %C\n"),
                              base_transport->is_connected () ? "connected" :
                                                                "unconnected",
                              base_transport->id (),
                              cr == TAO::TAO_SERVER_ROLE ? "TAO_SERVER_ROLE" :
                              cr == TAO::TAO_CLIENT_ROLE ? "TAO_CLIENT_ROLE" :
                              "TAO_UNSPECIFIED_ROLE" ));
                }

              // If connected return.
              if (base_transport->is_connected ())
                return base_transport;

              // Is it possible to get a transport from the cache that
              // is not connected? If not, then the following code is
              // bogus. We cannot wait for a connection to complete on
              // a transport in the cache.
              //
              // (mesnier_p@ociweb.com) It is indeed possible to reach
              // this point.  The AMI_Buffering test does. When using
              // non-blocking connects and the first request(s) are
              // asynch and may be queued, the connection
              // establishment may not be completed by the time the
              // invocation is done with it. In that case it is up to
              // a subsequent invocation to handle the connection
              // completion.

              TransportCleanupGuard tg(base_transport);
              if (!this->wait_for_connection_completion (r, *desc,
                                                         base_transport,
                                                         timeout))
                {
                  if (TAO_debug_level > 2)
                    {
                      ACE_ERROR ((LM_ERROR,
                                  "TAO (%P|%t) - Transport_Connector::connect,"
                                  " wait for completion failed\n"));
                    }
                  return 0;
                }

              if (base_transport->is_connected () &&
                  base_transport->wait_strategy ()->register_handler () == -1)
                {
                  // Registration failures.
                  if (TAO_debug_level > 0)
                    {
                      ACE_ERROR ((LM_ERROR,
                                  "TAO (%P|%t) - Transport_Connector::connect, "
                                  "could not register the transport [%d]"
                                  "in the reactor.\n",
                                  base_transport->id ()));
                    }
                  return 0;
                }

              tg.clear ();
              return base_transport;
            }
        }
      else if (found == TAO::Transport_Cache_Manager::CACHE_FOUND_CONNECTING)
        {
          if (r->blocked_connect ())
            {
              if (TAO_debug_level > 4)
                {
                  ACE_DEBUG ((LM_DEBUG,
                              ACE_TEXT("TAO (%P|%t) - ")
                              ACE_TEXT("Transport_Connector::waiting ")
                              ACE_TEXT("for connection on transport [%d]\n"),
                              base_transport->id ()));
                }

              // If wait_for_transport returns no errors, the base_transport
              // points to the connection we wait for.
              if (this->wait_for_transport (r, base_transport, timeout, false))
                {
                  // be sure this transport is registered with the reactor
                  // before using it.
                  if (!base_transport->register_if_necessary ())
                    {
                        base_transport->remove_reference ();
                        return 0;
                    }
                }

              // In either success or failure cases of wait_for_transport, the
              // ref counter in corresponding to the ref counter added by
              // find_transport is decremented.
              base_transport->remove_reference ();
            }
          else
            {
              if (TAO_debug_level > 4)
                {
                  ACE_DEBUG ((LM_DEBUG,
                              ACE_TEXT("TAO (%P|%t) - ")
                              ACE_TEXT("Transport_Connector::non-blocking:")
                              ACE_TEXT("returning unconnected ")
                              ACE_TEXT("transport [%d]\n"),
                    base_transport->id ()));
                }

              // return the transport in it's current, unconnected state
              return base_transport;
            }
        }
      else
        {
          if (desc == 0 ||
              (this->set_validate_endpoint (desc->endpoint ()) == -1))
            return 0;

          // @todo: This is not the right place for this! (bugzilla 3023)
          // Purge connections (if necessary)
          tcm.purge ();
          bool make_new_connection =
            (found == TAO::Transport_Cache_Manager::CACHE_FOUND_NONE) ||
            (found == TAO::Transport_Cache_Manager::CACHE_FOUND_BUSY
                && this->new_connection_is_ok (busy_count));

          if (make_new_connection)
            {
              // we aren't going to use the transport returned from the cache
              // (if any)
              if (base_transport != 0)
                {
                  base_transport->remove_reference ();
                }

              base_transport = this->make_connection (r, *desc, timeout);
              if (base_transport == 0)
                {
                  if (TAO_debug_level > 4)
                    {
                      ACE_DEBUG ((LM_DEBUG,
                        ACE_TEXT ("TAO (%P|%t) - Transport_Connector::")
                        ACE_TEXT ("connect, make_connection failed\n")));
                    }
                  return 0;
                }

              if (TAO_debug_level > 4)
                {
                  ACE_DEBUG ((LM_DEBUG,
                              ACE_TEXT("TAO (%P|%t) - ")
                              ACE_TEXT("Transport_Connector::connect, ")
                              ACE_TEXT("opening Transport[%d] in ")
                              ACE_TEXT("TAO_CLIENT_ROLE\n"),
                              base_transport->id ()));
                }

              // Call post connect hook. If the post_connect_hook () returns
              // false, just purge the entry.
              if (!base_transport->post_connect_hook ())
                {
                  if (TAO_debug_level > 4)
                    {
                      ACE_DEBUG ((LM_DEBUG,
                                  ACE_TEXT("TAO (%P|%t) - Post_connect_hook ")
                                  ACE_TEXT("failed. ")
                                  ACE_TEXT("Purging transport[%d]\n"),
                                  base_transport->id ()));
                    }
                  (void) base_transport->purge_entry ();
                }
              // The new transport is in the cache.  We'll pick it up from the
              // next time thru this loop (using it from here causes more
              // problems than it fixes due to the changes that allow a new
              // connection to be re-used by a nested upcall before we get back
              // here.)
              base_transport->remove_reference ();
            }
          else // not making new connection
            {
              (void) this->wait_for_transport (r, base_transport,
                                               timeout, true);
              base_transport->remove_reference ();
            }
        }
    }
}

TAO_Profile * TAO_Connector::corbaloc_scan ( const char *  ior,
size_t &  len 
) [virtual]

Helper function to assist corbaloc parsing. The default simply validates the protocol identifyier and scans up to the next comma or slash. Any protocol that has a specific need, such as uiop, can override this method to provide a custom scanner. The profile returned is either null if this the ior does not match or an empty profile of the correct type, obtained from make_profile().

Reimplemented in TAO_UIOP_Connector.

Definition at line 85 of file Transport_Connector.cpp.

{
  if (this->check_prefix (str) != 0)
    return 0;
  const char *comma_pos = ACE_OS::strchr (str,',');
  const char *slash_pos = ACE_OS::strchr (str,'/');
  if (comma_pos == 0 && slash_pos == 0)
    {
      len = ACE_OS::strlen (str);
    }
  else if (comma_pos == 0 || comma_pos > slash_pos)
    len = (slash_pos - str);
  else len = comma_pos - str;
  return this->make_profile();
}

int TAO_Connector::create_connect_strategy ( void   )  [protected]

Create a connect strategy.

Definition at line 1001 of file Transport_Connector.cpp.

{
  if (this->active_connect_strategy_ == 0)
    {
      this->active_connect_strategy_ =
        this->orb_core_->client_factory ()->create_connect_strategy (
          this->orb_core_);
    }

  if (this->active_connect_strategy_ == 0)
    {
      return -1;
    }

  return 0;
}

virtual TAO_Profile* TAO_Connector::create_profile ( TAO_InputCDR cdr  )  [pure virtual]

Create a profile for this protocol and initialize it based on the encapsulation in cdr

Implemented in TAO_IIOP_Connector, TAO_DIOP_Connector, and TAO_UIOP_Connector.

virtual TAO_Transport* TAO_Connector::make_connection ( TAO::Profile_Transport_Resolver *  r,
TAO_Transport_Descriptor_Interface desc,
ACE_Time_Value timeout 
) [protected, pure virtual]

Make a connection.

Implemented in TAO_IIOP_Connector, TAO_DIOP_Connector, and TAO_UIOP_Connector.

int TAO_Connector::make_mprofile ( const char *  ior,
TAO_MProfile mprofile 
)

Parse a string containing a URL style IOR and return an MProfile. Verify that ior is in the correct format.

Definition at line 102 of file Transport_Connector.cpp.

{
  // This method utilizes the "Template Method" design pattern to
  // parse the given URL style IOR for the protocol being used
  // and create an mprofile from it.
  //
  // The methods that must be defined by all Connector sub-classes are:
  //      make_profile
  //      check_prefix

  // Check for a valid string
  if (!string || !*string)
    {
      throw ::CORBA::INV_OBJREF (
        CORBA::SystemException::_tao_minor_code (
          0,
          EINVAL),
        CORBA::COMPLETED_NO);
    }

  // Check for the proper prefix in the IOR.  If the proper prefix isn't
  // in the IOR then it is not an IOR we can use.
  if (this->check_prefix (string) != 0)
    {
      return 1;
      // Failure: not the correct IOR for this protocol.
      // DO NOT throw an exception here since the Connector_Registry
      // should be allowed the opportunity to continue looking for
      // an appropriate connector.
    }

  if (TAO_debug_level > 0)
    {
      ACE_DEBUG ((LM_DEBUG,
                  ACE_TEXT ("TAO (%P|%t) - TAO_Connector::make_mprofile ")
                  ACE_TEXT ("<%C>\n"),
                  string));
    }

  ACE_CString ior;

  ior.set (string, ACE_OS::strlen (string), 1);

  // Find out where the protocol ends
  ACE_CString::size_type ior_index = ior.find ("://");

  if (ior_index == ACE_CString::npos)
    {
      throw ::CORBA::INV_OBJREF ();
      // No colon ':' in the IOR!
    }
  else
    {
      ior_index += 3;
      // Add the length of the colon and the two forward slashes `://'
      // to the IOR string index (i.e. 3)
    }

  // Find the object key
  const ACE_CString::size_type objkey_index =
    ior.find (this->object_key_delimiter (), ior_index);

  if (objkey_index == 0 || objkey_index == ACE_CString::npos)
    {
      throw ::CORBA::INV_OBJREF ();
      // Failure: No endpoints specified or no object key specified.
    }

  const char endpoint_delimiter = ',';
  // The delimiter used to seperate inidividual addresses.

  // Count the number of endpoints in the IOR.  This will be the number
  // of entries in the MProfile.

  CORBA::ULong profile_count = 1;
  // Number of endpoints in the IOR  (initialized to 1).

  // Only check for endpoints after the protocol specification and
  // before the object key.
  for (ACE_CString::size_type i = ior_index; i < objkey_index; ++i)
    {
      if (ior[i] == endpoint_delimiter)
        ++profile_count;
    }

  // Tell the MProfile object how many Profiles it should hold.
  // MProfile::set(size) returns the number profiles it can hold.
  if (mprofile.set (profile_count) != static_cast<int> (profile_count))
    {
      throw ::CORBA::INV_OBJREF (
        CORBA::SystemException::_tao_minor_code (
          TAO_MPROFILE_CREATION_ERROR,
          0),
        CORBA::COMPLETED_NO);
      // Error while setting the MProfile size!
    }

  // The idea behind the following loop is to split the IOR into several
  // strings that can be parsed by each profile.
  // For example,
  //    `1.3@moo,shu,1.1@chicken/arf'
  // will be parsed into:
  //    `1.3@moo/arf'
  //    `shu/arf'
  //    `1.1@chicken/arf'

  ACE_CString::size_type begin = 0;
  ACE_CString::size_type end = ior_index - 1;
  // Initialize the end of the endpoint index

  for (CORBA::ULong j = 0; j < profile_count; ++j)
    {
      begin = end + 1;

      if (j < profile_count - 1)
        {
          end = ior.find (endpoint_delimiter, begin);
        }
      else
        {
          end = objkey_index;  // Handle last endpoint differently
        }

      if (end < ior.length () && end != ior.npos)
        {
          ACE_CString endpoint = ior.substring (begin, end - begin);

          // Add the object key to the string.
          endpoint += ior.substring (objkey_index);

          // The endpoint should now be of the form:
          //    `N.n@endpoint/object_key'
          // or
          //    `endpoint/object_key'

          TAO_Profile *profile =
            this->make_profile ();
          // Failure:  Problem during profile creation

          // Initialize a Profile using the individual endpoint
          // string.
          // @@ Not exception safe!  We need a TAO_Profile_var!
          profile->parse_string (endpoint.c_str ()
                                );

          // Give up ownership of the profile.
          if (mprofile.give_profile (profile) == -1)
            {
              profile->_decr_refcnt ();

              throw ::CORBA::INV_OBJREF (
                CORBA::SystemException::_tao_minor_code (
                  TAO_MPROFILE_CREATION_ERROR,
                  0),
                CORBA::COMPLETED_NO);
              // Failure presumably only occurs when MProfile is full!
              // This should never happen.
            }
        }
      else
        {
          throw ::CORBA::INV_OBJREF ();
          // Unable to seperate endpoints
        }
    }

  return 0;  // Success
}

TAO_Transport * TAO_Connector::make_parallel_connection ( TAO::Profile_Transport_Resolver *  r,
TAO_Transport_Descriptor_Interface desc,
ACE_Time_Value timeout 
) [protected, virtual]

Make a connection using - not a pure virtual since not all protocols support this.

Reimplemented in TAO_IIOP_Connector.

Definition at line 278 of file Transport_Connector.cpp.

{
  return 0;
}

virtual TAO_Profile* TAO_Connector::make_profile ( void   )  [protected, pure virtual]

Create a profile with a given endpoint.

Implemented in TAO_IIOP_Connector, TAO_DIOP_Connector, and TAO_UIOP_Connector.

bool TAO_Connector::new_connection_is_ok ( size_t  busy_count  )  [protected]

See if a new connection is allowed.

Definition at line 1019 of file Transport_Connector.cpp.

{
  if (this->orb_core_ == 0)
    return true;

  unsigned int mux_limit = this->orb_core_->resource_factory ()
    ->max_muxed_connections ();

  return mux_limit == 0 || busy_count < mux_limit;
}

virtual char TAO_Connector::object_key_delimiter ( void   )  const [pure virtual]

Return the object key delimiter to use or expect.

Implemented in TAO_IIOP_Connector, TAO_DIOP_Connector, and TAO_UIOP_Connector.

virtual int TAO_Connector::open ( TAO_ORB_Core orb_core  )  [pure virtual]

Initialize object and register with reactor.

Implemented in TAO_IIOP_Connector, TAO_DIOP_Connector, and TAO_UIOP_Connector.

void TAO_Connector::orb_core ( TAO_ORB_Core orb_core  )  [protected]

Set the ORB Core pointer.

Definition at line 14 of file Transport_Connector.inl.

{
  this->orb_core_ = orb_core;
}

TAO_ORB_Core * TAO_Connector::orb_core ( void   )  [protected]

Return the TAO_ORB_Core pointer.

Definition at line 8 of file Transport_Connector.inl.

{
  return this->orb_core_;
}

TAO_Transport * TAO_Connector::parallel_connect ( TAO::Profile_Transport_Resolver *  r,
TAO_Transport_Descriptor_Interface desc,
ACE_Time_Value timeout 
) [virtual]

A variation on connect that will try simultanious connections on all endpoints listed in the desc.

Definition at line 287 of file Transport_Connector.cpp.

{
  if (this->supports_parallel_connects() == 0)
    {
      errno = ENOTSUP;
      return 0;
    }

  errno = 0; // need to clear errno to ensure a stale enotsup is not set
  if (desc == 0)
    return 0;
  TAO_Endpoint *root_ep = desc->endpoint();
  TAO_Transport *base_transport = 0;

  TAO::Transport_Cache_Manager &tcm =
    this->orb_core ()->lane_resources ().transport_cache ();

  // Iterate through the endpoints. Since find_transport takes a
  // Transport Descriptor rather than an endpoint, we must create a
  // local TDI for each endpoint. The first one found will be used.
  for (TAO_Endpoint *ep = root_ep->next_filtered (this->orb_core(),0);
       ep != 0;
       ep = ep->next_filtered(this->orb_core(),root_ep))
    {
      TAO_Base_Transport_Property desc2(ep,0);
      size_t busy_count = 0;
      if (tcm.find_transport (&desc2, base_transport, busy_count) ==
          TAO::Transport_Cache_Manager::CACHE_FOUND_AVAILABLE )
        {
          if (TAO_debug_level)
            {
              ACE_DEBUG ((LM_DEBUG,
                          ACE_TEXT ("TAO (%P|%t) - TAO_Connector::parallel_connect: ")
                          ACE_TEXT ("found a transport [%d]\n"),
                          base_transport->id ()));
            }
          return base_transport;
        }
    }

  // Now we have searched the cache on all endpoints and come up
  // empty. We need to initiate connections on each of the
  // endpoints. Presumably only one will have a route and will succeed,
  // and the rest will fail. This requires the use of asynch
  // connection establishment. Maybe a custom wait strategy is needed
  // at this point to register several potential transports so that
  // when one succeeds the rest are cancelled or closed.

  unsigned int endpoint_count = 0;
  for (TAO_Endpoint *ep = root_ep->next_filtered (this->orb_core(),0);
       ep != 0;
       ep = ep->next_filtered(this->orb_core(),root_ep))
    if (this->set_validate_endpoint (ep) == 0)
      ++endpoint_count;
  if (endpoint_count == 0)
    return 0;
  return this->make_parallel_connection (r,*desc,timeout);
}

virtual int TAO_Connector::set_validate_endpoint ( TAO_Endpoint endpoint  )  [protected, pure virtual]

Set and validate endpoint. We need to do this to initialize our remote *_Addr's which have not been done during IOR decode.

Implemented in TAO_IIOP_Connector, TAO_DIOP_Connector, and TAO_UIOP_Connector.

int TAO_Connector::supports_parallel_connects ( void   )  const [protected, virtual]

A flag indicating the actual connector supports parallel connection attempts. The base implementation alwayse returns 0. Override to return non-zero if parallel connection attempts may be tried.

Reimplemented in TAO_IIOP_Connector.

Definition at line 272 of file Transport_Connector.cpp.

{
  return 0; // by default, we don't support parallel connection attempts;
}

CORBA::ULong TAO_Connector::tag ( void   )  const

The tag identifying the specific ORB transport layer protocol. For example IOP::TAG_INTERNET_IOP == 0. The tag is used in the IOR to identify the type of profile included. IOR -> {{tag0, profile0} {tag1, profile1} ...}. The IOP module defines the ProfileId typedef to be a CORBA::ULong.

Definition at line 20 of file Transport_Connector.inl.

{
  return this->tag_;
}

bool TAO_Connector::wait_for_connection_completion ( TAO::Profile_Transport_Resolver *  r,
TAO_Transport_Descriptor_Interface desc,
TAO_Transport *&  transport,
ACE_Time_Value timeout 
) [protected, virtual]

Wait for connection completion. We have a transport that is not connected yet, wait until it is connected.

Return values:
true When we could use transport
Returns:
false When we can't use the transport

Definition at line 723 of file Transport_Connector.cpp.

{
  int result = -1;
  if (transport->connection_handler ()->is_open ())
    {
      TAO::Transport_Cache_Manager &tcm =
        this->orb_core ()->lane_resources ().transport_cache ();
      result = tcm.cache_transport (&desc, transport);
      if (result == -1)
      {

      }
    }
  else if (transport->connection_handler ()->is_timeout ())
    {
      if (TAO_debug_level > 2)
        {
          ACE_DEBUG ((LM_DEBUG,
                      ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
                      ACE_TEXT("wait_for_connection_completion, ")
                      ACE_TEXT("transport [%d], Connection timed out.\n"),
                      transport->id ()));
        }
      result = -1;
      errno = ETIME;
    }
  else if (transport->connection_handler ()->is_closed ())
    {
      if (TAO_debug_level > 2)
        {
          ACE_DEBUG ((LM_DEBUG,
                      ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
                      ACE_TEXT("wait_for_connection_completion, ")
                      ACE_TEXT("transport [%d], Connection failed. (%d) %p\n"),
                      transport->id (), ACE_ERRNO_GET, ACE_TEXT("")));
        }
      result = -1;
    }
  else
    {
      if (TAO_debug_level > 2)
        {
          ACE_DEBUG ((LM_DEBUG,
                      ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
                      ACE_TEXT("wait_for_connection_completion, ")
                      ACE_TEXT("transport [%d], Connection not complete.\n"),
                      transport->id ()));
        }

      TAO::Transport_Cache_Manager &tcm =
        this->orb_core ()->lane_resources ().transport_cache ();
      result = tcm.cache_transport (&desc, transport, TAO::ENTRY_CONNECTING);

      if (result != -1)
        {
          if (r->blocked_connect ())
            {
              if (TAO_debug_level > 2)
                {
                  ACE_DEBUG ((LM_DEBUG,
                              ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
                              ACE_TEXT("wait_for_connection_completion, ")
                              ACE_TEXT("going to wait for connection completion on ")
                              ACE_TEXT("transport[%d]\n"),
                              transport->id ()));
                }

              result = this->active_connect_strategy_->wait (transport, timeout);

              if (TAO_debug_level > 2)
                {
                  ACE_DEBUG ((LM_DEBUG,
                              ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
                              ACE_TEXT("wait_for_connection_completion, ")
                              ACE_TEXT("transport [%d], wait done result = %d\n"),
                              transport->id (), result));
                }


              // There are three possibilities when wait() returns: (a)
              // connection succeeded; (b) connection failed; (c) wait()
              // failed because of some other error.  It is easy to deal with
              // (a) and (b).  (c) is tricky since the connection is still
              // pending and may get completed by some other thread.  The
              // following code deals with (c).

              if (result == -1)
                {
                  if (errno == ETIME)
                    {
                      if (timeout == 0)
                        {
                          // There was an error during connecting and the errno was
                          // ETIME.  We didn't pass in a timeout, so there's
                          // something wrong with this transport.  So, it must be
                          // purged.
                          transport->purge_entry ();
                        }

                      if (TAO_debug_level > 2)
                        {
                          ACE_DEBUG ((LM_DEBUG,
                                      ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
                                      ACE_TEXT("wait_for_connection_completion, ")
                                      ACE_TEXT("transport [%d], Connection timed out.\n"),
                                      transport->id ()));
                        }
                    }
                  else
                    {
                      // The wait failed for some other reason.
                      // Report that making the connection failed
                      if (TAO_debug_level > 2)
                        {
                          ACE_ERROR ((LM_ERROR,
                                      ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
                                      ACE_TEXT("wait_for_connection_completion, ")
                                      ACE_TEXT("transport [%d], wait for completion failed")
                                      ACE_TEXT(" (%d) %p\n"),
                                      transport->id (), ACE_ERRNO_GET, ACE_TEXT("")));
                        }
                      TAO_Connection_Handler *con =
                        transport->connection_handler ();
                      result = this->check_connection_closure (con);
                      transport->purge_entry ();
                    }
                }
            }
          else //non-blocked connect (based on invocation, not connect strategy)
            {
              transport->connection_handler ()->
                reset_state (TAO_LF_Event::LFS_CONNECTION_WAIT);
              if (TAO_debug_level > 9)
                {
                  ACE_DEBUG ((LM_DEBUG,
                              ACE_TEXT("TAO (%P|%t) - TAO_Connector[%d]::")
                              ACE_TEXT("wait_for_connection_completion reset_state to ")
                              ACE_TEXT("LFS_CONNECTION_WAIT\n"), transport->id ()));
                }
              result = 0;
            }
        }
    }

  if (result == -1)
    {
      // Set transport to zero, it is not usable, and the reference
      // count we added above was decremented by the base connector
      // handling the connection failure.
      transport = 0;
      return false;
    }
  // Connection not ready yet but we can use this transport, if
  // we need a connected one we will block later to make sure
  // it is connected
  return true;
}

bool TAO_Connector::wait_for_connection_completion ( TAO::Profile_Transport_Resolver *  r,
TAO_Transport *&  the_winner,
TAO_Transport **  transport,
unsigned int  count,
TAO_LF_Multi_Event mev,
ACE_Time_Value timeout 
) [protected, virtual]

In the case of a parallel connection attempt, we take an array of transports, and wait on any of them. When the first one completes, the rest are closed.

Definition at line 886 of file Transport_Connector.cpp.

{
  if (TAO_debug_level > 2)
    {
      ACE_DEBUG ((LM_DEBUG,
                  ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
                  ACE_TEXT("wait_for_connection_completion, ")
                  ACE_TEXT("waiting for connection completion on ")
                  ACE_TEXT("%d transports, ["),
                  count));
      for (unsigned int i = 0; i < count; i++)
        ACE_DEBUG ((LM_DEBUG,
                    ACE_TEXT("%d%C"),transport[i]->id (),
                    (i < (count -1) ? ", " : "]\n")));
    }

  int result = -1;
  if (r->blocked_connect ())
    {
      result = this->active_connect_strategy_->wait (mev, timeout);
      the_winner = 0;
    }
  else
    {
      errno = ETIME;
    }

  if (result != -1)
    {
      the_winner = mev->winner()->transport();
      if (TAO_debug_level > 2)
        {
          ACE_DEBUG ((LM_DEBUG,
                      ACE_TEXT ("TAO (%P|%t) - Transport_Connector::")
                      ACE_TEXT ("wait_for_connection_completion, ")
                      ACE_TEXT ("transport [%d]\n"),
                      the_winner->id ()));
        }
    }
  else if (errno == ETIME)
    {
      // this is the most difficult case. In this situation, there is no
      // nominated by the Multi_Event. The best we can do is pick one of
      // the pending connections.
      // Of course, this shouldn't happen in any case, since the wait
      // strategy is called with a timeout value of 0.
      for (unsigned int i = 0; i < count; i++)
        if (!transport[i]->connection_handler()->is_closed())
          {
            the_winner = transport[i];
            break;
          }
    }

  // It is possible that we have more than one connection that happened
  // to complete, or that none completed. Therefore we need to traverse
  // the list and ensure that all of the losers are closed.
  for (unsigned int i = 0; i < count; i++)
    {
      if (transport[i] != the_winner)
        this->check_connection_closure (transport[i]->connection_handler());
      // since we are doing this on may connections, the result isn't
      // particularly important.
    }

  // In case of errors.
  if (the_winner == 0)
    {
      // Report that making the connection failed, don't print errno
      // because we touched the reactor and errno could be changed
      if (TAO_debug_level > 2)
        {
          ACE_ERROR ((LM_ERROR,
                      ACE_TEXT ("TAO (%P|%t) - Transport_Connector::")
                      ACE_TEXT ("wait_for_connection_completion, failed\n")
                      ));
        }

      return false;
    }

  // Fix for a subtle problem. What happens if we are supposed to do
  // blocked connect but the transport is NOT connected? Force close
  // the connections
  if (r->blocked_connect () && !the_winner->is_connected ())
    {
      if (TAO_debug_level > 2)
        {
          ACE_DEBUG ((LM_DEBUG,
                      ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
                      ACE_TEXT("wait_for_connection_completion, ")
                      ACE_TEXT("no connected transport for a blocked connection, ")
                      ACE_TEXT("cancelling connections and reverting things\n")));
        }

      // Forget the return value. We are busted anyway. Try our best
      // here.
      (void) this->cancel_svc_handler (the_winner->connection_handler ());
      the_winner = 0;
      return false;
    }

  // Connection may not ready for SYNC_NONE and SYNC_DELAYED_BUFFERING cases
  // but we can use this transport, if we need a connected one we will poll
  // later to make sure it is connected
  return true;
}

bool TAO_Connector::wait_for_transport ( TAO::Profile_Transport_Resolver *  r,
TAO_Transport base_transport,
ACE_Time_Value timeout,
bool  force_wait 
) [protected]

Wait for a transport to be connected Note: no longer changes transport reference count @ returns true if wait was uneventful @ false if error occurred during wait

Definition at line 349 of file Transport_Connector.cpp.

{
  if (transport->connection_handler ()->is_timeout ())
    {
      if (TAO_debug_level > 2)
        {
          ACE_DEBUG ((LM_DEBUG,
            ACE_TEXT ("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
            ACE_TEXT ("transport [%d], Connection Timed out.\n"),
                      transport->id ()));
        }
      transport->purge_entry ();
      return false;
    }
  else if (transport->connection_handler ()->is_closed ())
    {
      if (TAO_debug_level > 2)
        {
          ACE_DEBUG ((LM_DEBUG,
            ACE_TEXT ("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
            ACE_TEXT ("transport [%d], Connection failed. (%d)\n"),
                      transport->id (), ACE_ERRNO_GET));
        }

      // purge from the connection cache.  If we are not in the
      // cache, this does nothing.
      transport->purge_entry ();

      // Close the handler.
      transport->close_connection ();

      return false;
    }
  else if (transport->connection_handler ()->is_open ())
    {
      if (TAO_debug_level > 5)
        {
          ACE_DEBUG ((LM_DEBUG,
            ACE_TEXT("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
            ACE_TEXT("transport [%d], connection is open: no wait.\n"),
            transport->id () ));
        }

      return true;
    }
  else if (force_wait || r->blocked_connect ())
    {
      if (TAO_debug_level > 2)
        {
          ACE_DEBUG ((LM_DEBUG,
            ACE_TEXT("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
            ACE_TEXT("waiting on transport [%d]\n"),
            transport->id () ));
        }

      // We must ensure that there is a timeout if there was none
      // supplied and the connection isn't a blocking connection.  If
      // another thread has called ORB::run() prior to this attempted
      // connection, the wait() call will block forever (or until the ORB
      // thread leaves the reactor, which may not happen).
      int result = 0;
      if (timeout == 0 && !r->blocked_connect ())
        {
          ACE_Time_Value tv (0, 500);
          result = this->active_connect_strategy_->wait (transport, &tv);
        }
      else
        result = this->active_connect_strategy_->wait (transport, timeout);

      if (result == -1 && errno == ETIME)
        {
          if (TAO_debug_level > 2)
            {
              ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
              ACE_TEXT(" timeout while waiting on transport [%d]\n"),
              transport->id () ));
            }
        }
      else if (result == -1)
        {
          if (TAO_debug_level > 2)
            {
              static int complain10times = 10;
              if (complain10times > 0)
                {
                  --complain10times;
                  ACE_DEBUG ((LM_DEBUG,
                    ACE_TEXT("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
                    ACE_TEXT(" unknown error waiting on transport [%d] (%d)\n"),
                    transport->id (),
                    ACE_ERRNO_GET));
                }
            }
          // purge from the connection cache.  If we are not in the
          // cache, this does nothing.
          transport->purge_entry ();

          // Close the handler.
          transport->close_connection ();
        }
      else
        {
          if (TAO_debug_level > 5)
            {
              ACE_DEBUG ((LM_DEBUG,
                ACE_TEXT("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
                ACE_TEXT("transport [%d], wait completed ok.\n"),
                transport->id () ));
            }
          return true;
        }
    }
  else
    {
      if (TAO_debug_level > 2)
        {
          ACE_DEBUG ((LM_DEBUG,
            ACE_TEXT ("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
            ACE_TEXT ("Connection not complete [%d] reset state to ")
            ACE_TEXT ("LFS_CONNECTION_WAIT\n"), transport->id ()));
        }
      transport->connection_handler ()->reset_state (
        TAO_LF_Event::LFS_CONNECTION_WAIT);

      return true;
    }

  return false;
}


Member Data Documentation

The (a)synch connect strategy.

Definition at line 214 of file Transport_Connector.h.

Pointer to our ORB core.

Definition at line 222 of file Transport_Connector.h.

IOP protocol tag.

Definition at line 219 of file Transport_Connector.h.


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