- add persistent cURL handle support
authorMichael Wallner <mike@php.net>
Sat, 27 Jan 2007 13:34:47 +0000 (13:34 +0000)
committerMichael Wallner <mike@php.net>
Sat, 27 Jan 2007 13:34:47 +0000 (13:34 +0000)
config9.m4
http.c
http_functions.c
http_persistent_handle_api.c [new file with mode: 0644]
http_request_api.c
package2.xml
php_http.h
php_http_persistent_handle_api.h [new file with mode: 0644]

index 9a0cda368d89d7458562fbddb496624eebf7a417..6539daf8c9266926d5a62138abb00f1779a85bcb 100644 (file)
@@ -4,6 +4,13 @@ dnl vim: noet ts=1 sw=1
 
 PHP_ARG_ENABLE([http], [whether to enable extended HTTP support],
 [  --enable-http           Enable extended HTTP support])
+PHP_ARG_ENABLE([http-persistent-handles], [whether to enable per-process persistent cURL handles],
+[  --enable-http-persistent-handles
+                           HTTP: enable per-process persistent cURL handles], "no", "no")
+PHP_ARG_WITH([http-shared-deps], [whether to depend on extensions which have been built shared],
+[  --with-http-shared-deps
+                           HTTP: disable to not depend on extensions like hash,
+                                 iconv and session (when built shared)], $PHP_HTTP, $PHP_HTTP)
 PHP_ARG_WITH([http-curl-requests], [whether to enable cURL HTTP request support],
 [  --with-http-curl-requests[=LIBCURLDIR]
                            HTTP: with cURL request support], $PHP_HTTP, $PHP_HTTP)
@@ -13,9 +20,6 @@ PHP_ARG_WITH([http-zlib-compression], [whether to enable zlib encodings support]
 PHP_ARG_WITH([http-magic-mime], [whether to enable response content type guessing],
 [  --with-http-magic-mime[=LIBMAGICDIR]
                            HTTP: with magic mime response content type guessing], "no", "no")
-PHP_ARG_WITH([http-shared-deps], [whether to depend on extensions which have been built shared],
-[  --with-http-shared-deps  HTTP: disable to not depend on extensions like hash,
-                                 iconv and session (when built shared)], $PHP_HTTP, $PHP_HTTP)
 
 if test "$PHP_HTTP" != "no"; then
 
@@ -265,6 +269,15 @@ dnl ----
                        [AC_DEFINE([HAVE_CURL_MULTI_TIMEOUT], [1], [ ])], [ ],
                        [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
                )
+               
+               dnl persistent cURL handles
+               AC_MSG_CHECKING([whether to enable per-process persistent cURL handles])
+               if test "$PHP_HTTP_PERSISTENT_HANDLES" != "no"; then
+                       AC_DEFINE([HTTP_HAVE_PERSISTENT_HANDLES], [1], [Have per-process persistent cURL handles])
+                       AC_MSG_RESULT([yes])
+               else
+                       AC_MSG_RESULT([no])
+               fi
        fi
 
 dnl ----
@@ -338,7 +351,8 @@ dnl ----
                http_info_api.c http_request_method_api.c http_encoding_api.c \
                http_filter_api.c http_request_body_api.c http_querystring_object.c \
                http_deflatestream_object.c http_inflatestream_object.c http_cookie_api.c \
-               http_querystring_api.c http_request_datashare_api.c http_requestdatashare_object.c"
+               http_querystring_api.c http_request_datashare_api.c http_requestdatashare_object.c \
+               http_persistent_handle_api.c"
        
        PHP_NEW_EXTENSION([http], $PHP_HTTP_SOURCES, $ext_shared)
        
@@ -357,7 +371,8 @@ dnl ----
                php_http_exception_object.h php_http_message_object.h php_http_request_object.h \
                php_http_requestpool_object.h php_http_response_object.h php_http_util_object.h \
                php_http_querystring_object.h php_http_deflatestream_object.h php_http_inflatestream_object.h \
-               php_http_cookie_api.h php_http_querystring_api.h php_http_request_datashare_api.h php_http_requestdatashare_object.h"
+               php_http_cookie_api.h php_http_querystring_api.h php_http_request_datashare_api.h php_http_requestdatashare_object.h \
+               php_http_persistent_handle_api.h"
        ifdef([PHP_INSTALL_HEADERS], [
                PHP_INSTALL_HEADERS(ext/http, $PHP_HTTP_HEADERS)
        ], [
diff --git a/http.c b/http.c
index 521f2b5ce58b7a0f660063e8e0ef8b3ac5b45f54..eccffd8e0bc7ed4576f5958e7d88db1b41ec35e8 100644 (file)
--- a/http.c
+++ b/http.c
@@ -32,6 +32,9 @@
 #ifdef HTTP_HAVE_CURL
 #      include "php_http_request_api.h"
 #      include "php_http_request_datashare_api.h"
+#      ifdef HTTP_HAVE_PERSISTENT_HANDLES
+#              include "php_http_persistent_handle_api.h"
+#      endif
 #endif
 #ifdef HTTP_HAVE_ZLIB
 #      include "php_http_encoding_api.h"
@@ -101,6 +104,10 @@ zend_function_entry http_functions[] = {
        PHP_FE(http_get_request_body_stream, NULL)
        PHP_FE(http_match_request_header, NULL)
 #ifdef HTTP_HAVE_CURL
+#      ifdef HTTP_HAVE_PERSISTENT_HANDLES
+       PHP_FE(http_persistent_handles_count, NULL)
+       PHP_FE(http_persistent_handles_clean, NULL)
+#      endif
        PHP_FE(http_get, http_arg_pass_ref_3)
        PHP_FE(http_head, http_arg_pass_ref_3)
        PHP_FE(http_post_data, http_arg_pass_ref_4)
@@ -280,6 +287,9 @@ PHP_MINIT_FUNCTION(http)
                        (SUCCESS != PHP_MINIT_CALL(http_send))          ||
                        (SUCCESS != PHP_MINIT_CALL(http_url))           ||
 #ifdef HTTP_HAVE_CURL
+#      ifdef HTTP_HAVE_PERSISTENT_HANDLES
+                       (SUCCESS != PHP_MINIT_CALL(http_persistent_handle)) ||
+#      endif
                        (SUCCESS != PHP_MINIT_CALL(http_request))       ||
 #      ifdef ZEND_ENGINE_2
                        (SUCCESS != PHP_MINIT_CALL(http_request_datashare)) ||
@@ -327,7 +337,11 @@ PHP_MSHUTDOWN_FUNCTION(http)
 #      ifdef ZEND_ENGINE_2
                        (SUCCESS != PHP_MSHUTDOWN_CALL(http_request_datashare)) ||
 #      endif
-                       (SUCCESS != PHP_MSHUTDOWN_CALL(http_request))) {
+                       (SUCCESS != PHP_MSHUTDOWN_CALL(http_request))
+#      ifdef HTTP_HAVE_PERSISTENT_HANDLES
+                       || (SUCCESS != PHP_MSHUTDOWN_CALL(http_persistent_handle))
+#      endif
+       ) {
                return FAILURE;
        }
 #endif
index c156c8a3f794ac761cc08821a83e741b7f246fa3..c4e358d2fe2939501fcde5c8fad0b3cf4b3898ff 100644 (file)
@@ -34,6 +34,7 @@
 #include "php_http_message_api.h"
 #include "php_http_request_api.h"
 #include "php_http_request_method_api.h"
+#include "php_http_persistent_handle_api.h"
 #include "php_http_send_api.h"
 #include "php_http_url_api.h"
 
@@ -807,6 +808,42 @@ PHP_FUNCTION(http_match_request_header)
 
 /* {{{ HAVE_CURL */
 #ifdef HTTP_HAVE_CURL
+#ifdef HTTP_HAVE_PERSISTENT_HANDLES
+
+/* {{{ proto object http_persistent_handles_count() */
+PHP_FUNCTION(http_persistent_handles_count)
+{
+       char **names;
+       int *counts;
+       int i, n;
+       
+       NO_ARGS;
+       
+       if ((n = http_persistent_handle_statall(&names, &counts))) {
+               object_init(return_value);
+               for (i = 0; i < n; ++i) {
+                       add_property_long(return_value, names[i], counts[i]);
+                       efree(names[i]);
+               }
+               efree(names);
+               efree(counts);
+       }
+}
+/* }}} */
+
+/* {{{ proto void http_persistent_handles_clean([string name]) */
+PHP_FUNCTION(http_persistent_handles_clean)
+{
+       char *name_str = NULL;
+       int name_len = 0;
+       
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name_str, &name_len)) {
+               http_persistent_handle_cleanup_ex(name_str, name_len);
+       }
+}
+/* }}} */
+
+#endif /* HTTP_HAVE_PERSISTENT_HANDLES */
 
 #define RETVAL_RESPONSE_OR_BODY(request) \
        { \
diff --git a/http_persistent_handle_api.c b/http_persistent_handle_api.c
new file mode 100644 (file)
index 0000000..8fc1b02
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+    +--------------------------------------------------------------------+
+    | PECL :: http                                                       |
+    +--------------------------------------------------------------------+
+    | Redistribution and use in source and binary forms, with or without |
+    | modification, are permitted provided that the conditions mentioned |
+    | in the accompanying LICENSE file are met.                          |
+    +--------------------------------------------------------------------+
+    | Copyright (c) 2004-2006, Michael Wallner <mike@php.net>            |
+    +--------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include "php_http.h"
+
+#ifdef HTTP_HAVE_PERSISTENT_HANDLES
+
+#include "php_http_persistent_handle_api.h"
+
+static HashTable http_persistent_handles_hash;
+#ifdef ZTS
+#      define LOCK() tsrm_mutex_lock(http_persistent_handles_lock)
+#      define UNLOCK() tsrm_mutex_unlock(http_persistent_handles_lock)
+static MUTEX_T http_persistent_handles_lock;
+#else
+#      define LOCK()
+#      define UNLOCK()
+#endif
+
+typedef struct _http_persistent_handles_hash_entry_t {
+       HashTable list;
+       http_persistent_handle_ctor ctor;
+       http_persistent_handle_dtor dtor;
+} http_persistent_handles_hash_entry;
+
+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*))
+{
+       http_persistent_handles_list_entry *lentry;
+       
+       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);
+       }
+}
+
+static void http_persistent_handles_hash_dtor(void *h)
+{
+       http_persistent_handles_hash_dtor_ex(h, zend_hash_destroy);
+}
+
+PHP_MINIT_FUNCTION(http_persistent_handle)
+{
+       zend_hash_init(&http_persistent_handles_hash, 0, NULL, http_persistent_handles_hash_dtor, 1);
+#ifdef ZTS
+       http_persistent_handles_lock = tsrm_mutex_alloc();
+#endif
+       return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(http_persistent_handle)
+{
+       zend_hash_destroy(&http_persistent_handles_hash);
+#ifdef ZTS
+       tsrm_mutex_free(http_persistent_handles_lock);
+#endif
+       return SUCCESS;
+}
+
+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;
+       
+       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;
+       }
+       UNLOCK();
+       
+       return status;
+}
+
+PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len)
+{
+       http_persistent_handles_hash_entry *hentry;
+       
+       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);
+               }
+       } 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);
+               }
+       }
+       UNLOCK();
+}
+
+PHP_HTTP_API int _http_persistent_handle_statall_ex(char ***names, int **counts, int persistent)
+{
+       int i, n;
+       char *key;
+       http_persistent_handles_hash_entry *hentry;
+       
+       LOCK();
+       if ((n = zend_hash_num_elements(&http_persistent_handles_hash))) {
+               *names = safe_pemalloc(n, sizeof(char **), 0, persistent);
+               *counts = safe_pemalloc(n, sizeof(int), 0, persistent);
+               
+               for (   i = 0, zend_hash_internal_pointer_reset(&http_persistent_handles_hash);
+                               HASH_KEY_NON_EXISTANT != zend_hash_get_current_key(&http_persistent_handles_hash, &key, NULL, 0) &&
+                               SUCCESS == zend_hash_get_current_data(&http_persistent_handles_hash, (void *) &hentry);
+                               ++i, zend_hash_move_forward(&http_persistent_handles_hash)) {
+                       (*names)[i] = pestrdup(key, persistent);
+                       (*counts)[i] = zend_hash_num_elements(&hentry->list);
+               }
+       }
+       UNLOCK();
+       
+       return n;
+}
+
+PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle)
+{
+       STATUS status = FAILURE;
+       ulong index;
+       http_persistent_handles_hash_entry *hentry;
+       http_persistent_handles_list_entry *lentry;
+       
+       LOCK();
+       if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &hentry)) {
+               zend_hash_internal_pointer_reset(&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;
+               }
+       }
+       UNLOCK();
+       
+       return status;
+}
+
+PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle)
+{
+       STATUS status = FAILURE;
+       http_persistent_handles_hash_entry *hentry;
+       http_persistent_handles_list_entry lentry;
+       
+       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;
+               }
+       }
+       UNLOCK();
+       
+       return status;
+}
+
+#endif /* HTTP_HAVE_PERSISTENT_HANDLES */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
+
index 6528b97d303c843eab4220bd81a557755f6ac10a..b9931c81dd35ca74611b01281021632ea7e5e396 100644 (file)
@@ -21,6 +21,9 @@
 #include "php_http_api.h"
 #include "php_http_request_api.h"
 #include "php_http_url_api.h"
+#ifdef HTTP_HAVE_PERSISTENT_HANDLES
+#      include "php_http_persistent_handle_api.h"
+#endif
 
 #ifdef ZEND_ENGINE_2
 #      include "php_http_request_object.h"
@@ -109,6 +112,12 @@ PHP_MINIT_FUNCTION(http_request)
                return FAILURE;
        }
        
+#ifdef HTTP_HAVE_PERSISTENT_HANDLES
+       if (SUCCESS != http_persistent_handle_provide("http_request", curl_easy_init, curl_easy_cleanup)) {
+               return FAILURE;
+       }
+#endif
+       
        HTTP_LONG_CONSTANT("HTTP_AUTH_BASIC", CURLAUTH_BASIC);
        HTTP_LONG_CONSTANT("HTTP_AUTH_DIGEST", CURLAUTH_DIGEST);
        HTTP_LONG_CONSTANT("HTTP_AUTH_NTLM", CURLAUTH_NTLM);
@@ -176,10 +185,18 @@ static int http_curl_dummy_callback(char *data, size_t n, size_t l, void *s) { r
 static curlioerr http_curl_ioctl_callback(CURL *, curliocmd, void *);
 /* }}} */
 
+#ifdef HTTP_HAVE_PERSISTENT_HANDLES
+#      define HTTP_CURL_HANDLE_CTOR(ch) (SUCCESS == http_persistent_handle_acquire("http_request", &(ch)))
+#      define HTTP_CURL_HANDLE_DTOR(chp) http_persistent_handle_release("http_request", (chp))
+#else
+#      define HTTP_CURL_HANDLE_CTOR(ch) ((ch) = curl_easy_init())
+#      define HTTP_CURL_HANDLE_DTOR(chp) curl_easy_cleanup(*(chp)); *(chp) = NULL
+#endif
+
 /* {{{ CURL *http_curl_init(http_request *) */
 PHP_HTTP_API CURL * _http_curl_init_ex(CURL *ch, http_request *request)
 {
-       if (ch || (ch = curl_easy_init())) {
+       if (ch || HTTP_CURL_HANDLE_CTOR(ch)) {
 #if defined(ZTS)
                curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
 #endif
@@ -214,13 +231,12 @@ PHP_HTTP_API CURL * _http_curl_init_ex(CURL *ch, http_request *request)
 PHP_HTTP_API void _http_curl_free(CURL **ch)
 {
        if (*ch) {
-               /* avoid nasty segfaults with already cleaned up callbacks */
                curl_easy_setopt(*ch, CURLOPT_NOPROGRESS, 1L);
                curl_easy_setopt(*ch, CURLOPT_PROGRESSFUNCTION, NULL);
                curl_easy_setopt(*ch, CURLOPT_VERBOSE, 0L);
                curl_easy_setopt(*ch, CURLOPT_DEBUGFUNCTION, NULL);
-               curl_easy_cleanup(*ch);
-               *ch = NULL;
+               
+               HTTP_CURL_HANDLE_DTOR(ch);
        }
 }
 /* }}} */
index 128ef6f32cbc06453c3bd9fe04074c3d8273aba3..12bcc978745d136853e3db71133b0f05583b9835 100644 (file)
@@ -31,7 +31,7 @@ support. Parallel requests are available for PHP 5 and greater.
  <date>2007-01-23</date>
  <version>
   <release>1.5.0dev</release>
-  <api>1.4.0</api>
+  <api>1.5.0</api>
  </version>
  <stability>
   <release>beta</release>
@@ -39,7 +39,8 @@ support. Parallel requests are available for PHP 5 and greater.
  </stability>
  <license>BSD, revised</license>
  <notes><![CDATA[
-+ Add HttpMessage::fromEnv(int type[, string class_name = "HttpMessage"]) (Clay Loveless)
++ Added HttpMessage::fromEnv(int type[, string class_name = "HttpMessage"]) (Clay Loveless)
++ Added --enable-http-persistent-handles (Clay Loveless)
 ]]></notes>
  <contents>
   <dir name="/">
@@ -75,6 +76,7 @@ support. Parallel requests are available for PHP 5 and greater.
    <file role="src" name="php_http_headers_api.h"/>
    <file role="src" name="php_http_info_api.h"/>
    <file role="src" name="php_http_message_api.h"/>
+   <file role="src" name="php_http_persistent_handles_api.h"/>
    <file role="src" name="php_http_querystring_api.h"/>
    <file role="src" name="php_http_request_api.h"/>
    <file role="src" name="php_http_request_int.h"/>
@@ -106,6 +108,7 @@ support. Parallel requests are available for PHP 5 and greater.
    <file role="src" name="http_headers_api.c"/>
    <file role="src" name="http_info_api.c"/>
    <file role="src" name="http_message_api.c"/>
+   <file role="src" name="http_persistent_handles_api.c"/>
    <file role="src" name="http_querystring_api.c"/>
    <file role="src" name="http_request_api.c"/>
    <file role="src" name="http_request_info.c"/>
@@ -287,6 +290,11 @@ support. Parallel requests are available for PHP 5 and greater.
    prompt="whether to depend on extensions which have been built shared"
    default="yes"
   />
+  <configureoption
+   name="enable-http-persistent-handles"
+   prompt="whether to enable per-process persistent cURL handles"
+   default="no"
+  />
   <filelist>
    <install as="http.ini" name="docs/http.ini"/>
    <install as="examples/tutorial.txt" name="docs/examples/tutorial.txt"/>
index caa5c0cff934197ee0cdf91e28a8dd88e8e825a3..a3d6bd85688a4ab00bef18622ed670921308db4e 100644 (file)
@@ -203,6 +203,10 @@ PHP_FUNCTION(http_get_request_body);
 PHP_FUNCTION(http_get_request_body_stream);
 PHP_FUNCTION(http_match_request_header);
 #ifdef HTTP_HAVE_CURL
+#      ifdef HTTP_HAVE_PERSISTENT_HANDLES
+PHP_FUNCTION(http_persistent_handles_count);
+PHP_FUNCTION(http_persistent_handles_clean);
+#      endif
 PHP_FUNCTION(http_get);
 PHP_FUNCTION(http_head);
 PHP_FUNCTION(http_post_data);
diff --git a/php_http_persistent_handle_api.h b/php_http_persistent_handle_api.h
new file mode 100644 (file)
index 0000000..661c8e1
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+    +--------------------------------------------------------------------+
+    | PECL :: http                                                       |
+    +--------------------------------------------------------------------+
+    | Redistribution and use in source and binary forms, with or without |
+    | modification, are permitted provided that the conditions mentioned |
+    | in the accompanying LICENSE file are met.                          |
+    +--------------------------------------------------------------------+
+    | Copyright (c) 2004-2006, Michael Wallner <mike@php.net>            |
+    +--------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef HTTP_PERSISTENT_HANDLE_H
+#define HTTP_PERSISTENT_HANDLE_H
+
+#ifdef HTTP_HAVE_PERSISTENT_HANDLES
+typedef void *(*http_persistent_handle_ctor)(void);
+typedef void (*http_persistent_handle_dtor)(void *handle);
+
+PHP_MINIT_FUNCTION(http_persistent_handle);
+PHP_MSHUTDOWN_FUNCTION(http_persistent_handle);
+
+#define http_persistent_handle_provide(n, c, d) _http_persistent_handle_provide_ex((n), strlen(n), (c), (d))
+#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_statall(n, c) _http_persistent_handle_statall_ex((n), (c), 0)
+#define http_persistent_handle_statall_ex(n, c, p) _http_persistent_handle_statall_ex((n), (c), (p))
+PHP_HTTP_API int _http_persistent_handle_statall_ex(char ***names, int **counts, int persistent);
+
+#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_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);
+
+#endif /* HTTP_HAVE_PERSISTENT_HANDLES */
+#endif /* HTTP_PERSISTENT_HANDLE_H */