]> granicus.if.org Git - php/commitdiff
Update mysqlnd - fix bg_store
authorAndrey Hristov <andrey@php.net>
Thu, 14 Feb 2008 12:49:30 +0000 (12:49 +0000)
committerAndrey Hristov <andrey@php.net>
Thu, 14 Feb 2008 12:49:30 +0000 (12:49 +0000)
ext/mysqlnd/mysqlnd.c
ext/mysqlnd/mysqlnd.h
ext/mysqlnd/mysqlnd_debug.c
ext/mysqlnd/mysqlnd_result.c
ext/mysqlnd/mysqlnd_wireprotocol.c
ext/mysqlnd/mysqlnd_wireprotocol.h
ext/mysqlnd/php_mysqlnd.c

index e40de9fa66f378ca7899098281a3bd923294ee4f..bda568bd19bc5ce16eff26d029c7d58b8da458df 100644 (file)
@@ -28,6 +28,8 @@
 #include "mysqlnd_charset.h"
 #include "mysqlnd_debug.h"
 #include "mysqlnd_block_alloc.h"
+/* for php_get_current_user() */
+#include "ext/standard/basic_functions.h" 
 
 /* the server doesn't support 4byte utf8, but let's make it forward compatible */
 #define MYSQLND_MAX_ALLOWED_USER_LEN   256  /* 64 char * 4byte */
@@ -544,7 +546,7 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
 
 
        PACKET_INIT_ALLOCA(greet_packet, PROT_GREET_PACKET);
-       PACKET_INIT(auth_packet, PROT_AUTH_PACKET, php_mysql_packet_auth *);
+       PACKET_INIT(auth_packet, PROT_AUTH_PACKET, php_mysql_packet_auth *, FALSE);
        PACKET_INIT_ALLOCA(ok_packet, PROT_OK_PACKET);
 
        if (!conn) {
@@ -849,7 +851,7 @@ MYSQLND_METHOD(mysqlnd_conn, query)(MYSQLND *conn, const char *query, unsigned i
                                                                           FALSE TSRMLS_CC)) {
                DBG_RETURN(FAIL);
        }
-
+       CONN_SET_STATE(conn, CONN_QUERY_SENT);
        /*
          Here read the result set. We don't do it in simple_command because it need
          information from the ok packet. We will fetch it ourselves.
@@ -1338,6 +1340,7 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, set_state)(MYSQLND * const conn, enum mysql
 #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);
index b6d72021524f93bee169d91344085a68663497f7..ff81adabfe1e7cde0ca276f8acb69b2a9087ea48 100644 (file)
@@ -346,6 +346,9 @@ ZEND_BEGIN_MODULE_GLOBALS(mysqlnd)
        MYSQLND_DEBUG   *dbg;   /* The DBG object */
        long                    net_cmd_buffer_size;
        long                    net_read_buffer_size;
+#ifdef ZTS
+       THREAD_T                thread_id;
+#endif
 ZEND_END_MODULE_GLOBALS(mysqlnd)
 
 ZEND_EXTERN_MODULE_GLOBALS(mysqlnd);
index d2d2d3e72c0a763f58ce25ce91741aee58d0e34e..6a7f0cbdc250c6ea208b163a229f7c549bbb8918 100644 (file)
@@ -95,6 +95,12 @@ MYSQLND_METHOD(mysqlnd_debug, log)(MYSQLND_DEBUG * self,
                 line_buffer[6], level_buffer[7];
        MYSQLND_ZTS(self);
 
+#ifdef ZTS
+       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;
@@ -195,6 +201,12 @@ MYSQLND_METHOD(mysqlnd_debug, log_va)(MYSQLND_DEBUG *self,
                 line_buffer[6], level_buffer[7];
        MYSQLND_ZTS(self);
 
+#ifdef ZTS
+       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;
@@ -291,9 +303,15 @@ MYSQLND_METHOD(mysqlnd_debug, func_enter)(MYSQLND_DEBUG * self,
                                                                                  unsigned int line, const char * const file,
                                                                                  char * func_name, uint func_name_len)
 {
+       MYSQLND_ZTS(self);
        if ((self->flags & MYSQLND_DEBUG_DUMP_TRACE) == 0 || self->file_name == NULL) {
                return FALSE;
        }
+#ifdef ZTS
+       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;
        }
@@ -303,7 +321,6 @@ MYSQLND_METHOD(mysqlnd_debug, func_enter)(MYSQLND_DEBUG * self,
                 func_name == mysqlnd_ecalloc_name      || func_name == mysqlnd_pecalloc_name   ||
                 func_name == mysqlnd_erealloc_name || func_name == mysqlnd_perealloc_name      ||
                 func_name == mysqlnd_efree_name        || func_name == mysqlnd_pefree_name             || 
-                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 ||
@@ -332,10 +349,16 @@ MYSQLND_METHOD(mysqlnd_debug, func_leave)(MYSQLND_DEBUG * self, unsigned int lin
                                                                                  const char * const file)
 {
        char *func_name;
+       MYSQLND_ZTS(self);
 
        if ((self->flags & MYSQLND_DEBUG_DUMP_TRACE) == 0 || self->file_name == NULL) {
                return PASS;
        }
+#ifdef ZTS
+       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;
        }
@@ -644,6 +667,12 @@ void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)
 {
        void *ret;
        DBG_ENTER(mysqlnd_emalloc_name);
+#ifdef ZTS
+       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));
        ret = emalloc(size);
@@ -691,6 +720,11 @@ void * _mysqlnd_ecalloc(uint nmemb, size_t size MYSQLND_MEM_D)
 {
        void *ret;
        DBG_ENTER(mysqlnd_ecalloc_name);
+#ifdef ZTS
+       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));
 
@@ -739,6 +773,11 @@ void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
 {
        void *ret;
        DBG_ENTER(mysqlnd_erealloc_name);
+#ifdef ZTS
+       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));
@@ -788,6 +827,11 @@ 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 ZTS
+       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));
index 0d4804f50a709a687ec8cba6b8824a01e10678ad..135216a19e6d1a932129c03ab4ee6f2909e2da07 100644 (file)
@@ -40,32 +40,36 @@ void * mysqlnd_fetch_thread(void *arg)
        MYSQLND_RES * result = NULL;
        void ***tsrm_ls = conn->tsrm_ls;
 #ifndef MYSQLND_SILENT
-       printf("conn=%p tsrm_ls=%p\n", conn, conn->tsrm_ls);
+       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 /* && there is work */) {
+               while (conn->thread_killed == FALSE && !conn->current_result) {
 #ifndef MYSQLND_SILENT
-                       printf("Waiting for work in %s\n", __FUNCTION__);
+                       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 killed in %s\n", __FUNCTION__);
+                       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("Got work in %s\n", __FUNCTION__);
+               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 */
@@ -74,13 +78,13 @@ void * mysqlnd_fetch_thread(void *arg)
                CONN_SET_STATE(conn, CONN_READY);
                pthread_cond_signal(&conn->COND_work_done);
 #ifndef MYSQLND_SILENT
-               printf("Signaling work done in %s\n", __FUNCTION__);
+               printf("THREAD] Signaling work done in %s\n", __FUNCTION__);
 #endif
                pthread_mutex_unlock(&conn->LOCK_work);
        } while (1);
 
 #ifndef MYSQLND_SILENT
-       printf("Exiting worker thread in %s\n", __FUNCTION__);
+       printf("THREAD] Exiting worker thread in %s\n", __FUNCTION__);
 #endif
        return NULL;
 }
@@ -461,6 +465,8 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC
                        */
                        conn->error_info = rset_header.error_info;
                        ret = FAIL;
+                       /* Return back from CONN_QUERY_SENT */
+                       CONN_SET_STATE(conn, CONN_READY);
                        break;
                }
                conn->error_info.error_no = 0;
@@ -976,7 +982,8 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps
          by the resource destructor. mysqlnd_fetch_row_unbuffered() expects
          this to be not NULL.
        */
-       PACKET_INIT(result->row_packet, PROT_ROW_PACKET, php_mysql_packet_row *);
+       /* FALSE = non-persistent */
+       PACKET_INIT(result->row_packet, PROT_ROW_PACKET, php_mysql_packet_row *, FALSE);
        result->row_packet->field_count = result->field_count;
        result->row_packet->binary_protocol = ps;
        result->row_packet->fields_metadata = result->meta->fields;
@@ -1182,7 +1189,8 @@ mysqlnd_store_result_fetch_data(MYSQLND * const conn, MYSQLND_RES *result,
        set->qcache             = to_cache? mysqlnd_qcache_get_cache_reference(conn->qcache):NULL;
        set->references = 1;
 
-       PACKET_INIT(row_packet, PROT_ROW_PACKET, php_mysql_packet_row *);
+       /* non-persistent */
+       PACKET_INIT(row_packet, PROT_ROW_PACKET, php_mysql_packet_row *, FALSE);
        row_packet->field_count = meta->field_count;
        row_packet->binary_protocol = binary_protocol;
        row_packet->fields_metadata = meta->fields;
@@ -1315,6 +1323,7 @@ mysqlnd_fetch_row_async_buffered(MYSQLND_RES *result, void *param, unsigned int
        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)) {
@@ -1439,14 +1448,14 @@ mysqlnd_background_store_result_fetch_data(MYSQLND_RES *result TSRMLS_DC)
 
        free_rows = next_extend;
 
-       PACKET_INIT(row_packet, PROT_ROW_PACKET, php_mysql_packet_row *);
+       /* persistent */
+       PACKET_INIT(row_packet, PROT_ROW_PACKET, php_mysql_packet_row *, TRUE);
        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->skip_extraction = TRUE; /* let php_mysqlnd_rowp_read() not allocate row_packet->fields, we will do it */
+       row_packet->persistent_alloc = TRUE;
 
        while (FAIL != (ret = PACKET_READ(row_packet, conn)) && !row_packet->eof) {
                tsrm_mutex_lock(set->LOCK);
@@ -1560,7 +1569,7 @@ MYSQLND_METHOD(mysqlnd_res, background_store_result)(MYSQLND_RES * result, MYSQL
        return (result->m.store_result(result, conn, ps TSRMLS_CC));
 #else
        enum_func_status ret;
-       zend_bool to_cache = FALSE;
+       zend_bool to_cache = TRUE;
 
        DBG_ENTER("mysqlnd_res::background_store_result");
        DBG_INF_FMT("conn=%d ps_protocol=%d", conn->thread_id, ps);
@@ -1585,11 +1594,26 @@ MYSQLND_METHOD(mysqlnd_res, background_store_result)(MYSQLND_RES * result, MYSQL
                                                                php_mysqlnd_rowp_read_text_protocol;
 
        CONN_SET_STATE(conn, CONN_FETCHING_DATA);
-       result->bg_stored_data->decode_in_foreground = FALSE;
+       /*
+         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
index 11a2719ea86c4176f5d931e7b67cefefa29d91b7..40c6d74442d1a89d456de8ecdfd427ecf5b0c9c1 100644 (file)
@@ -1685,7 +1685,7 @@ void php_mysqlnd_rowp_free_mem(void *_packet, zend_bool alloca TSRMLS_DC)
                not free the array. As it is passed to us, we should not clean it ourselves.
        */
        if (!alloca) {
-               mnd_efree(p);
+               mnd_pefree(p, p->header.persistent);
        }
 }
 /* }}} */
@@ -1723,7 +1723,7 @@ void php_mysqlnd_stats_free_mem(void *_packet, zend_bool alloca TSRMLS_DC)
                p->message = NULL;
        }
        if (!alloca) {
-               mnd_efree(p);
+               mnd_pefree(p, p->header.persistent);
        }
 }
 /* }}} */
@@ -1807,7 +1807,7 @@ void php_mysqlnd_prepare_free_mem(void *_packet, zend_bool alloca TSRMLS_DC)
 {
        php_mysql_packet_prepare_response *p= (php_mysql_packet_prepare_response *) _packet;
        if (!alloca) {
-               mnd_efree(p);
+               mnd_pefree(p, p->header.persistent);
        }
 }
 /* }}} */
@@ -1866,7 +1866,7 @@ static
 void php_mysqlnd_chg_user_free_mem(void *_packet, zend_bool alloca TSRMLS_DC)
 {
        if (!alloca) {
-               mnd_efree(_packet);
+               mnd_pefree(_packet, ((php_mysql_packet_chg_user_resp *)_packet)->header.persistent);
        }
 }
 /* }}} */
index 7d3fe83ab30e92975f487cef8e0600384c2d2899..ca2a4640e3c541915ee08ec9728b8f408a7b7278 100644 (file)
@@ -37,10 +37,11 @@ extern char * mysqlnd_read_body_name;
 
 
 /* Packet handling */
-#define PACKET_INIT(packet, enum_type, c_type)  \
+#define PACKET_INIT(packet, enum_type, c_type, pers)  \
        { \
-               packet = (c_type) ecalloc(1, packet_methods[enum_type].struct_size); \
-               ((c_type) (packet))->header.m = &packet_methods[enum_type]; \
+               packet = (c_type) pecalloc(1, packet_methods[(enum_type)].struct_size, (pers)); \
+               ((c_type) (packet))->header.m = &packet_methods[(enum_type)]; \
+               ((c_type) (packet))->header.persistent = (pers); \
        }
 #define PACKET_WRITE(packet, conn)     ((packet)->header.m->write_to_net((packet), (conn) TSRMLS_CC))
 #define PACKET_READ(packet, conn)      ((packet)->header.m->read_from_net((packet), (conn) TSRMLS_CC))
@@ -126,8 +127,9 @@ extern mysqlnd_packet_methods packet_methods[];
 
 typedef struct st_mysqlnd_packet_header {
        size_t          size;
-       zend_uchar      packet_no;
        mysqlnd_packet_methods *m;
+       zend_uchar      packet_no;
+       zend_bool       persistent;
 } mysqlnd_packet_header;
 
 /* Server greets the client */
index bb7d9008a4f61a8726aa0d9701a0dacf4e1bcf1f..a4b7b4f30d8b473a624830f82c7048794bc9039f 100644 (file)
@@ -189,7 +189,8 @@ static PHP_RINIT_FUNCTION(mysqlnd)
                        return FAILURE;
                }
                dbg->m->set_mode(dbg, MYSQLND_G(debug));
-               MYSQLND_G(dbg) = dbg;   
+               MYSQLND_G(dbg) = dbg;
+               MYSQLND_G(thread_id) = tsrm_thread_id();
        }
        return SUCCESS;
 }