From d2e943a191d4abe7d0c8f766a2e296e52e852e09 Mon Sep 17 00:00:00 2001 From: Xuefer Date: Thu, 23 Aug 2012 08:27:54 +0000 Subject: [PATCH] closes #287: namespace support git-svn-id: svn://svn.lighttpd.net/xcache/trunk@1146 c26eb9a1-5813-0410-bd6c-c2e55f420ca7 --- ChangeLog | 3 + NEWS | 1 + htdocs/cacher/edit.php | 7 +- htdocs/cacher/edit.tpl.php | 2 +- htdocs/cacher/index.php | 1 + htdocs/cacher/sub/entrylist.tpl.php | 15 +- mod_cacher/xc_cacher.c | 431 ++++++++++++++++++++++++---- xcache_globals.h | 6 + 8 files changed, 408 insertions(+), 58 deletions(-) diff --git a/ChangeLog b/ChangeLog index 29a328e..85adc9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,8 @@ API Changes ======== * chg: proto array xcache_clear_cache(int type, [ int id = -1 ]). -1 means all cache splits * new: proto array xcache_enable_cache(int type, [ int id = -1, [ bool enable = true ] ]) + * new: proto array xcache_admin_namespace() + * new: proto array xcache_set_namespace(string namespace) Ini Settings Changes ======== @@ -17,6 +19,7 @@ ChangeLog * closes #73: warn for improper PHP_FCGI_CHILDREN setting fcgi mode (>=PHP_5_3) * closes #174: updates api to support "clear all cache" * closes #198: support for caching protocol url + * closes #287: namespace support * fixes #39: ini_set never work for xcache.coverager setting. use API instead * code refactor * uses extension= to load XCache. loading via zend_extension= is unsupported diff --git a/NEWS b/NEWS index 3d2a4cf..da4f34a 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ * updates api, adds a few ini * uses extension= to load XCache. loading via zend_extension= is unsupported * updates XCache admin page + * namespace support * professional helpers * adds an diagnosis module to give advise @ htdocs * auto disable caching on crash @ runtime diff --git a/htdocs/cacher/edit.php b/htdocs/cacher/edit.php index aca800e..a1da0f9 100644 --- a/htdocs/cacher/edit.php +++ b/htdocs/cacher/edit.php @@ -6,9 +6,14 @@ if (!isset($_GET['name'])) { die("missing name"); } -$name = $_GET['name']; // trigger auth $vcnt = xcache_count(XC_TYPE_VAR); +xcache_admin_namespace(); + +$name = $_GET['name']; +if (!empty($config['enable_eval'])) { + eval('$name = ' . $name . ';'); +} if ($_SERVER['REQUEST_METHOD'] == 'POST') { if (!empty($config['enable_eval'])) { diff --git a/htdocs/cacher/edit.tpl.php b/htdocs/cacher/edit.tpl.php index 317cf21..534c466 100644 --- a/htdocs/cacher/edit.tpl.php +++ b/htdocs/cacher/edit.tpl.php @@ -1,6 +1,6 @@
diff --git a/htdocs/cacher/index.php b/htdocs/cacher/index.php index de5acfb..8b91274 100644 --- a/htdocs/cacher/index.php +++ b/htdocs/cacher/index.php @@ -257,6 +257,7 @@ if (!extension_loaded('XCache')) { } xcache_count(XC_TYPE_PHP); // trigger auth +xcache_admin_namespace(); $doTypes = array( '' => _T('Summary'), diff --git a/htdocs/cacher/sub/entrylist.tpl.php b/htdocs/cacher/sub/entrylist.tpl.php index 6a871cd..2711c1d 100644 --- a/htdocs/cacher/sub/entrylist.tpl.php +++ b/htdocs/cacher/sub/entrylist.tpl.php @@ -60,7 +60,6 @@ foreach ($entries as $i => $entry) { TR; - $name = htmlspecialchars($entry['name']); $hits = number_format($entry['hits']); $size = size($entry['size']); if ($isphp) { @@ -80,19 +79,25 @@ TR; } if ($isphp) { - $namelink = $name; + $hname = htmlspecialchars($entry['name']); + $namelink = $hname; echo <<{$entry['cache_name']} {$i} ENTRY; } else { + $name = $entry['name']; + if (!empty($config['enable_eval'])) { + $name = var_export($name, true); + } + $uname = urlencode($name); + $hname = htmlspecialchars(str_replace("\0", "\\0", $entry['name'])); echo << + ENTRY; - $uname = urlencode($entry['name']); - $namelink = "$name"; + $namelink = "$hname"; } echo <<name_type == IS_UNICODE) { return entry1->name.ustr.len == entry2->name.ustr.len - && memcmp(entry1->name.ustr.val, entry2->name.ustr.val, (entry1->name.ustr.len + 1) * sizeof(UChar)) == 0; + && memcmp(entry1->name.ustr.val, entry2->name.ustr.val, (entry1->name.ustr.len + 1) * sizeof(entry1->name.ustr.val[0])) == 0; } #endif return entry1->name.str.len == entry2->name.str.len @@ -269,33 +273,6 @@ static inline int xc_entry_equal_unlocked(xc_entry_type_t type, const xc_entry_t return 0; } /* }}} */ -static inline int xc_entry_has_prefix_unlocked(xc_entry_type_t type, xc_entry_t *entry, zval *prefix) /* {{{ */ -{ - /* this function isn't required but can be in unlocked */ - -#ifdef IS_UNICODE - if (entry->name_type != prefix->type) { - return 0; - } - - if (entry->name_type == IS_UNICODE) { - if (entry->name.ustr.len < Z_USTRLEN_P(prefix)) { - return 0; - } - return memcmp(entry->name.ustr.val, Z_USTRVAL_P(prefix), Z_USTRLEN_P(prefix) * sizeof(UChar)) == 0; - } -#endif - if (prefix->type != IS_STRING) { - return 0; - } - - if (entry->name.str.len < Z_STRLEN_P(prefix)) { - return 0; - } - - return memcmp(entry->name.str.val, Z_STRVAL_P(prefix), Z_STRLEN_P(prefix)) == 0; -} -/* }}} */ static void xc_entry_add_unlocked(xc_cached_t *cached, xc_hash_value_t entryslotid, xc_entry_t *entry) /* {{{ */ { xc_entry_t **head = &(cached->entries[entryslotid]); @@ -2306,6 +2283,308 @@ static void xc_gc_op_array(void *pDest) /* {{{ */ } /* }}} */ +/* variable namespace */ +#ifdef IS_UNICODE +void xc_var_namespace_init_from_unicodel(const UChar *string, int len TSRMLS_DC) /* {{{ */ +{ + if (!len) { +#ifdef IS_UNICODE + ZVAL_EMPTY_UNICODE(&XG(uvar_namespace_hard)); +#endif + ZVAL_EMPTY_STRING(&XG(var_namespace_hard)); + } + else { + ZVAL_UNICODE_L(&XG(uvar_namespace_hard), string, len, 1); + /* TODO: copy to var */ + } +} +/* }}} */ +#endif +void xc_var_namespace_init_from_stringl(const char *string, int len TSRMLS_DC) /* {{{ */ +{ + if (!len) { +#ifdef IS_UNICODE + ZVAL_EMPTY_UNICODE(&XG(uvar_namespace_hard)); +#endif + ZVAL_EMPTY_STRING(&XG(var_namespace_hard)); + } + else { + ZVAL_STRINGL(&XG(var_namespace_hard), string, len, 1); +#ifdef IS_UNICODE + /* TODO: copy to uvar */ +#endif + } +} +/* }}} */ +void xc_var_namespace_init_from_long(long value TSRMLS_DC) /* {{{ */ +{ + ZVAL_LONG(&XG(var_namespace_hard), value); +#ifdef IS_UNICODE + /* TODO: copy to uvar_namespace */ +#endif +} +/* }}} */ +#ifdef IS_UNICODE +void xc_var_namespace_set_unicodel(const UChar *unicode, int len TSRMLS_DC) /* {{{ */ +{ + zval_dtor(&XG(uvar_namespace_soft)); + zval_dtor(&XG(var_namespace_soft)); + if (len) { + if (!Z_USTRLEN_P(&XG(uvar_namespace_soft))) { + ZVAL_UNICODEL(&XG(uvar_namespace_soft), unicode, len, 1); + } + else { + int buffer_len = Z_USTRLEN_P(&XG(var_namespace_hard)) + 1 + len; + char *buffer = emalloc((buffer_len + 1) * sizeof(unicode[0])); + char *p = buffer; + memcpy(p, Z_USTRVAL_P(&XG(var_namespace_hard)), (Z_USTRLEN_P(&XG(var_namespace_hard)) + 1)); + p += (Z_USTRLEN_P(&XG(var_namespace_hard)) + 1) * sizeof(unicode[0]); + memcpy(p, unicode, (len + 1) * sizeof(unicode[0])); + ZVAL_UNICODEL(&XG(uvar_namespace_soft), buffer, buffer_len, 0); + } + /* TODO: copy to var */ + } + else { +#ifdef IS_UNICODE + XG(uvar_namespace_soft) = XG(uvar_namespace_hard); + zval_copy_ctor(&XG(uvar_namespace_soft)); +#endif + XG(var_namespace_soft) = XG(var_namespace_hard); + zval_copy_ctor(&XG(var_namespace_soft)); + } +} +/* }}} */ +#endif +void xc_var_namespace_set_stringl(const char *string, int len TSRMLS_DC) /* {{{ */ +{ +#ifdef IS_UNICODE + zval_dtor(&XG(uvar_namespace_soft)); +#endif + zval_dtor(&XG(var_namespace_soft)); + if (len) { + if (!Z_STRLEN_P(&XG(var_namespace_soft))) { + ZVAL_STRINGL(&XG(var_namespace_soft), string, len, 1); + } + else { + int buffer_len = Z_STRLEN_P(&XG(var_namespace_hard)) + 1 + len; + char *buffer = emalloc(buffer_len + 1); + char *p = buffer; + memcpy(p, Z_STRVAL_P(&XG(var_namespace_hard)), Z_STRLEN_P(&XG(var_namespace_hard)) + 1); + p += Z_STRLEN_P(&XG(var_namespace_hard)) + 1; + memcpy(p, string, len + 1); + ZVAL_STRINGL(&XG(var_namespace_soft), buffer, buffer_len, 0); + } +#ifdef IS_UNICODE + /* TODO: copy to uvar */ +#endif + } + else { +#ifdef IS_UNICODE + XG(uvar_namespace_soft) = XG(uvar_namespace_hard); + zval_copy_ctor(&XG(uvar_namespace_soft)); +#endif + XG(var_namespace_soft) = XG(var_namespace_hard); + zval_copy_ctor(&XG(var_namespace_soft)); + } +} +/* }}} */ +static void xc_var_namespace_break(TSRMLS_D) /* {{{ */ +{ +#ifdef IS_UNICODE + zval_dtor(&XG(uvar_namespace_soft)); +#endif + zval_dtor(&XG(var_namespace_soft)); +#ifdef IS_UNICODE + ZVAL_EMPTY_UNICODE(&XG(uvar_namespace_soft)); +#endif + ZVAL_EMPTY_STRING(&XG(var_namespace_soft)); +} +/* }}} */ +static void xc_var_namespace_init(TSRMLS_D) /* {{{ */ +{ + uid_t id = (uid_t) -1; + + switch (xc_var_namespace_mode) { + case 1: + { + zval **server; + HashTable *ht; + zval **val; + +#ifdef ZEND_ENGINE_2_1 + zend_is_auto_global("_SERVER", sizeof("_SERVER") - 1 TSRMLS_CC); +#endif + + if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void**)&server) == FAILURE + || Z_TYPE_PP(server) != IS_ARRAY + || !(ht = Z_ARRVAL_P(*server)) + || zend_hash_find(ht, xc_var_namespace, strlen(xc_var_namespace) + 1, (void**)&val) == FAILURE) { + xc_var_namespace_init_from_stringl(NULL, 0 TSRMLS_CC); + } + else { +#ifdef IS_UNICODE + if (Z_TYPE_PP(val) == IS_UNICODE) { + xc_var_namespace_init_from_unicodel(Z_USTRVAL_PP(val), Z_USTRLEN_PP(val) TSRMLS_CC); + } + else +#endif + { + xc_var_namespace_init_from_stringl(Z_STRVAL_PP(val), Z_STRLEN_PP(val) TSRMLS_CC); + } + } + } + break; + + case 2: + if (strncmp(xc_var_namespace, "uid", 3) == 0) { + id = getuid(); + } + else if (strncmp(xc_var_namespace, "gid", 3) == 0) { + id = getgid(); + } + + if (id == (uid_t) -1){ + xc_var_namespace_init_from_stringl(NULL, 0 TSRMLS_CC); + } + else { + xc_var_namespace_init_from_long((long) id TSRMLS_CC); + } + break; + + case 0: + default: + xc_var_namespace_init_from_stringl(xc_var_namespace, strlen(xc_var_namespace) TSRMLS_CC); + break; + } + +#ifdef IS_UNICODE + INIT_ZVAL(XG(uvar_namespace_soft)); +#endif + INIT_ZVAL(XG(var_namespace_soft)); + xc_var_namespace_set_stringl("", 0 TSRMLS_CC); +} +/* }}} */ +static void xc_var_namespace_destroy(TSRMLS_D) /* {{{ */ +{ +#ifdef IS_UNICODE + zval_dtor(&XG(uvar_namespace_hard)); + zval_dtor(&XG(uvar_namespace_soft)); +#endif + zval_dtor(&XG(var_namespace_hard)); + zval_dtor(&XG(var_namespace_soft)); +} +/* }}} */ +static int xc_var_buffer_prepare(zval *name TSRMLS_DC) /* {{{ prepare name, calculate buffer size */ +{ + int namespace_len; + switch (name->type) { +#ifdef IS_UNICODE + case IS_UNICODE: +do_unicode: + namespace_len = Z_USTRLEN_P(&XG(uvar_namespace_soft)); + return (namespace_len ? namespace_len + 1 : 0) + Z_USTRLEN_P(name); +#endif + + case IS_STRING: +do_string: + namespace_len = Z_STRLEN_P(&XG(var_namespace_soft)); + return (namespace_len ? namespace_len + 1 : 0) + Z_STRLEN_P(name); + + default: +#ifdef IS_UNICODE + convert_to_unicode(name); + goto do_unicode; +#else + convert_to_string(name); + goto do_string; +#endif + } +} +/* }}} */ +static int xc_var_buffer_alloca_size(zval *name TSRMLS_DC) /* {{{ prepare name, calculate buffer size */ +{ + int namespace_len; + switch (name->type) { +#ifdef IS_UNICODE + case IS_UNICODE: + namespace_len = Z_USTRLEN_P(&XG(uvar_namespace_soft)); + return !namespace_len ? 0 : (namespace_len + 1 + Z_USTRLEN_P(name) + 1) * sizeof(Z_USTRVAL_P(&XG(uvar_namespace_soft))[0]); +#endif + + case IS_STRING: + namespace_len = Z_STRLEN_P(&XG(var_namespace_soft)); + return !namespace_len ? 0 : (namespace_len + 1 + Z_STRLEN_P(name) + 1); + } + assert(0); + return 0; +} +/* }}} */ +static void xc_var_buffer_init(char *buffer, zval *name TSRMLS_DC) /* {{{ prepare name, calculate buffer size */ +{ +#ifdef IS_UNICODE + if (Z_TYPE(name) == IS_UNICODE) { + memcpy(buffer, Z_USTRVAL_P(&XG(uvar_namespace_soft)), (Z_USTRLEN_P(&XG(uvar_namespace_soft)) + 1) * sizeof(Z_USTRVAL_P(name)[0])); + buffer += (Z_USTRLEN_P(&XG(uvar_namespace_soft)) + 1) * sizeof(Z_USTRVAL_P(name)[0]); + memcpy(buffer, Z_USTRVAL_P(name), (Z_USTRLEN_P(name) + 1) * sizeof(Z_USTRVAL_P(name)[0])); + } +#endif + memcpy(buffer, Z_STRVAL_P(&XG(var_namespace_soft)), (Z_STRLEN_P(&XG(var_namespace_soft)) + 1)); + buffer += (Z_STRLEN_P(&XG(var_namespace_soft)) + 1); + memcpy(buffer, Z_STRVAL_P(name), (Z_STRLEN_P(name) + 1)); +} +/* }}} */ +typedef struct xc_namebuffer_t_ { /* {{{ */ + ALLOCA_FLAG(useheap); + void *buffer; + int alloca_size; + int len; +} xc_namebuffer_t; +/* }}} */ + +#define VAR_BUFFER_FLAGS(name) \ + xc_namebuffer_t name##_buffer; + +#define VAR_BUFFER_INIT(name) \ + name##_buffer.len = xc_var_buffer_prepare(name TSRMLS_CC); \ + name##_buffer.alloca_size = xc_var_buffer_alloca_size(name TSRMLS_CC); \ + name##_buffer.buffer = name##_buffer.alloca_size \ + ? do_alloca(name##_buffer.alloca_size, name##_buffer.useheap) \ + : UNISW(Z_STRVAL_P(name), Z_TYPE(name) == IS_UNICODE ? Z_USTRVAL_P(name) : Z_STRVAL_P(name)); \ + if (name##_buffer.alloca_size) xc_var_buffer_init(name##_buffer.buffer, name TSRMLS_CC); + +#define VAR_BUFFER_FREE(name) \ + if (name##_buffer.alloca_size) { \ + free_alloca(name##_buffer.buffer, name##_buffer.useheap); \ + } + +static inline int xc_var_has_prefix(xc_entry_t *entry, zval *prefix TSRMLS_DC) /* {{{ */ +{ + zend_bool result = 0; + VAR_BUFFER_FLAGS(prefix); + + if (UNISW(IS_STRING, entry->name_type) != prefix->type) { + return 0; + } + VAR_BUFFER_INIT(prefix); + +#ifdef IS_UNICODE + if (Z_TYPE(prefix) == IS_UNICODE) { + result = entry->name.ustr.len >= prefix_buffer.len + && memcmp(entry->name.ustr.val, prefix_buffer.buffer, prefix_buffer.len * sizeof(Z_USTRVAL_P(prefix)[0])) == 0; + goto finish; + } +#endif + + result = entry->name.str.len >= prefix_buffer.len + && memcmp(entry->name.str.val, prefix_buffer.buffer, prefix_buffer.len) == 0; + goto finish; + +finish: + VAR_BUFFER_FREE(prefix); + return result; +} +/* }}} */ + /* module helper function */ static int xc_init_constant(int module_number TSRMLS_DC) /* {{{ */ { @@ -2501,7 +2780,7 @@ static void xc_request_init(TSRMLS_D) /* {{{ */ xc_stack_init(&XG(var_holds[i])); } } - + xc_var_namespace_init(TSRMLS_C); #ifdef ZEND_ENGINE_2 zend_llist_init(&XG(gc_op_arrays), sizeof(xc_gc_op_array_t), xc_gc_op_array, 0); #endif @@ -2519,6 +2798,7 @@ static void xc_request_shutdown(TSRMLS_D) /* {{{ */ xc_gc_expires_php(TSRMLS_C); xc_gc_expires_var(TSRMLS_C); xc_gc_deletes(TSRMLS_C); + xc_var_namespace_destroy(TSRMLS_C); #ifdef ZEND_ENGINE_2 zend_llist_destroy(&XG(gc_op_arrays)); #endif @@ -2565,7 +2845,7 @@ static int xcache_admin_auth_check(TSRMLS_D) /* {{{ */ php_error_docref(NULL TSRMLS_CC, E_ERROR, "_SERVER is corrupted"); zend_bailout(); } - ht = HASH_OF((*server)); + ht = Z_ARRVAL_P((*server)); if (zend_hash_find(ht, "PHP_AUTH_USER", sizeof("PHP_AUTH_USER"), (void **) &user) == FAILURE) { user = NULL; @@ -2798,32 +3078,28 @@ PHP_FUNCTION(xcache_enable_cache) xcache_admin_operate(XC_OP_ENABLE, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ +/* {{{ proto mixed xcache_admin_namespace() + Break out of namespace limitation */ +PHP_FUNCTION(xcache_admin_namespace) +{ + xcache_admin_auth_check(TSRMLS_C); + xc_var_namespace_break(TSRMLS_C); +} +/* }}} */ #define VAR_CACHE_NOT_INITIALIZED() do { \ php_error_docref(NULL TSRMLS_CC, E_WARNING, "XCache var cache was not initialized properly. Check php log for actual reason"); \ } while (0) -static int xc_entry_var_init_key(xc_entry_var_t *entry_var, xc_entry_hash_t *entry_hash, zval *name TSRMLS_DC) /* {{{ */ +static int xc_entry_var_init_key(xc_entry_var_t *entry_var, xc_entry_hash_t *entry_hash, xc_namebuffer_t *name_buffer TSRMLS_DC) /* {{{ */ { xc_hash_value_t hv; - switch (name->type) { -#ifdef IS_UNICODE - case IS_UNICODE: - case IS_STRING: -#endif - default: -#ifdef IS_UNICODE - convert_to_unicode(name); -#else - convert_to_string(name); -#endif - } - #ifdef IS_UNICODE entry_var->name_type = name->type; #endif - entry_var->entry.name = name->value; + entry_var->entry.name.str.val = name_buffer->buffer; + entry_var->entry.name.str.len = name_buffer->len; hv = xc_entry_hash_var((xc_entry_t *) entry_var TSRMLS_CC); @@ -2833,6 +3109,31 @@ static int xc_entry_var_init_key(xc_entry_var_t *entry_var, xc_entry_hash_t *ent return SUCCESS; } /* }}} */ +/* {{{ proto mixed xcache_set_namespace(string namespace) + Switch to user defined namespace */ +PHP_FUNCTION(xcache_set_namespace) +{ + zval *namespace; + + if (!xc_var_caches) { + VAR_CACHE_NOT_INITIALIZED(); + RETURN_NULL(); + } + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &namespace) == FAILURE) { + return; + } + + if (Z_TYPE_P(namespace) == IS_STRING) { + xc_var_namespace_set_stringl(Z_STRVAL_P(namespace), Z_STRLEN_P(namespace) TSRMLS_CC); + } +#ifdef IS_UNICODE + else if (Z_TYPE_P(namespace) == IS_UNICODE) { + xc_var_namespace_set_unicodel(Z_USTRVAL_P(namespace), Z_USTRLEN_P(namespace) TSRMLS_CC); + } +#endif +} +/* }}} */ /* {{{ proto mixed xcache_get(string name) Get cached data by specified name */ PHP_FUNCTION(xcache_get) @@ -2841,6 +3142,7 @@ PHP_FUNCTION(xcache_get) xc_cache_t *cache; xc_entry_var_t entry_var, *stored_entry_var; zval *name; + VAR_BUFFER_FLAGS(name); if (!xc_var_caches) { VAR_CACHE_NOT_INITIALIZED(); @@ -2850,10 +3152,12 @@ PHP_FUNCTION(xcache_get) if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &name) == FAILURE) { return; } - xc_entry_var_init_key(&entry_var, &entry_hash, name TSRMLS_CC); + VAR_BUFFER_INIT(name); + xc_entry_var_init_key(&entry_var, &entry_hash, &name_buffer TSRMLS_CC); cache = &xc_var_caches[entry_hash.cacheid]; if (cache->cached->disabled) { + VAR_BUFFER_FREE(name); RETURN_NULL(); } @@ -2868,6 +3172,7 @@ PHP_FUNCTION(xcache_get) RETVAL_NULL(); } } LEAVE_LOCK(cache); + VAR_BUFFER_FREE(name); } /* }}} */ /* {{{ proto bool xcache_set(string name, mixed value [, int ttl]) @@ -2879,6 +3184,7 @@ PHP_FUNCTION(xcache_set) xc_entry_var_t entry_var, *stored_entry_var; zval *name; zval *value; + VAR_BUFFER_FLAGS(name); if (!xc_var_caches) { VAR_CACHE_NOT_INITIALIZED(); @@ -2900,10 +3206,12 @@ PHP_FUNCTION(xcache_set) entry_var.entry.ttl = xc_var_maxttl; } - xc_entry_var_init_key(&entry_var, &entry_hash, name TSRMLS_CC); + VAR_BUFFER_INIT(name); + xc_entry_var_init_key(&entry_var, &entry_hash, &name_buffer TSRMLS_CC); cache = &xc_var_caches[entry_hash.cacheid]; if (cache->cached->disabled) { + VAR_BUFFER_FREE(name); RETURN_NULL(); } @@ -2915,6 +3223,7 @@ PHP_FUNCTION(xcache_set) entry_var.value = value; RETVAL_BOOL(xc_entry_var_store_unlocked(cache, entry_hash.entryslotid, &entry_var TSRMLS_CC) != NULL ? 1 : 0); } LEAVE_LOCK(cache); + VAR_BUFFER_FREE(name); } /* }}} */ /* {{{ proto bool xcache_isset(string name) @@ -2925,6 +3234,7 @@ PHP_FUNCTION(xcache_isset) xc_cache_t *cache; xc_entry_var_t entry_var, *stored_entry_var; zval *name; + VAR_BUFFER_FLAGS(name); if (!xc_var_caches) { VAR_CACHE_NOT_INITIALIZED(); @@ -2934,10 +3244,12 @@ PHP_FUNCTION(xcache_isset) if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &name) == FAILURE) { return; } - xc_entry_var_init_key(&entry_var, &entry_hash, name TSRMLS_CC); + VAR_BUFFER_INIT(name); + xc_entry_var_init_key(&entry_var, &entry_hash, &name_buffer TSRMLS_CC); cache = &xc_var_caches[entry_hash.cacheid]; if (cache->cached->disabled) { + VAR_BUFFER_FREE(name); RETURN_FALSE; } @@ -2953,6 +3265,7 @@ PHP_FUNCTION(xcache_isset) } } LEAVE_LOCK(cache); + VAR_BUFFER_FREE(name); } /* }}} */ /* {{{ proto bool xcache_unset(string name) @@ -2963,6 +3276,7 @@ PHP_FUNCTION(xcache_unset) xc_cache_t *cache; xc_entry_var_t entry_var, *stored_entry_var; zval *name; + VAR_BUFFER_FLAGS(name); if (!xc_var_caches) { VAR_CACHE_NOT_INITIALIZED(); @@ -2972,10 +3286,12 @@ PHP_FUNCTION(xcache_unset) if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &name) == FAILURE) { return; } - xc_entry_var_init_key(&entry_var, &entry_hash, name TSRMLS_CC); + VAR_BUFFER_INIT(name); + xc_entry_var_init_key(&entry_var, &entry_hash, &name_buffer TSRMLS_CC); cache = &xc_var_caches[entry_hash.cacheid]; if (cache->cached->disabled) { + VAR_BUFFER_FREE(name); RETURN_FALSE; } @@ -2989,6 +3305,7 @@ PHP_FUNCTION(xcache_unset) RETVAL_FALSE; } } LEAVE_LOCK(cache); + VAR_BUFFER_FREE(name); } /* }}} */ /* {{{ proto bool xcache_unset_by_prefix(string prefix) @@ -3019,7 +3336,7 @@ PHP_FUNCTION(xcache_unset_by_prefix) xc_entry_t *entry, *next; for (entry = cache->cached->entries[entryslotid]; entry; entry = next) { next = entry->next; - if (xc_entry_has_prefix_unlocked(XC_TYPE_VAR, entry, prefix)) { + if (xc_var_has_prefix(entry, prefix TSRMLS_CC)) { xc_entry_remove_unlocked(XC_TYPE_VAR, cache, entryslotid, entry TSRMLS_CC); } } @@ -3037,6 +3354,7 @@ static inline void xc_var_inc_dec(int inc, INTERNAL_FUNCTION_PARAMETERS) /* {{{ long count = 1; long value = 0; zval oldzval; + VAR_BUFFER_FLAGS(name); if (!xc_var_caches) { VAR_CACHE_NOT_INITIALIZED(); @@ -3053,10 +3371,12 @@ static inline void xc_var_inc_dec(int inc, INTERNAL_FUNCTION_PARAMETERS) /* {{{ entry_var.entry.ttl = xc_var_maxttl; } - xc_entry_var_init_key(&entry_var, &entry_hash, name TSRMLS_CC); + VAR_BUFFER_INIT(name); + xc_entry_var_init_key(&entry_var, &entry_hash, &name_buffer TSRMLS_CC); cache = &xc_var_caches[entry_hash.cacheid]; if (cache->cached->disabled) { + VAR_BUFFER_FREE(name); RETURN_NULL(); } @@ -3102,6 +3422,7 @@ static inline void xc_var_inc_dec(int inc, INTERNAL_FUNCTION_PARAMETERS) /* {{{ } xc_entry_var_store_unlocked(cache, entry_hash.entryslotid, &entry_var TSRMLS_CC); } LEAVE_LOCK(cache); + VAR_BUFFER_FREE(name); } /* }}} */ /* {{{ proto int xcache_inc(string name [, int value [, int ttl]]) @@ -3125,6 +3446,8 @@ static zend_function_entry xcache_cacher_functions[] = /* {{{ */ PHP_FE(xcache_list, NULL) PHP_FE(xcache_clear_cache, NULL) PHP_FE(xcache_enable_cache, NULL) + PHP_FE(xcache_admin_namespace, NULL) + PHP_FE(xcache_set_namespace, NULL) PHP_FE(xcache_get, NULL) PHP_FE(xcache_set, NULL) PHP_FE(xcache_isset, NULL) @@ -3220,6 +3543,8 @@ PHP_INI_BEGIN() PHP_INI_ENTRY1 ("xcache.var_gc_interval", "120", PHP_INI_SYSTEM, xcache_OnUpdateULong, &xc_var_gc_interval) PHP_INI_ENTRY1 ("xcache.var_allocator", "bestfit", PHP_INI_SYSTEM, xcache_OnUpdateString, &xc_var_allocator) STD_PHP_INI_ENTRY ("xcache.var_ttl", "0", PHP_INI_ALL, OnUpdateLong, var_ttl, zend_xcache_globals, xcache_globals) + PHP_INI_ENTRY1 ("xcache.var_namespace_mode", "0", PHP_INI_SYSTEM, xcache_OnUpdateULong, &xc_var_namespace_mode) + PHP_INI_ENTRY1 ("xcache.var_namespace", "", PHP_INI_SYSTEM, xcache_OnUpdateString, &xc_var_namespace) PHP_INI_END() /* }}} */ static PHP_MINFO_FUNCTION(xcache_cacher) /* {{{ */ @@ -3394,6 +3719,10 @@ static PHP_MSHUTDOWN_FUNCTION(xcache_cacher) /* {{{ */ pefree(xc_var_allocator, 1); xc_var_allocator = NULL; } + if (xc_var_namespace) { + pefree(xc_var_namespace, 1); + xc_var_namespace = NULL; + } return SUCCESS; } diff --git a/xcache_globals.h b/xcache_globals.h index 52131f6..e583cee 100644 --- a/xcache_globals.h +++ b/xcache_globals.h @@ -20,6 +20,12 @@ ZEND_BEGIN_MODULE_GLOBALS(xcache) zend_uint var_holds_size; time_t request_time; long var_ttl; +#ifdef IS_UNCODE + zval uvar_namespace_hard; + zval uvar_namespace_soft; +#endif + zval var_namespace_hard; + zval var_namespace_soft; zend_llist gc_op_arrays;