Re: svn: /pecl/apc/trunk/ apc_cache.c apc_cache.h php_apc.c php_apc.h
| From: | shire | Date: | Thu, 24 Dec 2009 09:34:13 +0000 |
| Subject: | Re: svn: /pecl/apc/trunk/ apc_cache.c apc_cache.h php_apc.c php_apc.h | ||
| References: | 1 | Groups: | php.apc.dev |
| Request: | Send a blank email to php-apc-dev+get-252@lists.php.net to get a copy of this message | ||
hrm, yeah I don't think we can get away without the lock here, simply because of the (*slot)->next/key type pointer usage. I believe the structure would allow that to be an invalid pointer if it's still in the process of being updated, inserted, removed etc.
-shire
Rasmus Lerdorf wrote:
rasmus Wed, 23 Dec 2009 22:56:44 +0000Revision: http://svn.php.net/viewvc?view=revision&revision=292569 Log: I think apc_exists() is useful. Here is a non-locking version. Still mulling over whether we can get away without the lock here. I think we can. Requested in bug #16981 Bug: http://pecl.php.net/bugs/16981 (unknown) Changed paths:U pecl/apc/trunk/apc_cache.c U pecl/apc/trunk/apc_cache.h U pecl/apc/trunk/php_apc.c U pecl/apc/trunk/php_apc.hModified: pecl/apc/trunk/apc_cache.c =================================================================== --- pecl/apc/trunk/apc_cache.c 2009-12-23 22:33:12 UTC (rev 292568) +++ pecl/apc/trunk/apc_cache.c 2009-12-23 22:56:44 UTC (rev 292569) @@ -635,6 +635,36 @@ } /* }}} */ +/* {{{ apc_cache_user_exists */ +apc_cache_entry_t* apc_cache_user_exists(apc_cache_t* cache, char *strkey, int keylen, time_t t) +{+ slot_t** slot; + volatile apc_cache_entry_t* value = NULL;++ if(apc_cache_busy(cache)) + { + /* cache cleanup in progress */ + return NULL; + }++ slot =&cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];++ while (*slot) { + if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) { + /* Check to make sure this entry isn't expired by a hard TTL */ + if((*slot)->value->data.user.ttl&& (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl)< t) { + return NULL; + } + /* Otherwise we are fine, increase counters and return the cache entry */ + value = (*slot)->value; + return (apc_cache_entry_t*)value; + } + slot =&(*slot)->next; + } + return NULL;+} +/* }}} */ + /* {{{ apc_cache_user_update */ int _apc_cache_user_update(apc_cache_t* cache, char *strkey, int keylen, apc_cache_updater_t updater, void* data TSRMLS_DC) { Modified: pecl/apc/trunk/apc_cache.h =================================================================== --- pecl/apc/trunk/apc_cache.h 2009-12-23 22:33:12 UTC (rev 292568) +++ pecl/apc/trunk/apc_cache.h 2009-12-23 22:56:44 UTC (rev 292569) @@ -198,6 +198,15 @@ extern apc_cache_entry_t* apc_cache_user_find(T cache, char* strkey, int keylen, time_t t); /* + * apc_cache_user_exists searches for a cache entry by its hashed identifier, + * and returns a pointer to the entry if found, NULL otherwise. This is a + * quick non-locking version of apc_cache_user_find that does not modify the + * shared memory segment in any way. + * + */ +extern apc_cache_entry_t* apc_cache_user_exists(T cache, char* strkey, int keylen, time_t t); + +/* * apc_cache_delete and apc_cache_user_delete finds an entry in the cache and deletes it. */ extern int apc_cache_delete(apc_cache_t* cache, char *filename, int filename_len); Modified: pecl/apc/trunk/php_apc.c =================================================================== --- pecl/apc/trunk/php_apc.c 2009-12-23 22:33:12 UTC (rev 292568) +++ pecl/apc/trunk/php_apc.c 2009-12-23 22:56:44 UTC (rev 292569) @@ -984,7 +984,69 @@ } /* }}} */ +/* {{{ proto mixed apc_exists(mixed key) + */ +PHP_FUNCTION(apc_exists) {+ zval *key; + HashTable *hash; + HashPosition hpos; + zval **hentry; + char *strkey; + int strkey_len; + apc_cache_entry_t* entry; + zval *result; + zval *result_entry; + time_t t;+ if(!APCG(enabled)) RETURN_FALSE;++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z",&key) == FAILURE) { + return; + }++ t = apc_time();++ if(Z_TYPE_P(key) != IS_STRING&& Z_TYPE_P(key) != IS_ARRAY) { + convert_to_string(key); + }++ if(Z_TYPE_P(key) == IS_STRING) { + strkey = Z_STRVAL_P(key); + strkey_len = Z_STRLEN_P(key); + if(!strkey_len) RETURN_FALSE; + entry = apc_cache_user_exists(apc_user_cache, strkey, strkey_len + 1, t); + if(entry) { + RETURN_TRUE; + } + } else if(Z_TYPE_P(key) == IS_ARRAY) { + hash = Z_ARRVAL_P(key); + MAKE_STD_ZVAL(result); + array_init(result); + zend_hash_internal_pointer_reset_ex(hash,&hpos); + while(zend_hash_get_current_data_ex(hash, (void**)&hentry,&hpos) == SUCCESS) { + if(Z_TYPE_PP(hentry) != IS_STRING) { + apc_wprint("apc_exists() expects a string or array of strings."); + goto done; + } + entry = apc_cache_user_exists(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t); + if(entry) { + MAKE_STD_ZVAL(result_entry); + ZVAL_BOOL(result_entry, 1); + zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1,&result_entry, sizeof(zval*), NULL); + } /* don't set values we didn't find */ + zend_hash_move_forward_ex(hash,&hpos); + } + RETVAL_ZVAL(result, 0, 1); + } else { + apc_wprint("apc_exists() expects a string or array of strings."); + }+ +done:+ RETURN_FALSE;+} +/* }}} */ + + /* {{{ proto mixed apc_delete(mixed keys) */ PHP_FUNCTION(apc_delete) { @@ -1680,6 +1742,11 @@ZEND_ARG_INFO(0, context) ZEND_ARG_INFO(0, flags)ZEND_END_ARG_INFO() + +PHP_APC_ARGINFO +ZEND_BEGIN_ARG_INFO(arginfo_apc_exists, 0) + ZEND_ARG_INFO(0, keys) +ZEND_END_ARG_INFO() /* }}} */ /* {{{ apc_functions[] */ @@ -1702,6 +1769,7 @@PHP_FE(apc_bin_load, arginfo_apc_bin_load) PHP_FE(apc_bin_dumpfile, arginfo_apc_bin_dumpfile) PHP_FE(apc_bin_loadfile, arginfo_apc_bin_loadfile) + PHP_FE(apc_exists, arginfo_apc_exists) {NULL, NULL, NULL}}; /* }}} */ Modified: pecl/apc/trunk/php_apc.h =================================================================== --- pecl/apc/trunk/php_apc.h 2009-12-23 22:33:12 UTC (rev 292568) +++ pecl/apc/trunk/php_apc.h 2009-12-23 22:56:44 UTC (rev 292569) @@ -35,7 +35,7 @@ #include "apc_php.h" #include "apc_globals.h" -#define PHP_APC_VERSION "3.1.3p1" +#define PHP_APC_VERSION "3.1.4-dev" extern zend_module_entry apc_module_entry; #define apc_module_ptr&apc_module_entry