LTP GCOV extension - code coverage report
Current view: directory - ext/http - http_persistent_handle_api.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 135
Code covered: 71.9 % Executed lines: 97
Legend: not executed executed

       1                 : /*
       2                 :     +--------------------------------------------------------------------+
       3                 :     | PECL :: http                                                       |
       4                 :     +--------------------------------------------------------------------+
       5                 :     | Redistribution and use in source and binary forms, with or without |
       6                 :     | modification, are permitted provided that the conditions mentioned |
       7                 :     | in the accompanying LICENSE file are met.                          |
       8                 :     +--------------------------------------------------------------------+
       9                 :     | Copyright (c) 2004-2007, Michael Wallner <mike@php.net>            |
      10                 :     +--------------------------------------------------------------------+
      11                 : */
      12                 : 
      13                 : /* $Id: http_persistent_handle_api.c,v 1.9 2007/02/09 14:19:39 mike Exp $ */
      14                 : 
      15                 : #include "php_http.h"
      16                 : #include "php_http_api.h"
      17                 : 
      18                 : #include "php_http_persistent_handle_api.h"
      19                 : 
      20                 : #ifndef HTTP_DEBUG_PHANDLES
      21                 : #       define HTTP_DEBUG_PHANDLES 0
      22                 : #endif
      23                 : 
      24                 : static HashTable http_persistent_handles_hash;
      25                 : #ifdef ZTS
      26                 : #       define LOCK() tsrm_mutex_lock(http_persistent_handles_lock)
      27                 : #       define UNLOCK() tsrm_mutex_unlock(http_persistent_handles_lock)
      28                 : static MUTEX_T http_persistent_handles_lock;
      29                 : #else
      30                 : #       define LOCK()
      31                 : #       define UNLOCK()
      32                 : #endif
      33                 : 
      34                 : typedef struct _http_persistent_handle_t {
      35                 :         void *ptr;
      36                 : } http_persistent_handle;
      37                 : 
      38                 : typedef struct _http_persistent_handle_list_t {
      39                 :         HashTable free;
      40                 :         ulong used;
      41                 : } http_persistent_handle_list;
      42                 : 
      43                 : typedef struct _http_persistent_handle_provider_t {
      44                 :         http_persistent_handle_list list; /* "ident" => array(handles) entries */
      45                 :         http_persistent_handle_ctor ctor;
      46                 :         http_persistent_handle_dtor dtor;
      47                 :         http_persistent_handle_copy copy;
      48                 : } http_persistent_handle_provider;
      49                 : 
      50                 : static inline http_persistent_handle_list *http_persistent_handle_list_init(http_persistent_handle_list *list)
      51             912 : {
      52                 :         int free_list;
      53                 :         
      54             912 :         if ((free_list = !list)) {
      55             249 :                 list = pemalloc(sizeof(http_persistent_handle_list), 1);
      56                 :         }
      57                 :         
      58             912 :         list->used = 0;
      59                 :         
      60             912 :         if (SUCCESS != zend_hash_init(&list->free, 0, NULL, NULL, 1)) {
      61               0 :                 if (free_list) {
      62               0 :                         pefree(list, 1);
      63                 :                 }
      64               0 :                 list = NULL;
      65                 :         }
      66                 :         
      67             912 :         return list;
      68                 : }
      69                 : 
      70                 : static inline void http_persistent_handle_list_dtor(http_persistent_handle_list *list, http_persistent_handle_dtor dtor)
      71             251 : {
      72                 :         HashPosition pos;
      73                 :         http_persistent_handle *handle;
      74                 :         
      75             525 :         FOREACH_HASH_VAL(pos, &list->free, handle) {
      76                 : #if HTTP_DEBUG_PHANDLES
      77                 :                 fprintf(stderr, "DESTROY: %p\n", handle->ptr);
      78                 : #endif
      79                 :                 
      80             274 :                 dtor(handle->ptr);
      81                 :         }
      82             251 :         zend_hash_destroy(&list->free);
      83             251 : }
      84                 : 
      85                 : static inline void http_persistent_handle_list_free(http_persistent_handle_list **list, http_persistent_handle_dtor dtor)
      86             248 : {
      87             248 :         http_persistent_handle_list_dtor(*list, dtor);
      88             248 :         pefree(*list, 1);
      89             248 :         *list = NULL;
      90             248 : }
      91                 : 
      92                 : static inline http_persistent_handle_list *http_persistent_handle_list_find(http_persistent_handle_provider *provider TSRMLS_DC)
      93             624 : {
      94                 :         http_persistent_handle_list **list, *new_list;
      95                 :         
      96             624 :         if (SUCCESS == zend_hash_quick_find(&provider->list.free, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &list)) {
      97             375 :                 return *list;
      98                 :         }
      99                 :         
     100             249 :         if ((new_list = http_persistent_handle_list_init(NULL))) {
     101             249 :                 if (SUCCESS == zend_hash_quick_add(&provider->list.free, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &new_list, sizeof(http_persistent_handle_list *), (void *) &list)) {
     102             249 :                         return *list;
     103                 :                 }
     104               0 :                 http_persistent_handle_list_free(&new_list, provider->dtor);
     105                 :         }
     106                 :         
     107               0 :         return NULL;
     108                 : }
     109                 : 
     110                 : static inline STATUS http_persistent_handle_do_acquire(http_persistent_handle_provider *provider, void **handle_ptr TSRMLS_DC)
     111             311 : {
     112                 :         ulong index;
     113                 :         http_persistent_handle *handle;
     114                 :         http_persistent_handle_list *list;
     115                 :         
     116             311 :         if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
     117             311 :                 zend_hash_internal_pointer_end(&list->free);
     118             347 :                 if (HASH_KEY_NON_EXISTANT != zend_hash_get_current_key(&list->free, NULL, &index, 0) && SUCCESS == zend_hash_get_current_data(&list->free, (void *) &handle)) {
     119              36 :                         *handle_ptr = handle->ptr;
     120              36 :                         zend_hash_index_del(&list->free, index);
     121                 :                 } else {
     122             275 :                         *handle_ptr = provider->ctor();
     123                 :                 }
     124                 :                 
     125             311 :                 if (*handle_ptr) {
     126             311 :                         ++provider->list.used;
     127             311 :                         ++list->used;
     128             311 :                         return SUCCESS;
     129                 :                 }
     130                 :         }
     131                 :         
     132               0 :         return FAILURE;
     133                 : }
     134                 : 
     135                 : static inline STATUS http_persistent_handle_do_release(http_persistent_handle_provider *provider, void **handle_ptr TSRMLS_DC)
     136             310 : {
     137                 :         http_persistent_handle_list *list;
     138                 :         
     139             310 :         if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
     140             310 :                 if (provider->list.used >= HTTP_G->persistent.handles.limit) {
     141               0 :                         provider->dtor(*handle_ptr);
     142                 :                 } else {
     143             310 :                         http_persistent_handle handle = {*handle_ptr};
     144                 :                         
     145             310 :                         if (SUCCESS != zend_hash_next_index_insert(&list->free, (void *) &handle, sizeof(http_persistent_handle), NULL)) {
     146               0 :                                 return FAILURE;
     147                 :                         }
     148                 :                 }
     149                 :                 
     150             310 :                 *handle_ptr = NULL;
     151             310 :                 --provider->list.used;
     152             310 :                 --list->used;
     153             310 :                 return SUCCESS;
     154                 :         }
     155                 :         
     156               0 :         return FAILURE;
     157                 : }
     158                 : 
     159                 : static inline STATUS http_persistent_handle_do_accrete(http_persistent_handle_provider *provider, void *old_handle, void **new_handle TSRMLS_DC)
     160               0 : {
     161                 :         http_persistent_handle_list *list;
     162                 :         
     163               0 :         if (provider->copy && (*new_handle = provider->copy(old_handle))) {
     164               0 :                 if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
     165               0 :                         ++list->used;
     166                 :                 }
     167               0 :                 ++provider->list.used;
     168               0 :                 return SUCCESS;
     169                 :         }
     170               0 :         return FAILURE;
     171                 : }
     172                 : 
     173                 : static void http_persistent_handles_hash_dtor(void *p)
     174             657 : {
     175             657 :         http_persistent_handle_provider *provider = (http_persistent_handle_provider *) p;
     176                 :         http_persistent_handle_list **list;
     177                 :         HashPosition pos;
     178                 :         
     179             905 :         FOREACH_HASH_VAL(pos, &provider->list.free, list) {
     180             248 :                 http_persistent_handle_list_free(list, provider->dtor);
     181                 :         }
     182                 :         
     183             657 :         zend_hash_destroy(&provider->list.free);
     184             657 : }
     185                 : 
     186                 : PHP_MINIT_FUNCTION(http_persistent_handle)
     187             220 : {
     188             220 :         zend_hash_init(&http_persistent_handles_hash, 0, NULL, http_persistent_handles_hash_dtor, 1);
     189                 : #ifdef ZTS
     190                 :         http_persistent_handles_lock = tsrm_mutex_alloc();
     191                 : #endif
     192             220 :         return SUCCESS;
     193                 : }
     194                 : 
     195                 : PHP_MSHUTDOWN_FUNCTION(http_persistent_handle)
     196             219 : {
     197             219 :         zend_hash_destroy(&http_persistent_handles_hash);
     198                 : #ifdef ZTS
     199                 :         tsrm_mutex_free(http_persistent_handles_lock);
     200                 : #endif
     201             219 :         return SUCCESS;
     202                 : }
     203                 : 
     204                 : PHP_HTTP_API STATUS _http_persistent_handle_provide_ex(const char *name_str, size_t name_len, http_persistent_handle_ctor ctor, http_persistent_handle_dtor dtor, http_persistent_handle_copy copy)
     205             660 : {
     206             660 :         STATUS status = FAILURE;
     207                 :         http_persistent_handle_provider provider;
     208                 :         
     209                 :         LOCK();
     210             660 :         if (http_persistent_handle_list_init(&provider.list)) {
     211             660 :                 provider.ctor = ctor;
     212             660 :                 provider.dtor = dtor;
     213             660 :                 provider.copy = copy;
     214                 :                 
     215                 : #if HTTP_DEBUG_PHANDLES
     216                 :                 fprintf(stderr, "PROVIDE: %s\n", name_str);
     217                 : #endif
     218                 :                 
     219             660 :                 if (SUCCESS == zend_hash_add(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &provider, sizeof(http_persistent_handle_provider), NULL)) {
     220             660 :                         status = SUCCESS;
     221                 :                 } else {
     222               0 :                         http_persistent_handle_list_dtor(&provider.list, dtor);
     223                 :                 }
     224                 :         }
     225                 :         UNLOCK();
     226                 :         
     227             660 :         return status;
     228                 : }
     229                 : 
     230                 : PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle_ptr TSRMLS_DC)
     231             311 : {
     232             311 :         STATUS status = FAILURE;
     233                 :         http_persistent_handle_provider *provider;
     234                 :         
     235             311 :         *handle_ptr = NULL;
     236                 :         LOCK();
     237             311 :         if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &provider)) {
     238             311 :                 status = http_persistent_handle_do_acquire(provider, handle_ptr TSRMLS_CC);
     239                 :         }
     240                 :         UNLOCK();
     241                 :         
     242                 : #if HTTP_DEBUG_PHANDLES
     243                 :         fprintf(stderr, "ACQUIRE: %p (%s)\n", *handle_ptr, name_str);
     244                 : #endif
     245                 :         
     246             311 :         return status;
     247                 : }
     248                 : 
     249                 : PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle_ptr TSRMLS_DC)
     250             310 : {
     251             310 :         STATUS status = FAILURE;
     252                 :         http_persistent_handle_provider *provider;
     253                 :         
     254                 :         LOCK();
     255             310 :         if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &provider)) {
     256             310 :                 status = http_persistent_handle_do_release(provider, handle_ptr TSRMLS_CC);
     257                 :         }
     258                 :         UNLOCK();
     259                 :         
     260                 : #if HTTP_DEBUG_PHANDLES
     261                 :         fprintf(stderr, "RELEASE: %p (%s)\n", *handle_ptr, name_str);
     262                 : #endif
     263                 :         
     264             310 :         return status;
     265                 : }
     266                 : 
     267                 : PHP_HTTP_API STATUS _http_persistent_handle_accrete_ex(const char *name_str, size_t name_len, void *old_handle, void **new_handle TSRMLS_DC)
     268               0 : {
     269               0 :         STATUS status = FAILURE;
     270                 :         http_persistent_handle_provider *provider;
     271                 :         
     272               0 :         *new_handle = NULL;
     273                 :         LOCK();
     274               0 :         if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &provider)) {
     275               0 :                 status = http_persistent_handle_do_accrete(provider, old_handle, new_handle TSRMLS_CC);
     276                 :         }
     277                 :         UNLOCK();
     278                 :         
     279                 : #if HTTP_DEBUG_PHANDLES
     280                 :         fprintf(stderr, "ACCRETE: %p > %p (%s)\n", old_handle, *new_handle, name_str);
     281                 : #endif
     282                 :         
     283               0 :         return status;
     284                 : }
     285                 : 
     286                 : PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len, int current_ident_only TSRMLS_DC)
     287               1 : {
     288                 :         http_persistent_handle_provider *provider;
     289                 :         http_persistent_handle_list *list, **listp;
     290                 :         HashPosition pos1, pos2;
     291                 :         
     292                 :         LOCK();
     293               1 :         if (name_str && name_len) {
     294               0 :                 if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &provider)) {
     295               0 :                         if (current_ident_only) {
     296               0 :                                 if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
     297               0 :                                         http_persistent_handle_list_dtor(list, provider->dtor);
     298               0 :                                         http_persistent_handle_list_init(list);
     299                 :                                 }
     300                 :                         } else {
     301               0 :                                 FOREACH_HASH_VAL(pos1, &provider->list.free, listp) {
     302               0 :                                         http_persistent_handle_list_dtor(*listp, provider->dtor);
     303               0 :                                         http_persistent_handle_list_init(*listp);
     304                 :                                 }
     305                 :                         }
     306                 :                 }
     307                 :         } else {
     308               4 :                 FOREACH_HASH_VAL(pos1, &http_persistent_handles_hash, provider) {
     309               3 :                         if (current_ident_only) {
     310               3 :                                 if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
     311               3 :                                         http_persistent_handle_list_dtor(list, provider->dtor);
     312               3 :                                         http_persistent_handle_list_init(list);
     313                 :                                 }
     314                 :                         } else {
     315               0 :                                 FOREACH_HASH_VAL(pos2, &provider->list.free, listp) {
     316               0 :                                         http_persistent_handle_list_dtor(*listp, provider->dtor);
     317               0 :                                         http_persistent_handle_list_init(*listp);
     318                 :                                 }
     319                 :                         }
     320                 :                 }
     321                 :         }
     322                 :         UNLOCK();
     323               1 : }
     324                 : 
     325                 : PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht TSRMLS_DC)
     326               3 : {
     327                 :         zval *zentry[2];
     328                 :         HashPosition pos1, pos2;
     329               3 :         HashKey key1 = initHashKey(0), key2 = initHashKey(0);
     330                 :         http_persistent_handle_provider *provider;
     331                 :         http_persistent_handle_list **list;
     332                 :         
     333                 :         LOCK();
     334               3 :         if (zend_hash_num_elements(&http_persistent_handles_hash)) {
     335               3 :                 if (!ht) {
     336               0 :                         ALLOC_HASHTABLE(ht);
     337               0 :                         zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
     338                 :                 }
     339                 :                 
     340              12 :                 FOREACH_HASH_KEYVAL(pos1, &http_persistent_handles_hash, key1, provider) {
     341               9 :                         MAKE_STD_ZVAL(zentry[0]);
     342               9 :                         array_init(zentry[0]);
     343                 :                         
     344              15 :                         FOREACH_HASH_KEYVAL(pos2, &provider->list.free, key2, list) {
     345               6 :                                 MAKE_STD_ZVAL(zentry[1]);
     346               6 :                                 array_init(zentry[1]);
     347               6 :                                 add_assoc_long_ex(zentry[1], ZEND_STRS("used"), (*list)->used);
     348               6 :                                 add_assoc_long_ex(zentry[1], ZEND_STRS("free"), zend_hash_num_elements(&(*list)->free));
     349                 :                                 
     350                 :                                 /* use zend_hash_* not add_assoc_* (which is zend_symtable_*) as we want a string even for numbers */
     351               6 :                                 zend_hash_add(Z_ARRVAL_P(zentry[0]), key2.str, key2.len, &zentry[1], sizeof(zval *), NULL);
     352                 :                         }
     353                 :                         
     354               9 :                         zend_hash_add(ht, key1.str, key1.len, &zentry[0], sizeof(zval *), NULL);
     355                 :                 }
     356               0 :         } else if (ht) {
     357               0 :                 ht = NULL;
     358                 :         }
     359                 :         UNLOCK();
     360                 :         
     361               3 :         return ht;
     362                 : }
     363                 : 
     364                 : 
     365                 : /*
     366                 :  * Local variables:
     367                 :  * tab-width: 4
     368                 :  * c-basic-offset: 4
     369                 :  * End:
     370                 :  * vim600: noet sw=4 ts=4 fdm=marker
     371                 :  * vim<600: noet sw=4 ts=4
     372                 :  */
     373                 : 

Generated by: LTP GCOV extension version 1.5