Skip to content

File memory_alloc.c

File List > base > memory_alloc.c

Go to the documentation of this file

/*
 * Copyright 2008 Search Solution Corporation
 * 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.
 *
 */

/*
 * memory_alloc.c - Memory allocation module
 */

#ident "$Id$"

#include "config.h"

#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "set_object.h"
#include "misc_string.h"
#include "object_domain.h"
#include "dbtype.h"
#include "memory_alloc.h"
#include "util_func.h"
#include "error_manager.h"
#include "intl_support.h"
#include "resource_tracker.hpp"
#include "customheaps.h"
#if !defined (SERVER_MODE)
#include "quick_fit.h"
#endif /* SERVER_MODE */
#if defined (SERVER_MODE)
#include "thread_entry.hpp"
#endif // SERVER_MODE
#if defined (SERVER_MODE)
#include "thread_manager.hpp"   // for thread_get_thread_entry_info
// XXX: SHOULD BE THE LAST INCLUDE HEADER
#include "memory_wrapper.hpp"
#endif // SERVER_MODE

#define DEFAULT_OBSTACK_CHUNK_SIZE      32768   /* 1024 x 32 */

#if !defined (SERVER_MODE)
extern unsigned int db_on_server;
HL_HEAPID private_heap_id = 0;
#endif /* SERVER_MODE */

#if defined (SERVER_MODE)
static HL_HEAPID db_private_get_heapid_from_thread (REFPTR (THREAD_ENTRY, thread_p));
#endif // SERVER_MODE

/*
 * ansisql_strcmp - String comparison according to ANSI SQL
 *   return: an integer value which is less than zero
 *           if s is lexicographically less than t,
 *           equal to zero if s is equal to t,
 *           and greater than zero if s is greater than zero.
 *   s(in): first string to be compared
 *   t(in): second string to be compared
 *
 * Note: The contents of the null-terminated string s are compared with
 *       the contents of the null-terminated string t, using the ANSI
 *       SQL semantics. That is, if the lengths of the strings are not
 *       the same, the shorter string is considered to be extended
 *       with the blanks on the right, so that both strings have the
 *       same length.
 */
int
ansisql_strcmp (const char *s, const char *t)
{
  for (; *s == *t; s++, t++)
    {
      if (*s == '\0')
    {
      return 0;
    }
    }

  if (*s == '\0')
    {
      while (*t != '\0')
    {
      if (*t++ != ' ')
        {
          return -1;
        }
    }
      return 0;
    }
  else if (*t == '\0')
    {
      while (*s != '\0')
    {
      if (*s++ != ' ')
        {
          return 1;
        }
    }
      return 0;
    }
  else
    {
      return (*(unsigned const char *) s < *(unsigned const char *) t) ? -1 : 1;
    }
}

/*
 * ansisql_strcasecmp - Case-insensitive string comparison according to ANSI SQL
 *   return: an integer value which is less than zero
 *           if s is lexicographically less than t,
 *           equal to zero if s is equal to t,
 *           and greater than zero if s is greater than zero.
 *   s(in): first string to be compared
 *   t(in): second string to be compared
 *
 * Note: The contents of the null-terminated string s are compared with
 *       the contents of the null-terminated string t, using the ANSI
 *       SQL semantics. That is, if the lengths of the strings are not
 *       the same, the shorter string is considered to be extended
 *       with the blanks on the right, so that both strings have the
 *       same length.
 */
int
ansisql_strcasecmp (const char *s, const char *t)
{
  size_t s_length, t_length, min_length;
  int cmp_val;

  s_length = strlen (s);
  t_length = strlen (t);

  min_length = s_length < t_length ? s_length : t_length;

  cmp_val = intl_identifier_ncasecmp (s, t, (int) min_length);

  /* If not equal for shorter length, return */
  if (cmp_val)
    {
      return cmp_val;
    }

  /* If equal and same size, return */
  if (s_length == t_length)
    {
      return 0;
    }

  /* If equal for shorter length and not same size, look for trailing blanks */
  s += min_length;
  t += min_length;

  if (*s == '\0')
    {
      while (*t != '\0')
    {
      if (*t++ != ' ')
        {
          return -1;
        }
    }
      return 0;
    }
  else
    {
      while (*s != '\0')
    {
      if (*s++ != ' ')
        {
          return 1;
        }
    }
      return 0;
    }
}

/*
 * db_alignment () -
 *   return:
 *   n(in):
 */
int
db_alignment (int n)
{
  if (n >= (int) sizeof (double))
    {
      return (int) sizeof (double);
    }
  else if (n >= (int) sizeof (void *))
    {
      return (int) sizeof (void *);
    }
  else if (n >= (int) sizeof (int))
    {
      return (int) sizeof (int);
    }
  else if (n >= (int) sizeof (short))
    {
      return (int) sizeof (short);
    }
  else
    {
      return 1;
    }
}

/*
 * db_align_to () - Return the least multiple of 'alignment' that is greater
 * than or equal to 'n'.
 *   return:
 *   n(in):
 *   alignment(in):
 */
int
db_align_to (int n, int alignment)
{
  /*
   * Return the least multiple of 'alignment' that is greater than or
   * equal to 'n'.  'alignment' must be a power of 2.
   */
  return (n + alignment - 1) & ~(alignment - 1);
}

/*
 * db_create_ostk_heap () - create an obstack heap
 *   return: memory heap identifier
 *   chunk_size(in):
 */
HL_HEAPID
db_create_ostk_heap (int chunk_size)
{
  return hl_register_ostk_heap (chunk_size);
}

/*
 * db_destroy_ostk_heap () - destroy an obstack heap
 *   return:
 *   heap_id(in): memory heap identifier to destroy
 */
void
db_destroy_ostk_heap (HL_HEAPID heap_id)
{
  hl_unregister_ostk_heap (heap_id);
}

/*
 * db_ostk_alloc () - call allocation function for the obstack heap
 *   return: allocated memory pointer
 *   heap_id(in): memory heap identifier
 *   size(in): size to allocate
 */
void *
db_ostk_alloc (HL_HEAPID heap_id, size_t size)
{
  void *ptr = NULL;
  if (heap_id && size > 0)
    {
      ptr = hl_ostk_alloc (heap_id, size);
    }
  return ptr;
}

#if defined (ENABLE_UNUSED_FUNCTION)
/*
 * db_ostk_free () - call free function for the ostk heap
 *   return:
 *   heap_id(in): memory heap identifier
 *   ptr(in): memory pointer to free
 */
void
db_ostk_free (HL_HEAPID heap_id, void *ptr)
{
  if (heap_id && ptr)
    {
      hl_ostk_free (heap_id, ptr);
    }
}
#endif /* ENABLE_UNUSED_FUNCTION */

/*
 * db_create_private_heap () - create a thread specific heap
 *   return: memory heap identifier
 */
HL_HEAPID
db_create_private_heap (void)
{
  HL_HEAPID heap_id = 0;
#if defined (SERVER_MODE)
  heap_id = hl_register_lea_heap ();
#else /* SERVER_MODE */
  if (db_on_server)
    {
      heap_id = hl_register_lea_heap ();
    }
#endif /* SERVER_MODE */
  return heap_id;
}

/*
 * db_clear_private_heap () - clear a thread specific heap
 *   return:
 *   heap_id(in): memory heap identifier to clear
 */
void
db_clear_private_heap (THREAD_ENTRY * thread_p, HL_HEAPID heap_id)
{
  if (heap_id == 0)
    {
#if defined (SERVER_MODE)
      heap_id = db_private_get_heapid_from_thread (thread_p);
#else /* SERVER_MODE */
      heap_id = private_heap_id;
#endif /* SERVER_MODE */
    }

  if (heap_id)
    {
      hl_clear_lea_heap (heap_id);
    }
}

/*
 * db_change_private_heap () - change private heap
 *    return: old private heap id
 *    heap_id(in): heap id
 */
HL_HEAPID
db_change_private_heap (THREAD_ENTRY * thread_p, HL_HEAPID heap_id)
{
  HL_HEAPID old_heap_id;

#if defined (SERVER_MODE)
  old_heap_id = db_private_set_heapid_to_thread (thread_p, heap_id);
#else /* SERVER_MODE */
  old_heap_id = private_heap_id;
  if (db_on_server)
    {
      private_heap_id = heap_id;
    }
#endif
  return old_heap_id;
}

/*
 * db_replace_private_heap () - replace a thread specific heap
 *   return: old memory heap identifier
 *
 */
HL_HEAPID
db_replace_private_heap (THREAD_ENTRY * thread_p)
{
  HL_HEAPID old_heap_id, heap_id;

#if defined (SERVER_MODE)
  old_heap_id = db_private_get_heapid_from_thread (thread_p);
#else /* SERVER_MODE */
  old_heap_id = private_heap_id;
#endif /* SERVER_MODE */

#if defined (SERVER_MODE)
  heap_id = db_create_private_heap ();
  db_private_set_heapid_to_thread (thread_p, heap_id);
#else /* SERVER_MODE */
  if (db_on_server)
    {
      heap_id = db_create_private_heap ();
      private_heap_id = heap_id;
    }
#endif /* SERVER_MODE */
  return old_heap_id;
}

/*
 * db_destroy_private_heap () - destroy a thread specific heap
 *   return:
 *   heap_id(in): memory heap identifier to destroy
 */
void
db_destroy_private_heap (THREAD_ENTRY * thread_p, HL_HEAPID heap_id)
{
  if (heap_id == 0)
    {
#if defined (SERVER_MODE)
      heap_id = db_private_get_heapid_from_thread (thread_p);
#else /* SERVER_MODE */
      heap_id = private_heap_id;
#endif /* SERVER_MODE */
    }

  if (heap_id)
    {
      hl_unregister_lea_heap (heap_id);
    }
}

/*
 * db_private_alloc () - call allocation function for current private heap
 *   return: allocated memory pointer
 *   thrd(in): thread context if it is available, otherwise NULL; if called
 *             on the server and this parameter is NULL, the function will
 *             determine the appropriate thread context
 *   size(in): size to allocate
 */

/* dummy definition for Windows */
#if defined(WINDOWS)
#if !defined(NDEBUG)
void *
db_private_alloc_release (THREAD_ENTRY * thrd, size_t size, bool rc_track)
{
  return NULL;
}
#else
void *
db_private_alloc_debug (THREAD_ENTRY * thrd, size_t size, bool rc_track, const char *caller_file, int caller_line)
{
  return NULL;
}
#endif
#endif

#if !defined(NDEBUG)
void *
db_private_alloc_debug (THREAD_ENTRY * thrd, size_t size, bool rc_track, const char *caller_file, int caller_line)
#else /* NDEBUG */
void *
db_private_alloc_release (THREAD_ENTRY * thrd, size_t size, bool rc_track)
#endif              /* NDEBUG */
{
#if !defined (CS_MODE)
  void *ptr = NULL;
#endif /* !CS_MODE */

#if defined (SERVER_MODE)
  HL_HEAPID heap_id;
#endif

  assert (size > 0);

#if defined (CS_MODE)
  return db_ws_alloc (size);
#elif defined (SERVER_MODE)
  if (size <= 0)
    {
      return NULL;
    }

  heap_id = db_private_get_heapid_from_thread (thrd);

  if (heap_id)
    {
      ptr = hl_lea_alloc (heap_id, size);
    }
  else
    {
      ptr = malloc (size);
      if (ptr == NULL)
    {
      er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, size);
    }
    }

#if !defined (NDEBUG)
  if (rc_track && heap_id != 0)
    {
      if (ptr != NULL)
    {
      thread_get_thread_entry_info ()->get_alloc_tracker ().increment (caller_file, caller_line, ptr);
    }
    }
#endif /* !NDEBUG */

  return ptr;
#else /* SA_MODE */

  if (db_is_utility_thread ())
    {
      ptr = malloc (size);
      if (ptr == NULL)
    {
      er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, size);
    }
      return ptr;
    }

  if (!db_on_server)
    {
      return db_ws_alloc (size);
    }
  else
    {
      if (size <= 0)
    {
      return NULL;
    }

      if (private_heap_id)
    {
      PRIVATE_MALLOC_HEADER *h = NULL;
      size_t req_sz;

      req_sz = private_request_size (size);
      h = (PRIVATE_MALLOC_HEADER *) hl_lea_alloc (private_heap_id, req_sz);

      if (h != NULL)
        {
          h->magic = PRIVATE_MALLOC_HEADER_MAGIC;
          h->alloc_type = PRIVATE_ALLOC_TYPE_LEA;
          return private_hl2user_ptr (h);
        }
      else
        {
          return NULL;
        }
    }
      else
    {
      ptr = malloc (size);
      if (ptr == NULL)
        {
          er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, size);
        }
      return ptr;
    }
    }
#endif /* SA_MODE */
}


/*
 * db_private_realloc () - call re-allocation function for current private heap
 *   return: allocated memory pointer
 *   thrd(in): thread conext if it is server, otherwise NULL
 *   ptr(in): memory pointer to reallocate
 *   size(in): size to allocate
 */
/* dummy definition for Windows */
#if defined(WINDOWS)
#if !defined(NDEBUG)
void *
db_private_realloc_release (THREAD_ENTRY * thrd, void *ptr, size_t size, bool rc_track)
{
  return NULL;
}
#else
void *
db_private_realloc_debug (THREAD_ENTRY * thrd, void *ptr, size_t size, bool rc_track, const char *caller_file,
              int caller_line)
{
  return NULL;
}
#endif
#endif

#if !defined(NDEBUG)
void *
db_private_realloc_debug (THREAD_ENTRY * thrd, void *ptr, size_t size, bool rc_track, const char *caller_file,
              int caller_line)
#else /* NDEBUG */
void *
db_private_realloc_release (THREAD_ENTRY * thrd, void *ptr, size_t size, bool rc_track)
#endif              /* NDEBUG */
{
#if !defined (CS_MODE)
  void *new_ptr = NULL;
#endif /* !CS_MODE */

#if defined (SERVER_MODE)
  HL_HEAPID heap_id;
#endif

#if defined (CS_MODE)
  return db_ws_realloc (ptr, size);
#elif defined (SERVER_MODE)
  if (size <= 0)
    {
      return NULL;
    }

  heap_id = db_private_get_heapid_from_thread (thrd);

  if (heap_id)
    {
      new_ptr = hl_lea_realloc (heap_id, ptr, size);
    }
  else
    {
      new_ptr = realloc (ptr, size);
      if (new_ptr == NULL)
    {
      er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, size);
    }
    }

#if !defined (NDEBUG)
  if (rc_track && heap_id != 0 && new_ptr != ptr)
    {
      /* remove old pointer from track meter */
      if (ptr != NULL)
    {
      thread_get_thread_entry_info ()->get_alloc_tracker ().decrement (ptr);
    }
      /* add new pointer to track meter */
      if (new_ptr != NULL)
    {
      thread_get_thread_entry_info ()->get_alloc_tracker ().increment (caller_file, caller_line, new_ptr);
    }
    }
#endif /* !NDEBUG */

  return new_ptr;
#else /* SA_MODE */
  if (ptr == NULL)
    {
      return db_private_alloc (thrd, size);
    }

  if (db_is_utility_thread ())
    {
      new_ptr = realloc (ptr, size);
      if (new_ptr == NULL)
    {
      er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, size);
    }
      return new_ptr;
    }

  if (!db_on_server)
    {
      return db_ws_realloc (ptr, size);
    }
  else
    {
      if (private_heap_id)
    {
      PRIVATE_MALLOC_HEADER *h;

      h = private_user2hl_ptr (ptr);
      if (h->magic != PRIVATE_MALLOC_HEADER_MAGIC)
        {
          return NULL;
        }

      if (h->alloc_type == PRIVATE_ALLOC_TYPE_LEA)
        {
          PRIVATE_MALLOC_HEADER *new_h;
          size_t req_sz;

          req_sz = private_request_size (size);
          new_h = (PRIVATE_MALLOC_HEADER *) hl_lea_realloc (private_heap_id, h, req_sz);
          if (new_h == NULL)
        {
          return NULL;
        }
          return private_hl2user_ptr (new_h);
        }
      else if (h->alloc_type == PRIVATE_ALLOC_TYPE_WS)
        {
          return db_ws_realloc (ptr, size);
        }
      else
        {
          return NULL;
        }
    }
      else
    {
      new_ptr = realloc (ptr, size);
      if (new_ptr == NULL)
        {
          er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, size);
        }
      return new_ptr;
    }
    }
#endif /* SA_MODE */
}

/*
 * db_private_private_strdup () - duplicate string. memory for the duplicated
 *   string is obtanined by db_private_alloc
 *   return: pointer to duplicated str
 *   thrd(in): thread conext if it is server, otherwise NULL
 *   size(s): source string
 */
char *
db_private_strdup (THREAD_ENTRY * thrd, const char *s)
{
  char *cp;
  int len;

  /* fast return */
  if (s == NULL)
    {
      return NULL;
    }

  len = (int) strlen (s);
  cp = (char *) db_private_alloc (thrd, len + 1);

  if (cp != NULL)
    {
      memcpy (cp, s, len);
      cp[len] = '\0';
    }

  return cp;
}


/*
 * db_private_strndup () - duplicate string with size. memory for the duplicated
 *   string is obtanined by db_private_alloc
 *   return: pointer to duplicated str
 *   thrd(in): thread conext if it is server, otherwise NULL
 *   s(in): source string
 *   size(in): source string size
 */
char *
db_private_strndup (THREAD_ENTRY * thrd, const char *s, size_t size)
{
  char *cp;

  /* fast return */
  if (s == NULL)
    {
      return NULL;
    }

  cp = (char *) db_private_alloc (thrd, size + 1);

  if (cp != NULL)
    {
      memcpy (cp, s, size);
      cp[size] = '\0';
    }

  return cp;
}

/*
 * db_private_free () - call free function for current private heap
 *   return:
 *   thrd(in): thread conext if it is server, otherwise NULL
 *   ptr(in): memory pointer to free
 */

/* dummy definition for Windows */
#if defined(WINDOWS)
#if !defined(NDEBUG)
void
db_private_free_release (THREAD_ENTRY * thrd, void *ptr, bool rc_track)
{
  return;
}
#else
void
db_private_free_debug (THREAD_ENTRY * thrd, void *ptr, bool rc_track, const char *caller_file, int caller_line)
{
  return;
}
#endif
#endif

#if !defined(NDEBUG)
void
db_private_free_debug (THREAD_ENTRY * thrd, void *ptr, bool rc_track, const char *caller_file, int caller_line)
#else /* NDEBUG */
void
db_private_free_release (THREAD_ENTRY * thrd, void *ptr, bool rc_track)
#endif              /* NDEBUG */
{
#if defined (SERVER_MODE)
  HL_HEAPID heap_id;
#endif

  if (ptr == NULL)
    {
      return;
    }

#if defined (CS_MODE)
  db_ws_free (ptr);
#elif defined (SERVER_MODE)
  heap_id = db_private_get_heapid_from_thread (thrd);

  if (heap_id)
    {
      hl_lea_free (heap_id, ptr);
    }
  else
    {
      free (ptr);
    }

#if !defined (NDEBUG)
  if (rc_track && heap_id != 0)
    {
      if (ptr != NULL)
    {
      thrd->get_alloc_tracker ().decrement (ptr);
    }
    }
#endif /* !NDEBUG */

#else /* SA_MODE */

  if (db_is_utility_thread ())
    {
      free (ptr);
      return;
    }

  if (!db_on_server)
    {
      db_ws_free (ptr);
      return;
    }

  if (private_heap_id == 0)
    {
      free (ptr);
    }
  else
    {
      PRIVATE_MALLOC_HEADER *h;

      h = private_user2hl_ptr (ptr);
      if (h->magic != PRIVATE_MALLOC_HEADER_MAGIC)
    {
      /* assertion point */
      assert (false);
      return;
    }

      if (h->alloc_type == PRIVATE_ALLOC_TYPE_LEA)
    {
      hl_lea_free (private_heap_id, h);
    }
      else if (h->alloc_type == PRIVATE_ALLOC_TYPE_WS)
    {
      db_ws_free (ptr); /* not h */
    }
      else
    {
      return;
    }
    }
#endif /* SA_MODE */
}


void *
db_private_alloc_external (THREAD_ENTRY * thrd, size_t size)
{
#if !defined(NDEBUG)
  return db_private_alloc_debug (thrd, size, true, __FILE__, __LINE__);
#else /* NDEBUG */
  return db_private_alloc_release (thrd, size, false);
#endif /* NDEBUG */
}


void
db_private_free_external (THREAD_ENTRY * thrd, void *ptr)
{
#if !defined(NDEBUG)
  db_private_free_debug (thrd, ptr, true, __FILE__, __LINE__);
#else /* NDEBUG */
  db_private_free_release (thrd, ptr, false);
#endif /* NDEBUG */
}


void *
db_private_realloc_external (THREAD_ENTRY * thrd, void *ptr, size_t size)
{
#if !defined(NDEBUG)
  return db_private_realloc_debug (thrd, ptr, size, true, __FILE__, __LINE__);
#else /* NDEBUG */
  return db_private_realloc_release (thrd, ptr, size, false);
#endif /* NDEBUG */
}

#if defined (SERVER_MODE)
/*
 * os_malloc () -
 *   return: allocated memory pointer
 *   size(in): size to allocate
 */
#if !defined(NDEBUG)
void *
os_malloc_debug (size_t size, bool rc_track, const char *caller_file, int caller_line)
#else /* NDEBUG */
void *
os_malloc_release (size_t size, bool rc_track)
#endif              /* NDEBUG */
{
  void *ptr = NULL;

  assert (size > 0);

  ptr = malloc (size);
  if (ptr == NULL)
    {
      er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, size);
    }

#if !defined (NDEBUG)
  if (rc_track)
    {
      if (ptr != NULL)
    {
      thread_get_thread_entry_info ()->get_alloc_tracker ().increment (caller_file, caller_line, ptr);
    }
    }
#endif /* !NDEBUG */

  return ptr;
}


/*
 * os_calloc () -
 *   return: allocated memory pointer
 *   size(in): size to allocate
 */
#if !defined(NDEBUG)
void *
os_calloc_debug (size_t n, size_t size, bool rc_track, const char *caller_file, int caller_line)
#else /* NDEBUG */
void *
os_calloc_release (size_t n, size_t size, bool rc_track)
#endif              /* NDEBUG */
{
  void *ptr = NULL;

  assert (size > 0);

  ptr = calloc (n, size);
  if (ptr == NULL)
    {
      er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, size);
    }

#if !defined (NDEBUG)
  if (rc_track)
    {
      if (ptr != NULL)
    {
      thread_get_thread_entry_info ()->get_alloc_tracker ().increment (caller_file, caller_line, ptr);
    }
    }
#endif /* !NDEBUG */

  return ptr;
}

/*
 * os_free () -
 *   return:
 *   ptr(in): memory pointer to free
 */
#if !defined(NDEBUG)
void
os_free_debug (void *ptr, bool rc_track, const char *caller_file, int caller_line)
#else /* NDEBUG */
void
os_free_release (void *ptr, bool rc_track)
#endif              /* NDEBUG */
{
  free (ptr);

#if !defined (NDEBUG)
  if (rc_track)
    {
      if (ptr != NULL)
    {
      thread_get_thread_entry_info ()->get_alloc_tracker ().decrement (ptr);
    }
    }
#endif /* !NDEBUG */
}

#if defined (SERVER_MODE)
/*
 * db_private_get_heapid_from_thread () -
 *   return: heap id
 *   thread_p(in/out): thread local entry; output is never nil
 */
static HL_HEAPID
db_private_get_heapid_from_thread (REFPTR (THREAD_ENTRY, thread_p))
{
  if (thread_p == NULL)
    {
      thread_p = thread_get_thread_entry_info ();
    }
  assert (thread_p != NULL);

  return thread_p->private_heap_id;
}

/*
 * css_set_private_heap() -
 *   return:
 *   thread_p(in):
 *   heap_id(in):
 */
HL_HEAPID
db_private_set_heapid_to_thread (THREAD_ENTRY * thread_p, HL_HEAPID heap_id)
{
  HL_HEAPID old_heap_id = 0;

  if (thread_p == NULL)
    {
      thread_p = thread_get_thread_entry_info ();
    }

  assert (thread_p != NULL);

  old_heap_id = thread_p->private_heap_id;
  thread_p->private_heap_id = heap_id;

  return old_heap_id;
}
#endif // SERVER_MODE

#endif