summaryrefslogtreecommitdiff
path: root/ext/mysqlnd
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2017-11-15 14:07:09 +0300
committerDmitry Stogov <dmitry@zend.com>2017-11-15 14:07:09 +0300
commit6bcace1b729f48ad378d36c4bba9e576f5f3896e (patch)
tree3115049844dc58f20a07f32e0197d143b6c4864d /ext/mysqlnd
parenta0724819c2a370b64f85bebce396ff0047c878b8 (diff)
downloadphp-git-6bcace1b729f48ad378d36c4bba9e576f5f3896e.tar.gz
Use single memory pool for result metadata and result set.
Diffstat (limited to 'ext/mysqlnd')
-rw-r--r--ext/mysqlnd/mysqlnd_block_alloc.c44
-rw-r--r--ext/mysqlnd/mysqlnd_block_alloc.h2
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c18
-rw-r--r--ext/mysqlnd/mysqlnd_result.c62
-rw-r--r--ext/mysqlnd/mysqlnd_result.h6
-rw-r--r--ext/mysqlnd/mysqlnd_result_meta.c54
-rw-r--r--ext/mysqlnd/mysqlnd_result_meta.h2
-rw-r--r--ext/mysqlnd/mysqlnd_structs.h9
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.c4
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.h1
10 files changed, 121 insertions, 81 deletions
diff --git a/ext/mysqlnd/mysqlnd_block_alloc.c b/ext/mysqlnd/mysqlnd_block_alloc.c
index db183a4fb3..80aa3ffe14 100644
--- a/ext/mysqlnd/mysqlnd_block_alloc.c
+++ b/ext/mysqlnd/mysqlnd_block_alloc.c
@@ -76,6 +76,25 @@ static zend_always_inline void* mysqlnd_arena_alloc(zend_arena **arena_ptr, size
}
/* }}} */
+static zend_always_inline void* mysqlnd_arena_checkpoint(zend_arena *arena)
+{
+ return arena->ptr;
+}
+
+static zend_always_inline void mysqlnd_arena_release(zend_arena **arena_ptr, void *checkpoint)
+{
+ zend_arena *arena = *arena_ptr;
+
+ while (UNEXPECTED((char*)checkpoint > arena->end) ||
+ UNEXPECTED((char*)checkpoint <= (char*)arena)) {
+ zend_arena *prev = arena->prev;
+ mnd_efree(arena);
+ *arena_ptr = arena = prev;
+ }
+ ZEND_ASSERT((char*)checkpoint > (char*)arena && (char*)checkpoint <= arena->end);
+ arena->ptr = (char*)checkpoint;
+}
+
/* {{{ mysqlnd_mempool_free_chunk */
static void
mysqlnd_mempool_free_chunk(MYSQLND_MEMORY_POOL * pool, void * ptr)
@@ -145,6 +164,8 @@ mysqlnd_mempool_create(size_t arena_size)
arena = mysqlnd_arena_create(MAX(arena_size, sizeof(zend_arena)));
ret = mysqlnd_arena_alloc(&arena, sizeof(MYSQLND_MEMORY_POOL));
ret->arena = arena;
+ ret->last = NULL;
+ ret->checkpoint = NULL;
ret->get_chunk = mysqlnd_mempool_get_chunk;
ret->free_chunk = mysqlnd_mempool_free_chunk;
ret->resize_chunk = mysqlnd_mempool_resize_chunk;
@@ -164,6 +185,29 @@ mysqlnd_mempool_destroy(MYSQLND_MEMORY_POOL * pool)
}
/* }}} */
+/* {{{ mysqlnd_mempool_save_state */
+PHPAPI void
+mysqlnd_mempool_save_state(MYSQLND_MEMORY_POOL * pool)
+{
+ DBG_ENTER("mysqlnd_mempool_save_state");
+ pool->checkpoint = mysqlnd_arena_checkpoint(pool->arena);
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+/* {{{ mysqlnd_mempool_restore_state */
+PHPAPI void
+mysqlnd_mempool_restore_state(MYSQLND_MEMORY_POOL * pool)
+{
+ DBG_ENTER("mysqlnd_mempool_restore_state");
+ if (pool->checkpoint) {
+ mysqlnd_arena_release(&pool->arena, pool->checkpoint);
+ pool->last = NULL;
+ pool->checkpoint = NULL;
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
/*
* Local variables:
diff --git a/ext/mysqlnd/mysqlnd_block_alloc.h b/ext/mysqlnd/mysqlnd_block_alloc.h
index 8a2e2a6746..f95ed6e006 100644
--- a/ext/mysqlnd/mysqlnd_block_alloc.h
+++ b/ext/mysqlnd/mysqlnd_block_alloc.h
@@ -22,6 +22,8 @@
PHPAPI MYSQLND_MEMORY_POOL * mysqlnd_mempool_create(size_t arena_size);
PHPAPI void mysqlnd_mempool_destroy(MYSQLND_MEMORY_POOL * pool);
+PHPAPI void mysqlnd_mempool_save_state(MYSQLND_MEMORY_POOL * pool);
+PHPAPI void mysqlnd_mempool_restore_state(MYSQLND_MEMORY_POOL * pool);
#endif /* MYSQLND_BLOCK_ALLOC_H */
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index 9e8687fc4f..f1dac944ae 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -82,7 +82,7 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
result->type = MYSQLND_RES_PS_BUF;
/* result->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol; */
- result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_zval_init(result->field_count, TRUE);
+ result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_zval_init(result, result->field_count, TRUE);
if (!result->stored_data) {
SET_OOM_ERROR(conn->error_info);
DBG_RETURN(NULL);
@@ -122,7 +122,7 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
} else {
COPY_CLIENT_ERROR(conn->error_info, result->stored_data->error_info);
stmt->result->m.free_result_contents(stmt->result);
- mnd_efree(stmt->result);
+ mysqlnd_mempool_destroy(stmt->result->memory_pool);
stmt->result = NULL;
stmt->state = MYSQLND_STMT_PREPARED;
}
@@ -173,7 +173,7 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s)
break;
}
- result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta);
+ result->meta = stmt->result->meta->m->clone_metadata(result, stmt->result->meta);
if (!result->meta) {
SET_OOM_ERROR(conn->error_info);
break;
@@ -251,14 +251,21 @@ mysqlnd_stmt_skip_metadata(MYSQLND_STMT * s)
unsigned int i = 0;
enum_func_status ret = FAIL;
MYSQLND_PACKET_RES_FIELD field_packet;
+ MYSQLND_MEMORY_POOL * pool;
DBG_ENTER("mysqlnd_stmt_skip_metadata");
if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
+ pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size));
+ if (!pool) {
+ DBG_RETURN(FAIL);
+ }
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
conn->payload_decoder_factory->m.init_result_field_packet(&field_packet);
+ field_packet.memory_pool = pool;
+
ret = PASS;
field_packet.skip_parsing = TRUE;
for (;i < stmt->param_count; i++) {
@@ -268,6 +275,7 @@ mysqlnd_stmt_skip_metadata(MYSQLND_STMT * s)
}
}
PACKET_FREE(&field_packet);
+ mysqlnd_mempool_destroy(pool);
DBG_RETURN(ret);
}
@@ -1835,12 +1843,12 @@ MYSQLND_METHOD(mysqlnd_stmt, result_metadata)(MYSQLND_STMT * const s)
break;
}
result_meta->type = MYSQLND_RES_NORMAL;
- result_meta->unbuf = mysqlnd_result_unbuffered_init(stmt->field_count, TRUE);
+ result_meta->unbuf = mysqlnd_result_unbuffered_init(result_meta, stmt->field_count, TRUE);
if (!result_meta->unbuf) {
break;
}
result_meta->unbuf->eof_reached = TRUE;
- result_meta->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta);
+ result_meta->meta = stmt->result->meta->m->clone_metadata(result_meta, stmt->result->meta);
if (!result_meta->meta) {
break;
}
diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c
index 99cd85749b..3e97e2497b 100644
--- a/ext/mysqlnd/mysqlnd_result.c
+++ b/ext/mysqlnd/mysqlnd_result.c
@@ -190,7 +190,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, free_result)(MYSQLND_RES_UNBUFFERED *
result->row_packet = NULL;
}
- mysqlnd_mempool_destroy(result->result_set_memory_pool);
+ mysqlnd_mempool_restore_state(result->result_set_memory_pool);
DBG_VOID_RETURN;
}
@@ -261,7 +261,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * cons
set->row_buffers = NULL;
}
- mysqlnd_mempool_destroy(set->result_set_memory_pool);
+ mysqlnd_mempool_restore_state(set->result_set_memory_pool);
DBG_VOID_RETURN;
}
@@ -320,7 +320,7 @@ void MYSQLND_METHOD(mysqlnd_res, free_result_internal)(MYSQLND_RES * result)
result->conn = NULL;
}
- mnd_efree(result);
+ mysqlnd_mempool_destroy(result->memory_pool);
DBG_VOID_RETURN;
}
@@ -344,7 +344,7 @@ MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES * result, MYSQLND_
result->meta = NULL;
}
- result->meta = result->m.result_meta_init(result->field_count);
+ result->meta = result->m.result_meta_init(result, result->field_count);
if (!result->meta) {
SET_OOM_ERROR(conn->error_info);
DBG_RETURN(FAIL);
@@ -353,7 +353,7 @@ MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES * result, MYSQLND_
/* 1. Read all fields metadata */
/* It's safe to reread without freeing */
- if (FAIL == result->meta->m->read_metadata(result->meta, conn)) {
+ if (FAIL == result->meta->m->read_metadata(result->meta, conn, result)) {
result->m.free_result_contents(result);
DBG_RETURN(FAIL);
}
@@ -514,7 +514,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
if (FAIL == (ret = PACKET_READ(conn, &fields_eof))) {
DBG_ERR("Error occurred while reading the EOF packet");
result->m.free_result_contents(result);
- mnd_efree(result);
+ mysqlnd_mempool_destroy(result->memory_pool);
if (!stmt) {
conn->current_result = NULL;
} else {
@@ -906,7 +906,7 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, const zend_b
result->type = MYSQLND_RES_PS_UNBUF;
}
- result->unbuf = mysqlnd_result_unbuffered_init(result->field_count, ps);
+ result->unbuf = mysqlnd_result_unbuffered_init(result, result->field_count, ps);
if (!result->unbuf) {
goto oom;
}
@@ -1389,14 +1389,14 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
SET_CONNECTION_STATE(&conn->state, CONN_FETCHING_DATA);
if (flags & MYSQLND_STORE_NO_COPY) {
- result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_zval_init(result->field_count, flags & MYSQLND_STORE_PS);
+ result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_zval_init(result, result->field_count, flags & MYSQLND_STORE_PS);
if (!result->stored_data) {
SET_OOM_ERROR(conn->error_info);
DBG_RETURN(NULL);
}
row_buffers = &result->stored_data->row_buffers;
} else if (flags & MYSQLND_STORE_COPY) {
- result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_c_init(result->field_count, flags & MYSQLND_STORE_PS);
+ result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_c_init(result, result->field_count, flags & MYSQLND_STORE_PS);
if (!result->stored_data) {
SET_OOM_ERROR(conn->error_info);
DBG_RETURN(NULL);
@@ -1886,14 +1886,20 @@ PHPAPI MYSQLND_RES *
mysqlnd_result_init(const unsigned int field_count)
{
const size_t alloc_size = sizeof(MYSQLND_RES) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND_RES * ret = mnd_ecalloc(1, alloc_size);
+ MYSQLND_MEMORY_POOL * pool;
+ MYSQLND_RES * ret;
DBG_ENTER("mysqlnd_result_init");
- if (!ret) {
+ pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size));
+ if (!pool) {
DBG_RETURN(NULL);
}
+ ret = pool->get_chunk(pool, alloc_size);
+ memset(ret, 0, alloc_size);
+
+ ret->memory_pool = pool;
ret->field_count = field_count;
ret->m = *mysqlnd_result_get_methods();
@@ -1904,19 +1910,15 @@ mysqlnd_result_init(const unsigned int field_count)
/* {{{ mysqlnd_result_unbuffered_init */
PHPAPI MYSQLND_RES_UNBUFFERED *
-mysqlnd_result_unbuffered_init(const unsigned int field_count, const zend_bool ps)
+mysqlnd_result_unbuffered_init(MYSQLND_RES *result, const unsigned int field_count, const zend_bool ps)
{
const size_t alloc_size = sizeof(MYSQLND_RES_UNBUFFERED) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND_MEMORY_POOL * pool;
+ MYSQLND_MEMORY_POOL * pool = result->memory_pool;
MYSQLND_RES_UNBUFFERED * ret;
DBG_ENTER("mysqlnd_result_unbuffered_init");
- pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size));
- if (!pool) {
- DBG_RETURN(NULL);
- }
-
+ mysqlnd_mempool_save_state(pool);
ret = pool->get_chunk(pool, alloc_size);
memset(ret, 0, alloc_size);
@@ -1943,24 +1945,20 @@ mysqlnd_result_unbuffered_init(const unsigned int field_count, const zend_bool p
/* {{{ mysqlnd_result_buffered_zval_init */
PHPAPI MYSQLND_RES_BUFFERED_ZVAL *
-mysqlnd_result_buffered_zval_init(const unsigned int field_count, const zend_bool ps)
+mysqlnd_result_buffered_zval_init(MYSQLND_RES * result, const unsigned int field_count, const zend_bool ps)
{
const size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED_ZVAL) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND_MEMORY_POOL * pool;
+ MYSQLND_MEMORY_POOL * pool = result->memory_pool;
MYSQLND_RES_BUFFERED_ZVAL * ret;
DBG_ENTER("mysqlnd_result_buffered_zval_init");
- pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size));
- if (!pool) {
- DBG_RETURN(NULL);
- }
-
+ mysqlnd_mempool_save_state(pool);
ret = pool->get_chunk(pool, alloc_size);
memset(ret, 0, alloc_size);
if (FAIL == mysqlnd_error_info_init(&ret->error_info, 0)) {
- mysqlnd_mempool_destroy(pool);
+ mysqlnd_mempool_restore_state(pool);
DBG_RETURN(NULL);
}
@@ -1990,24 +1988,20 @@ mysqlnd_result_buffered_zval_init(const unsigned int field_count, const zend_boo
/* {{{ mysqlnd_result_buffered_c_init */
PHPAPI MYSQLND_RES_BUFFERED_C *
-mysqlnd_result_buffered_c_init(const unsigned int field_count, const zend_bool ps)
+mysqlnd_result_buffered_c_init(MYSQLND_RES * result, const unsigned int field_count, const zend_bool ps)
{
const size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED_C) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND_MEMORY_POOL * pool;
+ MYSQLND_MEMORY_POOL * pool = result->memory_pool;
MYSQLND_RES_BUFFERED_C * ret;
DBG_ENTER("mysqlnd_result_buffered_c_init");
- pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size));
- if (!pool) {
- DBG_RETURN(NULL);
- }
-
+ mysqlnd_mempool_save_state(pool);
ret = pool->get_chunk(pool, alloc_size);
memset(ret, 0, alloc_size);
if (FAIL == mysqlnd_error_info_init(&ret->error_info, 0)) {
- mysqlnd_mempool_destroy(pool);
+ mysqlnd_mempool_restore_state(pool);
DBG_RETURN(NULL);
}
diff --git a/ext/mysqlnd/mysqlnd_result.h b/ext/mysqlnd/mysqlnd_result.h
index f3b84f8508..03664e52a5 100644
--- a/ext/mysqlnd/mysqlnd_result.h
+++ b/ext/mysqlnd/mysqlnd_result.h
@@ -21,9 +21,9 @@
#define MYSQLND_RESULT_H
PHPAPI MYSQLND_RES * mysqlnd_result_init(const unsigned int field_count);
-PHPAPI MYSQLND_RES_UNBUFFERED * mysqlnd_result_unbuffered_init(const unsigned int field_count, const zend_bool ps);
-PHPAPI MYSQLND_RES_BUFFERED_ZVAL * mysqlnd_result_buffered_zval_init(const unsigned int field_count, const zend_bool ps);
-PHPAPI MYSQLND_RES_BUFFERED_C * mysqlnd_result_buffered_c_init(const unsigned int field_count, const zend_bool ps);
+PHPAPI MYSQLND_RES_UNBUFFERED * mysqlnd_result_unbuffered_init(MYSQLND_RES * result, const unsigned int field_count, const zend_bool ps);
+PHPAPI MYSQLND_RES_BUFFERED_ZVAL * mysqlnd_result_buffered_zval_init(MYSQLND_RES * result, const unsigned int field_count, const zend_bool ps);
+PHPAPI MYSQLND_RES_BUFFERED_C * mysqlnd_result_buffered_c_init(MYSQLND_RES * result, const unsigned int field_count, const zend_bool ps);
enum_func_status mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * stmt);
diff --git a/ext/mysqlnd/mysqlnd_result_meta.c b/ext/mysqlnd/mysqlnd_result_meta.c
index 1b2f4ddc33..5ff38d1f09 100644
--- a/ext/mysqlnd/mysqlnd_result_meta.c
+++ b/ext/mysqlnd/mysqlnd_result_meta.c
@@ -33,14 +33,8 @@ static void
php_mysqlnd_free_field_metadata(MYSQLND_FIELD *meta)
{
if (meta) {
- if (meta->root) {
- mnd_efree(meta->root);
- meta->root = NULL;
- }
- if (meta->def) {
- mnd_efree(meta->def);
- meta->def = NULL;
- }
+ meta->root = NULL;
+ meta->def = NULL;
if (meta->sname) {
zend_string_release(meta->sname);
}
@@ -50,7 +44,7 @@ php_mysqlnd_free_field_metadata(MYSQLND_FIELD *meta)
/* {{{ mysqlnd_res_meta::read_metadata */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND_CONN_DATA * conn)
+MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND_CONN_DATA * conn, MYSQLND_RES * result)
{
unsigned int i = 0;
MYSQLND_PACKET_RES_FIELD field_packet;
@@ -58,14 +52,13 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met
DBG_ENTER("mysqlnd_res_meta::read_metadata");
conn->payload_decoder_factory->m.init_result_field_packet(&field_packet);
+ field_packet.memory_pool = result->memory_pool;
for (;i < meta->field_count; i++) {
zend_ulong idx;
- if (meta->fields[i].root) {
- /* We re-read metadata for PS */
- mnd_efree(meta->fields[i].root);
- meta->fields[i].root = NULL;
- }
+ /* We re-read metadata for PS */
+ ZEND_ASSERT(meta->fields[i].root == NULL);
+ meta->fields[i].root = NULL;
field_packet.metadata = &(meta->fields[i]);
if (FAIL == PACKET_READ(conn, &field_packet)) {
@@ -112,12 +105,10 @@ MYSQLND_METHOD(mysqlnd_res_meta, free)(MYSQLND_RES_METADATA * meta)
while (i--) {
php_mysqlnd_free_field_metadata(fields++);
}
- mnd_efree(meta->fields);
meta->fields = NULL;
}
DBG_INF("Freeing metadata structure");
- mnd_efree(meta);
DBG_VOID_RETURN;
}
@@ -126,7 +117,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, free)(MYSQLND_RES_METADATA * meta)
/* {{{ mysqlnd_res::clone_metadata */
static MYSQLND_RES_METADATA *
-MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * const meta)
+MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(MYSQLND_RES * result, const MYSQLND_RES_METADATA * const meta)
{
unsigned int i;
/* +1 is to have empty marker at the end */
@@ -136,16 +127,18 @@ MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * co
DBG_ENTER("mysqlnd_res_meta::clone_metadata");
- new_meta = mnd_ecalloc(1, sizeof(MYSQLND_RES_METADATA));
+ new_meta = result->memory_pool->get_chunk(result->memory_pool, sizeof(MYSQLND_RES_METADATA));
if (!new_meta) {
goto oom;
}
+ memset(new_meta, 0, sizeof(MYSQLND_RES_METADATA));
new_meta->m = meta->m;
- new_fields = mnd_ecalloc(meta->field_count + 1, sizeof(MYSQLND_FIELD));
+ new_fields = result->memory_pool->get_chunk(result->memory_pool, (meta->field_count + 1) * sizeof(MYSQLND_FIELD));
if (!new_fields) {
goto oom;
}
+ memset(new_fields, 0, (meta->field_count + 1) * sizeof(MYSQLND_FIELD));
/*
This will copy also the strings and the root, which we will have
@@ -154,7 +147,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * co
memcpy(new_fields, orig_fields, (meta->field_count) * sizeof(MYSQLND_FIELD));
for (i = 0; i < meta->field_count; i++) {
/* First copy the root, then field by field adjust the pointers */
- new_fields[i].root = mnd_emalloc(orig_fields[i].root_len);
+ new_fields[i].root = result->memory_pool->get_chunk(result->memory_pool, orig_fields[i].root_len);
if (!new_fields[i].root) {
goto oom;
@@ -191,7 +184,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * co
}
/* def is not on the root, if allocated at all */
if (orig_fields[i].def) {
- new_fields[i].def = mnd_emalloc(orig_fields[i].def_length + 1);
+ new_fields[i].def = result->memory_pool->get_chunk(result->memory_pool, orig_fields[i].def_length + 1);
if (!new_fields[i].def) {
goto oom;
}
@@ -292,30 +285,25 @@ MYSQLND_CLASS_METHODS_END;
/* {{{ mysqlnd_result_meta_init */
PHPAPI MYSQLND_RES_METADATA *
-mysqlnd_result_meta_init(unsigned int field_count)
+mysqlnd_result_meta_init(MYSQLND_RES *result, unsigned int field_count)
{
size_t alloc_size = sizeof(MYSQLND_RES_METADATA) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND_RES_METADATA *ret = mnd_ecalloc(1, alloc_size);
+ MYSQLND_RES_METADATA *ret;
DBG_ENTER("mysqlnd_result_meta_init");
do {
- if (!ret) {
- break;
- }
+ ret = result->memory_pool->get_chunk(result->memory_pool, alloc_size);
+ memset(ret, 0, alloc_size);
ret->m = & mysqlnd_mysqlnd_res_meta_methods;
ret->field_count = field_count;
/* +1 is to have empty marker at the end */
- ret->fields = mnd_ecalloc(field_count + 1, sizeof(MYSQLND_FIELD));
- if (!ret->fields) {
- break;
- }
+ alloc_size = (field_count + 1) * sizeof(MYSQLND_FIELD);
+ ret->fields = result->memory_pool->get_chunk(result->memory_pool, alloc_size);
+ memset(ret->fields, 0, alloc_size);
DBG_INF_FMT("meta=%p", ret);
DBG_RETURN(ret);
} while (0);
- if (ret) {
- ret->m->free_metadata(ret);
- }
DBG_RETURN(NULL);
}
/* }}} */
diff --git a/ext/mysqlnd/mysqlnd_result_meta.h b/ext/mysqlnd/mysqlnd_result_meta.h
index 475795fe30..e25252aa73 100644
--- a/ext/mysqlnd/mysqlnd_result_meta.h
+++ b/ext/mysqlnd/mysqlnd_result_meta.h
@@ -21,7 +21,7 @@
#ifndef MYSQLND_RESULT_META_H
#define MYSQLND_RESULT_META_H
-PHPAPI MYSQLND_RES_METADATA * mysqlnd_result_meta_init(unsigned int field_count);
+PHPAPI MYSQLND_RES_METADATA * mysqlnd_result_meta_init(MYSQLND_RES * result, unsigned int field_count);
PHPAPI struct st_mysqlnd_res_meta_methods * mysqlnd_result_metadata_get_methods();
PHPAPI void ** _mysqlnd_plugin_get_plugin_result_metadata_data(const MYSQLND_RES_METADATA * meta, unsigned int plugin_id);
diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h
index cf848246c9..f5fb94daa8 100644
--- a/ext/mysqlnd/mysqlnd_structs.h
+++ b/ext/mysqlnd/mysqlnd_structs.h
@@ -54,6 +54,7 @@ struct st_mysqlnd_memory_pool
{
zend_arena *arena;
void *last;
+ void *checkpoint;
void* (*get_chunk)(MYSQLND_MEMORY_POOL * pool, size_t size);
void* (*resize_chunk)(MYSQLND_MEMORY_POOL * pool, void * ptr, size_t old_size, size_t size);
@@ -615,7 +616,7 @@ typedef void (*func_mysqlnd_res__free_buffered_data)(MYSQLND_RES *result);
typedef void (*func_mysqlnd_res__unbuffered_free_last_data)(MYSQLND_RES *result);
-typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res__result_meta_init)(unsigned int field_count);
+typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res__result_meta_init)(MYSQLND_RES *result, unsigned int field_count);
MYSQLND_CLASS_METHODS_TYPE(mysqlnd_res)
{
@@ -693,8 +694,8 @@ typedef const MYSQLND_FIELD * (*func_mysqlnd_res_meta__fetch_field_direct)(const
typedef const MYSQLND_FIELD * (*func_mysqlnd_res_meta__fetch_fields)(MYSQLND_RES_METADATA * const meta);
typedef MYSQLND_FIELD_OFFSET (*func_mysqlnd_res_meta__field_tell)(const MYSQLND_RES_METADATA * const meta);
typedef MYSQLND_FIELD_OFFSET (*func_mysqlnd_res_meta__field_seek)(MYSQLND_RES_METADATA * const meta, const MYSQLND_FIELD_OFFSET field_offset);
-typedef enum_func_status (*func_mysqlnd_res_meta__read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND_CONN_DATA * conn);
-typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res_meta__clone_metadata)(const MYSQLND_RES_METADATA * const meta);
+typedef enum_func_status (*func_mysqlnd_res_meta__read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND_CONN_DATA * conn, MYSQLND_RES * result);
+typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res_meta__clone_metadata)(MYSQLND_RES *result, const MYSQLND_RES_METADATA * const meta);
typedef void (*func_mysqlnd_res_meta__free_metadata)(MYSQLND_RES_METADATA * meta);
MYSQLND_CLASS_METHODS_TYPE(mysqlnd_res_meta)
@@ -1223,6 +1224,8 @@ struct st_mysqlnd_res
MYSQLND_RES_BUFFERED *stored_data;
MYSQLND_RES_UNBUFFERED *unbuf;
+ MYSQLND_MEMORY_POOL *memory_pool;
+
MYSQLND_CLASS_METHODS_TYPE(mysqlnd_res) m;
};
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c
index a3b1a1b13e..b7b486c349 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
@@ -1290,7 +1290,7 @@ php_mysqlnd_rset_field_read(MYSQLND_CONN_DATA * conn, void * _packet)
{
BAIL_IF_NO_MORE_DATA;
DBG_INF_FMT("Def found, length %lu", len);
- meta->def = mnd_emalloc(len + 1);
+ meta->def = packet->memory_pool->get_chunk(packet->memory_pool, len + 1);
if (!meta->def) {
SET_OOM_ERROR(error_info);
DBG_RETURN(FAIL);
@@ -1301,7 +1301,7 @@ php_mysqlnd_rset_field_read(MYSQLND_CONN_DATA * conn, void * _packet)
p += len;
}
- root_ptr = meta->root = mnd_emalloc(total_len);
+ root_ptr = meta->root = packet->memory_pool->get_chunk(packet->memory_pool, total_len);
if (!root_ptr) {
SET_OOM_ERROR(error_info);
DBG_RETURN(FAIL);
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.h b/ext/mysqlnd/mysqlnd_wireprotocol.h
index fdd26a6ca3..9455e908ad 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.h
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.h
@@ -196,6 +196,7 @@ typedef struct st_mysqlnd_packet_rset_header {
/* Result set field packet */
typedef struct st_mysqlnd_packet_res_field {
MYSQLND_PACKET_HEADER header;
+ MYSQLND_MEMORY_POOL *memory_pool;
MYSQLND_FIELD *metadata;
/* For table definitions, empty for result sets */
zend_bool skip_parsing;