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