#include "tao/Synch_Invocation.h"#include "tao/Profile_Transport_Resolver.h"#include "tao/Profile.h"#include "tao/Synch_Reply_Dispatcher.h"#include "tao/Transport.h"#include "tao/Stub.h"#include "tao/Bind_Dispatcher_Guard.h"#include "tao/operation_details.h"#include "tao/Wait_Strategy.h"#include "tao/debug.h"#include "tao/ORB_Constants.h"#include "tao/Messaging_SyncScopeC.h"#include "tao/ORB_Core.h"#include "tao/Service_Context.h"#include "tao/SystemException.h"#include "ace/Intrusive_Auto_Ptr.h"#include "tao/PortableInterceptorC.h"#include "ace/Auto_Ptr.h"#include "ace/OS_NS_string.h"#include "ace/Countdown_Time.h"
Go to the source code of this file.
Functions | |
| ACE_RCSID (tao, Synch_Invocation,"$Id: Synch_Invocation.cpp 86232 2009-07-24 21:52:20Z dai_y $") 1 namespace TAO | |
| ACE_RCSID | ( | tao | , | |
| Synch_Invocation | , | |||
| "$Id: Synch_Invocation.cpp 86232 2009-07-24 21:52:20Z dai_y $" | ||||
| ) |
There has been a unanimous view that this is not the right way to do things. But a need to be compliant is forcing us into this.
Definition at line 33 of file Synch_Invocation.cpp.
00035 : Synch_Invocation.cpp 86232 2009-07-24 21:52:20Z dai_y $") 00036 00037 00038 TAO_BEGIN_VERSIONED_NAMESPACE_DECL 00039 00040 namespace TAO 00041 { 00042 Synch_Twoway_Invocation::Synch_Twoway_Invocation ( 00043 CORBA::Object_ptr otarget, 00044 Profile_Transport_Resolver &resolver, 00045 TAO_Operation_Details &detail, 00046 bool response_expected) 00047 : Remote_Invocation (otarget, 00048 resolver, 00049 detail, 00050 response_expected) 00051 { 00052 } 00053 00054 Invocation_Status 00055 Synch_Twoway_Invocation::remote_twoway (ACE_Time_Value *max_wait_time) 00056 { 00057 ACE_Countdown_Time countdown (max_wait_time); 00058 00059 TAO_Synch_Reply_Dispatcher *rd_p = 0; 00060 ACE_NEW_NORETURN (rd_p, TAO_Synch_Reply_Dispatcher (this->resolver_.stub ()->orb_core (), 00061 this->details_.reply_service_info ())); 00062 if (!rd_p) 00063 { 00064 throw ::CORBA::NO_MEMORY (); 00065 } 00066 00067 ACE_Intrusive_Auto_Ptr<TAO_Synch_Reply_Dispatcher> rd(rd_p, false); 00068 00069 Invocation_Status s = TAO_INVOKE_FAILURE; 00070 00071 #if TAO_HAS_INTERCEPTORS == 1 00072 // Start the interception point here.. 00073 s = this->send_request_interception (); 00074 00075 if (s != TAO_INVOKE_SUCCESS) 00076 return s; 00077 00078 // We have started the interception flow. We need to call the 00079 // ending interception flow if things go wrong. The purpose of the 00080 // try block is to do just this. 00081 try 00082 { 00083 #endif /*TAO_HAS_INTERCEPTORS */ 00084 TAO_Transport* const transport = this->resolver_.transport (); 00085 00086 if (!transport) 00087 { 00088 // Way back, we failed to find a profile we could connect to. 00089 // We've come this far only so we reach the interception points 00090 // in case they can fix things. Time to bail.... 00091 throw CORBA::TRANSIENT (CORBA::OMGVMCID | 2, CORBA::COMPLETED_NO); 00092 } 00093 00094 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ace_mon, 00095 transport->output_cdr_lock (), TAO_INVOKE_FAILURE); 00096 00097 TAO_OutputCDR &cdr = transport->out_stream (); 00098 00099 cdr.message_attributes (this->details_.request_id (), 00100 this->resolver_.stub (), 00101 TAO_TWOWAY_REQUEST, 00102 max_wait_time); 00103 00104 this->write_header (cdr); 00105 00106 this->marshal_data (cdr); 00107 00108 // Register a reply dispatcher for this invocation. Use the 00109 // preallocated reply dispatcher. 00110 TAO_Bind_Dispatcher_Guard dispatch_guard ( 00111 this->details_.request_id (), 00112 rd.get (), 00113 transport->tms ()); 00114 00115 if (dispatch_guard.status () != 0) 00116 { 00117 // @@ What is the right way to handle this error? Why should 00118 // we close the connection? 00119 transport->close_connection (); 00120 00121 throw ::CORBA::INTERNAL (0, CORBA::COMPLETED_NO); 00122 } 00123 00124 countdown.update (); 00125 00126 s = this->send_message (cdr, 00127 TAO_TWOWAY_REQUEST, 00128 max_wait_time); 00129 00130 ace_mon.release(); 00131 00132 #if TAO_HAS_INTERCEPTORS == 1 00133 // @@NOTE: Too much code repetition. 00134 // If the above call returns a restart due to connection 00135 // failure then call the receive_other interception point 00136 // before we leave. 00137 if (s == TAO_INVOKE_RESTART) 00138 { 00139 Invocation_Status const tmp = this->receive_other_interception (); 00140 00141 if (tmp != TAO_INVOKE_SUCCESS) 00142 s = tmp; 00143 } 00144 #endif /* TAO_HAS_INTERCEPTORS */ 00145 00146 if (s != TAO_INVOKE_SUCCESS) 00147 return s; 00148 00149 countdown.update (); 00150 00151 // For some strategies one may want to release the transport 00152 // back to cache. If the idling is successfull let the 00153 // resolver about that. 00154 if (transport->idle_after_send ()) 00155 this->resolver_.transport_released (); 00156 00157 // @@ In all MT environments, there's a cancellation point lurking 00158 // here; need to investigate. Client threads would frequently be 00159 // canceled sometime during recv_request ... the correct action to 00160 // take on being canceled is to issue a CancelRequest message to the 00161 // server and then imediately let other client-side cancellation 00162 // handlers do their jobs. 00163 // 00164 // In C++, that basically means to unwind the stack using almost 00165 // normal procedures: all destructors should fire, and some "catch" 00166 // blocks should probably be able to handle things like releasing 00167 // pointers. (Without unwinding the C++ stack, resources that must 00168 // be freed by thread cancellation won't be freed, and the process 00169 // won't continue to function correctly.) The tricky part is that 00170 // according to POSIX, all C stack frames must also have their 00171 // (explicitly coded) handlers called. We assume a POSIX.1c/C/C++ 00172 // environment. 00173 00174 s = this->wait_for_reply (max_wait_time, *rd.get (), dispatch_guard); 00175 00176 #if TAO_HAS_INTERCEPTORS == 1 00177 if (s == TAO_INVOKE_RESTART) 00178 { 00179 Invocation_Status const tmp = this->receive_other_interception (); 00180 00181 // Push the latest values for the return.. 00182 if (tmp != TAO_INVOKE_SUCCESS) 00183 s = tmp; 00184 } 00185 #endif /* TAO_HAS_INTERCEPTORS */ 00186 00187 if (s != TAO_INVOKE_SUCCESS) 00188 return s; 00189 00190 // What happens when the above call returns an error through 00191 // the return value? That would be bogus as per the contract 00192 // in the interface. The call violated the contract 00193 s = this->check_reply_status (*rd.get ()); 00194 00195 // For some strategies one may want to release the transport 00196 // back to cache after receiving the reply. 00197 if (transport->idle_after_reply ()) 00198 this->resolver_.transport_released (); 00199 00200 #if TAO_HAS_INTERCEPTORS == 1 00201 Invocation_Status tmp = TAO_INVOKE_FAILURE; 00202 if (s == TAO_INVOKE_RESTART) 00203 { 00204 tmp = this->receive_other_interception (); 00205 } 00206 else if (s == TAO_INVOKE_SUCCESS) 00207 { 00208 tmp = this->receive_reply_interception (); 00209 } 00210 if (tmp != TAO_INVOKE_SUCCESS) 00211 s = tmp; 00212 } 00213 catch ( ::CORBA::Exception& ex) 00214 { 00215 PortableInterceptor::ReplyStatus const status = 00216 this->handle_any_exception (&ex); 00217 00218 if (status == PortableInterceptor::LOCATION_FORWARD || 00219 status == PortableInterceptor::TRANSPORT_RETRY) 00220 s = TAO_INVOKE_RESTART; 00221 else if (status == PortableInterceptor::SYSTEM_EXCEPTION 00222 || status == PortableInterceptor::USER_EXCEPTION) 00223 throw; 00224 } 00225 catch (...) 00226 { 00227 // Notify interceptors of non-CORBA exception, and propagate 00228 // that exception to the caller. 00229 00230 PortableInterceptor::ReplyStatus const st = 00231 this->handle_all_exception (); 00232 00233 if (st == PortableInterceptor::LOCATION_FORWARD || 00234 st == PortableInterceptor::TRANSPORT_RETRY) 00235 s = TAO_INVOKE_RESTART; 00236 else 00237 throw; 00238 } 00239 #endif /* TAO_HAS_INTERCEPTORS */ 00240 00241 return s; 00242 } 00243 00244 Invocation_Status 00245 Synch_Twoway_Invocation::wait_for_reply (ACE_Time_Value *max_wait_time, 00246 TAO_Synch_Reply_Dispatcher &rd, 00247 TAO_Bind_Dispatcher_Guard &bd) 00248 { 00249 /* 00250 * Precondition: The call went to the remote 00251 * peer. <ACE_Thread::self> is waiting for the reply. 00252 * 00253 * Postcondition: Any error during a wait is marked by raising an 00254 * exception. Success alone is returned through the return value. 00255 */ 00256 00257 bool const 00258 expired= (max_wait_time && ACE_Time_Value::zero == *max_wait_time); 00259 if (expired) 00260 errno= ETIME; 00261 int const 00262 reply_error = expired ? -1 : 00263 this->resolver_.transport ()->wait_strategy ()->wait (max_wait_time, rd); 00264 00265 if (TAO_debug_level > 0 && max_wait_time) 00266 { 00267 CORBA::ULong const msecs = max_wait_time->msec (); 00268 00269 ACE_DEBUG ((LM_DEBUG, 00270 "TAO (%P|%t) - Synch_Twoway_Invocation::wait_for_reply, " 00271 "timeout after recv is <%u> status <%d>\n", 00272 msecs, 00273 reply_error)); 00274 } 00275 00276 // Check the reply error. 00277 if (reply_error == -1) 00278 { 00279 // Unbind the dispatcher, since its of no use at this point of 00280 // time 00281 if (TAO_debug_level > 3) 00282 { 00283 ACE_DEBUG ((LM_DEBUG, 00284 "TAO (%P|%t) - Synch_Twoway_Invocation::wait_for_reply, " 00285 "recovering after an error\n")); 00286 } 00287 00288 // You the smarty, don't try to moving the unbind_dispatcher 00289 // () call since it looks like it is repeated twice. That 00290 // could land you in trouble. If you don't believe this 00291 // warning go ahead and try. Try running tests to see what is 00292 // going on ;) 00293 if (errno == ETIME) 00294 { 00295 // If the unbind succeeds then thrown an exception to the 00296 // application, else just collect the reply and dispatch 00297 // that to the application. 00298 // 00299 // NOTE: A fragile synchronization is provided when using 00300 // the Muxed Transport strategy. We could infact be a 00301 // follower thread getting timedout in the LF whereas the 00302 // dispatching thread could be on the reply_dispatcher 00303 // that we created. This would lead bad crashes. To get 00304 // around that, the call to unbind_dispatcher () will wait 00305 // on the lock on the Muxed_Transport_Strategy if 00306 // dispatching has started. This is fragile. 00307 if (bd.unbind_dispatcher () == 0) 00308 { 00309 // Just a timeout with completed_maybe, don't close 00310 // the connection or anything 00311 throw ::CORBA::TIMEOUT ( 00312 CORBA::SystemException::_tao_minor_code ( 00313 TAO_TIMEOUT_RECV_MINOR_CODE, 00314 errno), 00315 CORBA::COMPLETED_MAYBE); 00316 } 00317 } 00318 else 00319 { 00320 (void) bd.unbind_dispatcher (); 00321 this->resolver_.transport ()->close_connection (); 00322 00323 try 00324 { 00325 return 00326 this->stub()->orb_core ()->service_raise_comm_failure ( 00327 this->details_.request_service_context ().service_info (), 00328 this->resolver_.profile ()); 00329 00330 } 00331 catch (const ::CORBA::Exception&) 00332 { 00333 this->resolver_.stub ()->reset_profiles (); 00334 throw; 00335 } 00336 } 00337 } 00338 00339 return TAO_INVOKE_SUCCESS; 00340 } 00341 00342 Invocation_Status 00343 Synch_Twoway_Invocation::check_reply_status (TAO_Synch_Reply_Dispatcher &rd) 00344 { 00345 /* 00346 * Precondition: We probably got a reply. <ACE_Thread::self> is 00347 * checking the status of the reply 00348 * 00349 * Postcondition: Any error while reading the reply is marked by 00350 * raising an exception. LOCATION_FORWARDED replies are marked by 00351 * returning a restart since that is what needed to be done by the 00352 * callee. 00353 */ 00354 TAO_InputCDR &cdr = rd.reply_cdr (); 00355 00356 // Set the translators 00357 this->resolver_.transport ()->assign_translators (&cdr, 0); 00358 00359 // At this point it can be assumed that the GIOP/whatever protocol 00360 // header and the reply header are already handled. Further it 00361 // can be assumed that the reply body contains the details 00362 // required for further processing. All the other details should 00363 // have been handled in the reply dispatcher/protocol framework. 00364 switch (rd.reply_status ()) 00365 { 00366 case GIOP::NO_EXCEPTION: 00367 { 00368 Reply_Guard mon (this, TAO_INVOKE_FAILURE); 00369 if (this->details_.demarshal_args (cdr) == false) 00370 { 00371 throw ::CORBA::MARSHAL (); 00372 } 00373 00374 mon.set_status (TAO_INVOKE_SUCCESS); 00375 } 00376 break; 00377 case GIOP::LOCATION_FORWARD: 00378 return this->location_forward (cdr); 00379 case GIOP::LOCATION_FORWARD_PERM: 00380 { 00381 // Unmarshal the location forward object and set the 00382 // variable this->forward_to_. 00383 Invocation_Status const s = this->location_forward (cdr); 00384 if (s != TAO_INVOKE_FAILURE) 00385 { 00386 // de-marshalling of permanent object reference was successfull 00387 CORBA::Boolean const permanent_forward_condition = 00388 this->stub ()->orb_core ()->is_permanent_forward_condition 00389 (this->forwarded_to_.in (), 00390 this->request_service_context ()); 00391 00392 if (!permanent_forward_condition) 00393 { 00394 // permanent condition not given 00395 if (TAO_debug_level > 3) 00396 ACE_DEBUG ((LM_DEBUG, 00397 "TAO (%P|%t) - Synch_Twoway_Invocation::" 00398 "check_reply_status: unexpected LOCATION_FORWARD_PERM reply\n")); 00399 00400 throw ::CORBA::INTERNAL (0, CORBA::COMPLETED_NO); 00401 } 00402 00403 // This is the only place where we set in permanent forward state. 00404 this->reply_status (GIOP::LOCATION_FORWARD_PERM); 00405 } 00406 00407 return s; 00408 } 00409 case GIOP::USER_EXCEPTION: 00410 return this->handle_user_exception (cdr); 00411 case GIOP::SYSTEM_EXCEPTION: 00412 return this->handle_system_exception (cdr); 00413 00414 case GIOP::NEEDS_ADDRESSING_MODE: 00415 { 00416 Reply_Guard mon (this, TAO_INVOKE_FAILURE); 00417 // We have received a message with a request to change the 00418 // addressing mode. First let us read the mode that the 00419 // server/agent asks for. 00420 CORBA::Short addr_mode = 0; 00421 00422 if (cdr.read_short (addr_mode) == 0) 00423 { 00424 // Could not demarshal the addressing disposition, raise an local 00425 // CORBA::MARSHAL 00426 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE); 00427 } 00428 00429 // Now set this addressing mode in the profile, so that 00430 // the next invocation need not go through this. 00431 this->resolver_.profile ()->addressing_mode (addr_mode); 00432 00433 mon.set_status (TAO_INVOKE_RESTART); 00434 00435 // Now restart the invocation 00436 return TAO_INVOKE_RESTART; 00437 } 00438 } 00439 return TAO_INVOKE_SUCCESS; 00440 } 00441 00442 Invocation_Status 00443 Synch_Twoway_Invocation::location_forward (TAO_InputCDR &inp_stream) 00444 { 00445 Reply_Guard mon (this, TAO_INVOKE_FAILURE); 00446 00447 if (TAO_debug_level > 3) 00448 { 00449 ACE_DEBUG ((LM_DEBUG, 00450 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::location_forward ") 00451 ACE_TEXT ("being handled\n"))); 00452 } 00453 00454 CORBA::Object_var fwd; 00455 00456 if (!(inp_stream >> fwd)) 00457 { 00458 throw ::CORBA::MARSHAL ( 00459 CORBA::SystemException::_tao_minor_code ( 00460 TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE, 00461 errno), 00462 CORBA::COMPLETED_NO); 00463 } 00464 00465 this->forwarded_reference (fwd.in ()); 00466 00467 mon.set_status (TAO_INVOKE_RESTART); 00468 00469 return TAO_INVOKE_RESTART; 00470 } 00471 00472 Invocation_Status 00473 Synch_Twoway_Invocation::handle_user_exception (TAO_InputCDR &cdr) 00474 { 00475 Reply_Guard mon (this, 00476 TAO_INVOKE_FAILURE); 00477 00478 if (TAO_debug_level > 3) 00479 ACE_DEBUG ((LM_DEBUG, 00480 "TAO (%P|%t) - Synch_Twoway_Invocation::" 00481 "handle_user_exception\n")); 00482 00483 // Pull the exception from the stream. 00484 CORBA::String_var buf; 00485 00486 if (!(cdr >> buf.inout ())) 00487 { 00488 // Could not demarshal the exception id, raise an local 00489 // CORBA::MARSHAL 00490 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE); 00491 } 00492 00493 CORBA::Exception *exception = this->details_.corba_exception (buf.in ()); 00494 00495 exception->_tao_decode (cdr); 00496 00497 if (TAO_debug_level > 5) 00498 { 00499 ACE_DEBUG ((LM_DEBUG, 00500 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::") 00501 ACE_TEXT ("handle_user_exception - ") 00502 ACE_TEXT ("raising exception %C\n"), 00503 buf.in ())); 00504 } 00505 00506 mon.set_status (TAO_INVOKE_USER_EXCEPTION); 00507 00508 // If we have native exceptions, we must manage the memory allocated 00509 // by the call above to alloc(). Otherwise the Environment class 00510 // manages the memory. 00511 auto_ptr<CORBA::Exception> safety (exception); 00512 00513 // Direct throw because we don't have the try_ENV. 00514 exception->_raise (); 00515 00516 return TAO_INVOKE_USER_EXCEPTION; 00517 } 00518 00519 Invocation_Status 00520 Synch_Twoway_Invocation::handle_system_exception (TAO_InputCDR &cdr) 00521 { 00522 Reply_Guard mon (this, TAO_INVOKE_FAILURE); 00523 00524 if (TAO_debug_level > 3) 00525 ACE_DEBUG ((LM_DEBUG, 00526 "TAO (%P|%t) - Synch_Twoway_Invocation::" 00527 "handle_system_exception\n")); 00528 00529 CORBA::String_var type_id; 00530 00531 if (!(cdr >> type_id.inout ())) 00532 { 00533 // Could not demarshal the exception id, raise an local 00534 // CORBA::MARSHAL 00535 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE); 00536 } 00537 00538 CORBA::ULong minor = 0; 00539 CORBA::ULong completion = 0; 00540 00541 if (!(cdr >> minor) || !(cdr >> completion)) 00542 { 00543 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE); 00544 } 00545 00546 bool do_forward = false; 00547 int foe_kind = this->stub ()->orb_core ()->orb_params ()->forward_once_exception(); 00548 00549 if ((CORBA::CompletionStatus) completion != CORBA::COMPLETED_YES 00550 && (((foe_kind & TAO::FOE_TRANSIENT) == 0 00551 && ACE_OS_String::strcmp (type_id.in (), 00552 "IDL:omg.org/CORBA/TRANSIENT:1.0") == 0) || 00553 ACE_OS_String::strcmp (type_id.in (), 00554 "IDL:omg.org/CORBA/OBJ_ADAPTER:1.0") == 0 || 00555 ACE_OS_String::strcmp (type_id.in (), 00556 "IDL:omg.org/CORBA/NO_RESPONSE:1.0") == 0 || 00557 ((foe_kind & TAO::FOE_COMM_FAILURE) == 0 00558 && ACE_OS_String::strcmp (type_id.in (), 00559 "IDL:omg.org/CORBA/COMM_FAILURE:1.0") == 0) || 00560 (this->stub ()->orb_core ()->orb_params ()->forward_invocation_on_object_not_exist () 00561 && ACE_OS_String::strcmp (type_id.in (), 00562 "IDL:omg.org/CORBA/OBJECT_NOT_EXIST:1.0") == 0) || 00563 (do_forward = ! this->stub ()->forwarded_on_exception () 00564 && ((((foe_kind & TAO::FOE_OBJECT_NOT_EXIST) == TAO::FOE_OBJECT_NOT_EXIST) 00565 && (ACE_OS_String::strcmp (type_id.in (), 00566 "IDL:omg.org/CORBA/OBJECT_NOT_EXIST:1.0") == 0)) || 00567 (((foe_kind & TAO::FOE_COMM_FAILURE) == TAO::FOE_COMM_FAILURE) 00568 && (ACE_OS_String::strcmp (type_id.in (), 00569 "IDL:omg.org/CORBA/COMM_FAILURE:1.0") == 0)) || 00570 (((foe_kind & TAO::FOE_TRANSIENT) == TAO::FOE_TRANSIENT) 00571 && (ACE_OS_String::strcmp (type_id.in (), 00572 "IDL:omg.org/CORBA/TRANSIENT:1.0") == 0)) || 00573 (((foe_kind & TAO::FOE_INV_OBJREF) == TAO::FOE_INV_OBJREF) 00574 && (ACE_OS_String::strcmp (type_id.in (), 00575 "IDL:omg.org/CORBA/INV_OBJREF:1.0") == 0)))))) 00576 { 00577 if (do_forward) 00578 this->stub ()->forwarded_on_exception (true); 00579 00580 // Start the special case for FTCORBA. 00581 /** 00582 * There has been a unanimous view that this is not the 00583 * right way to do things. But a need to be compliant is 00584 * forcing us into this. 00585 */ 00586 Invocation_Status const s = 00587 this->stub ()->orb_core ()->service_raise_transient_failure ( 00588 this->details_.request_service_context ().service_info (), 00589 this->resolver_.profile ()); 00590 00591 if (s == TAO_INVOKE_RESTART) 00592 return s; 00593 00594 // Attempt profile retry. 00595 /** 00596 * @note A location forwarding loop may occur where a client 00597 * is bounced from the original target to the forwarded 00598 * target and back if the application is not equipped to 00599 * handle retries of previously called targets. TAO may 00600 * be able to help in this case but it ultimately ends 00601 * up being an application issue. 00602 */ 00603 if (completion != CORBA::COMPLETED_MAYBE && 00604 this->resolver_.stub ()->next_profile_retry ()) 00605 { 00606 return TAO_INVOKE_RESTART; 00607 } 00608 00609 // Fall through and raise an exception. 00610 } 00611 00612 CORBA::SystemException *ex = TAO::create_system_exception (type_id.in ()); 00613 00614 if (ex == 0) 00615 { 00616 // @@ We should raise a CORBA::NO_MEMORY, but we ran out 00617 // of memory already. We need a pre-allocated, TSS, 00618 // CORBA::NO_MEMORY instance 00619 ACE_NEW_RETURN (ex, 00620 CORBA::UNKNOWN, 00621 TAO_INVOKE_FAILURE); 00622 } 00623 00624 // Without this, the call to create_system_exception() above 00625 // causes a memory leak. On platforms without native exceptions, 00626 // the CORBA::Environment class manages the memory. 00627 auto_ptr<CORBA::SystemException> safety (ex); 00628 00629 ex->minor (minor); 00630 ex->completed (CORBA::CompletionStatus (completion)); 00631 00632 if (TAO_debug_level > 4) 00633 ACE_DEBUG ((LM_DEBUG, 00634 "TAO (%P|%t) - Synch_Twoway_Invocation::" 00635 "handle_system_exception, about to raise\n")); 00636 00637 mon.set_status (TAO_INVOKE_SYSTEM_EXCEPTION); 00638 00639 // Raise the exception. 00640 ex->_raise (); 00641 00642 return TAO_INVOKE_SYSTEM_EXCEPTION; 00643 } 00644 00645 // ========================================================================= 00646 00647 Synch_Oneway_Invocation::Synch_Oneway_Invocation ( 00648 CORBA::Object_ptr otarget, 00649 Profile_Transport_Resolver &r, 00650 TAO_Operation_Details &d) 00651 : Synch_Twoway_Invocation (otarget, r, d, false) 00652 { 00653 } 00654 00655 Invocation_Status 00656 Synch_Oneway_Invocation::remote_oneway (ACE_Time_Value *max_wait_time) 00657 { 00658 ACE_Countdown_Time countdown (max_wait_time); 00659 00660 CORBA::Octet const response_flags = this->details_.response_flags (); 00661 00662 Invocation_Status s = TAO_INVOKE_FAILURE; 00663 00664 if (response_flags == CORBA::Octet (Messaging::SYNC_WITH_SERVER) || 00665 response_flags == CORBA::Octet (Messaging::SYNC_WITH_TARGET)) 00666 { 00667 s = Synch_Twoway_Invocation::remote_twoway (max_wait_time); 00668 00669 return s; 00670 } 00671 00672 #if TAO_HAS_INTERCEPTORS == 1 00673 s = this->send_request_interception (); 00674 00675 if (s != TAO_INVOKE_SUCCESS) 00676 return s; 00677 00678 try 00679 { 00680 #endif /*TAO_HAS_INTERCEPTORS */ 00681 TAO_Transport* const transport = this->resolver_.transport (); 00682 00683 if (!transport) 00684 { 00685 // Way back, we failed to find a profile we could connect to. 00686 // We've come this far only so we reach the interception points 00687 // in case they can fix things. Time to bail.... 00688 throw CORBA::TRANSIENT (CORBA::OMGVMCID | 2, CORBA::COMPLETED_NO); 00689 } 00690 00691 { 00692 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ace_mon, transport->output_cdr_lock (), 00693 TAO_INVOKE_FAILURE); 00694 00695 TAO_OutputCDR &cdr = transport->out_stream (); 00696 00697 cdr.message_attributes (this->details_.request_id (), 00698 this->resolver_.stub (), 00699 TAO_ONEWAY_REQUEST, 00700 max_wait_time); 00701 00702 this->write_header (cdr); 00703 00704 this->marshal_data (cdr); 00705 00706 countdown.update (); 00707 00708 if (transport->is_connected ()) 00709 { 00710 // We have a connected transport so we can send the message 00711 s = this->send_message (cdr, 00712 TAO_ONEWAY_REQUEST, 00713 max_wait_time); 00714 } 00715 else 00716 { 00717 if (TAO_debug_level > 4) 00718 ACE_DEBUG ((LM_DEBUG, 00719 "TAO (%P|%t) - Synch_Oneway_Invocation::" 00720 "remote_oneway, queueing message\n")); 00721 00722 if (transport->format_queue_message (cdr, 00723 max_wait_time, 00724 this->resolver_.stub()) != 0) 00725 { 00726 s = TAO_INVOKE_FAILURE; 00727 } 00728 } 00729 } 00730 00731 #if TAO_HAS_INTERCEPTORS == 1 00732 s = this->receive_other_interception (); 00733 } 00734 catch ( ::CORBA::Exception& ex) 00735 { 00736 PortableInterceptor::ReplyStatus const status = 00737 this->handle_any_exception (&ex); 00738 00739 if (status == PortableInterceptor::LOCATION_FORWARD || 00740 status == PortableInterceptor::TRANSPORT_RETRY) 00741 s = TAO_INVOKE_RESTART; 00742 else if (status == PortableInterceptor::SYSTEM_EXCEPTION 00743 || status == PortableInterceptor::USER_EXCEPTION) 00744 throw; 00745 } 00746 catch (...) 00747 { 00748 // Notify interceptors of non-CORBA exception, and propagate 00749 // that exception to the caller. 00750 00751 PortableInterceptor::ReplyStatus const st = 00752 this->handle_all_exception (); 00753 00754 if (st == PortableInterceptor::LOCATION_FORWARD || 00755 st == PortableInterceptor::TRANSPORT_RETRY) 00756 s = TAO_INVOKE_RESTART; 00757 else 00758 throw; 00759 } 00760 #endif /* TAO_HAS_INTERCEPTORS */ 00761 00762 return s; 00763 } 00764 }
1.6.1