diff options
author | Dmitry Stogov <dmitry@zend.com> | 2017-11-15 14:07:09 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2017-11-15 14:07:09 +0300 |
commit | 6bcace1b729f48ad378d36c4bba9e576f5f3896e (patch) | |
tree | 3115049844dc58f20a07f32e0197d143b6c4864d /ext/mysqlnd | |
parent | a0724819c2a370b64f85bebce396ff0047c878b8 (diff) | |
download | php-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.c | 44 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_block_alloc.h | 2 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_ps.c | 18 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_result.c | 62 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_result.h | 6 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_result_meta.c | 54 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_result_meta.h | 2 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_structs.h | 9 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_wireprotocol.c | 4 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_wireprotocol.h | 1 |
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; |