Skip to content

File method_invoke_group.cpp

File List > cubrid > src > sp > method_invoke_group.cpp

Go to the documentation of this file

/*
 *
 * Copyright 2016 CUBRID Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

#include "method_invoke_group.hpp"

#include "boot_sr.h"
#include "dbtype.h"     /* db_value_* */
#include "db_value_printer.hpp"
#include "pl_comm.h"        /* common communcation functions for javasp */
#include "mem_block.hpp" /* cubmem::extensible_block */

#include "method_struct_invoke.hpp"
#include "object_primitive.h"
#include "object_representation.h"  /* OR_ */
#include "packer.hpp"
#include "pl_connection.hpp"
#include "session.h"
#include "string_buffer.hpp"
#include "pl_session.hpp"
#include "network_callback_sr.hpp"

#if defined (SA_MODE)
#include "query_method.hpp"
#endif
// XXX: SHOULD BE THE LAST INCLUDE HEADER
#include "memory_wrapper.hpp"

namespace cubmethod
{
// Method Group to invoke together
  method_invoke_group::method_invoke_group (cubpl::pl_signature_array *sig_array)
    : m_id ((std::uint64_t) this)
    , m_stack (nullptr)
    , m_sig_array (sig_array)
  {
    assert (sig_array->num_sigs > 0);

    // assert
#if !defined (NDEBUG)
    for (int i = 0; i < sig_array->num_sigs; i++)
      {
    assert (PL_TYPE_IS_METHOD (sig_array->sigs[i].type));
      }
#endif

    DB_VALUE v;
    db_make_null (&v);
    m_result_vector.resize (sig_array->num_sigs, v);
  }

  method_invoke_group::~method_invoke_group ()
  {
    destroy_resources ();
  }

  DB_VALUE &
  method_invoke_group::get_return_value (int index)
  {
    assert (index >= 0 && index < (int) m_sig_array->num_sigs);
    return m_result_vector[index];
  }

  METHOD_GROUP_ID
  method_invoke_group::get_id () const
  {
    return m_id;
  }

  bool
  method_invoke_group::is_running () const
  {
    return m_is_running;
  }

  int
  method_invoke_group::prepare (std::vector<std::reference_wrapper<DB_VALUE>> &arg_base)
  {
    int error = NO_ERROR;

    cubpl::session *pl_session = cubpl::get_session ();
    if (!pl_session)
      {
    return ER_SES_SESSION_EXPIRED;
      }

    SESSION_ID s_id = pl_session->get_id ();
    TRANID t_id = m_stack->get_tran_id ();

    cubmethod::header header (s_id, METHOD_REQUEST_ARG_PREPARE);
    cubmethod::prepare_args arg (m_id, t_id, METHOD_TYPE_CLASS_METHOD, arg_base); // TOD

    error = xs_callback_send_args (m_stack->get_thread_entry (), header, arg);

    return error;
  }

  int method_invoke_group::execute (std::vector<std::reference_wrapper<DB_VALUE>> &arg_base)
  {
    int error = NO_ERROR;
    SESSION_ID s_id;
    TRANID t_id;

    cubpl::session *pl_session = cubpl::get_session ();
    if (!pl_session)
      {
    return ER_SES_SESSION_EXPIRED;
      }

    m_stack = pl_session->create_and_push_stack (nullptr);
    s_id =  pl_session->get_id ();
    t_id = m_stack->get_tran_id ();

    // prepare args
    error = prepare (arg_base);
    if (error != NO_ERROR)
      {
    goto exit;
      }

    for (int i = 0; i < m_sig_array->num_sigs; i++)
      {
    // invoke
    cubmethod::header header (s_id, METHOD_REQUEST_INVOKE /* default */);
    error = xs_callback_send_args (m_stack->get_thread_entry (), header, m_id, m_sig_array->sigs[i]);
    if (error != NO_ERROR)
      {
        break;
      }

    DB_VALUE &result = m_result_vector[i];
    db_value_clear (&result);

    auto get_method_result = [&] (cubmem::block & b)
    {
      int e = NO_ERROR;
      packing_unpacker unpacker (b);
      int status;
      unpacker.unpack_int (status);
      if (status == METHOD_SUCCESS)
        {
          unpacker.unpack_db_value (result);
        }
      else
        {
          unpacker.unpack_int (e);  /* er_errid */
        }
      return e;
    };

    // get_return
    error = xs_callback_receive (m_stack->get_thread_entry (), get_method_result);
    if (error != NO_ERROR)
      {
        break;
      }

#if 0 // TODO
    if (m_session->is_interrupted ())
      {
        error = m_session->get_interrupt_id ();
      }

    if (error != NO_ERROR)
      {
        // if error is not interrupt reason, interrupt is not set
        m_session->set_interrupt (error, (er_has_error () && er_msg ()) ? er_msg () : "");
        break;
      }
#endif
      }

    if (m_stack)
      {
    delete m_stack;
      }
exit:
    return error;
  }

  void
  method_invoke_group::begin ()
  {
    if (m_is_running == true)
      {
    return;
      }

    m_is_running = true;
  }

  int method_invoke_group::reset (bool is_end_query)
  {
    int error = NO_ERROR;

    if (!is_end_query)
      {
    m_stack->reset_query_handlers ();
      }

    return error;
  }

  void
  method_invoke_group::destroy_resources ()
  {
    pr_clear_value_vector (m_result_vector);
  }

  void
  method_invoke_group::end ()
  {
    if (m_is_running == false)
      {
    return;
      }

    // FIXME
    // m_rctx->pop_stack (m_thread_p, this);

    m_is_running = false;
  }

  int
  method_invoke_group::get_num_methods ()
  {
    return m_sig_array->num_sigs;
  }

  std::string
  method_invoke_group::get_error_msg ()
  {
    return m_err_msg;
  }

  void
  method_invoke_group::set_error_msg (const std::string &msg)
  {
    m_err_msg = msg;
  }
}   // namespace cubmethod