void ReplicaController:: listener () { try { for (char buffer[1024];;) { size_t n = group_->recv (buffer, sizeof (buffer)); ACE_HEX_DUMP ((LM_DEBUG, buffer, n)); TAO_InputCDR cdr (buffer, n); CORBA::OctetSeq object_id; PortableInterceptor::AdapterName adapter_name; CORBA::String_var client_id; CORBA::Long retention_id; CORBA::OctetSeq reply; CORBA::Any state; cdr >> object_id; cdr >> adapter_name; cdr >> client_id.out (); cdr >> retention_id; cdr >> reply; cdr >> state; if (!cdr.good_bit ()) { ACE_DEBUG ((LM_DEBUG, "CDR failed\n")); //@@ what to do? } ACE_DEBUG ((LM_DEBUG, "Received log for %s with rid %i\n", client_id.in (), retention_id)); RecordId rid (client_id.in (), retention_id); CORBA::OctetSeq_var tmp (new CORBA::OctetSeq (reply)); log_.insert (rid, tmp); // Update state. CORBA::TypeCode_var tc = state.type (); if (tc->kind () != CORBA::tk_null) { PortableServer::POA_var poa = resolve_poa (adapter_name); PortableServer::ServantBase_var servant = poa->id_to_servant (object_id); Checkpointable* target = dynamic_cast<Checkpointable*> (servant.in ()); if (target) target->set_state (state); } } } catch (ACE_TMCast::Group::Failed const&) { ACE_DEBUG ((LM_DEBUG, "Group failure. Perhaps, I am alone in the group.\n")); } catch (ACE_TMCast::Group::InsufficienSpace const&) { ACE_DEBUG ((LM_DEBUG, "Group::InsufficienSpace\n")); } orb_->shutdown (0); }
void ReplicaController::send_reply ( PortableInterceptor::ServerRequestInfo_ptr ri) { FT::FTRequestServiceContext_var ftr ( extract_context (ri)); ACE_DEBUG ((LM_DEBUG, "(%P|%t) Sending reply for %s with rid %i\n", ftr->client_id.in (), ftr->retention_id)); // Prepare reply for logging. CORBA::Any_var result = ri->result (); TAO_OutputCDR cdr; result->impl ()->marshal_value (cdr); Dynamic::ParameterList_var pl = ri->arguments (); CORBA::ULong len = pl->length (); for (CORBA::ULong index = 0; index != len ; ++index) { //@@ No chance for PARAM_OUT if ((*pl)[index].mode == CORBA::PARAM_INOUT) { (*pl)[index].argument.impl ()->marshal_value (cdr); } } CORBA::OctetSeq_var reply; ACE_NEW (reply.out (), CORBA::OctetSeq (cdr.total_length ())); reply->length (cdr.total_length ()); CORBA::Octet* buf = reply->get_buffer (); // @@ What if this throws an exception?? We don't have any way to // check whether this succeeded for (ACE_Message_Block const* mb = cdr.begin (); mb != 0; mb = mb->cont ()) { ACE_OS::memcpy (buf, mb->rd_ptr (), mb->length ()); buf += mb->length (); } // Logging the reply and state update. // // First send message to members. // { // Extract state update. CORBA::OctetSeq_var oid = ri->object_id (); PortableInterceptor::AdapterName_var an = ri->adapter_name (); CORBA::Any_var state = ri->get_slot (state_slot_id ()); CORBA::TypeCode_var tc = state->type (); if (tc->kind () == CORBA::tk_null) { ACE_DEBUG ((LM_DEBUG, "Slot update is void\n")); PortableServer::POA_var poa = resolve_poa (an.in ()); PortableServer::ServantBase_var servant = poa->id_to_servant (oid.in ()); Checkpointable* target = dynamic_cast<Checkpointable*> (servant.in ()); if (target) { CORBA::Any_var tmp = target->get_state (); if (tmp.ptr () != 0) state = tmp._retn (); } } TAO_OutputCDR cdr; cdr << oid.in (); cdr << an.in (); cdr << ftr->client_id.in (); cdr << ftr->retention_id; cdr << reply.in (); cdr << state.in (); size_t size = cdr.total_length (); CORBA::OctetSeq_var msg; ACE_NEW (msg.out (), CORBA::OctetSeq (size)); msg->length (size); { CORBA::Octet* buf = msg->get_buffer (); for (ACE_Message_Block const* mb = cdr.begin (); mb != 0; mb = mb->cont ()) { ACE_OS::memcpy (buf, mb->rd_ptr (), mb->length ()); buf += mb->length (); } } CORBA::Octet* buf = msg->get_buffer (); // Crash point 1. // if (crash_point == 1 && ftr->retention_id > 2) ACE_OS::exit (1); try { while (true) { try { group_->send (buf, size); ACE_DEBUG ((LM_DEBUG, "Sent log record of length %i\n", size)); break; } catch (ACE_TMCast::Group::Aborted const&) { ACE_DEBUG ((LM_DEBUG, "Retrying to send log record.\n")); } } } catch (ACE_TMCast::Group::Failed const&) { ACE_DEBUG ((LM_DEBUG, "Group failure. Perhaps, I am alone in the group.\n")); } } // Now perform local logging. // RecordId rid (ftr->client_id.in (), ftr->retention_id); // This is slow but eh-safe ;-). // log_.insert (rid, reply); // Crash point 2. // if (crash_point == 2 && ftr->retention_id > 2) ACE_OS::exit (1); }
int ACE_TMAIN(int argc, ACE_TCHAR *argv[]) { try { CORBA::ORB_var orb = CORBA::ORB_init (argc, argv); CORBA::Object_var poa_object = orb->resolve_initial_references("RootPOA"); PortableServer::POA_var poa = PortableServer::POA::_narrow (poa_object.in ()); if (CORBA::is_nil (poa.in ())) ACE_ERROR_RETURN ((LM_ERROR, " (%P|%t) Panic: nil RootPOA\n"), 1); Hello_impl * h = 0; ACE_NEW_RETURN (h,Hello_impl, 1); CORBA::ULong before_act = h->_refcount_value (); ACE_DEBUG ((LM_DEBUG, "Before activation: %d\n", before_act)); PortableServer::ObjectId_var oid = poa->activate_object (h); CORBA::ULong after_act = h->_refcount_value (); ACE_DEBUG ((LM_DEBUG, "After activation: %d\n", after_act)); { /* * C++ Language Mapping (formal/03-06-03), section 1.37.3 (Servant * Memory Management Considerations), first bullet on page 1-136: * * POA::id_to_servant returns a Servant. The POA invokes _add_ref * once on the Servant before returning it; the caller of * id_to_servant is responsible for invoking _remove_ref on the * returned servant when it is finished with it. */ CORBA::ULong refCountBeforeIdToServant = h->_refcount_value (); ACE_DEBUG ((LM_DEBUG, "Before id_to_servant: %d\n", refCountBeforeIdToServant)); PortableServer::ServantBase_var srv = poa->id_to_servant (oid.in()); CORBA::ULong refCountAfterIdToServant = srv->_refcount_value ();; ACE_DEBUG ((LM_DEBUG, "After id_to_servant: %d\n", refCountAfterIdToServant)); /* * According to the above quote, this assertion shall be true. */ ACE_ASSERT (refCountAfterIdToServant == refCountBeforeIdToServant + 1); /* * At the end of this scope, "srv" is destructed, which decrements * the servant's reference count. */ } CORBA::ULong before_deact = h->_refcount_value (); ACE_DEBUG ((LM_DEBUG, "Before deactivate_object: %d\n", before_deact)); poa->deactivate_object (oid.in()); /* * Because id_to_servant did not increment the reference count, but * the reference count was decremented by the "srv" destructor, the * reference count, using TAO 1.4.5, is now 0, and the servant has * been destructed. So the following will crash, despite being * correct. */ CORBA::ULong after_deact = h->_refcount_value (); ACE_DEBUG ((LM_DEBUG, "After deactivate_object: %d\n", after_deact)); h->_remove_ref (); orb->shutdown (1); orb->destroy (); } catch (const CORBA::Exception& ex) { ex._tao_print_exception ("Exception caught:"); return 1; } return 0; }