From 4cf00c08bde40ff0924b9fd9da4c0eb3d42e2753 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 9 Apr 2013 11:57:28 +0400 Subject: [PATCH] Fixed issue #26 (added opcache_invalidate(string $filename [, bool $force = false]) function) --- ext/opcache/ZendAccelerator.c | 49 +++++++++++++++++++++++++++ ext/opcache/ZendAccelerator.h | 1 + ext/opcache/zend_accelerator_module.c | 21 ++++++++++++ 3 files changed, 71 insertions(+) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 168082ea13acd..b62f245f4c21b 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -1047,6 +1047,55 @@ static inline char *accel_make_persistent_key(zend_file_handle *file_handle, int return accel_make_persistent_key_ex(file_handle, strlen(file_handle->filename), key_len TSRMLS_CC); } +int zend_accel_invalidate(const char *filename, int filename_len, zend_bool force TSRMLS_DC) +{ + char *realpath; + zend_persistent_script *persistent_script; + + if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled) || accelerator_shm_read_lock(TSRMLS_C) != SUCCESS) { + return FAILURE; + } + +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + realpath = accel_php_resolve_path(filename, filename_len, ZCG(include_path) TSRMLS_CC); +#else + realpath = accelerator_orig_zend_resolve_path(filename, filename_len TSRMLS_CC); +#endif + + persistent_script = zend_accel_hash_find(&ZCSG(hash), realpath, strlen(realpath) + 1); + if (persistent_script && !persistent_script->corrupted) { + zend_file_handle file_handle; + + file_handle.type = ZEND_HANDLE_FILENAME; + file_handle.filename = realpath; + file_handle.opened_path = realpath; + + if (force || + !ZCG(accel_directives).validate_timestamps || + do_validate_timestamps(persistent_script, &file_handle TSRMLS_CC) == FAILURE) { + SHM_UNPROTECT(); + zend_shared_alloc_lock(TSRMLS_C); + if (!persistent_script->corrupted) { + persistent_script->corrupted = 1; + persistent_script->timestamp = 0; + ZSMMG(wasted_shared_memory) += persistent_script->dynamic_members.memory_consumption; + if (ZSMMG(memory_exhausted)) { + zend_accel_restart_reason reason = + zend_accel_hash_is_full(&ZCSG(hash)) ? ACCEL_RESTART_HASH : ACCEL_RESTART_OOM; + zend_accel_schedule_restart_if_necessary(reason TSRMLS_CC); + } + } + zend_shared_alloc_unlock(TSRMLS_C); + SHM_PROTECT(); + } + } + + accelerator_shm_read_unlock(TSRMLS_C); + efree(realpath); + + return SUCCESS; +} + /* Adds another key for existing cached script */ static void zend_accel_add_key(char *key, unsigned int key_length, zend_accel_hash_entry *bucket TSRMLS_DC) { diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h index f2005473b1eec..85f95708a28e2 100644 --- a/ext/opcache/ZendAccelerator.h +++ b/ext/opcache/ZendAccelerator.h @@ -318,6 +318,7 @@ extern char *zps_api_failure_reason; void zend_accel_schedule_restart(zend_accel_restart_reason reason TSRMLS_DC); void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason TSRMLS_DC); +int zend_accel_invalidate(const char *filename, int filename_len, zend_bool force TSRMLS_DC); int accelerator_shm_read_lock(TSRMLS_D); void accelerator_shm_read_unlock(TSRMLS_D); diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 8d6ed4ee27c14..94a6b6b19036b 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -43,6 +43,7 @@ static void (*orig_is_readable)(INTERNAL_FUNCTION_PARAMETERS) = NULL; /* User functions */ static ZEND_FUNCTION(opcache_reset); +static ZEND_FUNCTION(opcache_invalidate); /* Private functions */ static ZEND_FUNCTION(opcache_get_status); @@ -51,6 +52,7 @@ static ZEND_FUNCTION(opcache_get_configuration); static zend_function_entry accel_functions[] = { /* User functions */ ZEND_FE(opcache_reset, NULL) + ZEND_FE(opcache_invalidate, NULL) /* Private functions */ ZEND_FE(opcache_get_configuration, NULL) ZEND_FE(opcache_get_status, NULL) @@ -643,3 +645,22 @@ static ZEND_FUNCTION(opcache_reset) zend_accel_schedule_restart(ACCEL_RESTART_USER TSRMLS_CC); RETURN_TRUE; } + +/* {{{ proto void opcache_invalidate(string $script [, bool $force = false]) + Invalidates cached script (in necessary or forced) */ +static ZEND_FUNCTION(opcache_invalidate) +{ + char *script_name; + int script_name_len; + zend_bool force = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &script_name, &script_name_len, &force) == FAILURE) { + return; + } + + if (zend_accel_invalidate(script_name, script_name_len, force) == SUCCESS) { + RETURN_TRUE; + } else { + RETURN_FALSE; + } +}