} php_mysql_conn;
#ifdef MYSQL_USE_MYSQLND
-static MYSQLND_ZVAL_PCACHE *mysql_mysqlnd_zval_cache;
static MYSQLND_QCACHE *mysql_mysqlnd_qcache;
#endif
STD_PHP_INI_ENTRY("mysql.connect_timeout", "60", PHP_INI_ALL, OnUpdateLong, connect_timeout, zend_mysql_globals, mysql_globals)
STD_PHP_INI_BOOLEAN("mysql.trace_mode", "0", PHP_INI_ALL, OnUpdateLong, trace_mode, zend_mysql_globals, mysql_globals)
STD_PHP_INI_BOOLEAN("mysql.allow_local_infile", "1", PHP_INI_SYSTEM, OnUpdateLong, allow_local_infile, zend_mysql_globals, mysql_globals)
-#ifdef MYSQL_USE_MYSQLND
- STD_PHP_INI_ENTRY("mysql.cache_size", "2000", PHP_INI_SYSTEM, OnUpdateLong, cache_size, zend_mysql_globals, mysql_globals)
-#endif
PHP_INI_END()
/* }}} */
mysql_globals->trace_mode = 0;
mysql_globals->allow_local_infile = 1;
mysql_globals->result_allocated = 0;
-#ifdef MYSQL_USE_MYSQLND
- mysql_globals->cache_size = 0;
- mysql_globals->mysqlnd_thd_zval_cache = NULL;
-#endif
}
/* }}} */
}
#endif
#else
- mysql_mysqlnd_zval_cache = mysqlnd_palloc_init_cache(MySG(cache_size));
mysql_mysqlnd_qcache = mysqlnd_qcache_init_cache();
#endif
#endif
#endif
#else
- mysqlnd_palloc_free_cache(mysql_mysqlnd_zval_cache);
mysqlnd_qcache_free_cache_reference(&mysql_mysqlnd_qcache);
#endif
MySG(connect_errno) =0;
MySG(result_allocated) = 0;
-#ifdef MYSQL_USE_MYSQLND
- MySG(mysqlnd_thd_zval_cache) = mysqlnd_palloc_rinit(mysql_mysqlnd_zval_cache);
-#endif
-
return SUCCESS;
}
/* }}} */
#ifdef MYSQL_USE_MYSQLND
zend_hash_apply(&EG(persistent_list), (apply_func_t) php_mysql_persistent_helper TSRMLS_CC);
- mysqlnd_palloc_rshutdown(MySG(mysqlnd_thd_zval_cache));
#endif
return SUCCESS;
php_info_print_table_row(2, "MYSQL_INCLUDE", PHP_MYSQL_INCLUDE);
php_info_print_table_row(2, "MYSQL_LIBS", PHP_MYSQL_LIBS);
#endif
-#if defined(MYSQL_USE_MYSQLND)
- {
- zval values;
-
- php_info_print_table_header(2, "Persistent cache", mysql_mysqlnd_zval_cache? "enabled":"disabled");
-
- if (mysql_mysqlnd_zval_cache) {
- /* Now report cache status */
- mysqlnd_palloc_stats(mysql_mysqlnd_zval_cache, &values);
- mysqlnd_minfo_print_hash(&values);
- zval_dtor(&values);
- }
- }
-#endif
php_info_print_table_end();
#ifndef MYSQL_USE_MYSQLND
if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL)
#else
- if (mysqlnd_connect(mysql->conn, host, user, passwd, 0, NULL, 0,
- port, socket, client_flags, MySG(mysqlnd_thd_zval_cache) TSRMLS_CC) == NULL)
+ if (mysqlnd_connect(mysql->conn, host, user, passwd, 0, NULL, 0, port, socket, client_flags TSRMLS_CC) == NULL)
#endif
{
/* Populate connect error globals so that the error functions can read them */
#ifndef MYSQL_USE_MYSQLND
if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL)
#else
- if (mysqlnd_connect(mysql->conn, host, user, passwd, 0, NULL, 0,
- port, socket, client_flags, MySG(mysqlnd_thd_zval_cache) TSRMLS_CC) == NULL)
+ if (mysqlnd_connect(mysql->conn, host, user, passwd, 0, NULL, 0, port, socket, client_flags TSRMLS_CC) == NULL)
#endif
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link to server lost, unable to reconnect");
}
} else {
#ifdef MYSQL_USE_MYSQLND
- mysqlnd_restart_psession(mysql->conn, MySG(mysqlnd_thd_zval_cache));
+ mysqlnd_restart_psession(mysql->conn);
#endif
}
}
#ifndef MYSQL_USE_MYSQLND
if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL)
#else
- if (mysqlnd_connect(mysql->conn, host, user, passwd, 0, NULL, 0,
- port, socket, client_flags, MySG(mysqlnd_thd_zval_cache) TSRMLS_CC) == NULL)
+ if (mysqlnd_connect(mysql->conn, host, user, passwd, 0, NULL, 0, port, socket, client_flags TSRMLS_CC) == NULL)
#endif
{
/* Populate connect error globals so that the error functions can read them */
long trace_mode;
long allow_local_infile;
#ifdef MYSQL_USE_MYSQLND
- MYSQLND_THD_ZVAL_PCACHE *mysqlnd_thd_zval_cache;
MYSQLND_QCACHE *mysqlnd_qcache;
- long cache_size;
#endif
ZEND_END_MODULE_GLOBALS(mysql)
zend_class_entry *mysqli_exception_class_entry;
#ifdef MYSQLI_USE_MYSQLND
-MYSQLND_ZVAL_PCACHE *mysqli_mysqlnd_zval_cache;
MYSQLND_QCACHE *mysqli_mysqlnd_qcache;
#endif
#endif
STD_PHP_INI_BOOLEAN("mysqli.reconnect", "0", PHP_INI_SYSTEM, OnUpdateLong, reconnect, zend_mysqli_globals, mysqli_globals)
STD_PHP_INI_BOOLEAN("mysqli.allow_local_infile", "1", PHP_INI_SYSTEM, OnUpdateLong, allow_local_infile, zend_mysqli_globals, mysqli_globals)
-#ifdef MYSQLI_USE_MYSQLND
- STD_PHP_INI_ENTRY("mysqli.cache_size", "2000", PHP_INI_SYSTEM, OnUpdateLong, cache_size, zend_mysqli_globals, mysqli_globals)
-#endif
PHP_INI_END()
/* }}} */
#else
mysqli_globals->embedded = 0;
#endif
-#ifdef MYSQLI_USE_MYSQLND
- mysqli_globals->cache_size = 0;
- mysqli_globals->mysqlnd_thd_zval_cache = NULL;
-#endif
}
/* }}} */
}
#endif
#else
- mysqli_mysqlnd_zval_cache = mysqlnd_palloc_init_cache(MyG(cache_size));
mysqli_mysqlnd_qcache = mysqlnd_qcache_init_cache();
#endif
#endif
#endif
#else
- mysqlnd_palloc_free_cache(mysqli_mysqlnd_zval_cache);
mysqlnd_qcache_free_cache_reference(&mysqli_mysqlnd_qcache);
#endif
#endif
MyG(error_msg) = NULL;
MyG(error_no) = 0;
-#ifdef MYSQLI_USE_MYSQLND
- MyG(mysqlnd_thd_zval_cache) = mysqlnd_palloc_rinit(mysqli_mysqlnd_zval_cache);
-#endif
return SUCCESS;
}
}
#ifdef MYSQLI_USE_MYSQLND
zend_hash_apply(&EG(persistent_list), (apply_func_t) php_mysqli_persistent_helper_once TSRMLS_CC);
- mysqlnd_palloc_rshutdown(MyG(mysqlnd_thd_zval_cache));
#endif
return SUCCESS;
}
#if !defined(MYSQLI_USE_MYSQLND)
php_info_print_table_row(2, "Client API header version", MYSQL_SERVER_VERSION);
php_info_print_table_row(2, "MYSQLI_SOCKET", MYSQL_UNIX_ADDR);
-#else
- {
- zval values;
-
- php_info_print_table_header(2, "Persistent cache", mysqli_mysqlnd_zval_cache? "enabled":"disabled");
-
- if (mysqli_mysqlnd_zval_cache) {
- /* Now report cache status */
- mysqlnd_palloc_stats(mysqli_mysqlnd_zval_cache, &values);
- mysqlnd_minfo_print_hash(&values);
- zval_dtor(&values);
- }
- }
#endif
php_info_print_table_end();
if (!mysql_ping(mysql->mysql)) {
#endif
#ifdef MYSQLI_USE_MYSQLND
- mysqlnd_restart_psession(mysql->mysql, MyG(mysqlnd_thd_zval_cache));
+ mysqlnd_restart_psession(mysql->mysql);
#endif
MyG(num_active_persistent)++;
goto end;
if (mysql_real_connect(mysql->mysql, hostname, username, passwd, dbname, port, socket, CLIENT_MULTI_RESULTS) == NULL)
#else
if (mysqlnd_connect(mysql->mysql, hostname, username, passwd, passwd_len, dbname, dbname_len,
- port, socket, flags, MyG(mysqlnd_thd_zval_cache) TSRMLS_CC) == NULL)
+ port, socket, flags TSRMLS_CC) == NULL)
#endif
{
/* Save error messages - for mysqli_connect_error() & mysqli_connect_errno() */
if (zend_parse_parameters_none() == FAILURE) {
return;
}
- mysqlnd_palloc_stats(mysqli_mysqlnd_zval_cache, return_value);
+ array_init(return_value);
}
/* }}} */
extern zend_property_info mysqli_warning_property_info_entries[];
#ifdef MYSQLI_USE_MYSQLND
-extern MYSQLND_ZVAL_PCACHE *mysqli_mysqlnd_zval_cache;
extern MYSQLND_QCACHE *mysqli_mysqlnd_qcache;
#endif
HashTable *report_ht;
unsigned long multi_query;
unsigned long embedded;
-#ifdef MYSQLI_USE_MYSQLND
- MYSQLND_THD_ZVAL_PCACHE *mysqlnd_thd_zval_cache;
-#endif
ZEND_END_MODULE_GLOBALS(mysqli)
"mysqlnd_charset.c " +
"mysqlnd_debug.c " +
"mysqlnd_loaddata.c " +
- "mysqlnd_palloc.c " +
"mysqlnd_ps.c " +
"mysqlnd_ps_codec.c " +
"mysqlnd_qcache.c " +
dnl If some extension uses mysqlnd it will get compiled in PHP core
if test "$PHP_MYSQLND_ENABLED" = "yes"; then
mysqlnd_sources="mysqlnd.c mysqlnd_charset.c mysqlnd_wireprotocol.c \
- mysqlnd_ps.c mysqlnd_loaddata.c mysqlnd_palloc.c \
+ mysqlnd_ps.c mysqlnd_loaddata.c \
mysqlnd_ps_codec.c mysqlnd_statistics.c mysqlnd_qcache.c\
mysqlnd_result.c mysqlnd_result_meta.c mysqlnd_debug.c\
mysqlnd_block_alloc.c php_mysqlnd.c"
mnd_pefree(conn->last_message, pers);
conn->last_message = NULL;
}
- if (conn->zval_cache) {
- DBG_INF("Freeing zval cache reference");
- mysqlnd_palloc_free_thd_cache_reference(&conn->zval_cache);
- conn->zval_cache = NULL;
- }
if (conn->qcache) {
DBG_INF("Freeing qcache reference");
mysqlnd_qcache_free_cache_reference(&conn->qcache);
/* {{{ _mysqlnd_restart_psession */
-PHPAPI void _mysqlnd_restart_psession(MYSQLND *conn, MYSQLND_THD_ZVAL_PCACHE *cache TSRMLS_DC)
+PHPAPI void _mysqlnd_restart_psession(MYSQLND *conn TSRMLS_DC)
{
DBG_ENTER("_mysqlnd_restart_psession");
MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_CONNECT_REUSED);
The thd zval cache is always freed on request shutdown, so this has happened already.
Don't touch the old value! Get new reference
*/
- conn->zval_cache = mysqlnd_palloc_get_thd_cache_reference(cache);
DBG_VOID_RETURN;
}
/* }}} */
{
DBG_ENTER("_mysqlnd_end_psession");
/* The thd zval cache is always freed on request shutdown, so this has happened already */
- mysqlnd_palloc_free_thd_cache_reference(&conn->zval_cache);
DBG_VOID_RETURN;
}
/* }}} */
const char *db, unsigned int db_len,
unsigned int port,
const char *socket,
- unsigned int mysql_flags,
- MYSQLND_THD_ZVAL_PCACHE *zval_cache
+ unsigned int mysql_flags
TSRMLS_DC)
{
char *transport = NULL, *errstr = NULL;
SET_EMPTY_ERROR(conn->error_info);
- conn->zval_cache = mysqlnd_palloc_get_thd_cache_reference(zval_cache);
-
mysqlnd_local_infile_default(conn);
{
unsigned int buf_size;
const char *db, unsigned int db_len,
unsigned int port,
const char *socket,
- unsigned int mysql_flags,
- MYSQLND_THD_ZVAL_PCACHE *zval_cache
+ unsigned int mysql_flags
TSRMLS_DC)
{
enum_func_status ret;
self_alloced = TRUE;
}
- ret = conn->m->connect(conn, host, user, passwd, passwd_len, db, db_len, port, socket, mysql_flags, zval_cache TSRMLS_CC);
+ ret = conn->m->connect(conn, host, user, passwd, passwd_len, db, db_len, port, socket, mysql_flags TSRMLS_CC);
if (ret == FAIL) {
if (self_alloced) {
Prepare for the worst case.
MyISAM goes to 2500 BIT columns, double it for safety.
*/
- result = mysqlnd_result_init(5000, mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache) TSRMLS_CC);
+ result = mysqlnd_result_init(5000 TSRMLS_CC);
if (FAIL == result->m.read_result_metadata(result, conn TSRMLS_CC)) {
#include "mysqlnd_structs.h"
-
-
/* Library related */
void mysqlnd_library_init(TSRMLS_D);
void mysqlnd_library_end(TSRMLS_D);
PHPAPI void mysqlnd_stmt_set_methods(struct st_mysqlnd_stmt_methods *methods);
-#define mysqlnd_restart_psession(conn, cache) _mysqlnd_restart_psession((conn), (cache) TSRMLS_CC)
-PHPAPI void _mysqlnd_restart_psession(MYSQLND *conn, MYSQLND_THD_ZVAL_PCACHE *cache TSRMLS_DC);
+#define mysqlnd_restart_psession(conn) _mysqlnd_restart_psession((conn) TSRMLS_CC)
+PHPAPI void _mysqlnd_restart_psession(MYSQLND * conn TSRMLS_DC);
#define mysqlnd_end_psession(conn) _mysqlnd_end_psession((conn) TSRMLS_CC)
PHPAPI void _mysqlnd_end_psession(MYSQLND *conn TSRMLS_DC);
PHPAPI void mysqlnd_minfo_print_hash(zval *values);
const char *db, unsigned int db_len,
unsigned int port,
const char *socket,
- unsigned int mysql_flags,
- MYSQLND_THD_ZVAL_PCACHE *zval_cache
+ unsigned int mysql_flags
TSRMLS_DC);
#define mysqlnd_change_user(conn, user, passwd, db, silent) (conn)->m->change_user((conn), (user), (passwd), (db), (silent) TSRMLS_CC)
/* Performance statistics */
PHPAPI void _mysqlnd_get_client_stats(zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
-/* Persistent caching zval allocator */
-#define mysqlnd_palloc_init_cache(size) _mysqlnd_palloc_init_cache((size) TSRMLS_CC)
-#define mysqlnd_palloc_free_cache(cache) _mysqlnd_palloc_free_cache((cache) TSRMLS_CC)
-PHPAPI MYSQLND_ZVAL_PCACHE* _mysqlnd_palloc_init_cache(unsigned int cache_size TSRMLS_DC);
-PHPAPI void _mysqlnd_palloc_free_cache(MYSQLND_ZVAL_PCACHE *cache TSRMLS_DC);
-PHPAPI void mysqlnd_palloc_stats(const MYSQLND_ZVAL_PCACHE * const cache,
- zval *return_value);
-
-#define mysqlnd_palloc_rinit(cache) _mysqlnd_palloc_rinit((cache) TSRMLS_CC)
-#define mysqlnd_palloc_rshutdown(cache) _mysqlnd_palloc_rshutdown((cache) TSRMLS_CC)
-PHPAPI MYSQLND_THD_ZVAL_PCACHE * _mysqlnd_palloc_rinit(MYSQLND_ZVAL_PCACHE * cache TSRMLS_DC);
-PHPAPI void _mysqlnd_palloc_rshutdown(MYSQLND_THD_ZVAL_PCACHE * cache TSRMLS_DC);
-
-
-#define mysqlnd_palloc_init_thd_cache(cache) _mysqlnd_palloc_init_thd_cache((cache) TSRMLS_CC)
-#define mysqlnd_palloc_free_thd_cache_reference(cache) _mysqlnd_palloc_free_thd_cache_reference((cache) TSRMLS_CC)
-#define mysqlnd_palloc_get_thd_cache_reference(cache) _mysqlnd_palloc_get_thd_cache_reference((cache) TSRMLS_CC)
-
-PHPAPI MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_init_thd_cache(MYSQLND_ZVAL_PCACHE * const cache TSRMLS_DC);
-MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE * const cache TSRMLS_DC);
-PHPAPI void _mysqlnd_palloc_free_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE **cache TSRMLS_DC);
-
-
-/* There two should not be used from outside */
-void * mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const cache, zend_bool *allocated TSRMLS_DC);
-void mysqlnd_palloc_zval_ptr_dtor(zval **zv, MYSQLND_THD_ZVAL_PCACHE * const cache,
- enum_mysqlnd_res_type type, zend_bool *copy_ctor_called TSRMLS_DC);
-
-
/* ---------------------- QUERY CACHE ---------------*/
struct st_mysqlnd_qcache {
-/*
+;/*
+----------------------------------------------------------------------+
| PHP Version 6 |
+----------------------------------------------------------------------+
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
#include "mysqlnd_wireprotocol.h"
-#include "mysqlnd_palloc.h"
#include "mysqlnd_statistics.h"
#include "zend_builtin_functions.h"
func_name == mysqlnd_efree_name || func_name == mysqlnd_pefree_name ||
func_name == mysqlnd_malloc_name || func_name == mysqlnd_calloc_name ||
func_name == mysqlnd_realloc_name || func_name == mysqlnd_free_name ||
- func_name == mysqlnd_palloc_zval_ptr_dtor_name || func_name == mysqlnd_palloc_get_zval_name ||
func_name == mysqlnd_read_header_name || func_name == mysqlnd_read_body_name)) {
zend_stack_push(&self->call_stack, "", sizeof(""));
return FALSE;
+++ /dev/null
-/*
- +----------------------------------------------------------------------+
- | PHP Version 6 |
- +----------------------------------------------------------------------+
- | Copyright (c) 2006-2009 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
- | Ulf Wendel <uwendel@mysql.com> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id$ */
-#include "php.h"
-#include "mysqlnd.h"
-#include "mysqlnd_priv.h"
-#include "mysqlnd_palloc.h"
-#include "mysqlnd_debug.h"
-
-/* Used in mysqlnd_debug.c */
-char * mysqlnd_palloc_zval_ptr_dtor_name = "mysqlnd_palloc_zval_ptr_dtor";
-char * mysqlnd_palloc_get_zval_name = "mysqlnd_palloc_get_zval";
-
-
-#ifdef ZTS
-#define LOCK_PCACHE(cache) tsrm_mutex_lock((cache)->LOCK_access)
-#define UNLOCK_PCACHE(cache) tsrm_mutex_unlock((cache)->LOCK_access)
-#else
-#define LOCK_PCACHE(cache)
-#define UNLOCK_PCACHE(cache)
-#endif
-
-
-/* {{{ _mysqlnd_palloc_init_cache */
-PHPAPI MYSQLND_ZVAL_PCACHE* _mysqlnd_palloc_init_cache(unsigned int cache_size TSRMLS_DC)
-{
- MYSQLND_ZVAL_PCACHE *ret = mnd_calloc(1, sizeof(MYSQLND_ZVAL_PCACHE));
- unsigned int i;
-
- DBG_ENTER("_mysqlnd_palloc_init_cache");
- DBG_INF_FMT("cache=%p size=%u", ret, cache_size);
-
-#ifdef ZTS
- ret->LOCK_access = tsrm_mutex_alloc();
-#endif
-
- ret->max_items = cache_size;
- ret->free_items = cache_size;
- ret->references = 1;
-
- /* 1. First initialize the free list part of the structure */
- /* One more for empty position of last_added - always 0x0, bounds checking */
- ret->free_list.ptr_line = mnd_calloc(ret->max_items + 1, sizeof(mysqlnd_zval *));
- ret->free_list.last_added = ret->free_list.ptr_line + ret->max_items;
- ret->free_list.canary1 = (void*)0xBEEF;
- ret->free_list.canary2 = (void*)0xAFFE;
-
- /* 3. Allocate and initialize our zvals and initialize the free list */
- ret->block = mnd_calloc(ret->max_items, sizeof(mysqlnd_zval));
- ret->last_in_block = &(ret->block[ret->max_items]);
- for (i = 0; i < ret->max_items; i++) {
- /* 1. Initialize */
- INIT_PZVAL(&(ret->block[i].zv));
- ZVAL_NULL(&(ret->block[i].zv));
- /* Assure it will never be freed before MSHUTDOWN */
- Z_ADDREF_P(&(ret->block[i].zv));
- /* 2. Add to the free list */
- *(--ret->free_list.last_added) = &(ret->block[i]);
- }
-
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_palloc_get_cache_reference */
-MYSQLND_ZVAL_PCACHE* mysqlnd_palloc_get_cache_reference(MYSQLND_ZVAL_PCACHE * const cache)
-{
- if (cache) {
- LOCK_PCACHE(cache);
- cache->references++;
- UNLOCK_PCACHE(cache);
- }
- return cache;
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_palloc_free_cache */
-/*
- As this call will happen on MSHUTDOWN(), then we don't need to copy the zvals with
- copy_ctor but scrap what they point to with zval_dtor() and then just free our
- pre-allocated block. Precondition is that we ZVAL_NULL() the zvals when we put them
- to the free list after usage. We ZVAL_NULL() them when we allocate them in the
- constructor of the cache.
-*/
-void _mysqlnd_palloc_free_cache(MYSQLND_ZVAL_PCACHE *cache TSRMLS_DC)
-{
- DBG_ENTER("_mysqlnd_palloc_free_cache");
- DBG_INF_FMT("cache=%p", cache);
-
-#ifdef ZTS
- tsrm_mutex_free(cache->LOCK_access);
-#endif
-
- /* Data in pointed by 'block' was cleaned in RSHUTDOWN */
- mnd_free(cache->block);
- mnd_free(cache->free_list.ptr_line);
- mnd_free(cache);
-
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_palloc_init_thd_cache */
-PHPAPI MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_init_thd_cache(MYSQLND_ZVAL_PCACHE * const cache TSRMLS_DC)
-{
- MYSQLND_THD_ZVAL_PCACHE *ret = mnd_calloc(1, sizeof(MYSQLND_THD_ZVAL_PCACHE));
- DBG_ENTER("_mysqlnd_palloc_init_thd_cache");
- DBG_INF_FMT("ret = %p", ret);
-
-#if PHP_DEBUG
- LOCK_PCACHE(cache);
- if (cache->references == 1 && cache->max_items != cache->free_items) {
- UNLOCK_PCACHE(cache);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "No references to mysqlnd's zval cache but max_items != free_items");
- } else {
- UNLOCK_PCACHE(cache);
- }
-#endif
- ret->parent = mysqlnd_palloc_get_cache_reference(cache);
-
-#ifdef ZTS
- ret->thread_id = tsrm_thread_id();
-#endif
-
- ret->references = 1;
-
- /* 1. Initialize the GC list */
- ret->gc_list.ptr_line = mnd_calloc(cache->max_items, sizeof(mysqlnd_zval *));
- /* Backward and forward looping is possible */
- ret->gc_list.last_added = ret->gc_list.ptr_line;
- ret->gc_list.canary1 = (void*)0xCAFE;
- ret->gc_list.canary2 = (void*)0x190280;
-
- DBG_INF_FMT("ptr_line=%p last_added=%p", ret->gc_list.ptr_line, ret->gc_list.last_added);
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_palloc_get_thd_cache_reference */
-MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE * const cache TSRMLS_DC)
-{
- DBG_ENTER("_mysqlnd_palloc_get_thd_cache_reference");
- if (cache) {
- ++cache->references;
- DBG_INF_FMT("cache=%p new_refc=%d gc_list.canary1=%p gc_list.canary2=%p",
- cache, cache->references, cache->gc_list.canary1, cache->gc_list.canary2);
- mysqlnd_palloc_get_cache_reference(cache->parent);
- }
- DBG_RETURN(cache);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_palloc_free_cache */
-/*
- As this call will happen on MSHUTDOWN(), then we don't need to copy the zvals with
- copy_ctor but scrap what they point to with zval_dtor() and then just free our
- pre-allocated block. Precondition is that we ZVAL_NULL() the zvals when we put them
- to the free list after usage. We ZVAL_NULL() them when we allocate them in the
- constructor of the cache.
-*/
-static
-void mysqlnd_palloc_free_thd_cache(MYSQLND_THD_ZVAL_PCACHE *thd_cache TSRMLS_DC)
-{
- MYSQLND_ZVAL_PCACHE *global_cache;
- mysqlnd_zval **p;
-
- DBG_ENTER("mysqlnd_palloc_free_thd_cache");
- DBG_INF_FMT("thd_cache=%p", thd_cache);
-
- if ((global_cache = thd_cache->parent)) {
- /*
- Keep in mind that for pthreads pthread_equal() should be used to be
- fully standard compliant. However, the PHP code all-around, incl. the
- the Zend MM uses direct comparison.
- */
- p = thd_cache->gc_list.ptr_line;
- while (p < thd_cache->gc_list.last_added) {
- zval_dtor(&(*p)->zv);
- p++;
- }
-
- p = thd_cache->gc_list.ptr_line;
-
- LOCK_PCACHE(global_cache);
- while (p < thd_cache->gc_list.last_added) {
- (*p)->point_type = MYSQLND_POINTS_FREE;
- *(--global_cache->free_list.last_added) = *p;
- ++global_cache->free_items;
-#ifdef ZTS
- memset(&((*p)->thread_id), 0, sizeof(THREAD_T));
-#endif
- p++;
- }
- UNLOCK_PCACHE(global_cache);
-
- }
- mnd_free(thd_cache->gc_list.ptr_line);
- mnd_free(thd_cache);
-
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_palloc_free_thd_cache_reference */
-PHPAPI void _mysqlnd_palloc_free_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE **cache TSRMLS_DC)
-{
- DBG_ENTER("_mysqlnd_palloc_free_thd_cache_reference");
- if (*cache) {
- --(*cache)->parent->references;
- DBG_INF_FMT("cache=%p references_left=%d canary1=%p canary2=%p",
- *cache, (*cache)->references, (*cache)->gc_list.canary1, (*cache)->gc_list.canary2);
-
- DBG_INF_FMT("gc_list.ptr_line=%p gc_list.last_added=%p", (*cache)->gc_list.ptr_line, (*cache)->gc_list.last_added);
-
- if (--(*cache)->references == 0) {
- mysqlnd_palloc_free_thd_cache(*cache TSRMLS_CC);
- }
- *cache = NULL;
- }
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-
-/*
- The cache line is a big contiguous array of zval pointers.
- Because the CPU cache will cache starting from an address, and not
- before it, then we have to organize our structure according to this.
- Thus, if 'last_added' is valid pointer (not NULL) then last_added is
- increased. When zval is cached, if there is room, last_added is decreased
- and then the zval pointer will be assigned to it. This means that some
- positions may become hot points and stay in the cache.
- Imagine we have 5 pointers in a line
- 1. last_added = list_item->ptr_line + cache->max_items;
- 2. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL
- 3. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL
- 4. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL
- 0x0
- 0x0
- 0x0
- 0x0
- 0x0
- ---
- empty_position, always 0x0 <-- last_added
-
- 5. free_zval -> if (free_items++ != max_items) {// we can add more
- *(--last_added) = zval_ptr;
- }
- (memory addresses increase downwards)
- 0x0
- 0x0
- 0x0
- 0x0
- 0xA <-- last_added
- ---
- 0x0
-
- 6. free_zval -> if (free_items++ != max_items) {// we can add more
- *(--last_added) = zval_ptr;
- }
- 0x0
- 0x0
- 0x0
- 0xB <-- last_added
- 0xA
- ---
- 0x0
-
- 7. free_zval -> if (free_items++ != max_items) {// we can add more
- *(--last_added) = zval_ptr;
- }
- 0x0
- 0x0
- 0xC <-- last_added
- 0xB
- 0xA
- ---
- 0x0
-
- 8. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL;
- 0x0
- 0x0
- 0x0
- 0xB <-- last_added
- 0xA
- ---
- 0x0
-
- 9. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL;
- 0x0
- 0x0
- 0x0
- 0x0
- 0xA <-- last_added
- ---
- 0x0
-
- 10. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL;
- 0x0
- 0x0
- 0x0
- 0x0
- 0x0
- ---
- 0x0 <-- last_added
-
-*/
-
-
-/* {{{ mysqlnd_palloc_get_zval */
-void *mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const thd_cache, zend_bool *allocated TSRMLS_DC)
-{
- void *ret = NULL;
-
- DBG_ENTER("mysqlnd_palloc_get_zval");
- if (thd_cache) {
- DBG_INF_FMT("cache=%p *last_added=%p free_items=%d",
- thd_cache, thd_cache->parent->free_list.last_added,
- thd_cache->parent->free_items);
- DBG_INF_FMT("gc_list.ptr_line=%p gc_list.last_added=%p gc_list.canary1=%p gc_list.canary2=%p",
- thd_cache->gc_list.ptr_line, thd_cache->gc_list.last_added,
- thd_cache->gc_list.canary1, thd_cache->gc_list.canary2);
- }
-
- if (thd_cache) {
- MYSQLND_ZVAL_PCACHE *cache = thd_cache->parent;
- LOCK_PCACHE(cache);
-
- DBG_INF_FMT("free_items=%d free_list.ptr_line=%p free_list.last_added=%p *free_list.last_added=%p free_list.canary1=%p free_list.canary2=%p",
- cache->free_items, cache->free_list.ptr_line, cache->free_list.last_added,
- *cache->free_list.last_added,
- cache->free_list.canary1, cache->free_list.canary2);
-
- /* We have max_items + 1 allocated block for free_list, thus we know if we */
- if ((ret = *cache->free_list.last_added)) {
- *cache->free_list.last_added++ = NULL;
- *allocated = FALSE;
-#ifdef ZTS
- ((mysqlnd_zval *) ret)->thread_id = thd_cache->thread_id;
-#endif
- --cache->free_items;
- ++cache->get_hits;
- } else {
- ++cache->get_misses;
- }
- UNLOCK_PCACHE(cache);
- }
- if (!ret) {
- /*
- We allocate a bit more. The user of this function will use it, but at
- end it will use only the zval part. Because the zval part is first then
- when freeing the zval part the whole allocated block will be cleaned, not
- only the zval part (by the Engine when destructing the zval).
- */
- ALLOC_ZVAL(ret);
- INIT_PZVAL((zval *) ret);
- *allocated = TRUE;
- } else {
- /* This will set the refcount to 1, increase it, to keep the variable */
- INIT_PZVAL(&((mysqlnd_zval *) ret)->zv);
- Z_ADDREF_P(&(((mysqlnd_zval *)ret)->zv));
- }
-
- DBG_INF_FMT("allocated=%d ret=%p", *allocated, ret);
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_palloc_zval_ptr_dtor */
-void mysqlnd_palloc_zval_ptr_dtor(zval **zv, MYSQLND_THD_ZVAL_PCACHE * const thd_cache,
- enum_mysqlnd_res_type type, zend_bool *copy_ctor_called TSRMLS_DC)
-{
- MYSQLND_ZVAL_PCACHE *cache;
- DBG_ENTER("mysqlnd_palloc_zval_ptr_dtor");
- if (thd_cache) {
- DBG_INF_FMT("cache=%p parent_block=%p last_in_block=%p *zv=%p refc=%d type=%d ",
- thd_cache,
- thd_cache->parent->block,
- thd_cache->parent->last_in_block,
- *zv, Z_REFCOUNT_PP(zv), type);
- DBG_INF_FMT("gc_list.ptr_line=%p gc_list.last_added=%p gc_list.canary1=%p gc_list.canary2=%p",
- thd_cache->gc_list.ptr_line, thd_cache->gc_list.last_added, thd_cache->gc_list.canary1, thd_cache->gc_list.canary2);
- }
- *copy_ctor_called = FALSE;
- /* Check whether cache is used and the zval is from the cache */
- if (!thd_cache || !(cache = thd_cache->parent) || ((char *)*zv < (char *)thd_cache->parent->block ||
- (char *)*zv > (char *)thd_cache->parent->last_in_block)) {
- /*
- This zval is not from the cache block.
- Thus the refcount is -1 than of a zval from the cache,
- because the zvals from the cache are owned by it.
- */
- if (type == MYSQLND_RES_PS_BUF || type == MYSQLND_RES_PS_UNBUF) {
- ; /* do nothing, zval_ptr_dtor will do the job*/
- } else if (Z_REFCOUNT_PP(zv) > 1) {
- /*
- Not a prepared statement, then we have to
- call copy_ctor and then zval_ptr_dtor()
-
- In Unicode mode the destruction of the zvals should not call
- zval_copy_ctor() because then we will leak.
- I suppose we can use UG(unicode) in mysqlnd.c when freeing a result set
- to check if we need to call copy_ctor().
-
- If the type is IS_UNICODE, which can happen with PHP6, then we don't
- need to copy_ctor, as the data doesn't point to our internal buffers.
- If it's string (in PHP5 always) and in PHP6 if data is binary, then
- it still points to internal buffers and has to be copied.
- */
- if (Z_TYPE_PP(zv) == IS_STRING) {
- zval_copy_ctor(*zv);
- }
- *copy_ctor_called = TRUE;
- } else {
- if (Z_TYPE_PP(zv) == IS_STRING) {
- ZVAL_NULL(*zv);
- }
- }
- zval_ptr_dtor(zv);
- DBG_VOID_RETURN;
- }
-
- /* The zval is from our cache */
- /* refcount is always > 1, because we call Z_ADDREF_P(). Thus test refcount > 2 */
- if (Z_REFCOUNT_PP(zv) > 2) {
- /*
- Because the zval is first element in mysqlnd_zval structure, then we can
- do upcasting from zval to mysqlnd_zval here. Because we know that this
- zval is part of our pre-allocated block.
-
- Now check whether this zval points to ZE allocated memory or to our
- buffers. If it points to the internal buffers, call copy_ctor()
- which will do estrndup for strings. And nothing for null, int, double.
-
- This branch will be skipped for PS, because there is no need to copy
- what is pointed by them, as they don't point to the internal buffers.
- */
- if (((mysqlnd_zval *)*zv)->point_type == MYSQLND_POINTS_INT_BUFFER) {
- zval_copy_ctor(*zv);
- *copy_ctor_called = TRUE;
- ((mysqlnd_zval *)*zv)->point_type = MYSQLND_POINTS_EXT_BUFFER;
- }
- /*
- This will decrease the counter of the user-level (mysqlnd). When the engine
- layer (the script) has finished working this this zval, when the variable is
- no more used, out of scope whatever, then it will try zval_ptr_dtor() but
- and the refcount will reach 1 and the engine won't try to destruct the
- memory allocated by us.
- */
- zval_ptr_dtor(zv);
-
- /*
- Unfortunately, we can't return this variable to the free_list
- because it's still used. And this cleaning up will happen at request
- shutdown :(.
- */
- LOCK_PCACHE(cache);
- DBG_INF_FMT("gc_list.ptr_line=%p gc_list.last_added=%p *gc_list.last_added=%p free_list.canary1=%p free_list.canary2=%p",
- thd_cache->gc_list.ptr_line,
- thd_cache->gc_list.last_added,
- *thd_cache->gc_list.last_added,
- cache->free_list.canary1, cache->free_list.canary2);
- if ((thd_cache->gc_list.last_added - thd_cache->gc_list.ptr_line) > (int) cache->max_items) {
- DBG_ERR("Buffer overflow follows");
- DBG_ERR_FMT("parent->max_items=%d parent->free_items=%d diff=%d",
- cache->max_items, cache->free_items,
- thd_cache->gc_list.last_added - thd_cache->gc_list.ptr_line);
-
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "We will get buffer overflow");
- }
- ++cache->put_misses;
- *(thd_cache->gc_list.last_added++) = (mysqlnd_zval *)*zv;
- UNLOCK_PCACHE(cache);
- } else {
- DBG_INF("No user reference");
- /* No user reference */
- if (((mysqlnd_zval *)*zv)->point_type == MYSQLND_POINTS_EXT_BUFFER) {
- DBG_INF("Points to external buffer. Calling zval_dtor");
- /*
- PS are here
- Unicode mode goes also here if the column is not binary but a text
- */
- zval_dtor(*zv);
- }
- LOCK_PCACHE(cache);
- ++cache->put_hits;
- ++cache->free_items;
- ((mysqlnd_zval *)*zv)->point_type = MYSQLND_POINTS_FREE;
- Z_DELREF_PP(zv); /* Make it 1 */
- ZVAL_NULL(*zv);
-#ifdef ZTS
- memset(&((mysqlnd_zval *)*zv)->thread_id, 0, sizeof(THREAD_T));
-#endif
- *(--cache->free_list.last_added) = (mysqlnd_zval *)*zv;
-
- UNLOCK_PCACHE(cache);
- }
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_palloc_rinit */
-PHPAPI MYSQLND_THD_ZVAL_PCACHE * _mysqlnd_palloc_rinit(MYSQLND_ZVAL_PCACHE * cache TSRMLS_DC)
-{
- return mysqlnd_palloc_init_thd_cache(cache);
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_palloc_rshutdown */
-PHPAPI void _mysqlnd_palloc_rshutdown(MYSQLND_THD_ZVAL_PCACHE * thd_cache TSRMLS_DC)
-{
- DBG_ENTER("_mysqlnd_palloc_rshutdown");
- DBG_INF_FMT("cache=%p", thd_cache);
- mysqlnd_palloc_free_thd_cache_reference(&thd_cache);
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_palloc_rshutdown */
-PHPAPI void mysqlnd_palloc_stats(const MYSQLND_ZVAL_PCACHE * const cache, zval *return_value)
-{
- if (cache) {
-#if PHP_MAJOR_VERSION >= 6
- UChar *ustr;
- int ulen;
-
- TSRMLS_FETCH();
-#endif
-
- LOCK_PCACHE(cache);
- array_init(return_value);
-#if PHP_MAJOR_VERSION >= 6
- zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "put_hits", sizeof("put_hits") TSRMLS_CC);
- add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
- efree(ustr);
- zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "put_misses", sizeof("put_misses") TSRMLS_CC);
- add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
- efree(ustr);
- zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "get_hits", sizeof("get_hits") TSRMLS_CC);
- add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
- efree(ustr);
- zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "get_misses", sizeof("get_misses") TSRMLS_CC);
- add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
- efree(ustr);
- zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "size", sizeof("size") TSRMLS_CC);
- add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
- efree(ustr);
- zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "free_items", sizeof("free_items") TSRMLS_CC);
- add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
- efree(ustr);
- zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "references", sizeof("references") TSRMLS_CC);
- add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
- efree(ustr);
-#else
- add_assoc_long_ex(return_value, "put_hits", sizeof("put_hits"), cache->put_hits);
- add_assoc_long_ex(return_value, "put_misses", sizeof("put_misses"), cache->put_misses);
- add_assoc_long_ex(return_value, "get_hits", sizeof("get_hits"), cache->get_hits);
- add_assoc_long_ex(return_value, "get_misses", sizeof("get_misses"), cache->get_misses);
- add_assoc_long_ex(return_value, "size", sizeof("size"), cache->max_items);
- add_assoc_long_ex(return_value, "free_items", sizeof("free_items"), cache->free_items);
- add_assoc_long_ex(return_value, "references", sizeof("references"), cache->references);
-#endif
- UNLOCK_PCACHE(cache);
- } else {
- ZVAL_NULL(return_value);
- }
-}
-/* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
+++ /dev/null
-/*
- +----------------------------------------------------------------------+
- | PHP Version 6 |
- +----------------------------------------------------------------------+
- | Copyright (c) 2006-2009 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
- | Ulf Wendel <uwendel@mysql.com> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id$ */
-#ifndef MYSQLND_PALLOC_H
-#define MYSQLND_PALLOC_H
-
-/* Used in mysqlnd_debug.c */
-extern char * mysqlnd_palloc_zval_ptr_dtor_name;
-extern char * mysqlnd_palloc_get_zval_name;
-
-
-/* Session caching allocator */
-struct st_mysqlnd_zval_list {
- zval **ptr_line;
- zval **last_added;
-};
-
-typedef struct st_mysqlnd_zval_cache MYSQLND_ZVAL_CACHE;
-
-struct st_mysqlnd_zval_cache {
- struct st_mysqlnd_zval_list *free_list;
- unsigned int free_items;
- unsigned int max_items;
- unsigned int references;
- unsigned long get_hits;
- unsigned long get_misses;
- unsigned long put_hits;
- unsigned long put_full_misses;
- unsigned long put_refcount_misses;
-};
-
-
-enum mysqlnd_zval_ptr_type
-{
- MYSQLND_POINTS_INT_BUFFER,
- MYSQLND_POINTS_EXT_BUFFER,
- MYSQLND_POINTS_FREE
-};
-
-/* Persistent caching allocator */
-typedef struct st_mysqlnd_zval {
- /* Should be first */
- zval zv;
- enum mysqlnd_zval_ptr_type point_type;
-#ifdef ZTS
- THREAD_T thread_id;
-#endif
-} mysqlnd_zval;
-
-
-typedef struct st_mysqlnd_ndzval_list {
- mysqlnd_zval **ptr_line; /* we allocate this, all are pointers to the block */
- void *canary1;
- void *canary2;
- mysqlnd_zval **last_added; /* this points to the ptr_line, and moves left-right. It's our stack */
-} mysqlnd_ndzval_list;
-
-
-struct st_mysqlnd_zval_pcache {
- mysqlnd_zval *block;
- mysqlnd_zval *last_in_block;
- mysqlnd_ndzval_list free_list; /* Fetch from here */
-
-#ifdef ZTS
- MUTEX_T LOCK_access;
-#endif
- unsigned int references;
-
- /* These are just for statistics and not used for operational purposes */
- unsigned int free_items;
- unsigned int max_items;
-
- unsigned long get_hits;
- unsigned long get_misses;
- unsigned long put_hits;
- unsigned long put_misses;
-};
-
-struct st_mysqlnd_thread_zval_pcache {
- struct st_mysqlnd_zval_pcache *parent;
-
- unsigned int references;
-#ifdef ZTS
- THREAD_T thread_id;
-#endif
- mysqlnd_ndzval_list gc_list; /* GC these from time to time */
-};
-
-#endif /* MYSQLND_PALLOC_H */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
result->type = MYSQLND_RES_PS_BUF;
result->m.fetch_row = mysqlnd_fetch_stmt_row_buffered;
result->m.fetch_lengths = NULL;/* makes no sense */
- if (!result->zval_cache) {
- result->zval_cache = mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache);
- }
result->result_set_memory_pool = mysqlnd_mempool_create(16000 TSRMLS_CC);
SET_EMPTY_ERROR(stmt->conn->error_info);
MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_BUFFERED_SETS);
- result = mysqlnd_result_init(stmt->result->field_count,
- mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache) TSRMLS_CC);
+ result = mysqlnd_result_init(stmt->result->field_count TSRMLS_CC);
result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC);
no metadata at prepare.
*/
if (stmt_to_prepare->field_count) {
- MYSQLND_RES *result = mysqlnd_result_init(stmt_to_prepare->field_count,
- mysqlnd_palloc_get_thd_cache_reference(stmt->conn->zval_cache)
- TSRMLS_CC);
+ MYSQLND_RES *result = mysqlnd_result_init(stmt_to_prepare->field_count TSRMLS_CC);
/* Allocate the result now as it is needed for the reading of metadata */
stmt_to_prepare->result = result;
result->stored_data->persistent,
result->conn->options.numeric_and_datetime_as_unicode,
result->conn->options.int_and_float_native,
- result->conn->zval_cache,
&result->conn->stats TSRMLS_CC);
if (stmt->update_max_length) {
for (i = 0; i < result->field_count; i++) {
FALSE,
result->conn->options.numeric_and_datetime_as_unicode,
result->conn->options.int_and_float_native,
- result->conn->zval_cache,
&result->conn->stats TSRMLS_CC);
for (i = 0; i < field_count; i++) {
FALSE,
result->conn->options.numeric_and_datetime_as_unicode,
result->conn->options.int_and_float_native,
- result->conn->zval_cache,
&result->conn->stats TSRMLS_CC);
/* If no result bind, do nothing. We consumed the data */
In the meantime we don't need a zval cache reference for this fake
result set, so we don't get one.
*/
- result = mysqlnd_result_init(stmt->field_count, NULL TSRMLS_CC);
+ result = mysqlnd_result_init(stmt->field_count TSRMLS_CC);
result->type = MYSQLND_RES_NORMAL;
result->m.fetch_row = result->m.fetch_row_normal_unbuffered;
result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
result->stored_data->persistent,
result->conn->options.numeric_and_datetime_as_unicode,
result->conn->options.int_and_float_native,
- result->conn->zval_cache,
&result->conn->stats TSRMLS_CC);
for (i = 0; i < result->field_count; i++) {
/*
/* }}} */
+
+/* {{{ mysqlnd_palloc_zval_ptr_dtor */
+void mysqlnd_palloc_zval_ptr_dtor(zval **zv, enum_mysqlnd_res_type type, zend_bool * copy_ctor_called TSRMLS_DC)
+{
+ DBG_ENTER("mysqlnd_palloc_zval_ptr_dtor");
+ *copy_ctor_called = FALSE;
+ {
+ /*
+ This zval is not from the cache block.
+ Thus the refcount is -1 than of a zval from the cache,
+ because the zvals from the cache are owned by it.
+ */
+ if (type == MYSQLND_RES_PS_BUF || type == MYSQLND_RES_PS_UNBUF) {
+ ; /* do nothing, zval_ptr_dtor will do the job*/
+ } else if (Z_REFCOUNT_PP(zv) > 1) {
+ /*
+ Not a prepared statement, then we have to
+ call copy_ctor and then zval_ptr_dtor()
+
+ In Unicode mode the destruction of the zvals should not call
+ zval_copy_ctor() because then we will leak.
+ I suppose we can use UG(unicode) in mysqlnd.c when freeing a result set
+ to check if we need to call copy_ctor().
+
+ If the type is IS_UNICODE, which can happen with PHP6, then we don't
+ need to copy_ctor, as the data doesn't point to our internal buffers.
+ If it's string (in PHP5 always) and in PHP6 if data is binary, then
+ it still points to internal buffers and has to be copied.
+ */
+ if (Z_TYPE_PP(zv) == IS_STRING) {
+ zval_copy_ctor(*zv);
+ }
+ *copy_ctor_called = TRUE;
+ } else {
+ if (Z_TYPE_PP(zv) == IS_STRING) {
+ ZVAL_NULL(*zv);
+ }
+ }
+ zval_ptr_dtor(zv);
+ DBG_VOID_RETURN;
+ }
+
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
/* {{{ mysqlnd_res::unbuffered_free_last_data */
static void
MYSQLND_METHOD(mysqlnd_res, unbuffered_free_last_data)(MYSQLND_RES * result TSRMLS_DC)
DBG_INF_FMT("%u columns to free", result->field_count);
for (i = 0; i < result->field_count; i++) {
- mysqlnd_palloc_zval_ptr_dtor(&(unbuf->last_row_data[i]),
- result->zval_cache, result->type,
- ©_ctor_called TSRMLS_CC);
+ mysqlnd_palloc_zval_ptr_dtor(&(unbuf->last_row_data[i]), result->type, ©_ctor_called TSRMLS_CC);
if (copy_ctor_called) {
ctor_called_count++;
}
static void
MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES *result TSRMLS_DC)
{
- MYSQLND_THD_ZVAL_PCACHE *zval_cache = result->zval_cache;
MYSQLND_RES_BUFFERED *set = result->stored_data;
unsigned int field_count = result->field_count;
int row;
if (current_row[0] == NULL) {
break;/* row that was never initialized */
}
- mysqlnd_palloc_zval_ptr_dtor(&(current_row[col]), zval_cache,
- result->type, ©_ctor_called TSRMLS_CC);
+ mysqlnd_palloc_zval_ptr_dtor(&(current_row[col]), result->type, ©_ctor_called TSRMLS_CC);
#if MYSQLND_DEBUG_MEMORY
DBG_INF_FMT("Copy_ctor_called=%d", copy_ctor_called);
#endif
result->meta = NULL;
}
- if (result->zval_cache) {
- DBG_INF("Freeing zval cache reference");
- mysqlnd_palloc_free_thd_cache_reference(&result->zval_cache);
- result->zval_cache = NULL;
- }
-
DBG_VOID_RETURN;
}
/* }}} */
/* PS has already allocated it */
conn->field_count = rset_header.field_count;
if (!stmt) {
- result =
- conn->current_result=
- mysqlnd_result_init(rset_header.field_count,
- mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache)
- TSRMLS_CC);
+ result = conn->current_result = mysqlnd_result_init(rset_header.field_count TSRMLS_CC);
} else {
if (!stmt->result) {
DBG_INF("This is 'SHOW'/'EXPLAIN'-like query.");
prepared statements can't send result set metadata for these queries
on prepare stage. Read it now.
*/
- result =
- stmt->result =
- mysqlnd_result_init(rset_header.field_count,
- mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache)
- TSRMLS_CC);
+ result = stmt->result = mysqlnd_result_init(rset_header.field_count TSRMLS_CC);
} else {
/*
Update result set metadata if it for some reason changed between
FALSE,
result->conn->options.numeric_and_datetime_as_unicode,
result->conn->options.int_and_float_native,
- result->conn->zval_cache,
&result->conn->stats TSRMLS_CC);
retrow = mnd_malloc(result->field_count * sizeof(char *));
FALSE,
result->conn->options.numeric_and_datetime_as_unicode,
result->conn->options.int_and_float_native,
- result->conn->zval_cache,
&result->conn->stats TSRMLS_CC);
for (i = 0; i < field_count; i++, field++, zend_hash_key++) {
FALSE,
result->conn->options.numeric_and_datetime_as_unicode,
result->conn->options.int_and_float_native,
- result->conn->zval_cache,
&result->conn->stats TSRMLS_CC);
for (i = 0; i < result->field_count; i++) {
/*
result->stored_data->persistent,
result->conn->options.numeric_and_datetime_as_unicode,
result->conn->options.int_and_float_native,
- result->conn->zval_cache,
&result->conn->stats TSRMLS_CC);
for (i = 0; i < result->field_count; i++) {
/*
/* {{{ mysqlnd_result_init */
-MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCACHE *cache TSRMLS_DC)
+MYSQLND_RES *mysqlnd_result_init(unsigned int field_count TSRMLS_DC)
{
size_t alloc_size = sizeof(MYSQLND_RES) + mysqlnd_plugin_count() * sizeof(void *);
MYSQLND_RES *ret = mnd_ecalloc(1, alloc_size);
DBG_ENTER("mysqlnd_result_init");
- DBG_INF_FMT("field_count=%u cache=%p", field_count, cache);
+ DBG_INF_FMT("field_count=%u", field_count);
ret->field_count = field_count;
- ret->zval_cache = cache;
ret->m.use_result = MYSQLND_METHOD(mysqlnd_res, use_result);
ret->m.store_result = MYSQLND_METHOD(mysqlnd_res, store_result);
#ifndef MYSQLND_RESULT_H
#define MYSQLND_RESULT_H
-MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCACHE *cache TSRMLS_DC);
+MYSQLND_RES *mysqlnd_result_init(unsigned int field_count TSRMLS_DC);
enum_func_status mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC);
} mysqlnd_error_info;
-typedef struct st_mysqlnd_zval_pcache MYSQLND_ZVAL_PCACHE;
-typedef struct st_mysqlnd_thread_zval_pcache MYSQLND_THD_ZVAL_PCACHE;
typedef struct st_mysqlnd_qcache MYSQLND_QCACHE;
struct st_mysqlnd_conn_methods
{
- enum_func_status (*connect)(MYSQLND *conn, const char *host, const char * user, const char * passwd, unsigned int passwd_len, const char * db, unsigned int db_len, unsigned int port, const char * socket, unsigned int mysql_flags, MYSQLND_THD_ZVAL_PCACHE * zval_cache TSRMLS_DC);
+ enum_func_status (*connect)(MYSQLND *conn, const char *host, const char * user, const char * passwd, unsigned int passwd_len, const char * db, unsigned int db_len, unsigned int port, const char * socket, unsigned int mysql_flags TSRMLS_DC);
ulong (*escape_string)(const MYSQLND * const conn, char *newstr, const char *escapestr, size_t escapestr_len TSRMLS_DC);
enum_func_status (*set_charset)(MYSQLND * const conn, const char * const charset TSRMLS_DC);
enum_func_status (*query)(MYSQLND *conn, const char *query, unsigned int query_len TSRMLS_DC);
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
- MYSQLND_THD_ZVAL_PCACHE * zval_cache,
MYSQLND_STATS * stats TSRMLS_DC);
/* options */
MYSQLND_OPTION options;
- /* zval cache */
- MYSQLND_THD_ZVAL_PCACHE *zval_cache;
-
/* qcache */
MYSQLND_QCACHE *qcache;
php_mysql_packet_row *row_packet;
- /* zval cache */
- MYSQLND_THD_ZVAL_PCACHE *zval_cache;
-
MYSQLND_MEMORY_POOL * result_set_memory_pool;
};
#include "mysqlnd_priv.h"
#include "mysqlnd_wireprotocol.h"
#include "mysqlnd_statistics.h"
-#include "mysqlnd_palloc.h"
#include "mysqlnd_debug.h"
#include "mysqlnd_block_alloc.h"
#include "ext/standard/sha1.h"
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
- MYSQLND_THD_ZVAL_PCACHE * zval_cache,
MYSQLND_STATS * stats TSRMLS_DC)
{
int i;
zend_uchar *p = row_buffer->ptr;
zend_uchar *null_ptr, bit;
zval **current_field, **end_field, **start_field;
-#ifdef USE_ZVAL_CACHE
- zend_bool allocated;
- void *obj;
-#endif
DBG_ENTER("php_mysqlnd_rowp_read_binary_protocol");
bit = 4; /* first 2 bits are reserved */
for (i = 0; current_field < end_field; current_field++, i++) {
-#ifdef USE_ZVAL_CACHE
- DBG_INF("Trying to use the zval cache");
- obj = mysqlnd_palloc_get_zval(zval_cache, &allocated TSRMLS_CC);
- if (allocated) {
- *current_field = (zval *) obj;
- } else {
- /* It's from the cache, so we can upcast here */
- *current_field = &((mysqlnd_zval *) obj)->zv;
- ((mysqlnd_zval *) obj)->point_type = MYSQLND_POINTS_EXT_BUFFER;
- }
-#else
DBG_INF("Directly creating zval");
MAKE_STD_ZVAL(*current_field);
-#endif
DBG_INF_FMT("Into zval=%p decoding column %d [%s.%s.%s] type=%d field->flags&unsigned=%d flags=%u is_bit=%d as_unicode=%d",
*current_field, i,
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
- MYSQLND_THD_ZVAL_PCACHE * zval_cache,
MYSQLND_STATS * stats TSRMLS_DC)
{
int i;
end_field = (current_field = start_field = fields) + field_count;
for (i = 0; current_field < end_field; current_field++, i++) {
/* Don't reverse the order. It is significant!*/
- void *obj = NULL;
- zend_bool allocated = TRUE;
zend_uchar *this_field_len_pos = p;
/* php_mysqlnd_net_field_length() call should be after *this_field_len_pos = p; */
unsigned long len = php_mysqlnd_net_field_length(&p);
-#ifdef USE_ZVAL_CACHE
- obj = mysqlnd_palloc_get_zval(zval_cache, &allocated TSRMLS_CC);
- if (allocated) {
- *current_field = (zval *) obj;
- } else {
- /* It's from the cache, so we can upcast here */
- *current_field = &((mysqlnd_zval *) obj)->zv;
- ((mysqlnd_zval *) obj)->point_type = MYSQLND_POINTS_FREE;
- }
-#else
DBG_INF("Directly creating zval");
MAKE_STD_ZVAL(*current_field);
-#endif
if (current_field > start_field && last_field_was_string) {
/*
{
ZVAL_STRINGL(*current_field, (char *) start, bit_area - start - 1, 0);
}
- if (allocated == FALSE) {
- ((mysqlnd_zval *) obj)->point_type = MYSQLND_POINTS_INT_BUFFER;
- }
} else if (Z_TYPE_PP(current_field) == IS_STRING){
memcpy(bit_area, Z_STRVAL_PP(current_field), Z_STRLEN_PP(current_field));
bit_area += Z_STRLEN_PP(current_field);
{
ZVAL_STRINGL(*current_field, (char *) start, bit_area - start - 1, 0);
}
- if (allocated == FALSE) {
- ((mysqlnd_zval *) obj)->point_type = MYSQLND_POINTS_INT_BUFFER;
- }
}
/*
IS_UNICODE should not be specially handled. In unicode mode
#if PHP_MAJOR_VERSION < 6
{
ZVAL_STRINGL(*current_field, (char *)p, len, 0);
- if (allocated == FALSE) {
- ((mysqlnd_zval *) obj)->point_type = MYSQLND_POINTS_INT_BUFFER;
- }
}
#else
/*
Also the destruction of the zvals should not call zval_copy_ctor()
because then we will leak.
- I suppose we can use UG(unicode) in mysqlnd.c/mysqlnd_palloc.c when
- freeing a result set
- to check if we need to call copy_ctor().
-
XXX: Keep in mind that up there there is an open `else` in
#ifdef MYSQLND_STRING_TO_INT_CONVERSION
which will make with this `if` an `else if`.
} else {
ZVAL_UTF8_STRINGL(*current_field, (char *)p, len, 0);
}
- if (allocated == FALSE) {
- /*
- The zval cache will check and see that the type is IS_STRING.
- In this case it will call copy_ctor(). This is valid when
- allocated == TRUE . In this case we can't upcast. Thus for non-PS
- point_type doesn't matter much, as the valuable information is
- in the type of result set. Still good to set it.
- */
- if (Z_TYPE_P(*current_field) == IS_STRING) {
- ((mysqlnd_zval *) obj)->point_type = MYSQLND_POINTS_INT_BUFFER;
- } else {
- ((mysqlnd_zval *) obj)->point_type = MYSQLND_POINTS_EXT_BUFFER;
- }
- }
#endif
p += len;
last_field_was_string = TRUE;
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
- MYSQLND_THD_ZVAL_PCACHE * zval_cache,
MYSQLND_STATS * stats TSRMLS_DC);
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
- MYSQLND_THD_ZVAL_PCACHE * zval_cache,
MYSQLND_STATS * stats TSRMLS_DC);
enum_func_status mysqlnd_read_from_stream(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC);