Skip to content

File pl_signature.cpp

File List > cubrid > src > sp > pl_signature.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 "pl_signature.hpp"

#include <new>
#include "memory_alloc.h"
#include "memory_private_allocator.hpp"
#include "sp_constants.hpp"
#include "error_manager.h"
#if defined (SERVER_MODE)
#include "thread_manager.hpp"
#endif


// XXX: SHOULD BE THE LAST INCLUDE HEADER
#include "memory_wrapper.hpp"
#define CHECK_NULL_AND_FREE(owner, val)                        \
    do {                                                  \
      if (val != nullptr)                                 \
      {                                                   \
       db_private_free_and_init (owner, val);             \
      }                                                   \
    } while(0)

namespace cubpl
{
  static const char *EMPTY_STRING = "";

  pl_arg::pl_arg ()
    : pl_arg (0)
  {}

  pl_arg::pl_arg (int num_args)
    : arg_size {num_args}
  {
    set_arg_size (num_args);
  }

  pl_arg::~pl_arg ()
  {
    clear ();
  }

  void
  pl_arg::clear ()
  {
    if (arg_size > 0)
      {
    THREAD_ENTRY *owner = NULL;
#if defined(SERVER_MODE)
    owner = thread_get_thread_entry_info ();
#endif
    CHECK_NULL_AND_FREE (owner, arg_mode);
    CHECK_NULL_AND_FREE (owner, arg_type);
    if (arg_default_value_size)
      {
        for (int i = 0; i < arg_size; i++)
          {
        if (arg_default_value_size[i] > 0)
          {
            CHECK_NULL_AND_FREE (owner, arg_default_value[i]);
          }
          }
      }
    CHECK_NULL_AND_FREE (owner, arg_default_value_size);
    CHECK_NULL_AND_FREE (owner, arg_default_value);
      }
  }

  void
  pl_arg::pack (cubpacking::packer &serializator) const
  {
    serializator.pack_int (arg_size);

    if (arg_size > 0)
      {
    serializator.pack_int_array (arg_mode, arg_size);
    serializator.pack_int_array (arg_type, arg_size);
      }
  }

  void
  pl_arg::unpack (cubpacking::unpacker &deserializator)
  {
    deserializator.unpack_int (arg_size);

    if (arg_size > 0)
      {
    set_arg_size (arg_size);

    int cnt;
    deserializator.unpack_int_array (arg_mode, cnt);
    assert (arg_size == cnt);

    deserializator.unpack_int_array (arg_type, cnt);
    assert (arg_size == cnt);
      }
  }

  size_t
  pl_arg::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const
  {
    size_t size = serializator.get_packed_int_size (start_offset); // arg_size
    if (arg_size > 0)
      {
    size += serializator.get_packed_int_array_size (size, arg_size); // arg_mode
    size += serializator.get_packed_int_array_size (size, arg_size); // arg_type
      }
    return size;
  }

  void
  pl_arg::set_arg_size (int num_args)
  {
    clear ();
    if (num_args > 0)
      {
    arg_size = num_args;

    arg_mode = (int *) db_private_alloc (NULL, (num_args) * sizeof (int));
    arg_type = (int *) db_private_alloc (NULL, (num_args) * sizeof (int));
    arg_default_value_size = (int *) db_private_alloc (NULL, (num_args) * sizeof (int));
    arg_default_value = (char **) db_private_alloc (NULL, (num_args) * sizeof (char *));

    if (arg_mode && arg_type && arg_default_value_size && arg_default_value)
      {
        memset (arg_mode, 0x00, (num_args * sizeof (int)));
        memset (arg_type, 0x00, (num_args * sizeof (int)));
        memset (arg_default_value_size, 0x00, (num_args * sizeof (int)));
        memset (arg_default_value, 0x00, (num_args * sizeof (char *)));
      }
    else
      {
        assert_release (false);
      }
      }
    else
      {
    arg_size = 0;
    arg_mode = nullptr;
    arg_type = nullptr;
    arg_default_value_size = nullptr;
    arg_default_value = nullptr;
      }
  }

  pl_signature::pl_signature ()
    : type {PL_TYPE_NONE}
    , name {nullptr}
    , auth {nullptr}
    , result_type {0}
  {
    memset (&ext, 0, sizeof (pl_ext));

#if defined (SERVER_MODE)
    is_disposable = (thread_get_thread_entry_info ()->private_heap_id != 0);
#else
    is_disposable = true;
#endif
  }

  pl_signature::~pl_signature ()
  {
    THREAD_ENTRY *owner = NULL;
#if defined(SERVER_MODE)
    owner = thread_get_thread_entry_info ();
#endif

    CHECK_NULL_AND_FREE (owner, name);
    CHECK_NULL_AND_FREE (owner, auth);

    if (PL_TYPE_IS_METHOD (type))
      {
    CHECK_NULL_AND_FREE (owner, ext.method.class_name);
    CHECK_NULL_AND_FREE (owner, ext.method.arg_pos);
      }
    else
      {
    CHECK_NULL_AND_FREE (owner, ext.sp.target_class_name);
    CHECK_NULL_AND_FREE (owner, ext.sp.target_method_name);
      }
  }

  void
  pl_signature::pack (cubpacking::packer &serializator) const
  {
    serializator.pack_int (type);
    serializator.pack_c_string (name, strlen (name));

    serializator.pack_bool (auth != nullptr);
    if (auth)
      {
    serializator.pack_c_string (auth, strlen (auth));
      }

    serializator.pack_int (result_type);

    // arg
    arg.pack (serializator);

    // ext
    if (PL_TYPE_IS_METHOD (type))
      {
    serializator.pack_bool (ext.method.class_name != nullptr);
    if (ext.method.class_name)
      {
        serializator.pack_c_string (ext.method.class_name, strlen (ext.method.class_name));
      }
    if (arg.arg_size > 0)
      {
        serializator.pack_int_array (ext.method.arg_pos, arg.arg_size);
      }
      }
    else
      {
    serializator.pack_bool (ext.sp.target_class_name != nullptr);
    if (ext.sp.target_class_name)
      {
        serializator.pack_c_string (ext.sp.target_class_name, strlen (ext.sp.target_class_name));
      }
    serializator.pack_bool (ext.sp.target_method_name != nullptr);
    if (ext.sp.target_method_name)
      {
        serializator.pack_c_string (ext.sp.target_method_name, strlen (ext.sp.target_method_name));
      }
    serializator.pack_oid (ext.sp.code_oid);
      }
  }

  void
  pl_signature::unpack (cubpacking::unpacker &deserializator)
  {
#if defined(SERVER_MODE)
    size_t len = 0;
    char *ptr = NULL;
#endif

    deserializator.unpack_int (type);

    cubmem::extensible_block name_blk { cubmem::PRIVATE_BLOCK_ALLOCATOR };
    deserializator.unpack_string_to_memblock (name_blk);
    name = name_blk.release_ptr ();

    bool has_auth = false;
    deserializator.unpack_bool (has_auth);
    if (has_auth)
      {
    cubmem::extensible_block auth_name_blk { cubmem::PRIVATE_BLOCK_ALLOCATOR };
    deserializator.unpack_string_to_memblock (auth_name_blk);
    auth = auth_name_blk.release_ptr ();
      }
    else
      {
    auth = nullptr;
      }

    deserializator.unpack_int (result_type);

    arg.unpack (deserializator);

    // ext
    if (PL_TYPE_IS_METHOD (type))
      {
    bool has_cn = false;
    deserializator.unpack_bool (has_cn);
    if (has_cn)
      {
        cubmem::extensible_block class_name_blk { cubmem::PRIVATE_BLOCK_ALLOCATOR };
        deserializator.unpack_string_to_memblock (class_name_blk);
        ext.method.class_name = class_name_blk.release_ptr ();
      }
    else
      {
        ext.method.class_name = nullptr;
      }

    if (arg.arg_size > 0)
      {
        int cnt;
        ext.method.arg_pos = (int *) db_private_alloc (NULL, sizeof (int) * arg.arg_size);
        deserializator.unpack_int_array (ext.method.arg_pos, cnt);
        assert (cnt == arg.arg_size);
      }
    else
      {
        ext.method.arg_pos = nullptr;
      }
      }
    else
      {
    bool has_n = false;
    deserializator.unpack_bool (has_n);
    if (has_n)
      {
        cubmem::extensible_block class_name_blk { cubmem::PRIVATE_BLOCK_ALLOCATOR };
        deserializator.unpack_string_to_memblock (class_name_blk);
        ext.sp.target_class_name = class_name_blk.release_ptr ();
      }
    else
      {
        ext.sp.target_class_name = nullptr;
      }

    deserializator.unpack_bool (has_n);
    if (has_n)
      {
        cubmem::extensible_block class_name_blk { cubmem::PRIVATE_BLOCK_ALLOCATOR };
        deserializator.unpack_string_to_memblock (class_name_blk);
        ext.sp.target_method_name = class_name_blk.release_ptr ();
      }
    else
      {
        ext.sp.target_method_name = nullptr;
      }

    deserializator.unpack_oid (ext.sp.code_oid);
      }
  }

  size_t
  pl_signature::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const
  {
    size_t size = serializator.get_packed_int_size (start_offset); /* type */

    size += serializator.get_packed_c_string_size (name, strlen (name), size); // name
    size += serializator.get_packed_bool_size (size); // has auth
    if (auth)
      {
    size += serializator.get_packed_c_string_size (auth, strlen (auth), size);
      }

    size += serializator.get_packed_int_size (size); /* result_type */

    size += arg.get_packed_size (serializator, size); // arg

    if (PL_TYPE_IS_METHOD (type))
      {
    size += serializator.get_packed_bool_size (size); // has class_name
    if (ext.method.class_name)
      {
        size += serializator.get_packed_c_string_size (ext.method.class_name, strlen (ext.method.class_name), size);
      }

    if (arg.arg_size > 0)
      {
        size += serializator.get_packed_int_array_size (size, arg.arg_size); // arg_pos
      }
      }
    else
      {
    size += serializator.get_packed_bool_size (size); // has target_class_name
    if (ext.sp.target_class_name)
      {
        size += serializator.get_packed_c_string_size (ext.sp.target_class_name, strlen (ext.sp.target_class_name), size);
      }
    size += serializator.get_packed_bool_size (size); // has target_method_name
    if (ext.sp.target_method_name)
      {
        size += serializator.get_packed_c_string_size (ext.sp.target_method_name, strlen (ext.sp.target_method_name), size);
      }

    size += serializator.get_packed_oid_size (size); // code_oid
      }

    return size;
  }

  bool
  pl_signature::has_args ()
  {
    return arg.arg_size > 0;
  }

  pl_signature_array::pl_signature_array ()
    : num_sigs {0}
    , sigs {nullptr}
  {
#if defined (SERVER_MODE)
    is_disposable = (thread_get_thread_entry_info ()->private_heap_id != 0);
#else
    is_disposable = true;
#endif
  }

  pl_signature_array::~pl_signature_array ()
  {
    if (sigs)
      {
    delete [] sigs;
    sigs = nullptr;
      }
  }

  void
  pl_signature_array::pack (cubpacking::packer &serializator) const
  {
    serializator.pack_int (num_sigs);
    for (int i = 0; i < num_sigs; i++)
      {
    sigs[i].pack (serializator);
      }
  }

  void
  pl_signature_array::unpack (cubpacking::unpacker &deserializator)
  {
    deserializator.unpack_int (num_sigs);
    if (num_sigs > 0)
      {
#if defined(MMON_DEBUG_LEVEL)
    sigs = new  pl_signature [num_sigs];
#else
    sigs = new (std::nothrow) pl_signature [num_sigs];
#endif
    assert_release (sigs != NULL);
    if (sigs)
      {
        for (int i = 0; i < num_sigs; i++)
          {
        sigs[i].unpack (deserializator);
          }
      }
      }
  }

  size_t
  pl_signature_array::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const
  {
    size_t size = serializator.get_packed_int_size (start_offset); /* num_sigs */
    for (int i = 0; i < num_sigs; i++)
      {
    size += sigs[i].get_packed_size (serializator, size);
      }
    return size;
  }
}