]> granicus.if.org Git - php/commitdiff
Cleaned up Andrei's patch for caching WSDL in process memory, added TTL and LIMIT...
authorDmitry Stogov <dmitry@php.net>
Wed, 19 Apr 2006 10:48:54 +0000 (10:48 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 19 Apr 2006 10:48:54 +0000 (10:48 +0000)
Memory cache is disblead by fefault because it is experemental and isn't tested enough. It can be enabled whit configuartion directive "soap.wsdl_cache = WSDL_CACHE_MEMORY" or "soap.wsdl_cache = WSDL_CACHE_BOTH" or derectly in SoapClent/SoapServer constructor: $ws = new SoapClient($wsdl, array("cache_wsdl"=>WSDL_CACHE_BOTH))
Disk and memory caches use the same TTL value - "soap.wsdl_cache_ttl".
Configuration directive "soap.wsdl_cache_limit" restricts the number of cached wsdl files in memory. Adding new files into full memory cache will delete oldest files from it.
Note that, each PHP process or thread uses it's own memory cache.

NEWS
ext/soap/php_sdl.c
ext/soap/php_sdl.h
ext/soap/php_soap.h
ext/soap/soap.c
ext/soap/tests/bugs/bug37083.phpt

diff --git a/NEWS b/NEWS
index 952dd6a62e24896cc52265e7ce44e4c68f4b17ea..80ed4314a3cef8a2d7f06c7600dead7e684a539b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -30,7 +30,7 @@ PHP                                                                        NEWS
 06 Apr 2006, PHP 5.1.3RC3
 - Eliminated run-time constant fetching for TRUE, FALSE and NULL. (Dmitry)
 - Changed SOAP extension to cache WSDL structure in memory and thus speed up
-  SoapClient/SoapServer construction. (Andrei)
+  SoapClient/SoapServer construction. (Andrei, Dmitry)
 - Removed the E_STRICT deprecation notice from "var". (Ilia)
 - Added overflow checks to wordwrap() function. (Ilia)
 - Added support for BINARY_DOUBLE and BINARY_FLOAT to PDO_OCI and OCI8 
index 3d09b6bbc0ca4b0e8bac42ef6252d8f8098632d5..e0f1a8dffafa90663bfb3b02fed008b717958a9c 100644 (file)
@@ -1417,7 +1417,7 @@ static HashTable* sdl_deserialize_parameters(encodePtr *encoders, sdlTypePtr *ty
        return ht;
 }
 
-static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t TSRMLS_DC)
+static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t, time_t *cached TSRMLS_DC)
 {
        sdlPtr sdl;
        time_t old_t;
@@ -1461,6 +1461,7 @@ static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t TSRML
                efree(buf);
                return NULL;
        }
+       *cached = old_t;
 
        WSDL_CACHE_GET_INT(i, &in);
        if (i == 0 && strncmp(in, uri, i) != 0) {
@@ -3027,29 +3028,109 @@ static sdlPtr make_persistent_sdl(sdlPtr sdl TSRMLS_DC)
        return psdl;
 }
 
-sdlPtr get_sdl(zval *this_ptr, char *uri, zend_bool persistent TSRMLS_DC)
+typedef struct _sdl_cache_bucket {
+       sdlPtr sdl;
+       time_t time;
+} sdl_cache_bucket;
+
+static void delete_psdl(void *data)
+{
+       sdl_cache_bucket *p = (sdl_cache_bucket*)data;
+       sdlPtr tmp = p->sdl;
+
+       zend_hash_destroy(&tmp->functions);
+       if (tmp->source) {
+               free(tmp->source);
+       }
+       if (tmp->target_ns) {
+               free(tmp->target_ns);
+       }
+       if (tmp->elements) {
+               zend_hash_destroy(tmp->elements);
+               free(tmp->elements);
+       }
+       if (tmp->encoders) {
+               zend_hash_destroy(tmp->encoders);
+               free(tmp->encoders);
+       }
+       if (tmp->types) {
+               zend_hash_destroy(tmp->types);
+               free(tmp->types);
+       }
+       if (tmp->groups) {
+               zend_hash_destroy(tmp->groups);
+               free(tmp->groups);
+       }
+       if (tmp->bindings) {
+               zend_hash_destroy(tmp->bindings);
+               free(tmp->bindings);
+       }
+       if (tmp->requests) {
+               zend_hash_destroy(tmp->requests);
+               free(tmp->requests);
+       }
+       free(tmp);
+}
+
+sdlPtr get_sdl(zval *this_ptr, char *uri, long cache_wsdl TSRMLS_DC)
 {
+       char  fn[MAXPATHLEN];
        sdlPtr sdl = NULL;
        char* old_error_code = SOAP_GLOBAL(error_code);
-       int uri_len;
+       int uri_len = 0;
        php_stream_context *context=NULL;
        zval **tmp, **proxy_host, **proxy_port, *orig_context = NULL, *new_context = NULL;
        smart_str headers = {0};
-       char *pkey = NULL;
-       int plen;
+       char* key = NULL;
+       time_t t = time(0);
+
+       if (strchr(uri,':') != NULL || IS_ABSOLUTE_PATH(uri, uri_len)) {
+               uri_len = strlen(uri);
+       } else if (VCWD_REALPATH(uri, fn) == NULL) {
+               cache_wsdl = WSDL_CACHE_NONE;
+       } else {
+               uri = fn;
+               uri_len = strlen(uri);
+       }
 
-       if (persistent) {
-               zend_rsrc_list_entry *le_ptr;
+       if ((cache_wsdl & WSDL_CACHE_MEMORY) && SOAP_GLOBAL(mem_cache)) {
+               sdl_cache_bucket *p;
 
-               plen = spprintf(&pkey, 0, "SOAP:WSDL:%s", uri);
-               if (SUCCESS == zend_hash_find(&EG(persistent_list), pkey, plen+1, (void*)&le_ptr)) {
-                       if (Z_TYPE_P(le_ptr) == php_soap_psdl_list_entry()) {
-                               efree(pkey);
-                               return (sdlPtr)le_ptr->ptr;
+               if (SUCCESS == zend_hash_find(SOAP_GLOBAL(mem_cache), uri, uri_len+1, (void*)&p)) {
+                       if (p->time < t - SOAP_GLOBAL(cache_ttl)) {
+                               /* in-memory cache entry is expired */
+                               zend_hash_del(&EG(persistent_list), uri, uri_len+1);
+                       } else {
+                               return p->sdl;
                        }
                }
        }
 
+       if ((cache_wsdl & WSDL_CACHE_DISK) && (uri_len < MAXPATHLEN)) {
+               time_t t = time(0);
+               char md5str[33];
+               PHP_MD5_CTX context;
+               unsigned char digest[16];
+               int len = strlen(SOAP_GLOBAL(cache_dir));
+               time_t cached;
+
+               md5str[0] = '\0';
+               PHP_MD5Init(&context);
+               PHP_MD5Update(&context, uri, uri_len);
+               PHP_MD5Final(digest, &context);
+               make_digest(md5str, digest);
+               key = emalloc(len+sizeof("/wsdl-")-1+sizeof(md5str));
+               memcpy(key,SOAP_GLOBAL(cache_dir),len);
+               memcpy(key+len,"/wsdl-",sizeof("/wsdl-")-1);
+               memcpy(key+len+sizeof("/wsdl-")-1,md5str,sizeof(md5str));
+
+               if ((sdl = get_sdl_from_cache(key, uri, t-SOAP_GLOBAL(cache_ttl), &cached TSRMLS_CC)) != NULL) {
+                       t = cached;
+                       efree(key);
+                       goto cache_in_memory;
+               }
+       }
+
        if (SUCCESS == zend_hash_find(Z_OBJPROP_P(this_ptr),
                        "_stream_context", sizeof("_stream_context"), (void**)&tmp)) {
                context = php_stream_context_from_zval(*tmp, 0);
@@ -3113,59 +3194,66 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, zend_bool persistent TSRMLS_DC)
 
        SOAP_GLOBAL(error_code) = "WSDL";
 
-       if (SOAP_GLOBAL(cache_enabled) && ((uri_len = strlen(uri)) < MAXPATHLEN)) {
-               char  fn[MAXPATHLEN];
-
-               if (strchr(uri,':') != NULL || IS_ABSOLUTE_PATH(uri, uri_len)) {
-                       strcpy(fn, uri);
-               } else if (VCWD_REALPATH(uri, fn) == NULL) {
-                       sdl = load_wsdl(this_ptr, uri TSRMLS_CC);
-               }
-               if (sdl == NULL) {
-                       char* key;
-                       time_t t = time(0);
-                       char md5str[33];
-                       PHP_MD5_CTX context;
-                       unsigned char digest[16];
-                       int len = strlen(SOAP_GLOBAL(cache_dir));
-
-                       md5str[0] = '\0';
-                       PHP_MD5Init(&context);
-                       PHP_MD5Update(&context, fn, strlen(fn));
-                       PHP_MD5Final(digest, &context);
-                       make_digest(md5str, digest);
-                       key = emalloc(len+sizeof("/wsdl-")-1+sizeof(md5str));
-                       memcpy(key,SOAP_GLOBAL(cache_dir),len);
-                       memcpy(key+len,"/wsdl-",sizeof("/wsdl-")-1);
-                       memcpy(key+len+sizeof("/wsdl-")-1,md5str,sizeof(md5str));
-
-                       if ((sdl = get_sdl_from_cache(key, fn, t-SOAP_GLOBAL(cache_ttl) TSRMLS_CC)) == NULL) {
-                               sdl = load_wsdl(this_ptr, fn TSRMLS_CC);
-                               if (sdl != NULL) {
-                                       add_sdl_to_cache(key, fn, t, sdl TSRMLS_CC);
-                               }
-                       }
-                       efree(key);
-               }
-       } else {
-               sdl = load_wsdl(this_ptr, uri TSRMLS_CC);
-       }
-
+       sdl = load_wsdl(this_ptr, uri TSRMLS_CC);
        if (sdl) {
                sdl->is_persistent = 0;
        }
 
-       if (persistent) {
+       SOAP_GLOBAL(error_code) = old_error_code;
+
+       if (context) {
+               php_libxml_switch_context(orig_context TSRMLS_CC);
+               zval_ptr_dtor(&new_context);
+       }
+
+       if ((cache_wsdl & WSDL_CACHE_DISK) && key) {
                if (sdl) {
-                       zend_rsrc_list_entry le;
-                       sdlPtr psdl = make_persistent_sdl(sdl TSRMLS_CC);
+                       add_sdl_to_cache(key, uri, t, sdl TSRMLS_CC);
+               }
+               efree(key);
+       }
+
+cache_in_memory:
+       if (cache_wsdl & WSDL_CACHE_MEMORY) {
+               if (sdl) {
+                       sdlPtr psdl;
+                       sdl_cache_bucket p;
+
+                       if (SOAP_GLOBAL(mem_cache) == NULL) {
+                               SOAP_GLOBAL(mem_cache) = malloc(sizeof(HashTable));
+                               zend_hash_init(SOAP_GLOBAL(mem_cache), 0, NULL, delete_psdl, 1);
+                       } else if (SOAP_GLOBAL(cache_limit) > 0 &&
+                                  SOAP_GLOBAL(cache_limit) <= zend_hash_num_elements(SOAP_GLOBAL(mem_cache))) {
+                               /* in-memory cache overflow */
+                               sdl_cache_bucket *q;
+                               HashPosition pos;
+                               time_t latest = t;
+                               char *key = NULL;
+                               uint key_len;
+                               ulong idx;
+
+                               for (zend_hash_internal_pointer_reset_ex(SOAP_GLOBAL(mem_cache), &pos);
+                                        zend_hash_get_current_data_ex(SOAP_GLOBAL(mem_cache), (void **) &q, &pos) == SUCCESS;
+                                        zend_hash_move_forward_ex(SOAP_GLOBAL(mem_cache), &pos)) {
+                                       if (q->time < latest) {
+                                               latest = q->time;
+                                               zend_hash_get_current_key_ex(SOAP_GLOBAL(mem_cache), &key, &key_len, &idx, 0, &pos);
+                                       }
+                               }
+                               if (key) {
+                                       zend_hash_del(SOAP_GLOBAL(mem_cache), key, key_len);
+                               } else {
+                                       return sdl;
+                               }
+                       }
 
+                       psdl = make_persistent_sdl(sdl TSRMLS_CC);
                        psdl->is_persistent = 1;
-                       le.type = php_soap_psdl_list_entry();
-                       le.ptr = psdl;
-                       le.refcount = 0;
-                       if (SUCCESS == zend_hash_update(&EG(persistent_list), pkey,
-                                                                                       plen+1, (void*)&le, sizeof(le), NULL)) {
+                       p.time = t;
+                       p.sdl = psdl;
+
+                       if (SUCCESS == zend_hash_update(SOAP_GLOBAL(mem_cache), uri,
+                                                                                       uri_len+1, (void*)&p, sizeof(sdl_cache_bucket), NULL)) {
                                /* remove non-persitent sdl structure */
                                delete_sdl_impl(sdl);
                                /* and replace it with persistent one */
@@ -3173,18 +3261,10 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, zend_bool persistent TSRMLS_DC)
                        } else {
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to register persistent entry");
                                /* clean up persistent sdl */
-                               delete_psdl(&le TSRMLS_CC);
+                               delete_psdl(&p);
                                /* keep non-persistent sdl and return it */
                        }
                }
-               efree(pkey);
-       }
-
-       SOAP_GLOBAL(error_code) = old_error_code;
-
-       if (context) {
-               php_libxml_switch_context(orig_context TSRMLS_CC);
-               zval_ptr_dtor(&new_context);
        }
 
        return sdl;
@@ -3238,46 +3318,6 @@ void delete_sdl(void *handle)
        }
 }
 
-ZEND_RSRC_DTOR_FUNC(delete_psdl)
-{
-       if (rsrc->ptr) {
-               sdlPtr tmp = (sdlPtr)rsrc->ptr;
-
-               zend_hash_destroy(&tmp->functions);
-               if (tmp->source) {
-                       free(tmp->source);
-               }
-               if (tmp->target_ns) {
-                       free(tmp->target_ns);
-               }
-               if (tmp->elements) {
-                       zend_hash_destroy(tmp->elements);
-                       free(tmp->elements);
-               }
-               if (tmp->encoders) {
-                       zend_hash_destroy(tmp->encoders);
-                       free(tmp->encoders);
-               }
-               if (tmp->types) {
-                       zend_hash_destroy(tmp->types);
-                       free(tmp->types);
-               }
-               if (tmp->groups) {
-                       zend_hash_destroy(tmp->groups);
-                       free(tmp->groups);
-               }
-               if (tmp->bindings) {
-                       zend_hash_destroy(tmp->bindings);
-                       free(tmp->bindings);
-               }
-               if (tmp->requests) {
-                       zend_hash_destroy(tmp->requests);
-                       free(tmp->requests);
-               }
-               free(tmp);
-       }
-}
-
 static void delete_binding(void *data)
 {
        sdlBindingPtr binding = *((sdlBindingPtr*)data);
index 31a8a8a07305fba51bd42ebe511626147ed2da8a..7ac46e86f301001d543ce8440b37ffbd6dd3fce3 100644 (file)
@@ -252,9 +252,7 @@ struct _sdlAttribute {
 };
 
 
-int php_soap_psdl_list_entry(void);
-
-sdlPtr get_sdl(zval *this_ptr, char *uri, zend_bool persistent TSRMLS_DC);
+sdlPtr get_sdl(zval *this_ptr, char *uri, long cache_wsdl TSRMLS_DC);
 
 encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr data, const char *type);
 encodePtr get_encoder(sdlPtr sdl, const char *ns, const char *type);
@@ -265,6 +263,5 @@ sdlBindingPtr get_binding_from_name(sdlPtr sdl, char *name, char *ns);
 
 void delete_sdl(void *handle);
 void delete_sdl_impl(void *handle);
-ZEND_RSRC_DTOR_FUNC(delete_psdl);
 
 #endif
index a0a7bf6dde7b05bb3772b2811e8ce272cdf4c6e2..d6988cd0f07a4e4c4ed0e0139535876b6f412b75 100644 (file)
@@ -158,6 +158,11 @@ struct _soapService {
 #define SOAP_SINGLE_ELEMENT_ARRAYS  (1<<0)
 #define SOAP_WAIT_ONE_WAY_CALLS     (2<<0)
 
+#define WSDL_CACHE_NONE     0x0
+#define WSDL_CACHE_DISK     0x1
+#define WSDL_CACHE_MEMORY   0x2
+#define WSDL_CACHE_BOTH     0x3
+
 ZEND_BEGIN_MODULE_GLOBALS(soap)
        HashTable  defEncNs;     /* mapping of default namespaces to prefixes */
        HashTable  defEnc;
@@ -169,9 +174,11 @@ ZEND_BEGIN_MODULE_GLOBALS(soap)
        zend_bool  use_soap_error_handler;
        char*      error_code;
        zval*      error_object;
-       zend_bool  cache_enabled;
+       long       cache;
        char*      cache_dir;
        long       cache_ttl;
+       long       cache_limit;
+       HashTable *mem_cache;
        xmlCharEncodingHandlerPtr encoding;
        HashTable *class_map;
        int        features;
index 3130c3abddfdc6f3403d871e237656d6d92f3f9b..626a633b2d8cc9723382f44542f8d38653e98f91 100644 (file)
@@ -33,7 +33,6 @@
 static int le_sdl = 0;
 int le_url = 0;
 static int le_service = 0;
-static int le_psdl = 0;
 
 typedef struct _soapHeader {
        sdlFunctionPtr                    function;
@@ -227,11 +226,6 @@ static char *zend_str_tolower_copy(char *dest, const char *source, unsigned int
 }
 #endif
 
-int php_soap_psdl_list_entry(void)
-{
-       return le_psdl;
-}
-
 /*
   Registry Functions
   TODO: this!
@@ -397,18 +391,49 @@ zend_module_entry soap_module_entry = {
 ZEND_GET_MODULE(soap)
 #endif
 
+#ifndef ZEND_ENGINE_2
+# define OnUpdateLong OnUpdateInt
+#endif
+
+ZEND_API ZEND_INI_MH(OnUpdateCacheEnabled)
+{
+       long *p;
+#ifndef ZTS
+       char *base = (char *) mh_arg2;
+#else
+       char *base;
+
+       base = (char *) ts_resource(*((int *) mh_arg2));
+#endif
+
+       p = (long*) (base+(size_t) mh_arg1);
+
+       if (new_value_length==2 && strcasecmp("on", new_value)==0) {
+               *p = 1;
+       } 
+       else if (new_value_length==3 && strcasecmp("yes", new_value)==0) {
+               *p = 1;
+       } 
+       else if (new_value_length==4 && strcasecmp("true", new_value)==0) {
+               *p = 1;
+       } 
+       else {
+               *p = (long) (atoi(new_value) != 0);
+       }
+       return SUCCESS;
+}
+
 PHP_INI_BEGIN()
-STD_PHP_INI_ENTRY("soap.wsdl_cache_enabled",     "1", PHP_INI_ALL, OnUpdateBool,
-                  cache_enabled, zend_soap_globals, soap_globals)
+STD_PHP_INI_ENTRY("soap.wsdl_cache_enabled",     "1", PHP_INI_ALL, OnUpdateCacheEnabled,
+                  cache, zend_soap_globals, soap_globals)
 STD_PHP_INI_ENTRY("soap.wsdl_cache_dir",         "/tmp", PHP_INI_ALL, OnUpdateString,
                   cache_dir, zend_soap_globals, soap_globals)
-#ifdef ZEND_ENGINE_2
 STD_PHP_INI_ENTRY("soap.wsdl_cache_ttl",         "86400", PHP_INI_ALL, OnUpdateLong,
                   cache_ttl, zend_soap_globals, soap_globals)
-#else
-STD_PHP_INI_ENTRY("soap.wsdl_cache_ttl",         "86400", PHP_INI_ALL, OnUpdateInt,
-                  cache_ttl, zend_soap_globals, soap_globals)
-#endif
+STD_PHP_INI_ENTRY("soap.wsdl_cache",             "1", PHP_INI_ALL, OnUpdateLong,
+                  cache, zend_soap_globals, soap_globals)
+STD_PHP_INI_ENTRY("soap.wsdl_cache_limit",       "5", PHP_INI_ALL, OnUpdateLong,
+                  cache_limit, zend_soap_globals, soap_globals)
 PHP_INI_END()
 
 static HashTable defEnc, defEncIndex, defEncNs;
@@ -465,6 +490,7 @@ static void php_soap_init_globals(zend_soap_globals *soap_globals TSRMLS_DC)
        soap_globals->error_object = NULL;
        soap_globals->sdl = NULL;
        soap_globals->soap_version = SOAP_1_1;
+       soap_globals->mem_cache = NULL;
 }
 
 PHP_MSHUTDOWN_FUNCTION(soap)
@@ -473,6 +499,10 @@ PHP_MSHUTDOWN_FUNCTION(soap)
        zend_hash_destroy(&SOAP_GLOBAL(defEnc));
        zend_hash_destroy(&SOAP_GLOBAL(defEncIndex));
        zend_hash_destroy(&SOAP_GLOBAL(defEncNs));
+       if (SOAP_GLOBAL(mem_cache)) {
+               zend_hash_destroy(SOAP_GLOBAL(mem_cache));
+               free(SOAP_GLOBAL(mem_cache));
+       }
        UNREGISTER_INI_ENTRIES();
        return SUCCESS;
 }
@@ -558,7 +588,6 @@ PHP_MINIT_FUNCTION(soap)
        soap_header_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
 
        le_sdl = register_list_destructors(delete_sdl, NULL);
-       le_psdl = zend_register_list_destructors_ex(NULL, delete_psdl, "SOAP persistent WSDL", module_number);
        le_url = register_list_destructors(delete_url, NULL);
        le_service = register_list_destructors(delete_service, NULL);
 
@@ -646,6 +675,11 @@ PHP_MINIT_FUNCTION(soap)
        REGISTER_LONG_CONSTANT("SOAP_SINGLE_ELEMENT_ARRAYS", SOAP_SINGLE_ELEMENT_ARRAYS, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("SOAP_WAIT_ONE_WAY_CALLS", SOAP_WAIT_ONE_WAY_CALLS, CONST_CS | CONST_PERSISTENT);
 
+       REGISTER_LONG_CONSTANT("WSDL_CACHE_NONE",   WSDL_CACHE_NONE,   CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("WSDL_CACHE_DISK",   WSDL_CACHE_DISK,   CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("WSDL_CACHE_MEMORY", WSDL_CACHE_MEMORY, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("WSDL_CACHE_BOTH",   WSDL_CACHE_BOTH,   CONST_CS | CONST_PERSISTENT);
+
        old_error_handler = zend_error_cb;
        zend_error_cb = soap_error_handler;
 
@@ -912,7 +946,7 @@ PHP_METHOD(SoapServer, SoapServer)
        zval *wsdl, *options = NULL;
        int ret;
        int version = SOAP_1_1;
-       zend_bool persistent;
+       long cache_wsdl;
 
        SOAP_SERVER_BEGIN_CODE();
 
@@ -930,7 +964,7 @@ PHP_METHOD(SoapServer, SoapServer)
        service = emalloc(sizeof(soapService));
        memset(service, 0, sizeof(soapService));
 
-       persistent = SOAP_GLOBAL(cache_enabled);
+       cache_wsdl = SOAP_GLOBAL(cache);
 
        if (options != NULL) {
                HashTable *ht = Z_ARRVAL_P(options);
@@ -982,8 +1016,9 @@ PHP_METHOD(SoapServer, SoapServer)
                        service->features = Z_LVAL_PP(tmp);
                }
 
-               if (zend_hash_find(ht, "cache_wsdl", sizeof("cache_wsdl"), (void**)&tmp) == SUCCESS) {
-                       persistent = zend_is_true(*tmp);
+               if (zend_hash_find(ht, "cache_wsdl", sizeof("cache_wsdl"), (void**)&tmp) == SUCCESS &&
+                   Z_TYPE_PP(tmp) == IS_LONG) {
+                       cache_wsdl = Z_LVAL_PP(tmp);
                }
 
        } else if (wsdl == NULL) {
@@ -997,7 +1032,7 @@ PHP_METHOD(SoapServer, SoapServer)
        zend_hash_init(service->soap_functions.ft, 0, NULL, ZVAL_PTR_DTOR, 0);
 
        if (wsdl) {
-               service->sdl = get_sdl(this_ptr, Z_STRVAL_P(wsdl), persistent TSRMLS_CC);
+               service->sdl = get_sdl(this_ptr, Z_STRVAL_P(wsdl), cache_wsdl TSRMLS_CC);
                if (service->uri == NULL) {
                        if (service->sdl->target_ns) {
                                service->uri = estrdup(service->sdl->target_ns);
@@ -2116,7 +2151,7 @@ PHP_METHOD(SoapClient, SoapClient)
        zval *options = NULL;
        int  soap_version = SOAP_1_1;
        php_stream_context *context = NULL;
-       zend_bool persistent;
+       long cache_wsdl;
 
        SOAP_CLIENT_BEGIN_CODE();
 
@@ -2133,7 +2168,7 @@ PHP_METHOD(SoapClient, SoapClient)
                wsdl = NULL;
        }
 
-       persistent = SOAP_GLOBAL(cache_enabled);
+       cache_wsdl = SOAP_GLOBAL(cache);
 
        if (options != NULL) {
                HashTable *ht = Z_ARRVAL_P(options);
@@ -2282,8 +2317,9 @@ PHP_METHOD(SoapClient, SoapClient)
                        add_property_resource(this_ptr, "_stream_context", context->rsrc_id);
                }
        
-               if (zend_hash_find(ht, "cache_wsdl", sizeof("cache_wsdl"), (void**)&tmp) == SUCCESS) {
-                       persistent = zend_is_true(*tmp);
+               if (zend_hash_find(ht, "cache_wsdl", sizeof("cache_wsdl"), (void**)&tmp) == SUCCESS &&
+                   Z_TYPE_PP(tmp) == IS_LONG) {
+                       cache_wsdl = Z_LVAL_PP(tmp);
                }
 
                if (zend_hash_find(ht, "user_agent", sizeof("user_agent"), (void**)&tmp) == SUCCESS &&
@@ -2305,7 +2341,7 @@ PHP_METHOD(SoapClient, SoapClient)
                old_soap_version = SOAP_GLOBAL(soap_version);
                SOAP_GLOBAL(soap_version) = soap_version;
 
-               sdl = get_sdl(this_ptr, Z_STRVAL_P(wsdl), persistent TSRMLS_CC);
+               sdl = get_sdl(this_ptr, Z_STRVAL_P(wsdl), cache_wsdl TSRMLS_CC);
                ret = zend_list_insert(sdl, le_sdl);
 
                add_property_resource(this_ptr, "sdl", ret);
index 77e9181a9234d01da764b088c173e9b99e0ffe30..471b5e49ad618dba924898c36c81130779afc6ab 100755 (executable)
@@ -3,7 +3,7 @@ Bug #37083 (Frequent crashs in SOAP extension with new WSDL caching code in mult
 --SKIPIF--
 <?php require_once('skipif.inc'); ?>
 --INI--
-soap.wsdl_cache_enabled=0
+soap.wsdl_cache_enabled=3
 --FILE--
 <?php
 class TestSoapClient extends SoapClient {
@@ -43,7 +43,7 @@ EOF;
 for ($i = 0; $i < 10; $i++) {
        $ws=new TestSoapClient(dirname(__FILE__).'/bug37083.wsdl',
                    array('encoding'=>'ISO-8859-1',
-                         'cache_wsdl'=>1));
+                         'cache_wsdl'=>WSDL_CACHE_BOTH));
        $search=new stdClass();
        $search->queryString='argo';
        $search->ranges[]=$r=new stdClass();