00001
00002
00003 #include "tao/Synch_Invocation.h"
00004 #include "tao/Profile_Transport_Resolver.h"
00005 #include "tao/Profile.h"
00006 #include "tao/Synch_Reply_Dispatcher.h"
00007 #include "tao/Transport.h"
00008 #include "tao/Stub.h"
00009 #include "tao/Bind_Dispatcher_Guard.h"
00010 #include "tao/operation_details.h"
00011 #include "tao/Wait_Strategy.h"
00012 #include "tao/debug.h"
00013 #include "tao/ORB_Constants.h"
00014 #include "tao/Messaging_SyncScopeC.h"
00015 #include "tao/ORB_Core.h"
00016 #include "tao/Service_Context.h"
00017 #include "tao/SystemException.h"
00018
00019 #if TAO_HAS_INTERCEPTORS == 1
00020 # include "tao/PortableInterceptorC.h"
00021 #endif
00022
00023 #include "ace/Auto_Ptr.h"
00024 #include "ace/OS_NS_string.h"
00025 #include "ace/Countdown_Time.h"
00026
00027 #if !defined (__ACE_INLINE__)
00028 # include "tao/Synch_Invocation.inl"
00029 #endif
00030
00031
00032 ACE_RCSID (tao,
00033 Synch_Invocation,
00034 "$Id: Synch_Invocation.cpp 81632 2008-05-07 09:19:05Z vzykov $")
00035
00036
00037 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00038
00039 namespace TAO
00040 {
00041 Synch_Twoway_Invocation::Synch_Twoway_Invocation (
00042 CORBA::Object_ptr otarget,
00043 Profile_Transport_Resolver &resolver,
00044 TAO_Operation_Details &detail,
00045 bool response_expected)
00046 : Remote_Invocation (otarget,
00047 resolver,
00048 detail,
00049 response_expected)
00050 {
00051 }
00052
00053 Invocation_Status
00054 Synch_Twoway_Invocation::remote_twoway (ACE_Time_Value *max_wait_time)
00055 {
00056 ACE_Countdown_Time countdown (max_wait_time);
00057
00058 TAO_Synch_Reply_Dispatcher rd (this->resolver_.stub ()->orb_core (),
00059 this->details_.reply_service_info ());
00060
00061 Invocation_Status s = TAO_INVOKE_FAILURE;
00062
00063 #if TAO_HAS_INTERCEPTORS == 1
00064
00065 s = this->send_request_interception ();
00066
00067 if (s != TAO_INVOKE_SUCCESS)
00068 return s;
00069
00070
00071
00072
00073 try
00074 {
00075 #endif
00076 TAO_Transport* const transport = this->resolver_.transport ();
00077
00078 if (!transport)
00079 {
00080
00081
00082
00083 throw CORBA::TRANSIENT (CORBA::OMGVMCID | 2, CORBA::COMPLETED_NO);
00084 }
00085
00086 TAO_OutputCDR &cdr = transport->out_stream ();
00087
00088 cdr.message_attributes (this->details_.request_id (),
00089 this->resolver_.stub (),
00090 TAO_Transport::TAO_TWOWAY_REQUEST,
00091 max_wait_time);
00092
00093 this->write_header (cdr);
00094
00095 this->marshal_data (cdr);
00096
00097
00098
00099 TAO_Bind_Dispatcher_Guard dispatch_guard (
00100 this->details_.request_id (),
00101 &rd,
00102 transport->tms ());
00103
00104 if (dispatch_guard.status () != 0)
00105 {
00106
00107
00108 transport->close_connection ();
00109
00110 throw ::CORBA::INTERNAL (0, CORBA::COMPLETED_NO);
00111 }
00112
00113 countdown.update ();
00114
00115 s = this->send_message (cdr,
00116 TAO_Transport::TAO_TWOWAY_REQUEST,
00117 max_wait_time);
00118
00119 #if TAO_HAS_INTERCEPTORS == 1
00120
00121
00122
00123
00124 if (s == TAO_INVOKE_RESTART)
00125 {
00126 Invocation_Status const tmp = this->receive_other_interception ();
00127
00128 if (tmp != TAO_INVOKE_SUCCESS)
00129 s = tmp;
00130 }
00131 #endif
00132
00133 if (s != TAO_INVOKE_SUCCESS)
00134 return s;
00135
00136 countdown.update ();
00137
00138
00139
00140
00141 if (transport->idle_after_send ())
00142 this->resolver_.transport_released ();
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 s = this->wait_for_reply (max_wait_time, rd, dispatch_guard);
00162
00163 #if TAO_HAS_INTERCEPTORS == 1
00164 if (s == TAO_INVOKE_RESTART)
00165 {
00166 Invocation_Status const tmp = this->receive_other_interception ();
00167
00168
00169 if (tmp != TAO_INVOKE_SUCCESS)
00170 s = tmp;
00171 }
00172 #endif
00173
00174 if (s != TAO_INVOKE_SUCCESS)
00175 return s;
00176
00177
00178
00179
00180 s = this->check_reply_status (rd);
00181
00182
00183
00184 if (transport->idle_after_reply ())
00185 this->resolver_.transport_released ();
00186
00187 #if TAO_HAS_INTERCEPTORS == 1
00188 Invocation_Status tmp = TAO_INVOKE_FAILURE;
00189 if (s == TAO_INVOKE_RESTART)
00190 {
00191 tmp = this->receive_other_interception ();
00192 }
00193 else if (s == TAO_INVOKE_SUCCESS)
00194 {
00195 tmp = this->receive_reply_interception ();
00196 }
00197 if (tmp != TAO_INVOKE_SUCCESS)
00198 s = tmp;
00199 }
00200 catch ( ::CORBA::Exception& ex)
00201 {
00202 PortableInterceptor::ReplyStatus const status =
00203 this->handle_any_exception (&ex);
00204
00205 if (status == PortableInterceptor::LOCATION_FORWARD ||
00206 status == PortableInterceptor::TRANSPORT_RETRY)
00207 s = TAO_INVOKE_RESTART;
00208 else if (status == PortableInterceptor::SYSTEM_EXCEPTION
00209 || status == PortableInterceptor::USER_EXCEPTION)
00210 throw;
00211 }
00212 catch (...)
00213 {
00214
00215
00216
00217 PortableInterceptor::ReplyStatus const st =
00218 this->handle_all_exception ();
00219
00220 if (st == PortableInterceptor::LOCATION_FORWARD ||
00221 st == PortableInterceptor::TRANSPORT_RETRY)
00222 s = TAO_INVOKE_RESTART;
00223 else
00224 throw;
00225 }
00226 #endif
00227
00228 return s;
00229 }
00230
00231 Invocation_Status
00232 Synch_Twoway_Invocation::wait_for_reply (ACE_Time_Value *max_wait_time,
00233 TAO_Synch_Reply_Dispatcher &rd,
00234 TAO_Bind_Dispatcher_Guard &bd)
00235 {
00236
00237
00238
00239
00240
00241
00242
00243
00244 int const reply_error =
00245 this->resolver_.transport ()->wait_strategy ()->wait (max_wait_time, rd);
00246
00247 if (TAO_debug_level > 0 && max_wait_time)
00248 {
00249 CORBA::ULong const msecs = max_wait_time->msec ();
00250
00251 ACE_DEBUG ((LM_DEBUG,
00252 "TAO (%P|%t) - Synch_Twoway_Invocation::wait_for_reply, "
00253 "timeout after recv is <%u> status <%d>\n",
00254 msecs,
00255 reply_error));
00256 }
00257
00258
00259 if (reply_error == -1)
00260 {
00261
00262
00263 if (TAO_debug_level > 3)
00264 {
00265 ACE_DEBUG ((LM_DEBUG,
00266 "TAO (%P|%t) - Synch_Twoway_Invocation::wait_for_reply, "
00267 "recovering after an error \n"));
00268 }
00269
00270
00271
00272
00273
00274
00275 if (errno == ETIME)
00276 {
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 if (bd.unbind_dispatcher () == 0)
00290 {
00291
00292
00293 throw ::CORBA::TIMEOUT (
00294 CORBA::SystemException::_tao_minor_code (
00295 TAO_TIMEOUT_RECV_MINOR_CODE,
00296 errno),
00297 CORBA::COMPLETED_MAYBE);
00298 }
00299 }
00300 else
00301 {
00302 (void) bd.unbind_dispatcher ();
00303 this->resolver_.transport ()->close_connection ();
00304
00305 try
00306 {
00307 return
00308 this->orb_core ()->service_raise_comm_failure (
00309 this->details_.request_service_context ().service_info (),
00310 this->resolver_.profile ());
00311
00312 }
00313 catch (const ::CORBA::Exception&)
00314 {
00315 this->resolver_.stub ()->reset_profiles ();
00316 throw;
00317 }
00318 }
00319 }
00320
00321 return TAO_INVOKE_SUCCESS;
00322 }
00323
00324 Invocation_Status
00325 Synch_Twoway_Invocation::check_reply_status (TAO_Synch_Reply_Dispatcher &rd)
00326 {
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 TAO_InputCDR &cdr = rd.reply_cdr ();
00337
00338
00339 this->resolver_.transport ()->assign_translators (&cdr, 0);
00340
00341
00342
00343
00344
00345
00346 switch (rd.reply_status ())
00347 {
00348 case GIOP::NO_EXCEPTION:
00349 {
00350 Reply_Guard mon (this, TAO_INVOKE_FAILURE);
00351 if (this->details_.demarshal_args (cdr) == false)
00352 {
00353 throw ::CORBA::MARSHAL ();
00354 }
00355
00356 mon.set_status (TAO_INVOKE_SUCCESS);
00357 }
00358 break;
00359 case GIOP::LOCATION_FORWARD:
00360 return this->location_forward (cdr);
00361 case GIOP::LOCATION_FORWARD_PERM:
00362 {
00363
00364
00365 Invocation_Status const s = this->location_forward (cdr);
00366 if (s != TAO_INVOKE_FAILURE)
00367 {
00368
00369 CORBA::Boolean const permanent_forward_condition =
00370 this->orb_core ()->is_permanent_forward_condition
00371 (this->forwarded_to_.in (),
00372 this->request_service_context ());
00373
00374 if (!permanent_forward_condition)
00375 {
00376
00377 if (TAO_debug_level > 3)
00378 ACE_DEBUG ((LM_DEBUG,
00379 "TAO (%P|%t) - Synch_Twoway_Invocation::"
00380 "check_reply_status: unexpected LOCATION_FORWARD_PERM reply\n"));
00381
00382 throw ::CORBA::INTERNAL (0, CORBA::COMPLETED_NO);
00383 }
00384
00385
00386 this->reply_status (GIOP::LOCATION_FORWARD_PERM);
00387 }
00388
00389 return s;
00390 }
00391 case GIOP::USER_EXCEPTION:
00392 return this->handle_user_exception (cdr);
00393 case GIOP::SYSTEM_EXCEPTION:
00394 return this->handle_system_exception (cdr);
00395
00396 case GIOP::NEEDS_ADDRESSING_MODE:
00397 {
00398 Reply_Guard mon (this, TAO_INVOKE_FAILURE);
00399
00400
00401
00402 CORBA::Short addr_mode = 0;
00403
00404 if (cdr.read_short (addr_mode) == 0)
00405 {
00406
00407
00408 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE);
00409 }
00410
00411
00412
00413 this->resolver_.profile ()->addressing_mode (addr_mode);
00414
00415 mon.set_status (TAO_INVOKE_RESTART);
00416
00417
00418 return TAO_INVOKE_RESTART;
00419 }
00420 }
00421 return TAO_INVOKE_SUCCESS;
00422 }
00423
00424 Invocation_Status
00425 Synch_Twoway_Invocation::location_forward (TAO_InputCDR &inp_stream)
00426 {
00427 Reply_Guard mon (this, TAO_INVOKE_FAILURE);
00428
00429 if (TAO_debug_level > 3)
00430 {
00431 ACE_DEBUG ((LM_DEBUG,
00432 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::location_forward ")
00433 ACE_TEXT ("being handled \n")));
00434 }
00435
00436 CORBA::Object_var fwd;
00437
00438 if ((inp_stream >> fwd) == 0)
00439 {
00440 throw ::CORBA::MARSHAL (
00441 CORBA::SystemException::_tao_minor_code (
00442 TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE,
00443 errno),
00444 CORBA::COMPLETED_NO);
00445 }
00446
00447 this->forwarded_reference (fwd.in ());
00448
00449 mon.set_status (TAO_INVOKE_RESTART);
00450
00451 return TAO_INVOKE_RESTART;
00452 }
00453
00454 Invocation_Status
00455 Synch_Twoway_Invocation::handle_user_exception (TAO_InputCDR &cdr)
00456 {
00457 Reply_Guard mon (this,
00458 TAO_INVOKE_FAILURE);
00459
00460 if (TAO_debug_level > 3)
00461 ACE_DEBUG ((LM_DEBUG,
00462 "TAO (%P|%t) - Synch_Twoway_Invocation::"
00463 "handle_user_exception \n"));
00464
00465
00466 CORBA::String_var buf;
00467
00468 if ((cdr >> buf.inout ()) == 0)
00469 {
00470
00471
00472 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE);
00473 }
00474
00475 CORBA::Exception *exception = this->details_.corba_exception (buf.in ());
00476
00477 exception->_tao_decode (cdr);
00478
00479 if (TAO_debug_level > 5)
00480 {
00481 ACE_DEBUG ((LM_DEBUG,
00482 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::")
00483 ACE_TEXT ("handle_user_exception - ")
00484 ACE_TEXT ("raising exception %s\n"),
00485 ACE_TEXT_CHAR_TO_TCHAR (buf.in ())));
00486 }
00487
00488 mon.set_status (TAO_INVOKE_USER_EXCEPTION);
00489
00490
00491
00492
00493 auto_ptr<CORBA::Exception> safety (exception);
00494
00495
00496 exception->_raise ();
00497
00498 return TAO_INVOKE_USER_EXCEPTION;
00499 }
00500
00501 Invocation_Status
00502 Synch_Twoway_Invocation::handle_system_exception (TAO_InputCDR &cdr)
00503 {
00504 Reply_Guard mon (this, TAO_INVOKE_FAILURE);
00505
00506 if (TAO_debug_level > 3)
00507 ACE_DEBUG ((LM_DEBUG,
00508 "TAO (%P|%t) - Synch_Twoway_Invocation::"
00509 "handle_system_exception \n"));
00510
00511 CORBA::String_var type_id;
00512
00513 if ((cdr >> type_id.inout ()) == 0)
00514 {
00515
00516
00517 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE);
00518 }
00519
00520 CORBA::ULong minor = 0;
00521 CORBA::ULong completion = 0;
00522
00523 if ((cdr >> minor) == 0 || (cdr >> completion) == 0)
00524 {
00525 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE);
00526 }
00527
00528
00529
00530
00531 if ((ACE_OS_String::strcmp (type_id.in (),
00532 "IDL:omg.org/CORBA/TRANSIENT:1.0") == 0 ||
00533 ACE_OS_String::strcmp (type_id.in (),
00534 "IDL:omg.org/CORBA/OBJ_ADAPTER:1.0") == 0 ||
00535 ACE_OS_String::strcmp (type_id.in (),
00536 "IDL:omg.org/CORBA/NO_RESPONSE:1.0") == 0 ||
00537 ACE_OS_String::strcmp (type_id.in (),
00538 "IDL:omg.org/CORBA/COMM_FAILURE:1.0") == 0) &&
00539 (CORBA::CompletionStatus) completion != CORBA::COMPLETED_YES)
00540 {
00541 {
00542
00543
00544
00545
00546
00547
00548 Invocation_Status const s =
00549 this->orb_core ()->service_raise_transient_failure (
00550 this->details_.request_service_context ().service_info (),
00551 this->resolver_.profile ());
00552
00553 if (s == TAO_INVOKE_RESTART)
00554 return s;
00555 }
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 if (completion != CORBA::COMPLETED_MAYBE &&
00567 this->resolver_.stub ()->next_profile_retry ())
00568 {
00569 return TAO_INVOKE_RESTART;
00570 }
00571
00572
00573 }
00574
00575 CORBA::SystemException *ex = TAO::create_system_exception (type_id.in ());
00576
00577 if (ex == 0)
00578 {
00579
00580
00581
00582 ACE_NEW_RETURN (ex,
00583 CORBA::UNKNOWN,
00584 TAO_INVOKE_FAILURE);
00585 }
00586
00587
00588
00589
00590 auto_ptr<CORBA::SystemException> safety (ex);
00591
00592 ex->minor (minor);
00593 ex->completed (CORBA::CompletionStatus (completion));
00594
00595 if (TAO_debug_level > 4)
00596 ACE_DEBUG ((LM_DEBUG,
00597 "TAO (%P|%t) - Synch_Twoway_Invocation::"
00598 "handle_system_exception, about to raise\n"));
00599
00600 mon.set_status (TAO_INVOKE_SYSTEM_EXCEPTION);
00601
00602
00603 ex->_raise ();
00604
00605 return TAO_INVOKE_SYSTEM_EXCEPTION;
00606 }
00607
00608
00609
00610 Synch_Oneway_Invocation::Synch_Oneway_Invocation (
00611 CORBA::Object_ptr otarget,
00612 Profile_Transport_Resolver &r,
00613 TAO_Operation_Details &d)
00614 : Synch_Twoway_Invocation (otarget, r, d, false)
00615 {
00616 }
00617
00618 Invocation_Status
00619 Synch_Oneway_Invocation::remote_oneway (ACE_Time_Value *max_wait_time)
00620 {
00621 ACE_Countdown_Time countdown (max_wait_time);
00622
00623 CORBA::Octet const response_flags = this->details_.response_flags ();
00624
00625 Invocation_Status s = TAO_INVOKE_FAILURE;
00626
00627 if (response_flags == CORBA::Octet (Messaging::SYNC_WITH_SERVER) ||
00628 response_flags == CORBA::Octet (Messaging::SYNC_WITH_TARGET))
00629 {
00630 s = Synch_Twoway_Invocation::remote_twoway (max_wait_time);
00631
00632 return s;
00633 }
00634
00635 #if TAO_HAS_INTERCEPTORS == 1
00636 s = this->send_request_interception ();
00637
00638 if (s != TAO_INVOKE_SUCCESS)
00639 return s;
00640
00641 try
00642 {
00643 #endif
00644 TAO_Transport* const transport = this->resolver_.transport ();
00645
00646 if (!transport)
00647 {
00648
00649
00650
00651 throw CORBA::TRANSIENT (CORBA::OMGVMCID | 2, CORBA::COMPLETED_NO);
00652 }
00653
00654 TAO_OutputCDR &cdr = transport->out_stream ();
00655
00656 cdr.message_attributes (this->details_.request_id (),
00657 this->resolver_.stub (),
00658 TAO_Transport::TAO_ONEWAY_REQUEST,
00659 max_wait_time);
00660
00661 this->write_header (cdr);
00662
00663 this->marshal_data (cdr);
00664
00665 countdown.update ();
00666
00667 if (transport->is_connected ())
00668 {
00669
00670 s = this->send_message (cdr,
00671 TAO_Transport::TAO_ONEWAY_REQUEST,
00672 max_wait_time);
00673 }
00674 else
00675 {
00676 if (TAO_debug_level > 4)
00677 ACE_DEBUG ((LM_DEBUG,
00678 "TAO (%P|%t) - Synch_Oneway_Invocation::"
00679 "remote_oneway, queueing message\n"));
00680
00681 if (transport->format_queue_message (cdr, max_wait_time) != 0)
00682 s = TAO_INVOKE_FAILURE;
00683 }
00684
00685 #if TAO_HAS_INTERCEPTORS == 1
00686 s = this->receive_other_interception ();
00687 }
00688 catch ( ::CORBA::Exception& ex)
00689 {
00690 PortableInterceptor::ReplyStatus const status =
00691 this->handle_any_exception (&ex);
00692
00693 if (status == PortableInterceptor::LOCATION_FORWARD ||
00694 status == PortableInterceptor::TRANSPORT_RETRY)
00695 s = TAO_INVOKE_RESTART;
00696 else if (status == PortableInterceptor::SYSTEM_EXCEPTION
00697 || status == PortableInterceptor::USER_EXCEPTION)
00698 throw;
00699 }
00700 catch (...)
00701 {
00702
00703
00704
00705 PortableInterceptor::ReplyStatus const st =
00706 this->handle_all_exception ();
00707
00708 if (st == PortableInterceptor::LOCATION_FORWARD ||
00709 st == PortableInterceptor::TRANSPORT_RETRY)
00710 s = TAO_INVOKE_RESTART;
00711 else
00712 throw;
00713 }
00714 #endif
00715
00716 return s;
00717 }
00718 }
00719
00720 TAO_END_VERSIONED_NAMESPACE_DECL