00001 #include "tao/Transport_Connector.h"
00002 #include "tao/Transport.h"
00003 #include "tao/ORB_Core.h"
00004 #include "tao/MProfile.h"
00005 #include "tao/Profile.h"
00006 #include "tao/Thread_Lane_Resources.h"
00007 #include "tao/debug.h"
00008 #include "tao/Connect_Strategy.h"
00009 #include "tao/LF_Multi_Event.h"
00010 #include "tao/Client_Strategy_Factory.h"
00011 #include "tao/Connection_Handler.h"
00012 #include "tao/Profile_Transport_Resolver.h"
00013 #include "tao/Wait_Strategy.h"
00014 #include "tao/SystemException.h"
00015 #include "tao/Endpoint.h"
00016 #include "tao/Base_Transport_Property.h"
00017
00018 #include "ace/OS_NS_string.h"
00019
00020
00021
00022 #if !defined (__ACE_INLINE__)
00023 # include "tao/Transport_Connector.inl"
00024 #endif
00025
00026 ACE_RCSID (tao,
00027 Connector,
00028 "$Id: Transport_Connector.cpp 79388 2007-08-17 16:05:00Z wilsond $")
00029
00030 namespace
00031 {
00032 class TransportCleanupGuard
00033 {
00034 public:
00035
00036 TransportCleanupGuard (TAO_Transport *tp)
00037 : tp_ (tp)
00038 , awake_ (true)
00039 {
00040 }
00041
00042 ~TransportCleanupGuard ()
00043 {
00044 if (this->awake_ && this->tp_)
00045 {
00046
00047
00048 this->tp_->purge_entry ();
00049
00050
00051 this->tp_->close_connection ();
00052
00053 this->tp_->remove_reference ();
00054 }
00055 }
00056
00057
00058 void down ()
00059 {
00060 this->awake_ = false;
00061 }
00062
00063 private:
00064
00065 TAO_Transport * const tp_;
00066 bool awake_;
00067
00068 };
00069 }
00070
00071 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00072
00073
00074 TAO_Connector::TAO_Connector (CORBA::ULong tag)
00075 : active_connect_strategy_ (0),
00076 tag_ (tag),
00077 orb_core_ (0)
00078 {
00079 }
00080
00081 TAO_Connector::~TAO_Connector (void)
00082 {
00083 delete this->active_connect_strategy_;
00084 }
00085
00086 TAO_Profile *
00087 TAO_Connector::corbaloc_scan (const char *str, size_t &len)
00088 {
00089 if (this->check_prefix (str) != 0)
00090 return 0;
00091 const char *comma_pos = ACE_OS::strchr (str,',');
00092 const char *slash_pos = ACE_OS::strchr (str,'/');
00093 if (comma_pos == 0 && slash_pos == 0)
00094 {
00095 len = ACE_OS::strlen (str);
00096 }
00097 else if (comma_pos == 0 || comma_pos > slash_pos)
00098 len = (slash_pos - str);
00099 else len = comma_pos - str;
00100 return this->make_profile();
00101 }
00102
00103 int
00104 TAO_Connector::make_mprofile (const char *string, TAO_MProfile &mprofile)
00105 {
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 if (!string || !*string)
00116 {
00117 throw ::CORBA::INV_OBJREF (
00118 CORBA::SystemException::_tao_minor_code (
00119 0,
00120 EINVAL),
00121 CORBA::COMPLETED_NO);
00122 }
00123
00124
00125
00126 if (this->check_prefix (string) != 0)
00127 {
00128 return 1;
00129
00130
00131
00132
00133 }
00134
00135 if (TAO_debug_level > 0)
00136 {
00137 ACE_DEBUG ((LM_DEBUG,
00138 ACE_TEXT ("TAO (%P|%t) - TAO_Connector::make_mprofile ")
00139 ACE_TEXT ("<%s>\n"),
00140 ACE_TEXT_CHAR_TO_TCHAR (string)));
00141 }
00142
00143 ACE_CString ior;
00144
00145 ior.set (string, ACE_OS::strlen (string), 1);
00146
00147
00148 ACE_CString::size_type ior_index = ior.find ("://");
00149
00150 if (ior_index == ACE_CString::npos)
00151 {
00152 throw ::CORBA::INV_OBJREF ();
00153
00154 }
00155 else
00156 {
00157 ior_index += 3;
00158
00159
00160 }
00161
00162
00163 const ACE_CString::size_type objkey_index =
00164 ior.find (this->object_key_delimiter (), ior_index);
00165
00166 if (objkey_index == 0 || objkey_index == ACE_CString::npos)
00167 {
00168 throw ::CORBA::INV_OBJREF ();
00169
00170 }
00171
00172 const char endpoint_delimiter = ',';
00173
00174
00175
00176
00177
00178 CORBA::ULong profile_count = 1;
00179
00180
00181
00182
00183 for (ACE_CString::size_type i = ior_index; i < objkey_index; ++i)
00184 {
00185 if (ior[i] == endpoint_delimiter)
00186 ++profile_count;
00187 }
00188
00189
00190
00191 if (mprofile.set (profile_count) != static_cast<int> (profile_count))
00192 {
00193 throw ::CORBA::INV_OBJREF (
00194 CORBA::SystemException::_tao_minor_code (
00195 TAO_MPROFILE_CREATION_ERROR,
00196 0),
00197 CORBA::COMPLETED_NO);
00198
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 ACE_CString::size_type begin = 0;
00211 ACE_CString::size_type end = ior_index - 1;
00212
00213
00214 for (CORBA::ULong j = 0; j < profile_count; ++j)
00215 {
00216 begin = end + 1;
00217
00218 if (j < profile_count - 1)
00219 {
00220 end = ior.find (endpoint_delimiter, begin);
00221 }
00222 else
00223 {
00224 end = objkey_index;
00225 }
00226
00227 if (end < ior.length () && end != ior.npos)
00228 {
00229 ACE_CString endpoint = ior.substring (begin, end - begin);
00230
00231
00232 endpoint += ior.substring (objkey_index);
00233
00234
00235
00236
00237
00238
00239 TAO_Profile *profile =
00240 this->make_profile ();
00241
00242
00243
00244
00245
00246 profile->parse_string (endpoint.c_str ()
00247 );
00248
00249
00250 if (mprofile.give_profile (profile) == -1)
00251 {
00252 profile->_decr_refcnt ();
00253
00254 throw ::CORBA::INV_OBJREF (
00255 CORBA::SystemException::_tao_minor_code (
00256 TAO_MPROFILE_CREATION_ERROR,
00257 0),
00258 CORBA::COMPLETED_NO);
00259
00260
00261 }
00262 }
00263 else
00264 {
00265 throw ::CORBA::INV_OBJREF ();
00266
00267 }
00268 }
00269
00270 return 0;
00271 }
00272
00273 int
00274 TAO_Connector::supports_parallel_connects(void) const
00275 {
00276 return 0;
00277 }
00278
00279 TAO_Transport*
00280 TAO_Connector::make_parallel_connection (TAO::Profile_Transport_Resolver *,
00281 TAO_Transport_Descriptor_Interface &,
00282 ACE_Time_Value *)
00283 {
00284 return 0;
00285 }
00286
00287
00288 TAO_Transport*
00289 TAO_Connector::parallel_connect (TAO::Profile_Transport_Resolver *r,
00290 TAO_Transport_Descriptor_Interface *desc,
00291 ACE_Time_Value *timeout)
00292 {
00293 if (this->supports_parallel_connects() == 0)
00294 {
00295 errno = ENOTSUP;
00296 return 0;
00297 }
00298
00299 errno = 0;
00300 if (desc == 0)
00301 return 0;
00302 unsigned int endpoint_count = 0;
00303 TAO_Endpoint *root_ep = desc->endpoint();
00304 for (TAO_Endpoint *ep = root_ep->next_filtered (this->orb_core(),0);
00305 ep != 0;
00306 ep = ep->next_filtered(this->orb_core(),root_ep))
00307 if (this->set_validate_endpoint (ep) == 0)
00308 ++endpoint_count;
00309 if (endpoint_count == 0)
00310 return 0;
00311
00312 TAO_Transport *base_transport = 0;
00313
00314 TAO::Transport_Cache_Manager &tcm =
00315 this->orb_core ()->lane_resources ().transport_cache ();
00316
00317
00318
00319
00320 for (TAO_Endpoint *ep = root_ep->next_filtered (this->orb_core(),0);
00321 ep != 0;
00322 ep = ep->next_filtered(this->orb_core(),root_ep))
00323 {
00324 TAO_Base_Transport_Property desc2(ep,0);
00325 if (tcm.find_transport (&desc2,
00326 base_transport) == 0)
00327 {
00328 if (TAO_debug_level)
00329 {
00330 ACE_DEBUG ((LM_DEBUG,
00331 ACE_TEXT ("TAO (%P|%t) - TAO_Connector::parallel_connect: ")
00332 ACE_TEXT ("found a transport [%d]\n"),
00333 base_transport->id ()));
00334 }
00335 return base_transport;
00336 }
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 return this->make_parallel_connection (r,*desc,timeout);
00348 }
00349
00350 TAO_Transport*
00351 TAO_Connector::connect (TAO::Profile_Transport_Resolver *r,
00352 TAO_Transport_Descriptor_Interface *desc,
00353 ACE_Time_Value *timeout)
00354 {
00355 if (desc == 0 ||
00356 (this->set_validate_endpoint (desc->endpoint ()) == -1))
00357 return 0;
00358
00359 TAO_Transport *base_transport = 0;
00360
00361 TAO::Transport_Cache_Manager &tcm =
00362 this->orb_core ()->lane_resources ().transport_cache ();
00363
00364
00365
00366
00367
00368 if (tcm.find_transport (desc,
00369 base_transport) != 0)
00370 {
00371
00372
00373 tcm.purge ();
00374
00375 TAO_Transport* t = this->make_connection (r, *desc, timeout);
00376
00377 if (t == 0)
00378 return t;
00379
00380 t->opened_as (TAO::TAO_CLIENT_ROLE);
00381
00382 if (TAO_debug_level > 4)
00383 {
00384 ACE_DEBUG ((LM_DEBUG,
00385 ACE_TEXT("TAO (%P|%t) - Transport_Connector::connect, ")
00386 ACE_TEXT("opening Transport[%d] in TAO_CLIENT_ROLE\n"),
00387 t->id ()));
00388 }
00389
00390
00391
00392 if (!t->post_connect_hook ())
00393 {
00394 (void) t->purge_entry ();
00395
00396
00397 return this->connect (r, desc, timeout);
00398 }
00399
00400 return t;
00401 }
00402
00403 if (TAO_debug_level > 4)
00404 {
00405 TAO::Connection_Role cr = base_transport->opened_as ();
00406
00407 ACE_DEBUG ((LM_DEBUG,
00408 "TAO (%P|%t) - Transport_Connector::connect, "
00409 "got an existing %s Transport[%d] in role %s\n",
00410 base_transport->is_connected () ? "connected" : "unconnected",
00411 base_transport->id (),
00412 cr == TAO::TAO_SERVER_ROLE ? "TAO_SERVER_ROLE" :
00413 cr == TAO::TAO_CLIENT_ROLE ? "TAO_CLIENT_ROLE" :
00414 "TAO_UNSPECIFIED_ROLE" ));
00415 }
00416
00417
00418 if (base_transport->is_connected ())
00419 return base_transport;
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 TransportCleanupGuard tg(base_transport);
00433 if (!this->wait_for_connection_completion (r, base_transport, timeout))
00434 {
00435 if (TAO_debug_level > 2)
00436 {
00437 ACE_ERROR ((LM_ERROR,
00438 "TAO (%P|%t) - Transport_Connector::"
00439 "connect, "
00440 "wait for completion failed\n"));
00441 }
00442 return 0;
00443 }
00444
00445 if (base_transport->is_connected () &&
00446 base_transport->wait_strategy ()->register_handler () == -1)
00447 {
00448
00449 if (TAO_debug_level > 0)
00450 {
00451 ACE_ERROR ((LM_ERROR,
00452 "TAO (%P|%t) - Transport_Connector [%d]::connect, "
00453 "could not register the transport "
00454 "in the reactor.\n",
00455 base_transport->id ()));
00456 }
00457 return 0;
00458 }
00459
00460 tg.down ();
00461 return base_transport;
00462 }
00463
00464 bool
00465 TAO_Connector::wait_for_connection_completion (
00466 TAO::Profile_Transport_Resolver *r,
00467 TAO_Transport *&transport,
00468 ACE_Time_Value *timeout)
00469 {
00470 int result = -1;
00471 if (!r->blocked_connect ())
00472 {
00473 if (transport->connection_handler ()->is_open ())
00474 {
00475 result = 0;
00476 }
00477 else if (transport->connection_handler ()->is_timeout ())
00478 {
00479 if (TAO_debug_level > 2)
00480 {
00481 ACE_DEBUG ((LM_DEBUG,
00482 "TAO (%P|%t) - Transport_Connector::"
00483 "wait_for_connection_completion, "
00484 "transport [%d], Connection timed out.\n",
00485 transport->id ()));
00486 }
00487 result = -1;
00488 errno = ETIME;
00489 }
00490 else if (transport->connection_handler ()->is_closed ())
00491 {
00492 if (TAO_debug_level > 2)
00493 {
00494 ACE_DEBUG ((LM_DEBUG,
00495 "TAO (%P|%t) - Transport_Connector::"
00496 "wait_for_connection_completion, "
00497 "transport [%d], Connection failed. (%d) %p\n",
00498 transport->id (), errno, ""));
00499 }
00500 result = -1;
00501 }
00502 else
00503 {
00504 if (TAO_debug_level > 2)
00505 {
00506 ACE_DEBUG ((LM_DEBUG,
00507 "TAO (%P|%t) - Transport_Connector::"
00508 "wait_for_connection_completion, "
00509 "transport [%d], Connection not complete.\n",
00510 transport->id ()));
00511 }
00512 transport->connection_handler ()->
00513 reset_state (TAO_LF_Event::LFS_CONNECTION_WAIT);
00514 result = 0;
00515 }
00516 }
00517 else
00518 {
00519 if (TAO_debug_level > 2)
00520 {
00521 ACE_DEBUG ((LM_DEBUG,
00522 "TAO (%P|%t) - Transport_Connector::"
00523 "wait_for_connection_completion, "
00524 "going to wait for connection completion on transport"
00525 "[%d]\n",
00526 transport->id ()));
00527 }
00528 result = this->active_connect_strategy_->wait (transport, timeout);
00529
00530 if (TAO_debug_level > 2)
00531 {
00532 ACE_DEBUG ((LM_DEBUG,
00533 "TAO (%P|%t) - Transport_Connector::"
00534 "wait_for_connection_completion, "
00535 "transport [%d], wait done result = %d\n",
00536 transport->id (), result));
00537 }
00538
00539
00540
00541
00542
00543
00544
00545 if (result == -1)
00546 {
00547 if (errno == ETIME)
00548 {
00549 if (TAO_debug_level > 2)
00550 {
00551 ACE_DEBUG ((LM_DEBUG,
00552 "TAO (%P|%t) - Transport_Connector::"
00553 "wait_for_connection_completion, "
00554 "transport [%d], Connection timed out.\n",
00555 transport->id ()));
00556 }
00557 }
00558 else
00559 {
00560
00561
00562
00563 if (TAO_debug_level > 2)
00564 {
00565 ACE_ERROR ((LM_ERROR,
00566 "TAO (%P|%t) - Transport_Connector::"
00567 "wait_for_connection_completion, "
00568 "transport [%d], wait for completion failed (%d) %p\n",
00569 transport->id (), errno, ""));
00570 }
00571 TAO_Connection_Handler *con = transport->connection_handler ();
00572 result = this->check_connection_closure (con);
00573 }
00574 }
00575 }
00576
00577 if (result == -1)
00578 {
00579
00580
00581
00582 transport = 0;
00583 return false;
00584 }
00585
00586
00587
00588 return true;
00589 }
00590
00591 bool
00592 TAO_Connector::wait_for_connection_completion (
00593 TAO::Profile_Transport_Resolver *r,
00594 TAO_Transport *&the_winner,
00595 TAO_Transport **transport,
00596 unsigned int count,
00597 TAO_LF_Multi_Event *mev,
00598 ACE_Time_Value *timeout)
00599 {
00600 if (TAO_debug_level > 2)
00601 {
00602 ACE_DEBUG ((LM_DEBUG,
00603 ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
00604 ACE_TEXT("wait_for_connection_completion, ")
00605 ACE_TEXT("waiting for connection completion on ")
00606 ACE_TEXT("%d transports, ["),
00607 count));
00608 for (unsigned int i = 0; i < count; i++)
00609 ACE_DEBUG ((LM_DEBUG,
00610 ACE_TEXT("%d%s"),transport[i]->id (),
00611 (i < (count -1) ? ", " : "]\n")));
00612 }
00613
00614 int result = -1;
00615 if (r->blocked_connect ())
00616 {
00617 result = this->active_connect_strategy_->wait (mev, timeout);
00618 the_winner = 0;
00619 }
00620 else
00621 {
00622 errno = ETIME;
00623 }
00624
00625 if (result != -1)
00626 {
00627 the_winner = mev->winner()->transport();
00628 if (TAO_debug_level > 2)
00629 {
00630 ACE_DEBUG ((LM_DEBUG,
00631 ACE_TEXT ("TAO (%P|%t) - Transport_Connector::")
00632 ACE_TEXT ("wait_for_connection_completion, ")
00633 ACE_TEXT ("transport [%d]\n"),
00634 the_winner->id ()));
00635 }
00636 }
00637 else if (errno == ETIME)
00638 {
00639
00640
00641
00642
00643
00644 for (unsigned int i = 0; i < count; i++)
00645 if (!transport[i]->connection_handler()->is_closed())
00646 {
00647 the_winner = transport[i];
00648 break;
00649 }
00650 }
00651
00652
00653
00654
00655 for (unsigned int i = 0; i < count; i++)
00656 {
00657 if (transport[i] != the_winner)
00658 this->check_connection_closure (transport[i]->connection_handler());
00659
00660
00661 }
00662
00663
00664 if (the_winner == 0)
00665 {
00666
00667
00668 if (TAO_debug_level > 2)
00669 {
00670 ACE_ERROR ((LM_ERROR,
00671 ACE_TEXT ("TAO (%P|%t) - Transport_Connector::")
00672 ACE_TEXT ("wait_for_connection_completion, failed\n")
00673 ));
00674 }
00675
00676 return false;
00677 }
00678
00679
00680
00681
00682 if (r->blocked_connect () && !the_winner->is_connected ())
00683 {
00684 if (TAO_debug_level > 2)
00685 {
00686 ACE_DEBUG ((LM_DEBUG,
00687 "TAO (%P|%t) - Transport_Connector::"
00688 "wait_for_connection_completion, "
00689 "no connected transport for a blocked connection, "
00690 "cancelling connections and reverting things \n"));
00691 }
00692
00693
00694
00695 (void) this->cancel_svc_handler (the_winner->connection_handler ());
00696 the_winner = 0;
00697 return false;
00698 }
00699
00700
00701
00702
00703 return true;
00704 }
00705
00706 int
00707 TAO_Connector::create_connect_strategy (void)
00708 {
00709 if (this->active_connect_strategy_ == 0)
00710 {
00711 this->active_connect_strategy_ =
00712 this->orb_core_->client_factory ()->create_connect_strategy (
00713 this->orb_core_);
00714 }
00715
00716 if (this->active_connect_strategy_ == 0)
00717 {
00718 return -1;
00719 }
00720
00721 return 0;
00722 }
00723
00724 int
00725 TAO_Connector::check_connection_closure (
00726 TAO_Connection_Handler *connection_handler)
00727 {
00728 int result = -1;
00729
00730
00731 bool closed = connection_handler->is_closed ();
00732
00733
00734 if (!closed)
00735 {
00736
00737 if (this->cancel_svc_handler (connection_handler) == -1)
00738 return -1;
00739
00740
00741
00742
00743
00744
00745
00746
00747 closed = connection_handler->is_closed ();
00748
00749
00750
00751 if (!closed)
00752 {
00753
00754 const bool open = connection_handler->is_open ();
00755
00756
00757
00758 if (open)
00759 {
00760
00761 result = 0;
00762 }
00763 else
00764 {
00765
00766 ACE_ASSERT (connection_handler->is_connecting ());
00767
00768
00769 connection_handler->close_handler ();
00770 }
00771 }
00772 }
00773
00774 return result;
00775 }
00776
00777
00778
00779 TAO_END_VERSIONED_NAMESPACE_DECL