- fix hash keys
[m6w6/ext-http] / http_persistent_handle_api.c
index a2e0ba908b258b6cc9e5b8750b69d306aefd5b54..b07caffdda4220966b5dc4564d48292387fd6a20 100644 (file)
@@ -6,7 +6,7 @@
     | modification, are permitted provided that the conditions mentioned |
     | in the accompanying LICENSE file are met.                          |
     +--------------------------------------------------------------------+
-    | Copyright (c) 2004-2006, Michael Wallner <mike@php.net>            |
+    | Copyright (c) 2004-2007, Michael Wallner <mike@php.net>            |
     +--------------------------------------------------------------------+
 */
 
 #ifdef HTTP_HAVE_PERSISTENT_HANDLES
 #include "php_http_persistent_handle_api.h"
 
+#ifndef HTTP_DEBUG_PHANDLES
+#      define HTTP_DEBUG_PHANDLES 0
+#endif
+
 static HashTable http_persistent_handles_hash;
 #ifdef ZTS
 #      define LOCK() tsrm_mutex_lock(http_persistent_handles_lock)
@@ -40,17 +44,53 @@ typedef struct _http_persistent_handle_provider_t {
        http_persistent_handle_dtor dtor;
 } http_persistent_handle_provider;
 
+
+static inline STATUS http_persistent_handle_list_find(http_persistent_handle_list parent_list, http_persistent_handle_list **ident_list, int create TSRMLS_DC)
+{
+       http_persistent_handle_list new_list;
+       
+       if (SUCCESS == zend_hash_quick_find(parent_list, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) ident_list)) {
+               return SUCCESS;
+       }
+       
+       if (create) {
+               if ((new_list = pemalloc(sizeof(HashTable), 1))) {
+                       if (SUCCESS == zend_hash_init(new_list, 0, NULL, NULL, 1)) {
+                               if (SUCCESS == zend_hash_quick_add(parent_list, 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 *) ident_list)) {
+                                       return SUCCESS;
+                               }
+                               zend_hash_destroy(new_list);
+                       }
+                       pefree(new_list, 1);
+               }
+       }
+       
+       return FAILURE;
+}
+
+static inline void http_persistent_handle_list_dtor(http_persistent_handle_list list, http_persistent_handle_dtor dtor)
+{
+       HashPosition pos;
+       http_persistent_handle *handle;
+       
+       FOREACH_HASH_VAL(pos, list, handle) {
+#if HTTP_DEBUG_PHANDLES
+               fprintf(stderr, "DESTROY: %p\n", handle->ptr);
+#endif
+               
+               dtor(handle->ptr);
+       }
+       zend_hash_clean(list);
+}
+
 static void http_persistent_handles_hash_dtor(void *p)
 {
        http_persistent_handle_provider *provider = (http_persistent_handle_provider *) p;
        http_persistent_handle_list *list;
-       http_persistent_handle *handle;
-       HashPosition pos1, pos2;
+       HashPosition pos;
        
-       FOREACH_HASH_VAL(pos1, provider->list, list) {
-               FOREACH_HASH_VAL(pos2, *list, handle) {
-                       provider->dtor(handle->ptr);
-               }
+       FOREACH_HASH_VAL(pos, provider->list, list) {
+               http_persistent_handle_list_dtor(*list, provider->dtor);
                zend_hash_destroy(*list);
                pefree(*list, 1);
        }
@@ -87,6 +127,11 @@ PHP_HTTP_API STATUS _http_persistent_handle_provide_ex(const char *name_str, siz
                provider.ctor = ctor;
                provider.dtor = dtor;
                zend_hash_init(provider.list, 0, NULL, NULL, 1);
+               
+#if HTTP_DEBUG_PHANDLES
+               fprintf(stderr, "PROVIDE: %p (%s)\n", provider.list, name_str);
+#endif
+               
                if (SUCCESS == zend_hash_add(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &provider, sizeof(http_persistent_handle_provider), NULL)) {
                        status = SUCCESS;
                } else {
@@ -109,7 +154,7 @@ PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, siz
        *handle_ptr = NULL;
        LOCK();
        if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &provider)) {
-               if (SUCCESS == zend_hash_quick_find(provider->list, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &list)) {
+               if (SUCCESS == http_persistent_handle_list_find(provider->list, &list, 0 TSRMLS_CC)) {
                        zend_hash_internal_pointer_end(*list);
                        if (HASH_KEY_NON_EXISTANT != zend_hash_get_current_key(*list, NULL, &index, 0) && SUCCESS == zend_hash_get_current_data(*list, (void *) &handle)) {
                                *handle_ptr = handle->ptr;
@@ -122,6 +167,10 @@ PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, siz
        }
        UNLOCK();
        
+#if HTTP_DEBUG_PHANDLES
+       fprintf(stderr, "ACQUIRE: %p (%s)\n", *handle_ptr, name_str);
+#endif
+       
        return status;
 }
 
@@ -129,25 +178,22 @@ PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, siz
 {
        STATUS status = FAILURE;
        http_persistent_handle_provider *provider;
-       http_persistent_handle_list *list, new_list;
+       http_persistent_handle_list *list;
        http_persistent_handle handle = {*handle_ptr};
        
        LOCK();
        if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &provider)) {
-               if (SUCCESS == zend_hash_quick_find(provider->list, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &list)) {
-                       status = zend_hash_next_index_insert(*list, (void *) &handle, sizeof(http_persistent_handle), NULL);
-               } else if ((new_list = pemalloc(sizeof(HashTable), 1))) {
-                       zend_hash_init(new_list, 0, NULL, NULL, 1);
-                       if (    SUCCESS == zend_hash_next_index_insert(new_list, (void *) &handle, sizeof(http_persistent_handle), NULL) &&
-                                       SUCCESS == zend_hash_quick_add(provider->list, 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 *), NULL)) {
-                               status = SUCCESS;
-                       } else {
-                               pefree(new_list, 1);
-                       }
+               if (    SUCCESS == http_persistent_handle_list_find(provider->list, &list, 1 TSRMLS_CC) &&
+                               SUCCESS == zend_hash_next_index_insert(*list, (void *) &handle, sizeof(http_persistent_handle), NULL)) {
+                       status = SUCCESS;
                }
        }
        UNLOCK();
        
+#if HTTP_DEBUG_PHANDLES
+       fprintf(stderr, "RELEASE: %p (%s)\n", *handle_ptr, name_str);
+#endif
+       
        return status;
 }
        
@@ -155,43 +201,30 @@ PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_
 {
        http_persistent_handle_provider *provider;
        http_persistent_handle_list *list;
-       http_persistent_handle *handle;
-       HashPosition pos1, pos2, pos3;
+       HashPosition pos1, pos2;
        
        LOCK();
        if (name_str && name_len) {
                if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &provider)) {
                        if (current_ident_only) {
-                               if (SUCCESS == zend_hash_quick_find(provider->list, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &list)) {
-                                       FOREACH_HASH_VAL(pos1, *list, handle) {
-                                               provider->dtor(handle->ptr);
-                                       }
-                                       zend_hash_clean(*list);
+                               if (SUCCESS == http_persistent_handle_list_find(provider->list, &list, 0 TSRMLS_CC)) {
+                                       http_persistent_handle_list_dtor(*list, provider->dtor);
                                }
                        } else {
                                FOREACH_HASH_VAL(pos1, provider->list, list) {
-                                       FOREACH_HASH_VAL(pos2, *list, handle) {
-                                               provider->dtor(handle->ptr);
-                                       }
-                                       zend_hash_clean(*list);
+                                       http_persistent_handle_list_dtor(*list, provider->dtor);
                                }
                        }
                }
        } else {
                FOREACH_HASH_VAL(pos1, &http_persistent_handles_hash, provider) {
                        if (current_ident_only) {
-                               if (SUCCESS == zend_hash_quick_find(provider->list, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &list)) {
-                                       FOREACH_HASH_VAL(pos2, *list, handle) {
-                                               provider->dtor(handle->ptr);
-                                       }
-                                       zend_hash_clean(*list);
+                               if (SUCCESS == http_persistent_handle_list_find(provider->list, &list, 0 TSRMLS_CC)) {
+                                       http_persistent_handle_list_dtor(*list, provider->dtor);
                                }
                        } else {
                                FOREACH_HASH_VAL(pos2, provider->list, list) {
-                                       FOREACH_HASH_VAL(pos3, *list, handle) {
-                                               provider->dtor(handle->ptr);
-                                       }
-                                       zend_hash_clean(*list);
+                                       http_persistent_handle_list_dtor(*list, provider->dtor);
                                }
                        }
                }
@@ -220,9 +253,9 @@ PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht)
                        FOREACH_HASH_KEYVAL(pos2, provider->list, key2, list) {
                                MAKE_STD_ZVAL(zentry);
                                ZVAL_LONG(zentry, zend_hash_num_elements(*list));
-                               zend_hash_quick_add(Z_ARRVAL_P(zlist), key2.str, key2.len, key2.num, (void *) &zentry, sizeof(zval *), NULL);
+                               zend_hash_add(Z_ARRVAL_P(zlist), key2.str, key2.len, (void *) &zentry, sizeof(zval *), NULL);
                        }
-                       zend_hash_quick_add(ht, key1.str, key1.len, key1.num, (void *) &zlist, sizeof(zval *), NULL);
+                       zend_hash_add(ht, key1.str, key1.len, (void *) &zlist, sizeof(zval *), NULL);
                }
        } else if (ht) {
                ht = NULL;