]> granicus.if.org Git - php/commitdiff
Use single memory pool for result metadata and result set.
authorDmitry Stogov <dmitry@zend.com>
Wed, 15 Nov 2017 11:07:09 +0000 (14:07 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 15 Nov 2017 11:07:09 +0000 (14:07 +0300)
ext/mysqli/tests/mysqli_debug_mysqlnd_only.phpt
ext/mysqlnd/mysqlnd_block_alloc.c
ext/mysqlnd/mysqlnd_block_alloc.h
ext/mysqlnd/mysqlnd_ps.c
ext/mysqlnd/mysqlnd_result.c
ext/mysqlnd/mysqlnd_result.h
ext/mysqlnd/mysqlnd_result_meta.c
ext/mysqlnd/mysqlnd_result_meta.h
ext/mysqlnd/mysqlnd_structs.h
ext/mysqlnd/mysqlnd_wireprotocol.c
ext/mysqlnd/mysqlnd_wireprotocol.h

index 603bb9bc32ce7017d0504c261365fdbd08c0216c..f46aec9359c7650afafff461ed5e0dfe025af4a3 100644 (file)
@@ -90,9 +90,9 @@ if (!$IS_MYSQLND)
                if (isset($functions_trace[$name]))
                        $found++;
 
-       if ($found < 2) {
+       if ($found < 1) {
                printf("[016] Only %d memory functions have been found, expecting at least %d.\n",
-                       $found, 2);
+                       $found, 1);
                var_dump($trace);
        }
 
index db183a4fb34a40b08cadc6771a744cc313b49f3b..80aa3ffe144944dceb89bc37adb35b7c1f0f3843 100644 (file)
@@ -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:
index 8a2e2a6746828091854925859ddd2dd35b17426d..f95ed6e006c64469c174a739f40f33ff9de4d9ce 100644 (file)
@@ -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 */
 
index 9e8687fc4fb7cd31ef80f24cc749dd80efab2ecf..f1dac944ae51e6a1dafbe50589aa78b3c26fd233 100644 (file)
@@ -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;
                }
index 99cd85749bb9cfc716bdef3df53267252e97374e..3e97e2497b8f0cb16e7e3e06edf04efabd5efb86 100644 (file)
@@ -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);
        }
 
index f3b84f85084759f42fdbf7d5871ef98b58ce14fe..03664e52a5b7ff2eb3b8fd233cc8309bf808d87a 100644 (file)
@@ -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);
 
index 1b2f4ddc33bc55a524220c65e9710d755886f2c9..5ff38d1f09240ca7279794f6d2aeb8ebee1132b5 100644 (file)
@@ -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);
 }
 /* }}} */
index 475795fe30ae8efb1749ae6ecfe24d7b6f5066f3..e25252aa73de3931dbdc97aef22eead4336f5e2e 100644 (file)
@@ -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);
 
index cf848246c9b2dde3739ab7152522bd7c944cf817..f5fb94daa88855e6caa752ad16dd0ceca8077842 100644 (file)
@@ -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;
 };
 
index a3b1a1b13e67343312fc30feb9e0eb2dfba63e2b..b7b486c3495986f091f155de25a95d4eac91b4bb 100644 (file)
@@ -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);
index fdd26a6ca38a5bd419b421fc3a07843333bde053..9455e908addde956dfb93a57dcfa3d8ace4ee71b 100644 (file)
@@ -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;