]> 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:49:16 +0000 (10:49 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 19 Apr 2006 10:49:16 +0000 (10:49 +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/Soa
pServer 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 w
sdl 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.

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

index 455b9653918b0acbc67796acde4ace704d9fb4cd..2cd36a8692c9539d318198ec50715985287ef6a2 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 875789143b638863ba179680c66a927ec4ae3c56..aa582911c72055b8ce311ddb254714dea4981c9a 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;
+       zend_bool 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);
@@ -2110,7 +2145,7 @@ PHP_METHOD(SoapClient, SoapClient)
        zval *options = NULL;
        int  soap_version = SOAP_1_1;
        php_stream_context *context = NULL;
-       zend_bool persistent;
+       zend_bool cache_wsdl;
 
        SOAP_CLIENT_BEGIN_CODE();
 
@@ -2127,7 +2162,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);
@@ -2276,8 +2311,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 &&
@@ -2299,7 +2335,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();