PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - mysqlnd - mysqlnd_palloc.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 154
Code covered: 64.9 % Executed lines: 100
Legend: not executed executed

       1                 : /*
       2                 :   +----------------------------------------------------------------------+
       3                 :   | PHP Version 6                                                        |
       4                 :   +----------------------------------------------------------------------+
       5                 :   | Copyright (c) 2006-2009 The PHP Group                                |
       6                 :   +----------------------------------------------------------------------+
       7                 :   | This source file is subject to version 3.01 of the PHP license,      |
       8                 :   | that is bundled with this package in the file LICENSE, and is        |
       9                 :   | available through the world-wide-web at the following url:           |
      10                 :   | http://www.php.net/license/3_01.txt                                  |
      11                 :   | If you did not receive a copy of the PHP license and are unable to   |
      12                 :   | obtain it through the world-wide-web, please send a note to          |
      13                 :   | license@php.net so we can mail you a copy immediately.               |
      14                 :   +----------------------------------------------------------------------+
      15                 :   | Authors: Georg Richter <georg@mysql.com>                             |
      16                 :   |          Andrey Hristov <andrey@mysql.com>                           |
      17                 :   |          Ulf Wendel <uwendel@mysql.com>                              |
      18                 :   +----------------------------------------------------------------------+
      19                 : */
      20                 : 
      21                 : /* $Id: mysqlnd_palloc.c 289028 2009-09-30 23:13:43Z andrey $ */
      22                 : #include "php.h"
      23                 : #include "mysqlnd.h"
      24                 : #include "mysqlnd_priv.h"
      25                 : #include "mysqlnd_palloc.h"
      26                 : #include "mysqlnd_debug.h"
      27                 : 
      28                 : /* Used in mysqlnd_debug.c */
      29                 : char * mysqlnd_palloc_zval_ptr_dtor_name = "mysqlnd_palloc_zval_ptr_dtor";
      30                 : char * mysqlnd_palloc_get_zval_name = "mysqlnd_palloc_get_zval";
      31                 : 
      32                 : 
      33                 : #ifdef ZTS
      34                 : #define LOCK_PCACHE(cache)  tsrm_mutex_lock((cache)->LOCK_access)
      35                 : #define UNLOCK_PCACHE(cache) tsrm_mutex_unlock((cache)->LOCK_access)
      36                 : #else
      37                 : #define LOCK_PCACHE(cache)
      38                 : #define UNLOCK_PCACHE(cache)
      39                 : #endif
      40                 : 
      41                 : 
      42                 : /* {{{ _mysqlnd_palloc_init_cache */
      43                 : PHPAPI MYSQLND_ZVAL_PCACHE* _mysqlnd_palloc_init_cache(unsigned int cache_size TSRMLS_DC)
      44           52899 : {
      45           52899 :         MYSQLND_ZVAL_PCACHE *ret = mnd_calloc(1, sizeof(MYSQLND_ZVAL_PCACHE));
      46                 :         unsigned int i;
      47                 : 
      48           52899 :         DBG_ENTER("_mysqlnd_palloc_init_cache");
      49           52899 :         DBG_INF_FMT("cache=%p size=%u", ret, cache_size);
      50                 : 
      51                 : #ifdef ZTS
      52                 :         ret->LOCK_access = tsrm_mutex_alloc();
      53                 : #endif
      54                 : 
      55           52899 :         ret->max_items = cache_size;
      56           52899 :         ret->free_items = cache_size;
      57           52899 :         ret->references = 1;
      58                 : 
      59                 :         /* 1. First initialize the free list part of the structure */
      60                 :         /* One more for empty position of last_added - always 0x0, bounds checking */
      61           52899 :         ret->free_list.ptr_line = mnd_calloc(ret->max_items + 1, sizeof(mysqlnd_zval *));
      62           52899 :         ret->free_list.last_added = ret->free_list.ptr_line + ret->max_items;
      63           52899 :         ret->free_list.canary1 = (void*)0xBEEF;
      64           52899 :         ret->free_list.canary2 = (void*)0xAFFE;
      65                 : 
      66                 :         /* 3. Allocate and initialize our zvals and initialize the free list */
      67           52899 :         ret->block = mnd_calloc(ret->max_items, sizeof(mysqlnd_zval));
      68           52899 :         ret->last_in_block = &(ret->block[ret->max_items]);
      69       105850899 :         for (i = 0; i < ret->max_items; i++) {
      70                 :                 /* 1. Initialize */
      71       105798000 :                 INIT_PZVAL(&(ret->block[i].zv));
      72       105798000 :                 ZVAL_NULL(&(ret->block[i].zv));
      73                 :                 /* Assure it will never be freed before MSHUTDOWN */
      74       105798000 :                 Z_ADDREF_P(&(ret->block[i].zv));
      75                 :                 /* 2. Add to the free list  */
      76       105798000 :                 *(--ret->free_list.last_added) = &(ret->block[i]);
      77                 :         }
      78                 : 
      79           52899 :         DBG_RETURN(ret);
      80                 : }
      81                 : /* }}} */
      82                 : 
      83                 : 
      84                 : /* {{{ mysqlnd_palloc_get_cache_reference */
      85                 : MYSQLND_ZVAL_PCACHE* mysqlnd_palloc_get_cache_reference(MYSQLND_ZVAL_PCACHE * const cache)
      86           59686 : {
      87           59686 :         if (cache) {
      88                 :                 LOCK_PCACHE(cache);
      89           59686 :                 cache->references++;
      90                 :                 UNLOCK_PCACHE(cache);
      91                 :         }
      92           59686 :         return cache;
      93                 : }
      94                 : /* }}} */
      95                 : 
      96                 : 
      97                 : /* {{{ mysqlnd_palloc_free_cache */
      98                 : /*
      99                 :   As this call will happen on MSHUTDOWN(), then we don't need to copy the zvals with
     100                 :   copy_ctor but scrap what they point to with zval_dtor() and then just free our
     101                 :   pre-allocated block. Precondition is that we ZVAL_NULL() the zvals when we put them
     102                 :   to the free list after usage. We ZVAL_NULL() them when we allocate them in the 
     103                 :   constructor of the cache.
     104                 : */
     105                 : void _mysqlnd_palloc_free_cache(MYSQLND_ZVAL_PCACHE *cache TSRMLS_DC)
     106           52995 : {
     107           52995 :         DBG_ENTER("_mysqlnd_palloc_free_cache");
     108           52995 :         DBG_INF_FMT("cache=%p", cache);
     109                 : 
     110                 : #ifdef ZTS
     111                 :         tsrm_mutex_free(cache->LOCK_access);
     112                 : #endif
     113                 : 
     114                 :         /* Data in pointed by 'block' was cleaned in RSHUTDOWN */
     115           52995 :         mnd_free(cache->block);
     116           52995 :         mnd_free(cache->free_list.ptr_line);
     117           52995 :         mnd_free(cache);
     118                 : 
     119                 :         DBG_VOID_RETURN;
     120                 : }
     121                 : /* }}} */
     122                 : 
     123                 : 
     124                 : /* {{{ _mysqlnd_palloc_init_thd_cache */
     125                 : PHPAPI MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_init_thd_cache(MYSQLND_ZVAL_PCACHE * const cache TSRMLS_DC)
     126           52857 : {
     127           52857 :         MYSQLND_THD_ZVAL_PCACHE *ret = mnd_calloc(1, sizeof(MYSQLND_THD_ZVAL_PCACHE));
     128           52857 :         DBG_ENTER("_mysqlnd_palloc_init_thd_cache");
     129           52857 :         DBG_INF_FMT("ret = %p", ret);
     130                 :         
     131                 : #if PHP_DEBUG
     132                 :         LOCK_PCACHE(cache);
     133                 :         if (cache->references == 1 && cache->max_items != cache->free_items) {
     134                 :                 UNLOCK_PCACHE(cache);
     135                 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No references to mysqlnd's zval cache but max_items != free_items");
     136                 :         } else {
     137                 :                 UNLOCK_PCACHE(cache);
     138                 :         }
     139                 : #endif
     140           52857 :         ret->parent = mysqlnd_palloc_get_cache_reference(cache);
     141                 : 
     142                 : #ifdef ZTS
     143                 :         ret->thread_id = tsrm_thread_id();
     144                 : #endif
     145                 : 
     146           52857 :         ret->references = 1;
     147                 : 
     148                 :         /* 1. Initialize the GC list */
     149           52857 :         ret->gc_list.ptr_line = mnd_calloc(cache->max_items, sizeof(mysqlnd_zval *));
     150                 :         /* Backward and forward looping is possible */
     151           52857 :         ret->gc_list.last_added = ret->gc_list.ptr_line;
     152           52857 :         ret->gc_list.canary1 = (void*)0xCAFE;
     153           52857 :         ret->gc_list.canary2 = (void*)0x190280;
     154                 : 
     155           52857 :         DBG_INF_FMT("ptr_line=%p last_added=%p", ret->gc_list.ptr_line, ret->gc_list.last_added);
     156           52857 :         DBG_RETURN(ret);
     157                 : }
     158                 : /* }}} */
     159                 : 
     160                 : 
     161                 : /* {{{ _mysqlnd_palloc_get_thd_cache_reference */
     162                 : MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE * const cache TSRMLS_DC)
     163            6829 : {
     164            6829 :         DBG_ENTER("_mysqlnd_palloc_get_thd_cache_reference");
     165            6829 :         if (cache) {
     166            6829 :                 ++cache->references;
     167            6829 :                 DBG_INF_FMT("cache=%p new_refc=%d gc_list.canary1=%p gc_list.canary2=%p",
     168                 :                                         cache, cache->references, cache->gc_list.canary1, cache->gc_list.canary2);
     169            6829 :                 mysqlnd_palloc_get_cache_reference(cache->parent);
     170                 :         }
     171            6829 :         DBG_RETURN(cache);
     172                 : }
     173                 : /* }}} */
     174                 : 
     175                 : 
     176                 : /* {{{ mysqlnd_palloc_free_cache */
     177                 : /*
     178                 :   As this call will happen on MSHUTDOWN(), then we don't need to copy the zvals with
     179                 :   copy_ctor but scrap what they point to with zval_dtor() and then just free our
     180                 :   pre-allocated block. Precondition is that we ZVAL_NULL() the zvals when we put them
     181                 :   to the free list after usage. We ZVAL_NULL() them when we allocate them in the 
     182                 :   constructor of the cache.
     183                 : */
     184                 : static
     185                 : void mysqlnd_palloc_free_thd_cache(MYSQLND_THD_ZVAL_PCACHE *thd_cache TSRMLS_DC)
     186           52952 : {
     187                 :         MYSQLND_ZVAL_PCACHE *global_cache;
     188                 :         mysqlnd_zval **p;
     189                 : 
     190           52952 :         DBG_ENTER("mysqlnd_palloc_free_thd_cache");
     191           52952 :         DBG_INF_FMT("thd_cache=%p", thd_cache);
     192                 : 
     193           52952 :         if ((global_cache = thd_cache->parent)) {
     194                 :                 /*
     195                 :                   Keep in mind that for pthreads pthread_equal() should be used to be
     196                 :                   fully standard compliant. However, the PHP code all-around, incl. the
     197                 :                   the Zend MM uses direct comparison.
     198                 :                 */
     199           52952 :                 p = thd_cache->gc_list.ptr_line;
     200          105904 :                 while (p < thd_cache->gc_list.last_added) {
     201               0 :                         zval_dtor(&(*p)->zv);
     202               0 :                         p++;
     203                 :                 }
     204                 : 
     205           52952 :                 p = thd_cache->gc_list.ptr_line;
     206                 : 
     207                 :                 LOCK_PCACHE(global_cache);
     208          105904 :                 while (p < thd_cache->gc_list.last_added) {
     209               0 :                         (*p)->point_type = MYSQLND_POINTS_FREE;
     210               0 :                         *(--global_cache->free_list.last_added) = *p;
     211               0 :                         ++global_cache->free_items;
     212                 : #ifdef ZTS
     213                 :                         memset(&((*p)->thread_id), 0, sizeof(THREAD_T));
     214                 : #endif
     215               0 :                         p++;
     216                 :                 }
     217                 :                 UNLOCK_PCACHE(global_cache);
     218                 : 
     219                 :         }
     220           52952 :         mnd_free(thd_cache->gc_list.ptr_line);
     221           52952 :         mnd_free(thd_cache);
     222                 : 
     223                 :         DBG_VOID_RETURN;
     224                 : }
     225                 : /* }}} */
     226                 : 
     227                 : 
     228                 : /* {{{ _mysqlnd_palloc_free_thd_cache_reference */
     229                 : PHPAPI void _mysqlnd_palloc_free_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE **cache TSRMLS_DC)
     230           59798 : {
     231           59798 :         DBG_ENTER("_mysqlnd_palloc_free_thd_cache_reference");
     232           59798 :         if (*cache) {
     233           59784 :                 --(*cache)->parent->references;
     234           59784 :                 DBG_INF_FMT("cache=%p references_left=%d canary1=%p canary2=%p",
     235                 :                                         *cache, (*cache)->references, (*cache)->gc_list.canary1, (*cache)->gc_list.canary2);
     236                 : 
     237           59784 :                 DBG_INF_FMT("gc_list.ptr_line=%p gc_list.last_added=%p", (*cache)->gc_list.ptr_line, (*cache)->gc_list.last_added);
     238                 : 
     239           59784 :                 if (--(*cache)->references == 0) {
     240           52952 :                         mysqlnd_palloc_free_thd_cache(*cache TSRMLS_CC);
     241                 :                 }
     242           59784 :                 *cache = NULL;
     243                 :         }
     244                 :         DBG_VOID_RETURN;
     245                 : }
     246                 : /* }}} */
     247                 : 
     248                 : 
     249                 : /*
     250                 :   The cache line is a big contiguous array of zval pointers.
     251                 :   Because the CPU cache will cache starting from an address, and not
     252                 :   before it, then we have to organize our structure according to this.
     253                 :   Thus, if 'last_added' is valid pointer (not NULL) then last_added is
     254                 :   increased. When zval is cached, if there is room, last_added is decreased
     255                 :   and then the zval pointer will be assigned to it. This means that some
     256                 :   positions may become hot points and stay in the cache.
     257                 :   Imagine we have 5 pointers in a line
     258                 :   1. last_added = list_item->ptr_line + cache->max_items;
     259                 :   2. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL
     260                 :   3. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL
     261                 :   4. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL
     262                 :         0x0
     263                 :         0x0
     264                 :         0x0
     265                 :         0x0
     266                 :         0x0
     267                 :         ---
     268                 :         empty_position, always 0x0 <-- last_added
     269                 : 
     270                 :   5. free_zval -> if (free_items++ != max_items) {// we can add more
     271                 :                                     *(--last_added) = zval_ptr;
     272                 :                                  }
     273                 :         (memory addresses increase downwards)
     274                 :         0x0
     275                 :         0x0
     276                 :         0x0
     277                 :         0x0 
     278                 :         0xA <-- last_added
     279                 :         ---
     280                 :         0x0
     281                 : 
     282                 :   6. free_zval -> if (free_items++ != max_items) {// we can add more
     283                 :                                    *(--last_added) = zval_ptr;
     284                 :                                  }
     285                 :         0x0
     286                 :         0x0
     287                 :         0x0
     288                 :         0xB <-- last_added
     289                 :         0xA 
     290                 :         ---
     291                 :         0x0
     292                 : 
     293                 :   7. free_zval -> if (free_items++ != max_items) {// we can add more
     294                 :                                    *(--last_added) = zval_ptr;
     295                 :                                  }
     296                 :         0x0
     297                 :         0x0
     298                 :         0xC <-- last_added
     299                 :         0xB
     300                 :         0xA
     301                 :         ---
     302                 :         0x0
     303                 : 
     304                 :   8. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL;
     305                 :         0x0
     306                 :         0x0
     307                 :         0x0
     308                 :         0xB <-- last_added
     309                 :         0xA
     310                 :         ---
     311                 :         0x0
     312                 : 
     313                 :   9. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL;
     314                 :         0x0
     315                 :         0x0
     316                 :         0x0
     317                 :         0x0
     318                 :         0xA <-- last_added
     319                 :         ---
     320                 :         0x0
     321                 : 
     322                 :   10. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL;
     323                 :         0x0
     324                 :         0x0
     325                 :         0x0
     326                 :         0x0
     327                 :         0x0
     328                 :         ---
     329                 :         0x0 <-- last_added
     330                 : 
     331                 : */
     332                 : 
     333                 : 
     334                 : /* {{{ mysqlnd_palloc_get_zval */
     335                 : void *mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const thd_cache, zend_bool *allocated TSRMLS_DC)
     336               0 : {
     337               0 :         void *ret = NULL;
     338                 : 
     339               0 :         DBG_ENTER("mysqlnd_palloc_get_zval");
     340               0 :         if (thd_cache) {
     341               0 :                 DBG_INF_FMT("cache=%p *last_added=%p free_items=%d",
     342                 :                                         thd_cache, thd_cache->parent->free_list.last_added,
     343                 :                                         thd_cache->parent->free_items);
     344               0 :                 DBG_INF_FMT("gc_list.ptr_line=%p gc_list.last_added=%p gc_list.canary1=%p gc_list.canary2=%p",
     345                 :                                         thd_cache->gc_list.ptr_line, thd_cache->gc_list.last_added,
     346                 :                                         thd_cache->gc_list.canary1, thd_cache->gc_list.canary2);
     347                 :         }
     348                 : 
     349               0 :         if (thd_cache) {
     350               0 :                 MYSQLND_ZVAL_PCACHE *cache = thd_cache->parent;
     351                 :                 LOCK_PCACHE(cache);
     352                 : 
     353               0 :                 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",
     354                 :                                         cache->free_items, cache->free_list.ptr_line, cache->free_list.last_added,
     355                 :                                         *cache->free_list.last_added,
     356                 :                                         cache->free_list.canary1, cache->free_list.canary2);
     357                 : 
     358                 :                 /* We have max_items + 1 allocated block for free_list, thus we know if we */
     359               0 :                 if ((ret = *cache->free_list.last_added)) {
     360               0 :                         *cache->free_list.last_added++ = NULL;
     361               0 :                         *allocated = FALSE;
     362                 : #ifdef ZTS
     363                 :                         ((mysqlnd_zval *) ret)->thread_id = thd_cache->thread_id;
     364                 : #endif
     365               0 :                         --cache->free_items;
     366               0 :                         ++cache->get_hits;
     367                 :                 } else {
     368               0 :                         ++cache->get_misses;
     369                 :                 }
     370                 :                 UNLOCK_PCACHE(cache);
     371                 :         }
     372               0 :         if (!ret) {
     373                 :                 /*
     374                 :                   We allocate a bit more. The user of this function will use it, but at
     375                 :                   end it will use only the zval part. Because the zval part is first then
     376                 :                   when freeing the zval part the whole allocated block will be cleaned, not
     377                 :                   only the zval part (by the Engine when destructing the zval).
     378                 :                 */
     379               0 :                 ALLOC_ZVAL(ret);
     380               0 :                 INIT_PZVAL((zval *) ret);
     381               0 :                 *allocated = TRUE;
     382                 :         } else {
     383                 :                 /* This will set the refcount to 1, increase it, to keep the variable */
     384               0 :                 INIT_PZVAL(&((mysqlnd_zval *) ret)->zv);
     385               0 :                 Z_ADDREF_P(&(((mysqlnd_zval *)ret)->zv));
     386                 :         }
     387                 : 
     388               0 :         DBG_INF_FMT("allocated=%d ret=%p", *allocated, ret);
     389               0 :         DBG_RETURN(ret);
     390                 : }
     391                 : /* }}} */
     392                 : 
     393                 : 
     394                 : /* {{{ mysqlnd_palloc_zval_ptr_dtor */
     395                 : void mysqlnd_palloc_zval_ptr_dtor(zval **zv, MYSQLND_THD_ZVAL_PCACHE * const thd_cache,
     396                 :                                                                   enum_mysqlnd_res_type type, zend_bool *copy_ctor_called TSRMLS_DC)
     397           72851 : {
     398                 :         MYSQLND_ZVAL_PCACHE *cache;
     399           72851 :         DBG_ENTER("mysqlnd_palloc_zval_ptr_dtor");
     400           72851 :         if (thd_cache) {
     401           72851 :                 DBG_INF_FMT("cache=%p parent_block=%p last_in_block=%p *zv=%p refc=%d type=%d ",
     402                 :                                         thd_cache,
     403                 :                                         thd_cache->parent->block,
     404                 :                                         thd_cache->parent->last_in_block,
     405                 :                                         *zv, Z_REFCOUNT_PP(zv), type);
     406           72851 :                 DBG_INF_FMT("gc_list.ptr_line=%p gc_list.last_added=%p gc_list.canary1=%p gc_list.canary2=%p",
     407                 :                                         thd_cache->gc_list.ptr_line, thd_cache->gc_list.last_added, thd_cache->gc_list.canary1, thd_cache->gc_list.canary2);
     408                 :         }
     409           72851 :         *copy_ctor_called = FALSE;
     410                 :         /* Check whether cache is used and the zval is from the cache */
     411           72851 :         if (!thd_cache || !(cache = thd_cache->parent) || ((char *)*zv < (char *)thd_cache->parent->block ||
     412                 :                                                                                                            (char *)*zv > (char *)thd_cache->parent->last_in_block)) {
     413                 :                 /*
     414                 :                   This zval is not from the cache block.
     415                 :                   Thus the refcount is -1 than of a zval from the cache,
     416                 :                   because the zvals from the cache are owned by it.
     417                 :                 */
     418           72851 :                 if (type == MYSQLND_RES_PS_BUF || type == MYSQLND_RES_PS_UNBUF) {
     419                 :                         ; /* do nothing, zval_ptr_dtor will do the job*/
     420           44922 :                 } else if (Z_REFCOUNT_PP(zv) > 1) {
     421                 :                         /*
     422                 :                           Not a prepared statement, then we have to
     423                 :                           call copy_ctor and then zval_ptr_dtor()
     424                 : 
     425                 :                           In Unicode mode the destruction  of the zvals should not call
     426                 :                           zval_copy_ctor() because then we will leak.
     427                 :                           I suppose we can use UG(unicode) in mysqlnd.c when freeing a result set
     428                 :                           to check if we need to call copy_ctor().
     429                 : 
     430                 :                           If the type is IS_UNICODE, which can happen with PHP6, then we don't
     431                 :                           need to copy_ctor, as the data doesn't point to our internal buffers.
     432                 :                           If it's string (in PHP5 always) and in PHP6 if data is binary, then
     433                 :                           it still points to internal buffers and has to be copied.
     434                 :                         */
     435            4420 :                         if (Z_TYPE_PP(zv) == IS_STRING) {
     436            3739 :                                 zval_copy_ctor(*zv);
     437                 :                         }
     438            4420 :                         *copy_ctor_called = TRUE;
     439                 :                 } else {
     440           40502 :                         if (Z_TYPE_PP(zv) == IS_STRING) {
     441           40453 :                                 ZVAL_NULL(*zv);
     442                 :                         }
     443                 :                 }
     444           72851 :                 zval_ptr_dtor(zv);
     445           72851 :                 DBG_VOID_RETURN;
     446                 :         }
     447                 : 
     448                 :         /* The zval is from our cache */
     449                 :         /* refcount is always > 1, because we call Z_ADDREF_P(). Thus test refcount > 2 */
     450               0 :         if (Z_REFCOUNT_PP(zv) > 2) {
     451                 :                 /*
     452                 :                   Because the zval is first element in mysqlnd_zval structure, then we can
     453                 :                   do upcasting from zval to mysqlnd_zval here. Because we know that this
     454                 :                   zval is part of our pre-allocated block.
     455                 : 
     456                 :                   Now check whether this zval points to ZE allocated memory or to our
     457                 :                   buffers. If it points to the internal buffers, call copy_ctor()
     458                 :                   which will do estrndup for strings. And nothing for null, int, double.
     459                 : 
     460                 :                   This branch will be skipped for PS, because there is no need to copy
     461                 :                   what is pointed by them, as they don't point to the internal buffers.
     462                 :                 */
     463               0 :                 if (((mysqlnd_zval *)*zv)->point_type == MYSQLND_POINTS_INT_BUFFER) {
     464               0 :                         zval_copy_ctor(*zv);
     465               0 :                         *copy_ctor_called = TRUE;
     466               0 :                         ((mysqlnd_zval *)*zv)->point_type = MYSQLND_POINTS_EXT_BUFFER;
     467                 :                 }
     468                 :                 /*
     469                 :                   This will decrease the counter of the user-level (mysqlnd). When the engine
     470                 :                   layer (the script) has finished working this this zval, when the variable is
     471                 :                   no more used, out of scope whatever, then it will try zval_ptr_dtor() but
     472                 :                   and the refcount will reach 1 and the engine won't try to destruct the
     473                 :                   memory allocated by us.
     474                 :                 */
     475               0 :                 zval_ptr_dtor(zv);
     476                 : 
     477                 :                 /*
     478                 :                   Unfortunately, we can't return this variable to the free_list
     479                 :                   because it's still used. And this cleaning up will happen at request
     480                 :                   shutdown :(.
     481                 :                 */
     482                 :                 LOCK_PCACHE(cache);
     483               0 :                 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",
     484                 :                                         thd_cache->gc_list.ptr_line,
     485                 :                                         thd_cache->gc_list.last_added,
     486                 :                                         *thd_cache->gc_list.last_added,
     487                 :                                         cache->free_list.canary1, cache->free_list.canary2);
     488               0 :                 if ((thd_cache->gc_list.last_added - thd_cache->gc_list.ptr_line) > (int) cache->max_items) {
     489               0 :                         DBG_ERR("Buffer overflow follows");
     490               0 :                         DBG_ERR_FMT("parent->max_items=%d parent->free_items=%d diff=%d",
     491                 :                                                 cache->max_items, cache->free_items,
     492                 :                                                 thd_cache->gc_list.last_added - thd_cache->gc_list.ptr_line);
     493                 : 
     494               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "We will get buffer overflow");
     495                 :                 }
     496               0 :                 ++cache->put_misses;
     497               0 :                 *(thd_cache->gc_list.last_added++) = (mysqlnd_zval *)*zv;
     498                 :                 UNLOCK_PCACHE(cache);
     499                 :         } else {
     500               0 :                 DBG_INF("No user reference");
     501                 :                 /* No user reference */
     502               0 :                 if (((mysqlnd_zval *)*zv)->point_type == MYSQLND_POINTS_EXT_BUFFER) {
     503               0 :                         DBG_INF("Points to external buffer. Calling zval_dtor");
     504                 :                         /*
     505                 :                           PS are here
     506                 :                           Unicode mode goes also here if the column is not binary but a text
     507                 :                         */
     508               0 :                         zval_dtor(*zv);
     509                 :                 }
     510                 :                 LOCK_PCACHE(cache);
     511               0 :                 ++cache->put_hits;
     512               0 :                 ++cache->free_items;
     513               0 :                 ((mysqlnd_zval *)*zv)->point_type = MYSQLND_POINTS_FREE;
     514               0 :                 Z_DELREF_PP(zv);        /* Make it 1 */
     515               0 :                 ZVAL_NULL(*zv);
     516                 : #ifdef ZTS
     517                 :                 memset(&((mysqlnd_zval *)*zv)->thread_id, 0, sizeof(THREAD_T));
     518                 : #endif
     519               0 :                 *(--cache->free_list.last_added) = (mysqlnd_zval *)*zv;
     520                 : 
     521                 :                 UNLOCK_PCACHE(cache);
     522                 :         }
     523               0 :         DBG_VOID_RETURN;
     524                 : }
     525                 : /* }}} */
     526                 : 
     527                 : 
     528                 : /* {{{ _mysqlnd_palloc_rinit */
     529                 : PHPAPI MYSQLND_THD_ZVAL_PCACHE * _mysqlnd_palloc_rinit(MYSQLND_ZVAL_PCACHE * cache TSRMLS_DC)
     530           52857 : {
     531           52857 :         return mysqlnd_palloc_init_thd_cache(cache);
     532                 : }
     533                 : /* }}} */
     534                 : 
     535                 : 
     536                 : /* {{{ _mysqlnd_palloc_rshutdown */
     537                 : PHPAPI void _mysqlnd_palloc_rshutdown(MYSQLND_THD_ZVAL_PCACHE * thd_cache TSRMLS_DC)
     538           52953 : {
     539           52953 :         DBG_ENTER("_mysqlnd_palloc_rshutdown");
     540           52953 :         DBG_INF_FMT("cache=%p", thd_cache);
     541           52953 :         mysqlnd_palloc_free_thd_cache_reference(&thd_cache);
     542                 :         DBG_VOID_RETURN;
     543                 : }
     544                 : /* }}} */
     545                 : 
     546                 : 
     547                 : /* {{{ mysqlnd_palloc_rshutdown */
     548                 : PHPAPI void mysqlnd_palloc_stats(const MYSQLND_ZVAL_PCACHE * const cache, zval *return_value)
     549             139 : {
     550             139 :         if (cache) {
     551                 : #if PHP_MAJOR_VERSION >= 6
     552                 :                 UChar *ustr;
     553                 :                 int ulen;
     554                 :                         
     555                 :                 TSRMLS_FETCH();
     556                 : #endif
     557                 : 
     558                 :                 LOCK_PCACHE(cache);
     559             139 :                 array_init(return_value);
     560                 : #if PHP_MAJOR_VERSION >= 6
     561                 :                 zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "put_hits", sizeof("put_hits") TSRMLS_CC);
     562                 :                 add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
     563                 :                 efree(ustr);
     564                 :                 zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "put_misses", sizeof("put_misses") TSRMLS_CC);
     565                 :                 add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
     566                 :                 efree(ustr);
     567                 :                 zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "get_hits", sizeof("get_hits") TSRMLS_CC);
     568                 :                 add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
     569                 :                 efree(ustr);
     570                 :                 zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "get_misses", sizeof("get_misses") TSRMLS_CC);
     571                 :                 add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
     572                 :                 efree(ustr);
     573                 :                 zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "size", sizeof("size") TSRMLS_CC);
     574                 :                 add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
     575                 :                 efree(ustr);
     576                 :                 zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "free_items", sizeof("free_items") TSRMLS_CC);
     577                 :                 add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
     578                 :                 efree(ustr);
     579                 :                 zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "references", sizeof("references") TSRMLS_CC);
     580                 :                 add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits);
     581                 :                 efree(ustr);
     582                 : #else
     583             139 :                 add_assoc_long_ex(return_value, "put_hits",           sizeof("put_hits"),           cache->put_hits);
     584             139 :                 add_assoc_long_ex(return_value, "put_misses", sizeof("put_misses"), cache->put_misses);
     585             139 :                 add_assoc_long_ex(return_value, "get_hits",           sizeof("get_hits"),           cache->get_hits);
     586             139 :                 add_assoc_long_ex(return_value, "get_misses", sizeof("get_misses"), cache->get_misses);
     587             139 :                 add_assoc_long_ex(return_value, "size",                       sizeof("size"),                       cache->max_items);
     588             139 :                 add_assoc_long_ex(return_value, "free_items", sizeof("free_items"), cache->free_items);
     589             139 :                 add_assoc_long_ex(return_value, "references", sizeof("references"), cache->references);
     590                 : #endif
     591                 :                 UNLOCK_PCACHE(cache);
     592                 :         } else {
     593               0 :                 ZVAL_NULL(return_value);
     594                 :         }
     595             139 : }
     596                 : /* }}} */
     597                 : 
     598                 : /*
     599                 :  * Local variables:
     600                 :  * tab-width: 4
     601                 :  * c-basic-offset: 4
     602                 :  * End:
     603                 :  * vim600: noet sw=4 ts=4 fdm=marker
     604                 :  * vim<600: noet sw=4 ts=4
     605                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:03 +0000 (3 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.