summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorVasil Dimov <vasil.dimov@oracle.com>2011-12-29 16:14:45 +0200
committerVasil Dimov <vasil.dimov@oracle.com>2011-12-29 16:14:45 +0200
commit371ebdbb0357b3d586033131b7c9c69298d2ebd2 (patch)
treee4b6c35959af4a4f257a8e69ab059a2dd9584fff /storage
parent40848aa1c4fec718aacb185742741ac8ef95ff26 (diff)
downloadmariadb-git-371ebdbb0357b3d586033131b7c9c69298d2ebd2.tar.gz
Partial fix for Bug#11764622 57480: MEMORY LEAK WHEN HAVING 256+ TABLES
Port vasil.dimov@oracle.com-20111205082900-lx9om1joscejr25e from mysql-trunk
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/dict/dict0load.c42
-rw-r--r--storage/innobase/include/data0data.h14
-rw-r--r--storage/innobase/include/data0data.ic53
3 files changed, 76 insertions, 33 deletions
diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c
index e13cc1b31f1..9828326dde1 100644
--- a/storage/innobase/dict/dict0load.c
+++ b/storage/innobase/dict/dict0load.c
@@ -2066,8 +2066,9 @@ static
void
dict_load_foreign_cols(
/*===================*/
- const char* id, /*!< in: foreign constraint id as a
- null-terminated string */
+ const char* id, /*!< in: foreign constraint id, not
+ necessary '\0'-terminated */
+ ulint id_len, /*!< in: id length */
dict_foreign_t* foreign)/*!< in: foreign constraint object */
{
dict_table_t* sys_foreign_cols;
@@ -2097,7 +2098,7 @@ dict_load_foreign_cols(
tuple = dtuple_create(foreign->heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
- dfield_set_data(dfield, id, ut_strlen(id));
+ dfield_set_data(dfield, id, id_len);
dict_index_copy_types(tuple, sys_index, 1);
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
@@ -2110,7 +2111,7 @@ dict_load_foreign_cols(
ut_a(!rec_get_deleted_flag(rec, 0));
field = rec_get_nth_field_old(rec, 0, &len);
- ut_a(len == ut_strlen(id));
+ ut_a(len == id_len);
ut_a(ut_memcmp(id, field, len) == 0);
field = rec_get_nth_field_old(rec, 1, &len);
@@ -2139,8 +2140,9 @@ static
ulint
dict_load_foreign(
/*==============*/
- const char* id, /*!< in: foreign constraint id as a
- null-terminated string */
+ const char* id, /*!< in: foreign constraint id, not
+ necessary '\0'-terminated */
+ ulint id_len, /*!< in: id length */
ibool check_charsets,
/*!< in: TRUE=check charset compatibility */
ibool check_recursive)
@@ -2176,7 +2178,7 @@ dict_load_foreign(
tuple = dtuple_create(heap2, 1);
dfield = dtuple_get_nth_field(tuple, 0);
- dfield_set_data(dfield, id, ut_strlen(id));
+ dfield_set_data(dfield, id, id_len);
dict_index_copy_types(tuple, sys_index, 1);
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
@@ -2188,8 +2190,8 @@ dict_load_foreign(
/* Not found */
fprintf(stderr,
- "InnoDB: Error A: cannot load foreign constraint %s\n",
- id);
+ "InnoDB: Error A: cannot load foreign constraint "
+ "%.*s\n", (int) id_len, id);
btr_pcur_close(&pcur);
mtr_commit(&mtr);
@@ -2201,11 +2203,11 @@ dict_load_foreign(
field = rec_get_nth_field_old(rec, 0, &len);
/* Check if the id in record is the searched one */
- if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
+ if (len != id_len || ut_memcmp(id, field, len) != 0) {
fprintf(stderr,
- "InnoDB: Error B: cannot load foreign constraint %s\n",
- id);
+ "InnoDB: Error B: cannot load foreign constraint "
+ "%.*s\n", (int) id_len, id);
btr_pcur_close(&pcur);
mtr_commit(&mtr);
@@ -2231,7 +2233,7 @@ dict_load_foreign(
foreign->type = (unsigned int) (n_fields_and_type >> 24);
foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
- foreign->id = mem_heap_strdup(foreign->heap, id);
+ foreign->id = mem_heap_strdupl(foreign->heap, id, id_len);
field = rec_get_nth_field_old(rec, 3, &len);
@@ -2247,7 +2249,7 @@ dict_load_foreign(
btr_pcur_close(&pcur);
mtr_commit(&mtr);
- dict_load_foreign_cols(id, foreign);
+ dict_load_foreign_cols(id, id_len, foreign);
ref_table = dict_table_check_if_in_cache_low(
foreign->referenced_table_name_lookup);
@@ -2326,8 +2328,8 @@ dict_load_foreigns(
ibool check_charsets) /*!< in: TRUE=check charset
compatibility */
{
+ char tuple_buf[DTUPLE_EST_ALLOC(1)];
btr_pcur_t pcur;
- mem_heap_t* heap;
dtuple_t* tuple;
dfield_t* dfield;
dict_index_t* sec_index;
@@ -2335,7 +2337,6 @@ dict_load_foreigns(
const rec_t* rec;
const byte* field;
ulint len;
- char* id ;
ulint err;
mtr_t mtr;
@@ -2362,9 +2363,8 @@ dict_load_foreigns(
sec_index = dict_table_get_next_index(
dict_table_get_first_index(sys_foreign));
start_load:
- heap = mem_heap_create(256);
- tuple = dtuple_create(heap, 1);
+ tuple = dtuple_create_from_mem(tuple_buf, sizeof(tuple_buf), 1);
dfield = dtuple_get_nth_field(tuple, 0);
dfield_set_data(dfield, table_name, ut_strlen(table_name));
@@ -2418,7 +2418,6 @@ loop:
/* Now we get a foreign key constraint id */
field = rec_get_nth_field_old(rec, 1, &len);
- id = mem_heap_strdupl(heap, (char*) field, len);
btr_pcur_store_position(&pcur, &mtr);
@@ -2426,11 +2425,11 @@ loop:
/* Load the foreign constraint definition to the dictionary cache */
- err = dict_load_foreign(id, check_charsets, check_recursive);
+ err = dict_load_foreign((char*) field, len, check_charsets,
+ check_recursive);
if (err != DB_SUCCESS) {
btr_pcur_close(&pcur);
- mem_heap_free(heap);
return(err);
}
@@ -2446,7 +2445,6 @@ next_rec:
load_next_index:
btr_pcur_close(&pcur);
mtr_commit(&mtr);
- mem_heap_free(heap);
sec_index = dict_table_get_next_index(sec_index);
diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h
index 9435169a0fd..6d3c2988fdc 100644
--- a/storage/innobase/include/data0data.h
+++ b/storage/innobase/include/data0data.h
@@ -238,6 +238,20 @@ creating a new dtuple_t object */
(sizeof(dtuple_t) + (n_fields) * sizeof(dfield_t))
/**********************************************************//**
+Creates a data tuple from an already allocated chunk of memory.
+The size of the chunk must be at least DTUPLE_EST_ALLOC(n_fields).
+The default value for number of fields used in record comparisons
+for this tuple is n_fields.
+@return created tuple (inside buf) */
+UNIV_INLINE
+dtuple_t*
+dtuple_create_from_mem(
+/*===================*/
+ void* buf, /*!< in, out: buffer to use */
+ ulint buf_size, /*!< in: buffer size */
+ ulint n_fields); /*!< in: number of fields */
+
+/**********************************************************//**
Creates a data tuple to a memory heap. The default value for number
of fields used in record comparisons for this tuple is n_fields.
@return own: created tuple */
diff --git a/storage/innobase/include/data0data.ic b/storage/innobase/include/data0data.ic
index 971f58412c0..205fa397987 100644
--- a/storage/innobase/include/data0data.ic
+++ b/storage/innobase/include/data0data.ic
@@ -348,23 +348,25 @@ dtuple_get_nth_field(
#endif /* UNIV_DEBUG */
/**********************************************************//**
-Creates a data tuple to a memory heap. The default value for number
-of fields used in record comparisons for this tuple is n_fields.
-@return own: created tuple */
+Creates a data tuple from an already allocated chunk of memory.
+The size of the chunk must be at least DTUPLE_EST_ALLOC(n_fields).
+The default value for number of fields used in record comparisons
+for this tuple is n_fields.
+@return created tuple (inside buf) */
UNIV_INLINE
dtuple_t*
-dtuple_create(
-/*==========*/
- mem_heap_t* heap, /*!< in: memory heap where the tuple
- is created, DTUPLE_EST_ALLOC(n_fields)
- bytes will be allocated from this heap */
- ulint n_fields) /*!< in: number of fields */
+dtuple_create_from_mem(
+/*===================*/
+ void* buf, /*!< in, out: buffer to use */
+ ulint buf_size, /*!< in: buffer size */
+ ulint n_fields) /*!< in: number of fields */
{
dtuple_t* tuple;
- ut_ad(heap);
+ ut_ad(buf != NULL);
+ ut_a(buf_size >= DTUPLE_EST_ALLOC(n_fields));
- tuple = (dtuple_t*) mem_heap_alloc(heap, DTUPLE_EST_ALLOC(n_fields));
+ tuple = (dtuple_t*) buf;
tuple->info_bits = 0;
tuple->n_fields = n_fields;
tuple->n_fields_cmp = n_fields;
@@ -386,9 +388,38 @@ dtuple_create(
dfield_get_type(field)->mtype = DATA_ERROR;
}
}
+#endif
+ return(tuple);
+}
+
+/**********************************************************//**
+Creates a data tuple to a memory heap. The default value for number
+of fields used in record comparisons for this tuple is n_fields.
+@return own: created tuple */
+UNIV_INLINE
+dtuple_t*
+dtuple_create(
+/*==========*/
+ mem_heap_t* heap, /*!< in: memory heap where the tuple
+ is created, DTUPLE_EST_ALLOC(n_fields)
+ bytes will be allocated from this heap */
+ ulint n_fields) /*!< in: number of fields */
+{
+ void* buf;
+ ulint buf_size;
+ dtuple_t* tuple;
+
+ ut_ad(heap);
+ buf_size = DTUPLE_EST_ALLOC(n_fields);
+ buf = mem_heap_alloc(heap, buf_size);
+
+ tuple = dtuple_create_from_mem(buf, buf_size, n_fields);
+
+#ifdef UNIV_DEBUG
UNIV_MEM_INVALID(tuple->fields, n_fields * sizeof *tuple->fields);
#endif
+
return(tuple);
}