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