# ifdef HTTP_HAVE_PERSISTENT_HANDLES
PHP_FE(http_persistent_handles_count, NULL)
PHP_FE(http_persistent_handles_clean, NULL)
+ PHP_FE(http_persistent_handles_ident, NULL)
# endif
PHP_FE(http_get, http_arg_pass_ref_3)
PHP_FE(http_head, http_arg_pass_ref_3)
G->request.time = time(NULL);
#endif
G->send.buffer_size = 0;
- G->send.not_found_404 = 1;
G->read_post_data = 0;
}
http_check_allowed_methods(new_value, new_value_length);
return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
}
+#ifdef HTTP_HAVE_PERSISTENT_HANDLES
+PHP_INI_MH(http_update_persistent_handle_ident)
+{
+ HTTP_G->persistent.handles.ident.h = zend_get_hash_value(new_value, HTTP_G->persistent.handles.ident.l = new_value_length+1);
+ return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
+}
+#endif
#ifndef ZEND_ENGINE_2
# define OnUpdateLong OnUpdateInt
HTTP_PHP_INI_ENTRY("http.send.inflate.start_flags", "0", PHP_INI_ALL, OnUpdateLong, send.inflate.start_flags)
HTTP_PHP_INI_ENTRY("http.send.deflate.start_auto", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, send.deflate.start_auto)
HTTP_PHP_INI_ENTRY("http.send.deflate.start_flags", "0", PHP_INI_ALL, OnUpdateLong, send.deflate.start_flags)
+#endif
+#ifdef HTTP_HAVE_PERSISTENT_HANDLES
+ HTTP_PHP_INI_ENTRY("http.persistent.handles.ident", "GLOBAL", PHP_INI_ALL, http_update_persistent_handle_ident, persistent.handles.ident.s)
#endif
HTTP_PHP_INI_ENTRY("http.send.not_found_404", "1", PHP_INI_ALL, OnUpdateBool, send.not_found_404)
#ifdef ZEND_ENGINE_2
#else
php_info_print_table_row(3, "libz", "disabled", "disabled");
#endif
-#if defined(HTTP_HAVE_MAGIC) && !defined(WONKY)
+#if defined(HTTP_HAVE_MAGIC)
php_info_print_table_row(3, "libmagic", "unknown", "unknown");
#else
php_info_print_table_row(3, "libmagic", "disabled", "disabled");
# define UNLOCK()
#endif
-typedef struct _http_persistent_handles_hash_entry_t {
- HashTable list;
+typedef struct _http_persistent_handle_t {
+ void *ptr;
+} http_persistent_handle;
+
+typedef HashTable *http_persistent_handle_list;
+
+typedef struct _http_persistent_handle_provider_t {
+ http_persistent_handle_list list; /* "ident" => array(handles) entries */
http_persistent_handle_ctor ctor;
http_persistent_handle_dtor dtor;
-} http_persistent_handles_hash_entry;
+} http_persistent_handle_provider;
-typedef struct _http_persistent_handles_list_entry_t {
- void *handle;
-} http_persistent_handles_list_entry;
-
-static inline void http_persistent_handles_hash_dtor_ex(http_persistent_handles_hash_entry *hentry, void (*list_dtor)(HashTable*))
+static void http_persistent_handles_hash_dtor(void *p)
{
- http_persistent_handles_list_entry *lentry;
+ http_persistent_handle_provider *provider = (http_persistent_handle_provider *) p;
+ http_persistent_handle_list *list;
+ http_persistent_handle *handle;
+ HashPosition pos1, pos2;
- for ( zend_hash_internal_pointer_reset(&hentry->list);
- SUCCESS == zend_hash_get_current_data(&hentry->list, (void *) &lentry);
- zend_hash_move_forward(&hentry->list)) {
- hentry->dtor(lentry->handle);
- }
-
- if (list_dtor) {
- list_dtor(&hentry->list);
+ FOREACH_HASH_VAL(pos1, provider->list, list) {
+ FOREACH_HASH_VAL(pos2, *list, handle) {
+ provider->dtor(handle->ptr);
+ }
+ zend_hash_destroy(*list);
+ pefree(*list, 1);
}
-}
-
-static void http_persistent_handles_hash_dtor(void *h)
-{
- http_persistent_handles_hash_dtor_ex(h, zend_hash_destroy);
+ zend_hash_destroy(provider->list);
+ pefree(provider->list, 1);
}
PHP_MINIT_FUNCTION(http_persistent_handle)
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)
{
- STATUS status = SUCCESS;
- http_persistent_handles_hash_entry e;
-
- zend_hash_init(&e.list, 0, NULL, NULL, 1);
- e.ctor = ctor;
- e.dtor = dtor;
+ STATUS status = FAILURE;
+ http_persistent_handle_provider provider;
LOCK();
- if (SUCCESS != zend_hash_add(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &e, sizeof(http_persistent_handles_hash_entry), NULL)) {
- zend_hash_destroy(&e.list);
- status = FAILURE;
+ provider.list = pemalloc(sizeof(HashTable), 1);
+ if (provider.list) {
+ provider.ctor = ctor;
+ provider.dtor = dtor;
+ zend_hash_init(provider.list, 0, NULL, NULL, 1);
+ 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 {
+ pefree(provider.list, 1);
+ }
}
UNLOCK();
return status;
}
-PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len)
+PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle_ptr TSRMLS_DC)
{
- http_persistent_handles_hash_entry *hentry;
+ STATUS status = FAILURE;
+ ulong index;
+ http_persistent_handle_provider *provider;
+ http_persistent_handle_list *list;
+ http_persistent_handle *handle;
+ *handle_ptr = NULL;
LOCK();
- if (name_str && name_len) {
- if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &hentry)) {
- http_persistent_handles_hash_dtor_ex(hentry, zend_hash_clean);
+ 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)) {
+ 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;
+ zend_hash_index_del(*list, index);
+ }
}
- } else {
- for ( zend_hash_internal_pointer_reset(&http_persistent_handles_hash);
- SUCCESS == zend_hash_get_current_data(&http_persistent_handles_hash, (void *) &hentry);
- zend_hash_move_forward(&http_persistent_handles_hash)) {
- http_persistent_handles_hash_dtor_ex(hentry, zend_hash_clean);
+ if (*handle_ptr || (*handle_ptr = provider->ctor())) {
+ status = SUCCESS;
}
}
UNLOCK();
+
+ return status;
}
-PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht)
+PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle_ptr TSRMLS_DC)
{
- zval *tmp;
- HashPosition pos;
- HashKey key = initHashKey(0);
- http_persistent_handles_hash_entry *hentry;
+ STATUS status = FAILURE;
+ http_persistent_handle_provider *provider;
+ http_persistent_handle_list *list, new_list;
+ http_persistent_handle handle = {*handle_ptr};
LOCK();
- if (zend_hash_num_elements(&http_persistent_handles_hash)) {
- if (!ht) {
- ALLOC_HASHTABLE(ht);
- zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
- }
-
- FOREACH_HASH_KEYVAL(pos, &http_persistent_handles_hash, key, hentry) {
- MAKE_STD_ZVAL(tmp);
- ZVAL_LONG(tmp, zend_hash_num_elements(&hentry->list));
- zend_hash_add(ht, key.str, key.len, (void *) &tmp, sizeof(zval *), NULL);
+ 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);
+ }
}
- } else if (ht) {
- ht = NULL;
}
UNLOCK();
- return ht;
+ return status;
}
-
-PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle)
+
+PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len, int current_ident_only TSRMLS_DC)
{
- STATUS status = FAILURE;
- ulong index;
- http_persistent_handles_hash_entry *hentry;
- http_persistent_handles_list_entry *lentry;
+ http_persistent_handle_provider *provider;
+ http_persistent_handle_list *list;
+ http_persistent_handle *handle;
+ HashPosition pos1, pos2, pos3;
LOCK();
- if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &hentry)) {
- zend_hash_internal_pointer_end(&hentry->list);
- if ( HASH_KEY_NON_EXISTANT != zend_hash_get_current_key(&hentry->list, NULL, &index, 0) &&
- SUCCESS == zend_hash_get_current_data(&hentry->list, (void *) &lentry)) {
- *handle = lentry->handle;
- zend_hash_index_del(&hentry->list, index);
- status = SUCCESS;
- } else if ((*handle = hentry->ctor())) {
- status = SUCCESS;
+ 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);
+ }
+ } else {
+ FOREACH_HASH_VAL(pos1, provider->list, list) {
+ FOREACH_HASH_VAL(pos2, *list, handle) {
+ provider->dtor(handle->ptr);
+ }
+ zend_hash_clean(*list);
+ }
+ }
+ }
+ } 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);
+ }
+ } else {
+ FOREACH_HASH_VAL(pos2, provider->list, list) {
+ FOREACH_HASH_VAL(pos3, *list, handle) {
+ provider->dtor(handle->ptr);
+ }
+ zend_hash_clean(*list);
+ }
+ }
}
}
UNLOCK();
-
- return status;
}
-PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle)
+PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht)
{
- STATUS status = FAILURE;
- http_persistent_handles_hash_entry *hentry;
- http_persistent_handles_list_entry lentry;
+ zval *zlist, *zentry;
+ HashPosition pos1, pos2;
+ HashKey key1 = initHashKey(0), key2 = initHashKey(0);
+ http_persistent_handle_provider *provider;
+ http_persistent_handle_list *list;
LOCK();
- if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &hentry)) {
- lentry.handle = *handle;
- if (SUCCESS == zend_hash_next_index_insert(&hentry->list, (void *) &lentry, sizeof(http_persistent_handles_list_entry), NULL)) {
- status = SUCCESS;
+ if (zend_hash_num_elements(&http_persistent_handles_hash)) {
+ if (!ht) {
+ ALLOC_HASHTABLE(ht);
+ zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
+ }
+
+ FOREACH_HASH_KEYVAL(pos1, &http_persistent_handles_hash, key1, provider) {
+ MAKE_STD_ZVAL(zlist);
+ array_init(zlist);
+ 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_quick_add(ht, key1.str, key1.len, key1.num, (void *) &zlist, sizeof(zval *), NULL);
}
+ } else if (ht) {
+ ht = NULL;
}
UNLOCK();
- return status;
+ return ht;
}
#endif /* HTTP_HAVE_PERSISTENT_HANDLES */
#define http_persistent_handle_provide_ex(n, l, c, d) _http_persistent_handle_provide_ex((n), (l), (c), (d))
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);
-#define http_persistent_handle_cleanup(n) _http_persistent_handle_cleanup_ex((n), strlen(n))
-#define http_persistent_handle_cleanup_ex(n, l) _http_persistent_handle_cleanup_ex((n), (l))
-PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len);
+#define http_persistent_handle_cleanup(n, c) _http_persistent_handle_cleanup_ex((n), strlen(n), (c) TSRMLS_CC)
+#define http_persistent_handle_cleanup_ex(n, l,c ) _http_persistent_handle_cleanup_ex((n), (l), (c) TSRMLS_CC)
+PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len, int current_ident_only TSRMLS_DC);
#define http_persistent_handle_statall() _http_persistent_handle_statall_ex(NULL)
#define http_persistent_handle_statall_ex(ht) _http_persistent_handle_statall_ex((ht))
PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht);
-#define http_persistent_handle_acquire(n, h) _http_persistent_handle_acquire_ex((n), strlen(n), (h))
-#define http_persistent_handle_acquire_ex(n, l, h) _http_persistent_handle_acquire_ex((n), (l), (h))
-PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle);
+#define http_persistent_handle_acquire(n, h) _http_persistent_handle_acquire_ex((n), strlen(n), (h) TSRMLS_CC)
+#define http_persistent_handle_acquire_ex(n, l, h) _http_persistent_handle_acquire_ex((n), (l), (h) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC);
-#define http_persistent_handle_release(n, h) _http_persistent_handle_release_ex((n), strlen(n), (h))
-#define http_persistent_handle_release_ex(n, l, h) _http_persistent_handle_release_ex((n), (l), (h))
-PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle);
+#define http_persistent_handle_release(n, h) _http_persistent_handle_release_ex((n), strlen(n), (h) TSRMLS_CC)
+#define http_persistent_handle_release_ex(n, l, h) _http_persistent_handle_release_ex((n), (l), (h) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC);
#endif /* HTTP_HAVE_PERSISTENT_HANDLES */
#endif /* HTTP_PERSISTENT_HANDLE_H */