예제 #1
0
int
ACE_Message_Block::release_i (ACE_Lock *lock)
{
  ACE_TRACE ("ACE_Message_Block::release_i");

  // Free up all the continuation messages.
  if (this->cont_)
    {
      ACE_Message_Block *mb = this->cont_;
      ACE_Message_Block *tmp = 0;

      do
        {
          tmp = mb;
          mb = mb->cont_;
          tmp->cont_ = 0;

          ACE_Data_Block *db = tmp->data_block ();
          if (tmp->release_i (lock) != 0)
            {
              ACE_Allocator *allocator = db->data_block_allocator ();
              ACE_DES_FREE (db,
                            allocator->free,
                            ACE_Data_Block);
            }
        }
      while (mb);

      this->cont_ = 0;
    }

  int result = 0;

  if (ACE_BIT_DISABLED (this->flags_,
                        ACE_Message_Block::DONT_DELETE) &&
      this->data_block ())
    {
      if (this->data_block ()->release_no_delete (lock) == 0)
        result = 1;
      this->data_block_ = 0;
    }

  // We will now commit suicide: this object *must* have come from the
  // allocator given.
  if (this->message_block_allocator_ == 0)
    delete this;
  else
    {
      ACE_Allocator *allocator = this->message_block_allocator_;
      ACE_DES_FREE (this,
                    allocator->free,
                    ACE_Message_Block);
    }

  return result;
}
예제 #2
0
int
TAO_DII_Asynch_Reply_Dispatcher::dispatch_reply (
    TAO_Pluggable_Reply_Params &params)
{
  this->reply_status_ = params.reply_status ();
  this->locate_reply_status_ = params.locate_reply_status ();

  // Transfer the <params.input_cdr_>'s content to this->reply_cdr_
  ACE_Data_Block *db =
    this->reply_cdr_.clone_from (*params.input_cdr_);

  // See whether we need to delete the data block by checking the
  // flags. We cannot be happy that we initally allocated the
  // datablocks of the stack. If this method is called twice, as is in
  // some cases where the same invocation object is used to make two
  // invocations like forwarding, the release becomes essential.
  if (ACE_BIT_DISABLED (db->flags (),
                        ACE_Message_Block::DONT_DELETE))
    db->release ();

  // Steal the buffer, that way we don't do any unnecesary copies of
  // this data.
  CORBA::ULong max = params.svc_ctx_.maximum ();
  CORBA::ULong len = params.svc_ctx_.length ();
  IOP::ServiceContext* context_list = params.svc_ctx_.get_buffer (1);
  this->reply_service_info_.replace (max, len, context_list, 1);

  if (TAO_debug_level >= 4)
    {
      TAOLIB_DEBUG ((LM_DEBUG,
                  ACE_TEXT ("(%P | %t):")
                  ACE_TEXT ("TAO_DII_Asynch_Reply_Dispatcher::dispatch_reply: status = %d\n"),
                  this->reply_status_));
    }

  try
    {
      // Call the handler with the reply data.
      CORBA::Request::_tao_reply_stub (this->reply_cdr_,
                                       this->callback_,
                                       this->reply_status_);
    }
  catch (const CORBA::Exception& ex)
    {
      if (TAO_debug_level >= 4)
        {
          ex._tao_print_exception ("Exception during reply handler");
        }
    }
  // This was dynamically allocated. Now the job is done.
  this->intrusive_remove_ref (this);

  return 1;
}
예제 #3
0
ACE_Message_Block *
ACE_Message_Block::release (void)
{
  ACE_TRACE ("ACE_Message_Block::release");

  // We want to hold the data block in a temporary variable because we
  // invoked "delete this;" at some point, so using this->data_block_
  // could be a bad idea.
  ACE_Data_Block *tmp = this->data_block ();

  // This flag is set to 1 when we have to destroy the data_block
  int destroy_dblock = 0;

  ACE_Lock *lock = 0;

  // Do we have a valid data block
  if (this->data_block ())
    {
      // Grab the lock that belongs to my data block
      lock = this->data_block ()->locking_strategy ();

      // if we have a lock
      if (lock != 0)
        {
          // One guard for all
          ACE_GUARD_RETURN (ACE_Lock, ace_mon, *lock, 0);

          // Call non-guarded release with <lock>
          destroy_dblock = this->release_i (lock);
        }
      // This is the case when we have a valid data block but no lock
      else
        // Call non-guarded release with no lock
        destroy_dblock = this->release_i (0);
    }
  else
    // This is the case when we don't even have a valid data block
    destroy_dblock = this->release_i (0);

  if (destroy_dblock != 0)
    {
      ACE_Allocator *allocator = tmp->data_block_allocator ();
      ACE_DES_FREE (tmp,
                    allocator->free,
                    ACE_Data_Block);
    }

  return 0;
}
예제 #4
0
ACE_Data_Block *
ACE_Data_Block::clone_nocopy (ACE_Message_Block::Message_Flags mask,
                              size_t max_size) const
{
  ACE_FUNCTION_TIMEPROBE(ACE_DATA_BLOCK_CLONE_ENTER);

  ACE_TRACE ("ACE_Data_Block::clone_nocopy");

  // You always want to clear this one to prevent memory leaks but you
  // might add some others later.
  const ACE_Message_Block::Message_Flags always_clear =
    ACE_Message_Block::DONT_DELETE;

  const size_t newsize =
    max_size == 0 ? this->max_size_ : max_size;

  ACE_Data_Block *nb = 0;

  ACE_NEW_MALLOC_RETURN (nb,
                         static_cast<ACE_Data_Block*> (
                           this->data_block_allocator_->malloc (sizeof (ACE_Data_Block))),
                         ACE_Data_Block (newsize, // size
                                         this->type_,     // type
                                         0,               // data
                                         this->allocator_strategy_, // allocator
                                         this->locking_strategy_, // locking strategy
                                         this->flags_,  // flags
                                         this->data_block_allocator_),
                         0);

  // Message block initialization may fail while the construction
  // succeds.  Since as a matter of policy, ACE may throw no
  // exceptions, we have to do a separate check like this.
  if (nb != 0 && nb->size () < newsize)
    {
      nb->ACE_Data_Block::~ACE_Data_Block();  // placement destructor ...
      this->data_block_allocator_->free (nb); // free ...
      errno = ENOMEM;
      return 0;
    }


  // Set new flags minus the mask...
  nb->clr_flags (mask | always_clear);
  return nb;
}
예제 #5
0
int
TAO_Synch_Reply_Dispatcher::dispatch_reply (
    TAO_Pluggable_Reply_Params &params)
{
  if (params.input_cdr_ == 0)
    return -1;

  this->reply_status_ = params.reply_status ();
  this->locate_reply_status_ = params.locate_reply_status ();

  // Steal the buffer, that way we don't do any unnecesary copies of
  // this data.
  CORBA::ULong const max = params.svc_ctx_.maximum ();
  CORBA::ULong const len = params.svc_ctx_.length ();
  IOP::ServiceContext* context_list = params.svc_ctx_.get_buffer (true);
  this->reply_service_info_.replace (max, len, context_list, true);

  if (this->reply_service_info_.length() > 0)
    {
      orb_core_->service_context_registry ().
        process_service_contexts (this->reply_service_info_, *(params.transport_), 0);
    }

  // Must reset the message state, it is possible that the same reply
  // dispatcher is used because the request must be re-sent.
  // this->message_state_.reset (0);

  // Transfer the <params.input_cdr_>'s content to this->reply_cdr_
  if (ACE_BIT_DISABLED ((*params.input_cdr_).start()->data_block()->flags(),
                        ACE_Message_Block::DONT_DELETE))
  {
    // Data block is on the heap, so just duplicate it.
    this->reply_cdr_ = *params.input_cdr_;
    this->reply_cdr_.clr_mb_flags (ACE_Message_Block::DONT_DELETE);
  }
  else
  {
    ACE_Data_Block *db = this->reply_cdr_.clone_from (*params.input_cdr_);

    if (db == 0)
      {
        if (TAO_debug_level > 2)
          {
            TAOLIB_ERROR ((LM_ERROR,
                        "TAO (%P|%t) - Synch_Reply_Dispatcher::dispatch_reply "
                        "clone_from failed\n"));
          }
        return -1;
      }

    // See whether we need to delete the data block by checking the
    // flags. We cannot be happy that we initally allocated the
    // datablocks of the stack. If this method is called twice, as is in
    // some cases where the same invocation object is used to make two
    // invocations like forwarding, the release becomes essential.
    if (ACE_BIT_DISABLED (db->flags (),
                          ACE_Message_Block::DONT_DELETE))
      {
        db->release ();
      }
  }

  this->state_changed (TAO_LF_Event::LFS_SUCCESS,
                       this->orb_core_->leader_follower ());

  return 1;
}
예제 #6
0
ACE_Message_Block *
ACE_Message_Block::clone (Message_Flags mask) const
{
  ACE_TRACE ("ACE_Message_Block::clone");

  // Get a pointer to a "cloned" <ACE_Data_Block> (will copy the
  // values rather than increment the reference count).
  ACE_Data_Block *db = this->data_block ()->clone (mask);

  if (db == 0)
    return 0;

  ACE_Message_Block *nb = 0;

  if (message_block_allocator_ == 0)
    {
      ACE_NEW_RETURN (nb,
                      ACE_Message_Block (0, // size
                                         ACE_Message_Type (0), // type
                                         0, // cont
                                         0, // data
                                         0, // allocator
                                         0, // locking strategy
                                         0, // flags
                                         this->priority_, // priority
                                         ACE_EXECUTION_TIME, // execution time
                                         ACE_DEADLINE_TIME, // absolute time to deadline
                                         // Get a pointer to a
                                         // "duplicated" <ACE_Data_Block>
                                         // (will simply increment the
                                         // reference count).
                                         db,
                                         db->data_block_allocator (),
                                         this->message_block_allocator_),
                      0);
    }
  else
    {
      // This is the ACE_NEW_MALLOC macro with the return check removed.
      // We need to do it this way because if it fails we need to release
      // the cloned data block that was created above.  If we used
      // ACE_NEW_MALLOC_RETURN, there would be a memory leak because the
      // above db pointer would be left dangling.
      nb = static_cast<ACE_Message_Block*> (message_block_allocator_->malloc (sizeof (ACE_Message_Block)));
      if (nb != 0)
        new (nb) ACE_Message_Block (0, // size
                                    ACE_Message_Type (0), // type
                                    0, // cont
                                    0, // data
                                    0, // allocator
                                    0, // locking strategy
                                    0, // flags
                                    this->priority_, // priority
                                    ACE_EXECUTION_TIME, // execution time
                                    ACE_DEADLINE_TIME, // absolute time to deadline
                                    db,
                                    db->data_block_allocator (),
                                    this->message_block_allocator_);
    }

  if (nb == 0)
    {
      db->release ();
      return 0;
    }

  // Set the read and write pointers in the new <Message_Block> to the
  // same relative offset as in the existing <Message_Block>.
  nb->rd_ptr (this->rd_ptr_);
  nb->wr_ptr (this->wr_ptr_);

  // Clone all the continuation messages if necessary.
  if (this->cont () != 0
      && (nb->cont_ = this->cont ()->clone (mask)) == 0)
    {
      nb->release ();
      return 0;
    }
  return nb;
}
예제 #7
0
// Dispatch the reply.
int
TAO_Asynch_Reply_Dispatcher::dispatch_reply (TAO_Pluggable_Reply_Params &params)
{
  if (this->timeout_handler_)
    {
      // If we had registered timeout handlers just cancel them and
      // loose ownership of the handlers
      this->timeout_handler_->cancel ();
      this->timeout_handler_->remove_reference ();
      this->timeout_handler_ = 0;
      // AMI Timeout Handling End
    }

  // With Asynch requests the invocation handler can't call idle_after_reply ()
  // since it does not handle the reply.
  // So we have to do that here in case f.i. the Exclusive TMS left the transport
  // busy after the send
  if (this->transport_ != 0)
    this->transport_->tms ()->idle_after_reply ();

  if (!params.input_cdr_)
    return -1;

  if (!this->try_dispatch_reply ())
    return 0;

  this->reply_status_ = params.reply_status ();
  this->locate_reply_status_ = params.locate_reply_status ();

  // Transfer the <params.input_cdr_>'s content to this->reply_cdr_
  ACE_Data_Block *db = this->reply_cdr_.clone_from (*params.input_cdr_);

  if (db == 0)
    {
      if (TAO_debug_level > 2)
        {
          TAOLIB_ERROR ((
            LM_ERROR,
            ACE_TEXT ("TAO_Messaging (%P|%t) - Asynch_Reply_Dispatcher::dispatch_reply ")
            ACE_TEXT ("clone_from failed\n")));
        }
      return -1;
    }

  // See whether we need to delete the data block by checking the
  // flags. We cannot be happy that we initially allocated the
  // datablocks of the stack. If this method is called twice, as is in
  // some cases where the same invocation object is used to make two
  // invocations like forwarding, the release becomes essential.
  if (ACE_BIT_DISABLED (db->flags (), ACE_Message_Block::DONT_DELETE))
    {
      db->release ();
    }

  if (!CORBA::is_nil (this->reply_handler_.in ()))
    {
      // Steal the buffer, that way we don't do any unnecesary copies of
      // this data.
      CORBA::ULong const max = params.svc_ctx_.maximum ();
      CORBA::ULong const len = params.svc_ctx_.length ();
      IOP::ServiceContext *context_list = params.svc_ctx_.get_buffer (1);
      this->reply_service_info_.replace (max, len, context_list, 1);

      if (TAO_debug_level >= 4)
        {
          TAOLIB_DEBUG ((LM_DEBUG,
                      ACE_TEXT ("TAO_Messaging (%P|%t) - Asynch_Reply_Dispatcher")
                      ACE_TEXT ("::dispatch_reply status = %d\n"),
                                this->reply_status_));
        }

      CORBA::ULong reply_error = TAO_AMI_REPLY_NOT_OK;
      switch (this->reply_status_)
        {
        case GIOP::NO_EXCEPTION:
          reply_error = TAO_AMI_REPLY_OK;
          break;
        case GIOP::USER_EXCEPTION:
          reply_error = TAO_AMI_REPLY_USER_EXCEPTION;
          break;
        case GIOP::SYSTEM_EXCEPTION:
          reply_error = TAO_AMI_REPLY_SYSTEM_EXCEPTION;
          break;
        case GIOP::LOCATION_FORWARD:
          reply_error = TAO_AMI_REPLY_LOCATION_FORWARD;
          break;
        case GIOP::LOCATION_FORWARD_PERM:
          reply_error = TAO_AMI_REPLY_LOCATION_FORWARD_PERM;
          break;

        default:
          // @@ Michael: Not even the spec mentions this case.
          //             We have to think about this case.
          // Handle the forwarding and return so the stub restarts the
          // request!
          reply_error = TAO_AMI_REPLY_NOT_OK;
          break;
        }

      try
        {
          // Call the Reply Handler's stub.
          this->reply_handler_stub_ (this->reply_cdr_,
                                     this->reply_handler_.in (),
                                     reply_error);
        }
      catch (const ::CORBA::Exception& ex)
        {
          if (TAO_debug_level >= 4)
            ex._tao_print_exception ("Exception during reply handler");
        }
    }

  this->intrusive_remove_ref (this);

  return 1;
}
예제 #8
0
ACE_Message_Block *
ACE_Message_Block::clone (Message_Flags mask) const
{
  ACE_TRACE ("ACE_Message_Block::clone");

  const ACE_Message_Block *old_message_block = this;
  ACE_Message_Block *new_message_block = 0;
  ACE_Message_Block *new_previous_message_block = 0;
  ACE_Message_Block *new_root_message_block = 0;

  do
    {
      // Get a pointer to a "cloned"<ACE_Data_Block> (will copy the
      // values rather than increment the reference count).
      ACE_Data_Block *db = old_message_block->data_block ()->clone (mask);

      if (db == 0)
        return 0;

      if(old_message_block->message_block_allocator_ == 0)
        {
          ACE_NEW_RETURN (new_message_block,
                          ACE_Message_Block (0, // size
                                             ACE_Message_Type (0), // type
                                             0, // cont
                                             0, // data
                                             0, // allocator
                                             0, // locking strategy
                                             0, // flags
                                             old_message_block->priority_, // priority
                                             ACE_EXECUTION_TIME, // execution time
                                             ACE_DEADLINE_TIME, // absolute time to deadline
                                             // Get a pointer to a
                                             // "duplicated"<ACE_Data_Block>
                                             // (will simply increment the
                                             // reference count).
                                             db,
                                             db->data_block_allocator (),
                                             old_message_block->message_block_allocator_),
                          0);
        }
      else
        {
          // This is the ACE_NEW_MALLOC macro with the return check removed.
          // We need to do it this way because if it fails we need to release
          // the cloned data block that was created above. If we used
          // ACE_NEW_MALLOC_RETURN, there would be a memory leak because the
          // above db pointer would be left dangling.
          new_message_block = static_cast<ACE_Message_Block*> (old_message_block->message_block_allocator_->malloc (sizeof (ACE_Message_Block)));
          if (new_message_block != 0)
            new (new_message_block) ACE_Message_Block (0, // size
                                                       ACE_Message_Type (0), // type
                                                       0, // cont
                                                       0, // data
                                                       0, // allocator
                                                       0, // locking strategy
                                                       0, // flags
                                                       old_message_block->priority_, // priority
                                                       ACE_EXECUTION_TIME, // execution time
                                                       ACE_DEADLINE_TIME, // absolute time to deadline
                                                       db,
                                                       db->data_block_allocator (),
                                                       old_message_block->message_block_allocator_);
        }

      if (new_message_block == 0)
        {
          db->release ();
          return 0;
        }

      // Set the read and write pointers in the new <Message_Block> to the
      // same relative offset as in the existing <Message_Block>.
      new_message_block->rd_ptr (old_message_block->rd_ptr_);
      new_message_block->wr_ptr (old_message_block->wr_ptr_);
      // save the root message block to return
      if (new_root_message_block == 0)
        new_root_message_block = new_message_block;
      if (new_previous_message_block != 0)
        // we're a continuation of the previous block, add ourself to its chain
        new_previous_message_block->cont_ = new_message_block;
      new_previous_message_block = new_message_block;
      old_message_block = old_message_block->cont ();
    }
  while (old_message_block != 0);

  return new_root_message_block;
}