mirror of
https://github.com/php/php-src.git
synced 2026-03-31 12:42:29 +02:00
Remove disabled code - threaded fetching. This can be implemented
on a upper level and by offloading it we reduce the complexity of the core.
This commit is contained in:
@@ -740,9 +740,6 @@ PHP_MINIT_FUNCTION(mysqli)
|
||||
/* for mysqli_query */
|
||||
REGISTER_LONG_CONSTANT("MYSQLI_STORE_RESULT", MYSQLI_STORE_RESULT, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("MYSQLI_USE_RESULT", MYSQLI_USE_RESULT, CONST_CS | CONST_PERSISTENT);
|
||||
#if defined(MYSQLI_USE_MYSQLND) && defined(MYSQLND_THREADED)
|
||||
REGISTER_LONG_CONSTANT("MYSQLI_BG_STORE_RESULT", MYSQLI_BG_STORE_RESULT, CONST_CS | CONST_PERSISTENT);
|
||||
#endif
|
||||
#if defined (MYSQLI_USE_MYSQLND)
|
||||
REGISTER_LONG_CONSTANT("MYSQLI_ASYNC", MYSQLI_ASYNC, CONST_CS | CONST_PERSISTENT);
|
||||
#endif
|
||||
@@ -1099,11 +1096,6 @@ PHP_FUNCTION(mysqli_result_construct)
|
||||
case MYSQLI_USE_RESULT:
|
||||
result = mysql_use_result(mysql->mysql);
|
||||
break;
|
||||
#if defined(MYSQLI_USE_MYSQLND) && defined(MYSQLND_THREADED)
|
||||
case MYSQLI_BG_STORE_RESULT:
|
||||
result = mysqli_bg_store_result(mysql->mysql);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for resultmode");
|
||||
}
|
||||
|
||||
@@ -530,11 +530,7 @@ PHP_FUNCTION(mysqli_query)
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty query");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~MYSQLI_ASYNC) != MYSQLI_STORE_RESULT
|
||||
#if defined(MYSQLI_USE_MYSQLND) && defined(MYSQLND_THREADED)
|
||||
&& (resultmode & ~MYSQLI_ASYNC) != MYSQLI_BG_STORE_RESULT
|
||||
#endif
|
||||
) {
|
||||
if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~MYSQLI_ASYNC) != MYSQLI_STORE_RESULT) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for resultmode");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
@@ -575,11 +571,6 @@ PHP_FUNCTION(mysqli_query)
|
||||
case MYSQLI_USE_RESULT:
|
||||
result = mysql_use_result(mysql->mysql);
|
||||
break;
|
||||
#if defined(MYSQLI_USE_MYSQLND) && defined(MYSQLND_THREADED)
|
||||
case MYSQLI_BG_STORE_RESULT:
|
||||
result = mysqli_bg_store_result(mysql->mysql);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (!result) {
|
||||
php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql) TSRMLS_CC,
|
||||
@@ -813,11 +804,6 @@ PHP_FUNCTION(mysqli_reap_async_query)
|
||||
case MYSQLI_USE_RESULT:
|
||||
result = mysql_use_result(mysql->mysql);
|
||||
break;
|
||||
#if defined(MYSQLI_USE_MYSQLND) && defined(MYSQLND_THREADED)
|
||||
case MYSQLI_BG_STORE_RESULT:
|
||||
result = mysqli_bg_store_result(mysql->mysql);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
|
||||
@@ -319,9 +319,6 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry * TSRML
|
||||
#define MYSQLI_STORE_RESULT 0
|
||||
#define MYSQLI_USE_RESULT 1
|
||||
#ifdef MYSQLI_USE_MYSQLND
|
||||
#ifdef MYSQLND_THREADED
|
||||
#define MYSQLI_BG_STORE_RESULT 4
|
||||
#endif
|
||||
#define MYSQLI_ASYNC 8
|
||||
#else
|
||||
/* libmysql */
|
||||
|
||||
@@ -3,11 +3,6 @@ dnl $Id$
|
||||
dnl config.m4 for mysqlnd driver
|
||||
|
||||
|
||||
PHP_ARG_ENABLE(mysqlnd_threading, whether to enable threaded fetch in mysqlnd,
|
||||
[ --enable-mysqlnd-threading
|
||||
EXPERIMENTAL: Enable mysqlnd threaded fetch.
|
||||
Note: This forces ZTS on!], no, no)
|
||||
|
||||
PHP_ARG_ENABLE(disable_mysqlnd_compression_support, whether to disable compressed protocol support in mysqlnd,
|
||||
[ --disable-mysqlnd-compression-support
|
||||
Enable support for the MySQL compressed protocol in mysqlnd], yes)
|
||||
@@ -29,10 +24,6 @@ if test "$PHP_MYSQLND_ENABLED" = "yes"; then
|
||||
PHP_ADD_BUILD_DIR([ext/mysqlnd], 1)
|
||||
|
||||
dnl Windows uses config.w32 thus this code is safe for now
|
||||
if test "$PHP_MYSQLND_THREADING" = "yes"; then
|
||||
PHP_BUILD_THREAD_SAFE
|
||||
AC_DEFINE([MYSQLND_THREADED], 1, [Use mysqlnd internal threading])
|
||||
fi
|
||||
|
||||
if test "$PHP_MYSQLND_COMPRESSION_SUPPORT" != "no"; then
|
||||
AC_DEFINE([MYSQLND_COMPRESSION_ENABLED], 1, [Enable compressed protocol support])
|
||||
|
||||
@@ -245,22 +245,6 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor)(MYSQLND *conn TSRMLS_DC)
|
||||
conn->m->free_contents(conn TSRMLS_CC);
|
||||
conn->m->free_options(conn TSRMLS_CC);
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
if (conn->thread_is_running) {
|
||||
pthread_mutex_lock(&conn->LOCK_work);
|
||||
conn->thread_killed = TRUE;
|
||||
pthread_cond_signal(&conn->COND_work);
|
||||
pthread_cond_wait(&conn->COND_thread_ended, &conn->LOCK_work);
|
||||
pthread_mutex_unlock(&conn->LOCK_work);
|
||||
}
|
||||
|
||||
tsrm_mutex_free(conn->LOCK_state);
|
||||
|
||||
pthread_cond_destroy(&conn->COND_work);
|
||||
pthread_cond_destroy(&conn->COND_work_done);
|
||||
pthread_mutex_destroy(&conn->LOCK_work);
|
||||
#endif
|
||||
|
||||
mnd_pefree(conn, conn->persistent);
|
||||
|
||||
DBG_VOID_RETURN;
|
||||
@@ -823,21 +807,6 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND *conn,
|
||||
DBG_INF("unicode set");
|
||||
}
|
||||
#endif
|
||||
#ifdef MYSQLND_THREADED
|
||||
{
|
||||
pthread_t th;
|
||||
pthread_attr_t connection_attrib;
|
||||
conn->tsrm_ls = tsrm_ls;
|
||||
|
||||
pthread_attr_init(&connection_attrib);
|
||||
pthread_attr_setdetachstate(&connection_attrib, PTHREAD_CREATE_DETACHED);
|
||||
|
||||
conn->thread_is_running = TRUE;
|
||||
if (pthread_create(&th, &connection_attrib, mysqlnd_fetch_thread, (void*)conn)) {
|
||||
conn->thread_is_running = FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (conn->options.init_commands) {
|
||||
int current_command = 0;
|
||||
@@ -1630,25 +1599,12 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, free_reference)(MYSQLND * const conn TSRMLS
|
||||
|
||||
|
||||
/* {{{ mysqlnd_conn::get_state */
|
||||
#ifdef MYSQLND_THREADED
|
||||
static enum mysqlnd_connection_state
|
||||
MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_state)(MYSQLND * const conn TSRMLS_DC)
|
||||
{
|
||||
enum mysqlnd_connection_state state;
|
||||
DBG_ENTER("mysqlnd_conn::get_state");
|
||||
tsrm_mutex_lock(conn->LOCK_state);
|
||||
state = conn->state;
|
||||
tsrm_mutex_unlock(conn->LOCK_state);
|
||||
DBG_RETURN(state);
|
||||
}
|
||||
#else
|
||||
static enum mysqlnd_connection_state
|
||||
MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_state)(MYSQLND * const conn TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_conn::get_state");
|
||||
DBG_RETURN(conn->state);
|
||||
}
|
||||
#endif
|
||||
/* }}} */
|
||||
|
||||
|
||||
@@ -1657,14 +1613,8 @@ static void
|
||||
MYSQLND_METHOD_PRIVATE(mysqlnd_conn, set_state)(MYSQLND * const conn, enum mysqlnd_connection_state new_state TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_conn::set_state");
|
||||
#ifdef MYSQLND_THREADED
|
||||
tsrm_mutex_lock(conn->LOCK_state);
|
||||
#endif
|
||||
DBG_INF_FMT("New state=%d", new_state);
|
||||
conn->state = new_state;
|
||||
#ifdef MYSQLND_THREADED
|
||||
tsrm_mutex_unlock(conn->LOCK_state);
|
||||
#endif
|
||||
DBG_VOID_RETURN;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -2190,44 +2140,6 @@ MYSQLND_METHOD(mysqlnd_conn, store_result)(MYSQLND * const conn TSRMLS_DC)
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_conn::background_store_result */
|
||||
MYSQLND_RES *
|
||||
MYSQLND_METHOD(mysqlnd_conn, background_store_result)(MYSQLND * const conn TSRMLS_DC)
|
||||
{
|
||||
MYSQLND_RES *result;
|
||||
|
||||
DBG_ENTER("mysqlnd_conn::store_result");
|
||||
DBG_INF_FMT("conn=%llu", conn->thread_id);
|
||||
|
||||
if (!conn->current_result) {
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
|
||||
/* Nothing to store for UPSERT/LOAD DATA*/
|
||||
if (conn->last_query_type != QUERY_SELECT || CONN_GET_STATE(conn) != CONN_FETCHING_DATA) {
|
||||
SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
|
||||
mysqlnd_out_of_sync);
|
||||
DBG_ERR("Command out of sync");
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
|
||||
MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_BUFFERED_SETS);
|
||||
|
||||
result = conn->current_result;
|
||||
|
||||
result = result->m.background_store_result(result, conn, FALSE TSRMLS_CC);
|
||||
|
||||
/*
|
||||
Should be here, because current_result is used by the fetching thread to get data info
|
||||
The thread is contacted in mysqlnd_res::background_store_result().
|
||||
*/
|
||||
conn->current_result = NULL;
|
||||
|
||||
DBG_RETURN(result);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_conn::get_connection_stats */
|
||||
static void
|
||||
MYSQLND_METHOD(mysqlnd_conn, get_connection_stats)(const MYSQLND * const conn,
|
||||
@@ -2254,7 +2166,6 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn)
|
||||
MYSQLND_METHOD(mysqlnd_conn, reap_query),
|
||||
MYSQLND_METHOD(mysqlnd_conn, use_result),
|
||||
MYSQLND_METHOD(mysqlnd_conn, store_result),
|
||||
MYSQLND_METHOD(mysqlnd_conn, background_store_result),
|
||||
MYSQLND_METHOD(mysqlnd_conn, next_result),
|
||||
MYSQLND_METHOD(mysqlnd_conn, more_results),
|
||||
|
||||
@@ -2326,15 +2237,6 @@ PHPAPI MYSQLND *_mysqlnd_init(zend_bool persistent TSRMLS_DC)
|
||||
ret->net.stream_read = mysqlnd_read_from_stream;
|
||||
ret->net.stream_write = mysqlnd_stream_write;
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
ret->LOCK_state = tsrm_mutex_alloc();
|
||||
|
||||
pthread_mutex_init(&ret->LOCK_work, NULL);
|
||||
pthread_cond_init(&ret->COND_work, NULL);
|
||||
pthread_cond_init(&ret->COND_work_done, NULL);
|
||||
pthread_cond_init(&ret->COND_thread_ended, NULL);
|
||||
#endif
|
||||
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -129,7 +129,6 @@ PHPAPI enum_func_status _mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQ
|
||||
|
||||
#define mysqlnd_use_result(conn) (conn)->m->use_result((conn) TSRMLS_CC)
|
||||
#define mysqlnd_store_result(conn) (conn)->m->store_result((conn) TSRMLS_CC)
|
||||
#define mysqlnd_bg_store_result(conn) (conn)->m->background_store_result((conn) TSRMLS_CC)
|
||||
#define mysqlnd_next_result(conn) (conn)->m->next_result((conn) TSRMLS_CC)
|
||||
#define mysqlnd_more_results(conn) (conn)->m->more_results((conn) TSRMLS_CC)
|
||||
#define mysqlnd_free_result(r,e_or_i) ((MYSQLND_RES*)r)->m.free_result(((MYSQLND_RES*)(r)), (e_or_i) TSRMLS_CC)
|
||||
@@ -279,7 +278,6 @@ PHPAPI ulong mysqlnd_old_escape_string(char *newstr, const char *escapestr, size
|
||||
/* PS */
|
||||
#define mysqlnd_stmt_init(conn) (conn)->m->stmt_init((conn) TSRMLS_CC)
|
||||
#define mysqlnd_stmt_store_result(stmt) (!mysqlnd_stmt_field_count((stmt)) ? PASS:((stmt)->m->store_result((stmt) TSRMLS_CC)? PASS:FAIL))
|
||||
#define mysqlnd_stmt_bg_store_result(stmt) (!mysqlnd_stmt_field_count((stmt)) ? PASS:((stmt)->m->background_store_result((stmt) TSRMLS_CC)? PASS:FAIL))
|
||||
#define mysqlnd_stmt_get_result(stmt) (stmt)->m->get_result((stmt) TSRMLS_CC)
|
||||
#define mysqlnd_stmt_more_results(stmt) (stmt)->m->more_results((stmt) TSRMLS_CC)
|
||||
#define mysqlnd_stmt_next_result(stmt) (stmt)->m->next_result((stmt) TSRMLS_CC)
|
||||
@@ -380,9 +378,6 @@ ZEND_BEGIN_MODULE_GLOBALS(mysqlnd)
|
||||
long net_cmd_buffer_size;
|
||||
long net_read_buffer_size;
|
||||
long log_mask;
|
||||
#ifdef MYSQLND_THREADED
|
||||
THREAD_T thread_id;
|
||||
#endif
|
||||
long net_read_timeout;
|
||||
ZEND_END_MODULE_GLOBALS(mysqlnd)
|
||||
|
||||
|
||||
@@ -95,12 +95,6 @@ MYSQLND_METHOD(mysqlnd_debug, log)(MYSQLND_DEBUG * self,
|
||||
line_buffer[6], level_buffer[7];
|
||||
MYSQLND_ZTS(self);
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
|
||||
return PASS; /* don't trace background threads */
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!self->stream) {
|
||||
if (FAIL == self->m->open(self, FALSE)) {
|
||||
return FAIL;
|
||||
@@ -201,12 +195,6 @@ MYSQLND_METHOD(mysqlnd_debug, log_va)(MYSQLND_DEBUG *self,
|
||||
line_buffer[6], level_buffer[7];
|
||||
MYSQLND_ZTS(self);
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
|
||||
return PASS; /* don't trace background threads */
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!self->stream) {
|
||||
if (FAIL == self->m->open(self, FALSE)) {
|
||||
return FAIL;
|
||||
@@ -303,17 +291,9 @@ MYSQLND_METHOD(mysqlnd_debug, func_enter)(MYSQLND_DEBUG * self,
|
||||
unsigned int line, const char * const file,
|
||||
char * func_name, unsigned int func_name_len)
|
||||
{
|
||||
#ifdef MYSQLND_THREADED
|
||||
MYSQLND_ZTS(self);
|
||||
#endif
|
||||
if ((self->flags & MYSQLND_DEBUG_DUMP_TRACE) == 0 || self->file_name == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
#ifdef MYSQLND_THREADED
|
||||
if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
|
||||
return FALSE; /* don't trace background threads */
|
||||
}
|
||||
#endif
|
||||
if (zend_stack_count(&self->call_stack) >= self->nest_level_limit) {
|
||||
return FALSE;
|
||||
}
|
||||
@@ -351,17 +331,9 @@ MYSQLND_METHOD(mysqlnd_debug, func_leave)(MYSQLND_DEBUG * self, unsigned int lin
|
||||
const char * const file)
|
||||
{
|
||||
char *func_name;
|
||||
#ifdef MYSQLND_THREADED
|
||||
MYSQLND_ZTS(self);
|
||||
#endif
|
||||
if ((self->flags & MYSQLND_DEBUG_DUMP_TRACE) == 0 || self->file_name == NULL) {
|
||||
return PASS;
|
||||
}
|
||||
#ifdef MYSQLND_THREADED
|
||||
if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
|
||||
return PASS; /* don't trace background threads */
|
||||
}
|
||||
#endif
|
||||
if (zend_stack_count(&self->call_stack) >= self->nest_level_limit) {
|
||||
return PASS;
|
||||
}
|
||||
@@ -670,11 +642,6 @@ void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)
|
||||
{
|
||||
void *ret;
|
||||
DBG_ENTER(mysqlnd_emalloc_name);
|
||||
#ifdef MYSQLND_THREADED
|
||||
if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
|
||||
DBG_RETURN(_mysqlnd_pemalloc(size, 1 TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC));
|
||||
}
|
||||
#endif
|
||||
|
||||
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
|
||||
DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
|
||||
@@ -723,11 +690,6 @@ void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
|
||||
{
|
||||
void *ret;
|
||||
DBG_ENTER(mysqlnd_ecalloc_name);
|
||||
#ifdef MYSQLND_THREADED
|
||||
if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
|
||||
DBG_RETURN(_mysqlnd_pecalloc(nmemb, size, 1 TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC));
|
||||
}
|
||||
#endif
|
||||
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
|
||||
DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
|
||||
|
||||
@@ -776,11 +738,6 @@ void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
|
||||
{
|
||||
void *ret;
|
||||
DBG_ENTER(mysqlnd_erealloc_name);
|
||||
#ifdef MYSQLND_THREADED
|
||||
if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
|
||||
DBG_RETURN(_mysqlnd_perealloc(ptr, new_size, 1 TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC));
|
||||
}
|
||||
#endif
|
||||
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
|
||||
DBG_INF_FMT("ptr=%p new_size=%lu", ptr, new_size);
|
||||
DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
|
||||
@@ -830,11 +787,6 @@ void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQL
|
||||
void _mysqlnd_efree(void *ptr MYSQLND_MEM_D)
|
||||
{
|
||||
DBG_ENTER(mysqlnd_efree_name);
|
||||
#ifdef MYSQLND_THREADED
|
||||
if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
|
||||
DBG_RETURN(_mysqlnd_pefree(ptr, 1 TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC));
|
||||
}
|
||||
#endif
|
||||
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
|
||||
DBG_INF_FMT("ptr=%p", ptr);
|
||||
DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
|
||||
|
||||
@@ -133,80 +133,6 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const stmt TSRMLS_DC)
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_stmt::background_store_result */
|
||||
static MYSQLND_RES *
|
||||
MYSQLND_METHOD(mysqlnd_stmt, background_store_result)(MYSQLND_STMT * const stmt TSRMLS_DC)
|
||||
{
|
||||
enum_func_status ret;
|
||||
MYSQLND *conn = stmt->conn;
|
||||
MYSQLND_RES *result;
|
||||
zend_bool to_cache = FALSE;
|
||||
|
||||
DBG_ENTER("mysqlnd_stmt::background_store_result");
|
||||
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
|
||||
|
||||
/* be compliant with libmysql - NULL will turn */
|
||||
if (!stmt->field_count) {
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
|
||||
if (stmt->cursor_exists) {
|
||||
/* Silently convert buffered to unbuffered, for now */
|
||||
MYSQLND_RES * res = stmt->m->use_result(stmt TSRMLS_CC);
|
||||
DBG_RETURN(res);
|
||||
}
|
||||
|
||||
/* Nothing to store for UPSERT/LOAD DATA*/
|
||||
if (CONN_GET_STATE(conn) != CONN_FETCHING_DATA ||
|
||||
stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE)
|
||||
{
|
||||
SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
|
||||
UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
|
||||
stmt->default_rset_handler = stmt->m->store_result;
|
||||
|
||||
SET_EMPTY_ERROR(stmt->error_info);
|
||||
SET_EMPTY_ERROR(stmt->conn->error_info);
|
||||
MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_PS_BUFFERED_SETS);
|
||||
|
||||
result = stmt->result;
|
||||
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);
|
||||
}
|
||||
|
||||
/* Create room for 'next_extend' rows */
|
||||
|
||||
/* Not set for SHOW statements at PREPARE stage */
|
||||
if (result->conn) {
|
||||
result->conn->m->free_reference(result->conn TSRMLS_CC);
|
||||
result->conn = NULL; /* store result does not reference the connection */
|
||||
}
|
||||
|
||||
ret = result->m.store_result_fetch_data(conn, result, result->meta, TRUE, to_cache TSRMLS_CC);
|
||||
|
||||
if (PASS == ret) {
|
||||
/* libmysql API docs say it should be so for SELECT statements */
|
||||
stmt->upsert_status.affected_rows = stmt->result->stored_data->row_count;
|
||||
|
||||
stmt->state = MYSQLND_STMT_USE_OR_STORE_CALLED;
|
||||
} else {
|
||||
conn->error_info = result->stored_data->error_info;
|
||||
stmt->result->m.free_result_contents(stmt->result TSRMLS_CC);
|
||||
mnd_efree(stmt->result);
|
||||
stmt->result = NULL;
|
||||
stmt->state = MYSQLND_STMT_PREPARED;
|
||||
}
|
||||
|
||||
DBG_RETURN(result);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_stmt::get_result */
|
||||
static MYSQLND_RES *
|
||||
MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const stmt TSRMLS_DC)
|
||||
@@ -2122,7 +2048,6 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_stmt)
|
||||
MYSQLND_METHOD(mysqlnd_stmt, execute),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, use_result),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, store_result),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, background_store_result),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, get_result),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, more_results),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, next_result),
|
||||
|
||||
@@ -33,65 +33,6 @@
|
||||
|
||||
#define MYSQLND_SILENT
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
/* {{{ mysqlnd_fetch_thread */
|
||||
void * mysqlnd_fetch_thread(void *arg)
|
||||
{
|
||||
MYSQLND *conn = (MYSQLND *) arg;
|
||||
MYSQLND_RES * result = NULL;
|
||||
void ***tsrm_ls = conn->tsrm_ls;
|
||||
#ifndef MYSQLND_SILENT
|
||||
printf("THREAD] conn=%p tsrm_ls=%p\n", conn, conn->tsrm_ls);
|
||||
#endif
|
||||
do {
|
||||
pthread_mutex_lock(&conn->LOCK_work);
|
||||
while (conn->thread_killed == FALSE && !conn->current_result) {
|
||||
#ifndef MYSQLND_SILENT
|
||||
printf("THREAD] Waiting for work in %s\n", __FUNCTION__);
|
||||
#endif
|
||||
pthread_cond_wait(&conn->COND_work, &conn->LOCK_work);
|
||||
}
|
||||
if (conn->thread_killed == TRUE) {
|
||||
#ifndef MYSQLND_SILENT
|
||||
printf("THREAD] Thread killed in %s\n", __FUNCTION__);
|
||||
#endif
|
||||
pthread_cond_signal(&conn->COND_thread_ended);
|
||||
pthread_mutex_unlock(&conn->LOCK_work);
|
||||
break;
|
||||
}
|
||||
#ifndef MYSQLND_SILENT
|
||||
printf("THREAD] Got work in %s\n", __FUNCTION__);
|
||||
#endif
|
||||
CONN_SET_STATE(conn, CONN_FETCHING_DATA);
|
||||
result = conn->current_result;
|
||||
conn->current_result = NULL;
|
||||
pthread_cond_signal(&conn->COND_work); /* sent notification back */
|
||||
pthread_mutex_unlock(&conn->LOCK_work);
|
||||
|
||||
#ifndef MYSQLND_SILENT
|
||||
printf("THREAD] Starting fetch %s\n", __FUNCTION__);
|
||||
#endif
|
||||
mysqlnd_background_store_result_fetch_data(result TSRMLS_CC);
|
||||
|
||||
/* do fetch the data from the wire */
|
||||
|
||||
pthread_mutex_lock(&conn->LOCK_work);
|
||||
CONN_SET_STATE(conn, CONN_READY);
|
||||
pthread_cond_signal(&conn->COND_work_done);
|
||||
#ifndef MYSQLND_SILENT
|
||||
printf("THREAD] Signaling work done in %s\n", __FUNCTION__);
|
||||
#endif
|
||||
pthread_mutex_unlock(&conn->LOCK_work);
|
||||
} while (1);
|
||||
|
||||
#ifndef MYSQLND_SILENT
|
||||
printf("THREAD] Exiting worker thread in %s\n", __FUNCTION__);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
/* }}} */
|
||||
#endif /* MYSQLND_THREADED */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_res::initialize_result_set_rest */
|
||||
static void
|
||||
@@ -253,85 +194,6 @@ MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES *result TSRMLS_DC)
|
||||
/* }}} */
|
||||
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
/* {{{ mysqlnd_free_background_buffered_data */
|
||||
void mysqlnd_free_background_buffered_data(MYSQLND_RES *result TSRMLS_DC)
|
||||
{
|
||||
MYSQLND_THD_ZVAL_PCACHE *zval_cache = result->zval_cache;
|
||||
MYSQLND_RES_BG_BUFFERED *set = result->bg_stored_data;
|
||||
unsigned int field_count = result->field_count;
|
||||
int row;
|
||||
|
||||
DBG_ENTER("mysqlnd_free_buffered_data");
|
||||
DBG_INF_FMT("Freeing "MYSQLND_LLU_SPEC" row(s)", set->row_count);
|
||||
|
||||
do {
|
||||
tsrm_mutex_lock(set->LOCK);
|
||||
if (set->bg_fetch_finished) {
|
||||
tsrm_mutex_unlock(set->LOCK);
|
||||
break;
|
||||
}
|
||||
tsrm_mutex_unlock(set->LOCK);
|
||||
#if HAVE_USLEEP
|
||||
usleep(2000);
|
||||
#else
|
||||
{
|
||||
volatile int i;
|
||||
for (i = 0; i < 1000; i++);
|
||||
}
|
||||
#endif
|
||||
} while (1);
|
||||
|
||||
DBG_INF_FMT("before: real_usage=%lu usage=%lu", zend_memory_usage(TRUE TSRMLS_CC), zend_memory_usage(FALSE TSRMLS_CC));
|
||||
for (row = set->row_count - 1; row >= 0; row--) {
|
||||
MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row];
|
||||
/* It could be the case that the user fetched no rows - then no set->data */
|
||||
if (row < set->data_size && set->data[row]) {
|
||||
zval **current_row = set->data[row];
|
||||
unsigned int col;
|
||||
|
||||
for (col = 0; col < field_count; col++) {
|
||||
zend_bool copy_ctor_called;
|
||||
mysqlnd_palloc_zval_ptr_dtor(&(current_row[col]), zval_cache,
|
||||
result->type, ©_ctor_called TSRMLS_CC);
|
||||
#if MYSQLND_DEBUG_MEMORY
|
||||
DBG_INF_FMT("Copy_ctor_called=%d", copy_ctor_called);
|
||||
#endif
|
||||
MYSQLND_INC_GLOBAL_STATISTIC(copy_ctor_called? STAT_COPY_ON_WRITE_PERFORMED:
|
||||
STAT_COPY_ON_WRITE_SAVED);
|
||||
}
|
||||
#if MYSQLND_DEBUG_MEMORY
|
||||
DBG_INF("Freeing current_row & current_buffer");
|
||||
#endif
|
||||
mnd_pefree(current_row, set->persistent);
|
||||
}
|
||||
current_buffer->free_chunk(current_buffer, TRUE TSRMLS_CC);
|
||||
}
|
||||
DBG_INF("Freeing data & row_buffer");
|
||||
mnd_pefree(set->data, set->persistent);
|
||||
mnd_pefree(set->row_buffers, set->persistent);
|
||||
set->data = NULL;
|
||||
set->row_buffers = NULL;
|
||||
set->data_cursor = NULL;
|
||||
set->row_count = 0;
|
||||
if (set->qcache) {
|
||||
mysqlnd_qcache_free_cache_reference(&set->qcache);
|
||||
}
|
||||
|
||||
if (set->LOCK) {
|
||||
tsrm_mutex_free(set->LOCK);
|
||||
}
|
||||
|
||||
DBG_INF("Freeing set");
|
||||
mnd_pefree(set, set->persistent);
|
||||
|
||||
DBG_INF_FMT("after: real_usage=%lu usage=%lu", zend_memory_usage(TRUE TSRMLS_CC), zend_memory_usage(FALSE TSRMLS_CC));
|
||||
DBG_VOID_RETURN;
|
||||
}
|
||||
/* }}} */
|
||||
#endif /* MYSQL_THREADING */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_res::free_result_buffers */
|
||||
static void
|
||||
MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES *result TSRMLS_DC)
|
||||
@@ -347,12 +209,6 @@ MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES *result TSRMLS_DC)
|
||||
result->m.free_buffered_data(result TSRMLS_CC);
|
||||
result->stored_data = NULL;
|
||||
}
|
||||
#ifdef MYSQLND_THREADED
|
||||
else if (result->bg_stored_data) {
|
||||
mysqlnd_free_background_buffered_data(result TSRMLS_CC);
|
||||
result->bg_stored_data = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (result->lengths) {
|
||||
mnd_efree(result->lengths);
|
||||
@@ -690,45 +546,6 @@ unsigned long * mysqlnd_fetch_lengths_buffered(MYSQLND_RES * const result)
|
||||
/* }}} */
|
||||
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
/* {{{ mysqlnd_fetch_lengths_async_buffered */
|
||||
/*
|
||||
Do lazy initialization for buffered results. As PHP strings have
|
||||
length inside, this function makes not much sense in the context
|
||||
of PHP, to be called as separate function. But let's have it for
|
||||
completeness.
|
||||
*/
|
||||
static
|
||||
unsigned long * mysqlnd_fetch_lengths_async_buffered(MYSQLND_RES * const result)
|
||||
{
|
||||
int i;
|
||||
zval **previous_row;
|
||||
MYSQLND_RES_BG_BUFFERED *set = result->bg_stored_data;
|
||||
|
||||
/*
|
||||
If:
|
||||
- unbuffered result
|
||||
- first row has not been read
|
||||
- last_row has been read
|
||||
*/
|
||||
if (set->data_cursor == NULL ||
|
||||
set->data_cursor == set->data ||
|
||||
((set->data_cursor - set->data) > set->row_count))
|
||||
{
|
||||
return NULL;/* No rows or no more rows */
|
||||
}
|
||||
|
||||
previous_row = *(set->data_cursor - 1);
|
||||
for (i = 0; i < result->meta->field_count; i++) {
|
||||
result->lengths[i] = (Z_TYPE_P(previous_row[i]) == IS_NULL)? 0:Z_STRLEN_P(previous_row[i]);
|
||||
}
|
||||
|
||||
return result->lengths;
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
|
||||
/* {{{ mysqlnd_fetch_lengths_unbuffered */
|
||||
static
|
||||
unsigned long * mysqlnd_fetch_lengths_unbuffered(MYSQLND_RES * const result)
|
||||
@@ -1355,329 +1172,6 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
|
||||
/* }}} */
|
||||
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
/* {{{ mysqlnd_fetch_row_async_buffered */
|
||||
static enum_func_status
|
||||
mysqlnd_fetch_row_async_buffered(MYSQLND_RES *result, void *param, unsigned int flags,
|
||||
zend_bool *fetched_anything TSRMLS_DC)
|
||||
{
|
||||
zval *row = (zval *) param;
|
||||
MYSQLND_RES_BG_BUFFERED *set = result->bg_stored_data;
|
||||
|
||||
DBG_ENTER("mysqlnd_fetch_row_async_buffered");
|
||||
DBG_INF_FMT("flags=%u row=%p", flags, row);
|
||||
|
||||
do {
|
||||
tsrm_mutex_lock(set->LOCK);
|
||||
if (set->bg_fetch_finished == TRUE) {
|
||||
/* Don't unlock here, will be done later */
|
||||
break;
|
||||
}
|
||||
if (!set->data_cursor || (set->data_cursor - set->data) < (set->row_count)) {
|
||||
tsrm_mutex_unlock(set->LOCK);
|
||||
#if HAVE_USLEEP
|
||||
usleep(2000);
|
||||
#else
|
||||
volatile int i = 0;
|
||||
for (int i = 0; i < 100; i++);
|
||||
#endif
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
/* At the point we are still under LOCK */
|
||||
if (set->data_cursor && (set->data_cursor - set->data) < (set->row_count)) {
|
||||
uint64_t row_num = set->data_cursor - set->data;
|
||||
zval **current_row = *set->data_cursor++;
|
||||
unsigned int i;
|
||||
|
||||
set->initialized_rows++;
|
||||
/* We don't forget to release the lock */
|
||||
tsrm_mutex_unlock(set->LOCK);
|
||||
|
||||
/* If there was no decoding in background, we have to decode here */
|
||||
if (set->decode_in_foreground == TRUE) {
|
||||
MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row_num];
|
||||
result->m.row_decoder(current_buffer,
|
||||
current_row,
|
||||
result->meta->field_count,
|
||||
result->meta->fields,
|
||||
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++) {
|
||||
/*
|
||||
NULL fields are 0 length, 0 is not more than 0
|
||||
String of zero size, definitely can't be the next max_length.
|
||||
Thus for NULL and zero-length we are quite efficient.
|
||||
*/
|
||||
if (Z_TYPE_P(current_row[i]) >= IS_STRING) {
|
||||
unsigned long len = Z_STRLEN_P(current_row[i]);
|
||||
if (result->meta->fields[i].max_length < len) {
|
||||
result->meta->fields[i].max_length = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < result->field_count; i++) {
|
||||
zval *data = current_row[i];
|
||||
|
||||
/*
|
||||
Let us later know what to do with this zval. If ref_count > 1, we will just
|
||||
decrease it, otherwise free it. zval_ptr_dtor() make this very easy job.
|
||||
*/
|
||||
Z_ADDREF_P(data);
|
||||
|
||||
if ((flags & MYSQLND_FETCH_BOTH) == MYSQLND_FETCH_BOTH) {
|
||||
Z_ADDREF_P(data);
|
||||
}
|
||||
if (flags & MYSQLND_FETCH_NUM) {
|
||||
zend_hash_next_index_insert(Z_ARRVAL_P(row), &data, sizeof(zval *), NULL);
|
||||
}
|
||||
if (flags & MYSQLND_FETCH_ASSOC) {
|
||||
/* zend_hash_quick_update needs length + trailing zero */
|
||||
/* QQ: Error handling ? */
|
||||
/*
|
||||
zend_hash_quick_update does not check, as add_assoc_zval_ex do, whether
|
||||
the index is a numeric and convert it to it. This however means constant
|
||||
hashing of the column name, which is not needed as it can be precomputed.
|
||||
*/
|
||||
if (result->meta->zend_hash_keys[i].is_numeric == FALSE) {
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
zend_u_hash_quick_update(Z_ARRVAL_P(row), IS_UNICODE,
|
||||
result->meta->zend_hash_keys[i].ustr,
|
||||
result->meta->zend_hash_keys[i].ulen + 1,
|
||||
result->meta->zend_hash_keys[i].key,
|
||||
(void *) &data, sizeof(zval *), NULL);
|
||||
#else
|
||||
zend_hash_quick_update(Z_ARRVAL_P(row),
|
||||
result->meta->fields[i].name,
|
||||
result->meta->fields[i].name_length + 1,
|
||||
result->meta->zend_hash_keys[i].key,
|
||||
(void *) &data, sizeof(zval *), NULL);
|
||||
#endif
|
||||
} else {
|
||||
zend_hash_index_update(Z_ARRVAL_P(row),
|
||||
result->meta->zend_hash_keys[i].key,
|
||||
(void *) &data, sizeof(zval *), NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
*fetched_anything = TRUE;
|
||||
MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF);
|
||||
} else {
|
||||
set->data_cursor = NULL;
|
||||
/* We don't forget to release the lock */
|
||||
tsrm_mutex_unlock(set->LOCK);
|
||||
*fetched_anything = FALSE;
|
||||
DBG_INF("EOF reached");
|
||||
}
|
||||
|
||||
DBG_INF_FMT("ret=PASS fetched=%d", *fetched_anything);
|
||||
DBG_RETURN(PASS);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_background_store_result_fetch_data */
|
||||
enum_func_status
|
||||
mysqlnd_background_store_result_fetch_data(MYSQLND_RES *result TSRMLS_DC)
|
||||
{
|
||||
enum_func_status ret;
|
||||
php_mysql_packet_row *row_packet;
|
||||
unsigned int next_extend = STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY, free_rows;
|
||||
MYSQLND_RES_BG_BUFFERED *set = result->bg_stored_data;
|
||||
MYSQLND *conn = result->conn;
|
||||
|
||||
DBG_ENTER("mysqlnd_background_store_result_fetch_data");
|
||||
|
||||
free_rows = next_extend;
|
||||
|
||||
/* persistent */
|
||||
PACKET_INIT(row_packet, PROT_ROW_PACKET, php_mysql_packet_row *, TRUE);
|
||||
row_packet->result_set_memory_pool = result->result_set_memory_pool;
|
||||
row_packet->field_count = result->meta->field_count;
|
||||
row_packet->binary_protocol = result->m.row_decoder == php_mysqlnd_rowp_read_binary_protocol;
|
||||
row_packet->fields_metadata = result->meta->fields;
|
||||
row_packet->bit_fields_count = result->meta->bit_fields_count;
|
||||
row_packet->bit_fields_total_len= result->meta->bit_fields_total_len;
|
||||
row_packet->persistent_alloc = TRUE;
|
||||
|
||||
while (FAIL != (ret = PACKET_READ(row_packet, conn)) && !row_packet->eof) {
|
||||
tsrm_mutex_lock(set->LOCK);
|
||||
if (!free_rows) {
|
||||
uint64_t total_rows = free_rows = next_extend = next_extend * 5 / 3; /* extend with 33% */
|
||||
uint64_t old_size;
|
||||
total_rows += set->row_count;
|
||||
|
||||
old_size = set->data_size;
|
||||
set->data_size = total_rows;
|
||||
set->data = mnd_perealloc(set->data, set->data_size * sizeof(zval **), set->persistent);
|
||||
#if 0
|
||||
memset(set->data + old_size, 0, (set->data_size - old_size) * sizeof(zval **));
|
||||
#endif
|
||||
set->row_buffers = mnd_perealloc(set->row_buffers,
|
||||
total_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *),
|
||||
set->persistent);
|
||||
}
|
||||
set->row_buffers[set->row_count] = row_packet->row_buffer;
|
||||
set->data[set->row_count] = row_packet->fields;
|
||||
|
||||
if (set->decode_in_foreground == FALSE) {
|
||||
unsigned int i;
|
||||
result->m.row_decoder(set->row_buffers[set->row_count],
|
||||
set->data[set->row_count],
|
||||
result->meta->field_count,
|
||||
result->meta->fields,
|
||||
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++) {
|
||||
/*
|
||||
NULL fields are 0 length, 0 is not more than 0
|
||||
String of zero size, definitely can't be the next max_length.
|
||||
Thus for NULL and zero-length we are quite efficient.
|
||||
*/
|
||||
if (Z_TYPE_P(set->data[set->row_count][i]) >= IS_STRING) {
|
||||
unsigned long len = Z_STRLEN_P(set->data[set->row_count][i]);
|
||||
if (result->meta->fields[i].max_length < len) {
|
||||
result->meta->fields[i].max_length = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
set->row_count++;
|
||||
|
||||
tsrm_mutex_unlock(set->LOCK);
|
||||
free_rows--;
|
||||
|
||||
/* So row_packet's destructor function won't efree() it */
|
||||
row_packet->row_buffer = NULL;
|
||||
row_packet->fields = NULL;
|
||||
|
||||
/*
|
||||
No need to FREE_ALLOCA as we can reuse the
|
||||
'lengths' and 'fields' arrays. For lengths its absolutely safe.
|
||||
'fields' is reused because the ownership of the strings has been
|
||||
transfered above.
|
||||
*/
|
||||
}
|
||||
#if 0
|
||||
MYSQLND_INC_CONN_STATISTIC_W_VALUE(&conn->stats,
|
||||
binary_protocol? STAT_ROWS_BUFFERED_FROM_CLIENT_PS:
|
||||
STAT_ROWS_BUFFERED_FROM_CLIENT_NORMAL,
|
||||
set->row_count);
|
||||
#endif
|
||||
tsrm_mutex_lock(set->LOCK);
|
||||
/* Finally clean */
|
||||
if (row_packet->eof) {
|
||||
set->upsert_status.warning_count = row_packet->warning_count;
|
||||
set->upsert_status.server_status = row_packet->server_status;
|
||||
}
|
||||
/* save some memory */
|
||||
if (free_rows) {
|
||||
set->data_size = set->row_count;
|
||||
set->data = mnd_perealloc(set->data,
|
||||
(size_t) set->data_size * sizeof(zval **), set->persistent);
|
||||
set->row_buffers = mnd_perealloc(set->row_buffers,
|
||||
set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *),
|
||||
set->persistent);
|
||||
}
|
||||
if (ret == FAIL) {
|
||||
set->error_info = row_packet->error_info;
|
||||
} else {
|
||||
/* Position at the first row */
|
||||
set->data_cursor = set->data;
|
||||
|
||||
/* libmysql's documentation says it should be so for SELECT statements */
|
||||
conn->upsert_status.affected_rows = set->row_count;
|
||||
set->upsert_status.affected_rows = set->row_count;
|
||||
}
|
||||
set->bg_fetch_finished = TRUE;
|
||||
tsrm_mutex_unlock(set->LOCK);
|
||||
|
||||
PACKET_FREE(row_packet);
|
||||
|
||||
if (conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS) {
|
||||
CONN_SET_STATE(conn, CONN_NEXT_RESULT_PENDING);
|
||||
} else {
|
||||
CONN_SET_STATE(conn, CONN_READY);
|
||||
}
|
||||
DBG_INF_FMT("ret=%s row_count=%u warnings=%u server_status=%u", ret == PASS? "PASS":"FAIL",
|
||||
set->row_count, conn->upsert_status.warning_count, conn->upsert_status.server_status);
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
|
||||
/* {{{ mysqlnd_res::background_store_result */
|
||||
static MYSQLND_RES *
|
||||
MYSQLND_METHOD(mysqlnd_res, background_store_result)(MYSQLND_RES * result, MYSQLND * const conn, zend_bool ps TSRMLS_DC)
|
||||
{
|
||||
#ifndef MYSQLND_THREADED
|
||||
return (result->m.store_result(result, conn, ps TSRMLS_CC));
|
||||
#else
|
||||
enum_func_status ret;
|
||||
zend_bool to_cache = TRUE;
|
||||
|
||||
DBG_ENTER("mysqlnd_res::background_store_result");
|
||||
DBG_INF_FMT("conn=%d ps_protocol=%d", conn->thread_id, ps);
|
||||
|
||||
/* We need the conn because we are doing lazy zval initialization in buffered_fetch_row */
|
||||
result->conn = conn->m->get_reference(conn TSRMLS_CC);
|
||||
result->type = MYSQLND_RES_NORMAL;
|
||||
result->m.fetch_row = mysqlnd_fetch_row_async_buffered;
|
||||
result->m.fetch_lengths = mysqlnd_fetch_lengths_async_buffered;
|
||||
|
||||
result->bg_stored_data = mnd_pecalloc(1, sizeof(MYSQLND_RES_BG_BUFFERED), to_cache);
|
||||
result->bg_stored_data->data_size = STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY;
|
||||
result->bg_stored_data->data = mnd_pecalloc(result->bg_stored_data->data_size, sizeof(zval **), to_cache);
|
||||
result->bg_stored_data->row_buffers = mnd_pemalloc(STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY * sizeof(MYSQLND_MEMORY_POOL_CHUNK *), to_cache);
|
||||
result->bg_stored_data->persistent = to_cache;
|
||||
result->bg_stored_data->qcache = to_cache? mysqlnd_qcache_get_cache_reference(conn->qcache):NULL;
|
||||
result->bg_stored_data->references = 1;
|
||||
|
||||
result->bg_stored_data->LOCK = tsrm_mutex_alloc();
|
||||
|
||||
result->m.row_decoder = ps? php_mysqlnd_rowp_read_binary_protocol:
|
||||
php_mysqlnd_rowp_read_text_protocol;
|
||||
|
||||
CONN_SET_STATE(conn, CONN_FETCHING_DATA);
|
||||
/*
|
||||
This should be definitely TRUE. Decoding in background means creating zvals
|
||||
which is not very safe for Zend MM, will complain in debug mode and more problems
|
||||
also manifest themselves - unstable.
|
||||
*/
|
||||
result->bg_stored_data->decode_in_foreground = TRUE;
|
||||
|
||||
result->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long));
|
||||
|
||||
pthread_mutex_lock(&conn->LOCK_work);
|
||||
|
||||
pthread_cond_signal(&conn->COND_work);
|
||||
do {
|
||||
pthread_cond_wait(&conn->COND_work, &conn->LOCK_work);
|
||||
} while (conn->current_result); /* this is our invariant */
|
||||
pthread_mutex_unlock(&conn->LOCK_work);
|
||||
|
||||
#if 0
|
||||
ret = mysqlnd_background_store_result_fetch_data(result TSRMLS_CC);
|
||||
#endif
|
||||
|
||||
DBG_RETURN(result);
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_res::skip_result */
|
||||
static enum_func_status
|
||||
MYSQLND_METHOD(mysqlnd_res, skip_result)(MYSQLND_RES * const result TSRMLS_DC)
|
||||
@@ -2030,7 +1524,6 @@ MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCAC
|
||||
|
||||
ret->m.use_result = MYSQLND_METHOD(mysqlnd_res, use_result);
|
||||
ret->m.store_result = MYSQLND_METHOD(mysqlnd_res, store_result);
|
||||
ret->m.background_store_result = MYSQLND_METHOD(mysqlnd_res, background_store_result);
|
||||
ret->m.free_result = MYSQLND_METHOD(mysqlnd_res, free_result);
|
||||
ret->m.seek_data = MYSQLND_METHOD(mysqlnd_res, data_seek);
|
||||
ret->m.num_rows = MYSQLND_METHOD(mysqlnd_res, num_rows);
|
||||
|
||||
@@ -27,11 +27,6 @@ MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCAC
|
||||
|
||||
enum_func_status mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC);
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
void * mysqlnd_fetch_thread(void *arg);
|
||||
#endif
|
||||
|
||||
enum_func_status mysqlnd_background_store_result_fetch_data(MYSQLND_RES *result TSRMLS_DC);
|
||||
#endif /* MYSQLND_RESULT_H */
|
||||
|
||||
/*
|
||||
|
||||
@@ -195,7 +195,6 @@ typedef struct st_mysqlnd_result_bind MYSQLND_RESULT_BIND;
|
||||
|
||||
typedef struct st_mysqlnd_result_metadata MYSQLND_RES_METADATA;
|
||||
typedef struct st_mysqlnd_buffered_result MYSQLND_RES_BUFFERED;
|
||||
typedef struct st_mysqlnd_background_buffered_result MYSQLND_RES_BG_BUFFERED;
|
||||
typedef struct st_mysqlnd_unbuffered_result MYSQLND_RES_UNBUFFERED;
|
||||
|
||||
typedef struct st_mysqlnd_debug MYSQLND_DEBUG;
|
||||
@@ -262,7 +261,6 @@ struct st_mysqlnd_conn_methods
|
||||
enum_func_status (*reap_query)(MYSQLND *conn TSRMLS_DC);
|
||||
MYSQLND_RES * (*use_result)(MYSQLND * const conn TSRMLS_DC);
|
||||
MYSQLND_RES * (*store_result)(MYSQLND * const conn TSRMLS_DC);
|
||||
MYSQLND_RES * (*background_store_result)(MYSQLND * const conn TSRMLS_DC);
|
||||
enum_func_status (*next_result)(MYSQLND * const conn TSRMLS_DC);
|
||||
zend_bool (*more_results)(const MYSQLND * const conn TSRMLS_DC);
|
||||
|
||||
@@ -323,7 +321,6 @@ struct st_mysqlnd_res_methods
|
||||
|
||||
MYSQLND_RES * (*use_result)(MYSQLND_RES * const result, zend_bool ps_protocol TSRMLS_DC);
|
||||
MYSQLND_RES * (*store_result)(MYSQLND_RES * result, MYSQLND * const conn, zend_bool ps TSRMLS_DC);
|
||||
MYSQLND_RES * (*background_store_result)(MYSQLND_RES * result, MYSQLND * const conn, zend_bool ps TSRMLS_DC);
|
||||
void (*fetch_into)(MYSQLND_RES *result, unsigned int flags, zval *return_value, enum_mysqlnd_extension ext TSRMLS_DC ZEND_FILE_LINE_DC);
|
||||
MYSQLND_ROW_C (*fetch_row_c)(MYSQLND_RES *result TSRMLS_DC);
|
||||
void (*fetch_all)(MYSQLND_RES *result, unsigned int flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
|
||||
@@ -380,7 +377,6 @@ struct st_mysqlnd_stmt_methods
|
||||
enum_func_status (*execute)(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
MYSQLND_RES * (*use_result)(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
MYSQLND_RES * (*store_result)(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
MYSQLND_RES * (*background_store_result)(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
MYSQLND_RES * (*get_result)(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
zend_bool (*more_results)(const MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
enum_func_status (*next_result)(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
@@ -496,20 +492,6 @@ struct st_mysqlnd_connection
|
||||
/* stats */
|
||||
MYSQLND_STATS stats;
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
MUTEX_T LOCK_state;
|
||||
|
||||
pthread_cond_t COND_work_done;
|
||||
|
||||
pthread_mutex_t LOCK_work;
|
||||
pthread_cond_t COND_work;
|
||||
pthread_cond_t COND_thread_ended;
|
||||
zend_bool thread_is_running;
|
||||
zend_bool thread_killed;
|
||||
void *** tsrm_ls;
|
||||
#endif
|
||||
|
||||
|
||||
struct st_mysqlnd_conn_methods *m;
|
||||
};
|
||||
|
||||
@@ -541,31 +523,6 @@ struct st_mysqlnd_result_metadata
|
||||
};
|
||||
|
||||
|
||||
struct st_mysqlnd_background_buffered_result
|
||||
{
|
||||
zval ***data;
|
||||
uint64_t data_size;
|
||||
zval ***data_cursor;
|
||||
MYSQLND_MEMORY_POOL_CHUNK **row_buffers;
|
||||
uint64_t row_count;
|
||||
uint64_t initialized_rows;
|
||||
zend_bool persistent;
|
||||
|
||||
MYSQLND_QCACHE *qcache;
|
||||
unsigned int references;
|
||||
|
||||
zend_bool decode_in_foreground;
|
||||
|
||||
#ifdef ZTS
|
||||
zend_bool bg_fetch_finished;
|
||||
MUTEX_T LOCK;
|
||||
#endif
|
||||
|
||||
mysqlnd_error_info error_info;
|
||||
mysqlnd_upsert_status upsert_status;
|
||||
};
|
||||
|
||||
|
||||
struct st_mysqlnd_buffered_result
|
||||
{
|
||||
zval **data;
|
||||
@@ -606,7 +563,6 @@ struct st_mysqlnd_res
|
||||
|
||||
/* To be used with store_result() - both normal and PS */
|
||||
MYSQLND_RES_BUFFERED *stored_data;
|
||||
MYSQLND_RES_BG_BUFFERED *bg_stored_data;
|
||||
MYSQLND_RES_UNBUFFERED *unbuf;
|
||||
|
||||
/*
|
||||
|
||||
@@ -198,7 +198,7 @@ static PHP_MSHUTDOWN_FUNCTION(mysqlnd)
|
||||
/* }}} */
|
||||
|
||||
|
||||
#if defined(PHP_DEBUG) || defined(MYSQLND_THREADED)
|
||||
#if defined(PHP_DEBUG)
|
||||
/* {{{ PHP_RINIT_FUNCTION
|
||||
*/
|
||||
static PHP_RINIT_FUNCTION(mysqlnd)
|
||||
@@ -212,9 +212,6 @@ static PHP_RINIT_FUNCTION(mysqlnd)
|
||||
dbg->m->set_mode(dbg, MYSQLND_G(debug));
|
||||
MYSQLND_G(dbg) = dbg;
|
||||
}
|
||||
#endif
|
||||
#ifdef MYSQLND_THREADED
|
||||
MYSQLND_G(thread_id) = tsrm_thread_id();
|
||||
#endif
|
||||
return SUCCESS;
|
||||
}
|
||||
@@ -256,7 +253,7 @@ zend_module_entry mysqlnd_module_entry = {
|
||||
mysqlnd_functions,
|
||||
PHP_MINIT(mysqlnd),
|
||||
PHP_MSHUTDOWN(mysqlnd),
|
||||
#if defined(PHP_DEBUG) || defined(MYSQLND_THREADED)
|
||||
#if defined(PHP_DEBUG)
|
||||
PHP_RINIT(mysqlnd),
|
||||
#else
|
||||
NULL,
|
||||
|
||||
Reference in New Issue
Block a user