root/ext/opcache/zend_accelerator_module.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. validate_api_restriction
  2. ZEND_INI_MH
  3. ZEND_INI_MH
  4. ZEND_INI_MH
  5. ZEND_INI_MH
  6. ZEND_INI_MH
  7. ZEND_INI_BEGIN
  8. accel_file_in_cache
  9. accel_file_exists
  10. accel_is_file
  11. accel_is_readable
  12. ZEND_MINIT_FUNCTION
  13. zend_accel_override_file_functions
  14. ZEND_MSHUTDOWN_FUNCTION
  15. zend_accel_info
  16. start_accel_module
  17. accelerator_get_scripts
  18. ZEND_FUNCTION
  19. add_blacklist_path
  20. ZEND_FUNCTION
  21. ZEND_FUNCTION
  22. ZEND_FUNCTION
  23. ZEND_FUNCTION
  24. ZEND_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | Zend OPcache                                                         |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1998-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Andi Gutmans <andi@zend.com>                                |
  16    |          Zeev Suraski <zeev@zend.com>                                |
  17    |          Stanislav Malyshev <stas@zend.com>                          |
  18    |          Dmitry Stogov <dmitry@zend.com>                             |
  19    +----------------------------------------------------------------------+
  20 */
  21 
  22 #include <time.h>
  23 
  24 #include "php.h"
  25 #include "ZendAccelerator.h"
  26 #include "zend_API.h"
  27 #include "zend_shared_alloc.h"
  28 #include "zend_accelerator_blacklist.h"
  29 #include "php_ini.h"
  30 #include "SAPI.h"
  31 #include "zend_virtual_cwd.h"
  32 #include "ext/standard/info.h"
  33 #include "ext/standard/php_filestat.h"
  34 
  35 #define STRING_NOT_NULL(s) (NULL == (s)?"":s)
  36 #define MIN_ACCEL_FILES 200
  37 #define MAX_ACCEL_FILES 1000000
  38 #define TOKENTOSTR(X) #X
  39 
  40 static void (*orig_file_exists)(INTERNAL_FUNCTION_PARAMETERS) = NULL;
  41 static void (*orig_is_file)(INTERNAL_FUNCTION_PARAMETERS) = NULL;
  42 static void (*orig_is_readable)(INTERNAL_FUNCTION_PARAMETERS) = NULL;
  43 
  44 ZEND_BEGIN_ARG_INFO(arginfo_opcache_none, 0)
  45 ZEND_END_ARG_INFO()
  46 
  47 ZEND_BEGIN_ARG_INFO_EX(arginfo_opcache_get_status, 0, 0, 0)
  48         ZEND_ARG_INFO(0, fetch_scripts)
  49 ZEND_END_ARG_INFO()
  50 
  51 ZEND_BEGIN_ARG_INFO_EX(arginfo_opcache_compile_file, 0, 0, 1)
  52         ZEND_ARG_INFO(0, file)
  53 ZEND_END_ARG_INFO()
  54 
  55 ZEND_BEGIN_ARG_INFO_EX(arginfo_opcache_invalidate, 0, 0, 1)
  56         ZEND_ARG_INFO(0, script)
  57         ZEND_ARG_INFO(0, force)
  58 ZEND_END_ARG_INFO()
  59 
  60 ZEND_BEGIN_ARG_INFO_EX(arginfo_opcache_is_script_cached, 0, 0, 1)
  61         ZEND_ARG_INFO(0, script)
  62 ZEND_END_ARG_INFO()
  63 
  64 /* User functions */
  65 static ZEND_FUNCTION(opcache_reset);
  66 static ZEND_FUNCTION(opcache_invalidate);
  67 static ZEND_FUNCTION(opcache_is_script_cached);
  68 
  69 /* Private functions */
  70 static ZEND_FUNCTION(opcache_get_status);
  71 static ZEND_FUNCTION(opcache_compile_file);
  72 static ZEND_FUNCTION(opcache_get_configuration);
  73 
  74 static zend_function_entry accel_functions[] = {
  75         /* User functions */
  76         ZEND_FE(opcache_reset,                                  arginfo_opcache_none)
  77         ZEND_FE(opcache_invalidate,                             arginfo_opcache_invalidate)
  78         ZEND_FE(opcache_compile_file,                   arginfo_opcache_compile_file)
  79         ZEND_FE(opcache_is_script_cached,               arginfo_opcache_is_script_cached)
  80         /* Private functions */
  81         ZEND_FE(opcache_get_configuration,              arginfo_opcache_none)
  82         ZEND_FE(opcache_get_status,                             arginfo_opcache_get_status)
  83         { NULL, NULL, NULL, 0, 0 }
  84 };
  85 
  86 static int validate_api_restriction(void)
  87 {
  88         if (ZCG(accel_directives).restrict_api && *ZCG(accel_directives).restrict_api) {
  89                 int len = strlen(ZCG(accel_directives).restrict_api);
  90 
  91                 if (!SG(request_info).path_translated ||
  92                     strlen(SG(request_info).path_translated) < len ||
  93                     memcmp(SG(request_info).path_translated, ZCG(accel_directives).restrict_api, len) != 0) {
  94                         zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " API is restricted by \"restrict_api\" configuration directive");
  95                         return 0;
  96                 }
  97         }
  98         return 1;
  99 }
 100 
 101 static ZEND_INI_MH(OnUpdateMemoryConsumption)
 102 {
 103         zend_long *p;
 104         zend_long memsize;
 105 #ifndef ZTS
 106         char *base = (char *) mh_arg2;
 107 #else
 108         char *base = (char *) ts_resource(*((int *) mh_arg2));
 109 #endif
 110 
 111         /* keep the compiler happy */
 112         (void)entry; (void)mh_arg2; (void)mh_arg3; (void)stage;
 113 
 114         p = (zend_long *) (base + (size_t)mh_arg1);
 115         memsize = atoi(ZSTR_VAL(new_value));
 116         /* sanity check we must use at least 8 MB */
 117         if (memsize < 8) {
 118                 const char *new_new_value = "8";
 119                 zend_ini_entry *ini_entry;
 120 
 121                 memsize = 8;
 122                 zend_accel_error(ACCEL_LOG_WARNING, "opcache.memory_consumption is set below the required 8MB.\n");
 123                 zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal 8MB configuration.\n");
 124 
 125                 if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives),
 126                                         "opcache.memory_consumption",
 127                                         sizeof("opcache.memory_consumption")-1)) == NULL) {
 128                         return FAILURE;
 129                 }
 130 
 131                 ini_entry->value = zend_string_init(new_new_value, 1, 1);
 132         }
 133         *p = memsize * (1024 * 1024);
 134         return SUCCESS;
 135 }
 136 
 137 static ZEND_INI_MH(OnUpdateMaxAcceleratedFiles)
 138 {
 139         zend_long *p;
 140         zend_long size;
 141 #ifndef ZTS
 142         char *base = (char *) mh_arg2;
 143 #else
 144         char *base = (char *) ts_resource(*((int *) mh_arg2));
 145 #endif
 146 
 147         /* keep the compiler happy */
 148         (void)entry; (void)mh_arg2; (void)mh_arg3; (void)stage;
 149 
 150         p = (zend_long *) (base + (size_t)mh_arg1);
 151         size = atoi(ZSTR_VAL(new_value));
 152         /* sanity check we must use a value between MIN_ACCEL_FILES and MAX_ACCEL_FILES */
 153 
 154         if (size < MIN_ACCEL_FILES || size > MAX_ACCEL_FILES) {
 155                 const char *new_new_value;
 156                 zend_ini_entry *ini_entry;
 157 
 158                 if (size < MIN_ACCEL_FILES) {
 159                         size = MIN_ACCEL_FILES;
 160                         new_new_value = TOKENTOSTR(MIN_ACCEL_FILES);
 161                         zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_accelerated_files is set below the required minimum (%d).\n", MIN_ACCEL_FILES);
 162                         zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal configuration.\n");
 163                 }
 164                 if (size > MAX_ACCEL_FILES) {
 165                         size = MAX_ACCEL_FILES;
 166                         new_new_value = TOKENTOSTR(MAX_ACCEL_FILES);
 167                         zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_accelerated_files is set above the limit (%d).\n", MAX_ACCEL_FILES);
 168                         zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the maximal configuration.\n");
 169                 }
 170                 if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives),
 171                                         "opcache.max_accelerated_files",
 172                                         sizeof("opcache.max_accelerated_files")-1)) == NULL) {
 173                         return FAILURE;
 174                 }
 175                 ini_entry->value = zend_string_init(new_new_value, strlen(new_new_value), 1);
 176         }
 177         *p = size;
 178         return SUCCESS;
 179 }
 180 
 181 static ZEND_INI_MH(OnUpdateMaxWastedPercentage)
 182 {
 183         double *p;
 184         zend_long percentage;
 185 #ifndef ZTS
 186         char *base = (char *) mh_arg2;
 187 #else
 188         char *base = (char *) ts_resource(*((int *) mh_arg2));
 189 #endif
 190 
 191         /* keep the compiler happy */
 192         (void)entry; (void)mh_arg2; (void)mh_arg3; (void)stage;
 193 
 194         p = (double *) (base + (size_t)mh_arg1);
 195         percentage = atoi(ZSTR_VAL(new_value));
 196 
 197         if (percentage <= 0 || percentage > 50) {
 198                 const char *new_new_value = "5";
 199                 zend_ini_entry *ini_entry;
 200 
 201                 percentage = 5;
 202                 zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_wasted_percentage must be set between 1 and 50.\n");
 203                 zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use 5%.\n");
 204                 if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives),
 205                                         "opcache.max_wasted_percentage",
 206                                         sizeof("opcache.max_wasted_percentage")-1)) == NULL) {
 207                         return FAILURE;
 208                 }
 209                 ini_entry->value = zend_string_init(new_new_value, strlen(new_new_value), 1);
 210         }
 211         *p = (double)percentage / 100.0;
 212         return SUCCESS;
 213 }
 214 
 215 static ZEND_INI_MH(OnEnable)
 216 {
 217         if (stage == ZEND_INI_STAGE_STARTUP ||
 218             stage == ZEND_INI_STAGE_SHUTDOWN ||
 219             stage == ZEND_INI_STAGE_DEACTIVATE) {
 220                 return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
 221         } else {
 222                 /* It may be only temporary disabled */
 223                 zend_bool *p;
 224 #ifndef ZTS
 225                 char *base = (char *) mh_arg2;
 226 #else
 227                 char *base = (char *) ts_resource(*((int *) mh_arg2));
 228 #endif
 229 
 230                 p = (zend_bool *) (base+(size_t) mh_arg1);
 231                 if ((ZSTR_LEN(new_value) == 2 && strcasecmp("on", ZSTR_VAL(new_value)) == 0) ||
 232                     (ZSTR_LEN(new_value) == 3 && strcasecmp("yes", ZSTR_VAL(new_value)) == 0) ||
 233                     (ZSTR_LEN(new_value) == 4 && strcasecmp("true", ZSTR_VAL(new_value)) == 0) ||
 234                         atoi(ZSTR_VAL(new_value)) != 0) {
 235                         zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " can't be temporary enabled (it may be only disabled till the end of request)");
 236                         return FAILURE;
 237                 } else {
 238                         *p = 0;
 239                         return SUCCESS;
 240                 }
 241         }
 242 }
 243 
 244 #ifdef HAVE_OPCACHE_FILE_CACHE
 245 static ZEND_INI_MH(OnUpdateFileCache)
 246 {
 247         if (new_value) {
 248                 if (!ZSTR_LEN(new_value)) {
 249                         new_value = NULL;
 250                 } else {
 251                         zend_stat_t buf;
 252 
 253                     if (!IS_ABSOLUTE_PATH(ZSTR_VAL(new_value), ZSTR_LEN(new_value)) ||
 254                             zend_stat(ZSTR_VAL(new_value), &buf) != 0 ||
 255                             !S_ISDIR(buf.st_mode) ||
 256 #ifndef ZEND_WIN32
 257                                 access(ZSTR_VAL(new_value), R_OK | W_OK | X_OK) != 0) {
 258 #else
 259                                 _access(ZSTR_VAL(new_value), 06) != 0) {
 260 #endif
 261                                 zend_accel_error(ACCEL_LOG_WARNING, "opcache.file_cache must be a full path of accessable directory.\n");
 262                                 new_value = NULL;
 263                         }
 264                 }
 265         }
 266         OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
 267         return SUCCESS;
 268 }
 269 #endif
 270 
 271 ZEND_INI_BEGIN()
 272         STD_PHP_INI_BOOLEAN("opcache.enable"             , "1", PHP_INI_ALL,    OnEnable,     enabled                             , zend_accel_globals, accel_globals)
 273         STD_PHP_INI_BOOLEAN("opcache.use_cwd"            , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.use_cwd            , zend_accel_globals, accel_globals)
 274         STD_PHP_INI_BOOLEAN("opcache.validate_timestamps", "1", PHP_INI_ALL   , OnUpdateBool, accel_directives.validate_timestamps, zend_accel_globals, accel_globals)
 275         STD_PHP_INI_BOOLEAN("opcache.inherited_hack"     , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.inherited_hack     , zend_accel_globals, accel_globals)
 276         STD_PHP_INI_BOOLEAN("opcache.dups_fix"           , "0", PHP_INI_ALL   , OnUpdateBool, accel_directives.ignore_dups        , zend_accel_globals, accel_globals)
 277         STD_PHP_INI_BOOLEAN("opcache.revalidate_path"    , "0", PHP_INI_ALL   , OnUpdateBool, accel_directives.revalidate_path    , zend_accel_globals, accel_globals)
 278 
 279         STD_PHP_INI_ENTRY("opcache.log_verbosity_level"   , "1"   , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.log_verbosity_level,       zend_accel_globals, accel_globals)
 280         STD_PHP_INI_ENTRY("opcache.memory_consumption"    , "64"  , PHP_INI_SYSTEM, OnUpdateMemoryConsumption,    accel_directives.memory_consumption,        zend_accel_globals, accel_globals)
 281         STD_PHP_INI_ENTRY("opcache.interned_strings_buffer", "4"  , PHP_INI_SYSTEM, OnUpdateLong,                 accel_directives.interned_strings_buffer,   zend_accel_globals, accel_globals)
 282         STD_PHP_INI_ENTRY("opcache.max_accelerated_files" , "2000", PHP_INI_SYSTEM, OnUpdateMaxAcceleratedFiles,         accel_directives.max_accelerated_files,     zend_accel_globals, accel_globals)
 283         STD_PHP_INI_ENTRY("opcache.max_wasted_percentage" , "5"   , PHP_INI_SYSTEM, OnUpdateMaxWastedPercentage,         accel_directives.max_wasted_percentage,     zend_accel_globals, accel_globals)
 284         STD_PHP_INI_ENTRY("opcache.consistency_checks"    , "0"   , PHP_INI_ALL   , OnUpdateLong,                    accel_directives.consistency_checks,        zend_accel_globals, accel_globals)
 285         STD_PHP_INI_ENTRY("opcache.force_restart_timeout" , "180" , PHP_INI_SYSTEM, OnUpdateLong,                    accel_directives.force_restart_timeout,     zend_accel_globals, accel_globals)
 286         STD_PHP_INI_ENTRY("opcache.revalidate_freq"       , "2"   , PHP_INI_ALL   , OnUpdateLong,                    accel_directives.revalidate_freq,           zend_accel_globals, accel_globals)
 287         STD_PHP_INI_ENTRY("opcache.file_update_protection", "2"   , PHP_INI_ALL   , OnUpdateLong,                accel_directives.file_update_protection,    zend_accel_globals, accel_globals)
 288         STD_PHP_INI_ENTRY("opcache.preferred_memory_model", ""    , PHP_INI_SYSTEM, OnUpdateStringUnempty,       accel_directives.memory_model,              zend_accel_globals, accel_globals)
 289         STD_PHP_INI_ENTRY("opcache.blacklist_filename"    , ""    , PHP_INI_SYSTEM, OnUpdateString,                  accel_directives.user_blacklist_filename,   zend_accel_globals, accel_globals)
 290         STD_PHP_INI_ENTRY("opcache.max_file_size"         , "0"   , PHP_INI_SYSTEM, OnUpdateLong,                    accel_directives.max_file_size,             zend_accel_globals, accel_globals)
 291 
 292         STD_PHP_INI_ENTRY("opcache.protect_memory"        , "0"  , PHP_INI_SYSTEM, OnUpdateBool,                  accel_directives.protect_memory,            zend_accel_globals, accel_globals)
 293         STD_PHP_INI_ENTRY("opcache.save_comments"         , "1"  , PHP_INI_SYSTEM, OnUpdateBool,                  accel_directives.save_comments,             zend_accel_globals, accel_globals)
 294         STD_PHP_INI_ENTRY("opcache.fast_shutdown"         , "0"  , PHP_INI_SYSTEM, OnUpdateBool,                  accel_directives.fast_shutdown,             zend_accel_globals, accel_globals)
 295 
 296         STD_PHP_INI_ENTRY("opcache.optimization_level"    , DEFAULT_OPTIMIZATION_LEVEL , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.optimization_level,   zend_accel_globals, accel_globals)
 297         STD_PHP_INI_BOOLEAN("opcache.enable_file_override"      , "0"   , PHP_INI_SYSTEM, OnUpdateBool,              accel_directives.file_override_enabled,     zend_accel_globals, accel_globals)
 298         STD_PHP_INI_BOOLEAN("opcache.enable_cli"             , "0"   , PHP_INI_SYSTEM, OnUpdateBool,              accel_directives.enable_cli,                zend_accel_globals, accel_globals)
 299         STD_PHP_INI_ENTRY("opcache.error_log"                , ""    , PHP_INI_SYSTEM, OnUpdateString,           accel_directives.error_log,                 zend_accel_globals, accel_globals)
 300         STD_PHP_INI_ENTRY("opcache.restrict_api"             , ""    , PHP_INI_SYSTEM, OnUpdateString,           accel_directives.restrict_api,              zend_accel_globals, accel_globals)
 301 
 302 #ifdef ZEND_WIN32
 303         STD_PHP_INI_ENTRY("opcache.mmap_base", NULL, PHP_INI_SYSTEM,    OnUpdateString,                              accel_directives.mmap_base,                 zend_accel_globals, accel_globals)
 304 #endif
 305 
 306 #ifdef HAVE_OPCACHE_FILE_CACHE
 307         STD_PHP_INI_ENTRY("opcache.file_cache"                    , NULL  , PHP_INI_SYSTEM, OnUpdateFileCache, accel_directives.file_cache,                    zend_accel_globals, accel_globals)
 308         STD_PHP_INI_ENTRY("opcache.file_cache_only"               , "0"   , PHP_INI_SYSTEM, OnUpdateBool,          accel_directives.file_cache_only,               zend_accel_globals, accel_globals)
 309         STD_PHP_INI_ENTRY("opcache.file_cache_consistency_checks" , "1"   , PHP_INI_SYSTEM, OnUpdateBool,          accel_directives.file_cache_consistency_checks, zend_accel_globals, accel_globals)
 310 #endif
 311 #if ENABLE_FILE_CACHE_FALLBACK
 312         STD_PHP_INI_ENTRY("opcache.file_cache_fallback"           , "1"   , PHP_INI_SYSTEM, OnUpdateBool,          accel_directives.file_cache_fallback,           zend_accel_globals, accel_globals)
 313 #endif
 314 #ifdef HAVE_HUGE_CODE_PAGES
 315         STD_PHP_INI_BOOLEAN("opcache.huge_code_pages"             , "0"   , PHP_INI_SYSTEM, OnUpdateBool,      accel_directives.huge_code_pages,               zend_accel_globals, accel_globals)
 316 #endif
 317 ZEND_INI_END()
 318 
 319 static int filename_is_in_cache(zend_string *filename)
 320 {
 321         char *key;
 322         int key_length;
 323 
 324         key = accel_make_persistent_key(ZSTR_VAL(filename), ZSTR_LEN(filename), &key_length);
 325         if (key != NULL) {
 326                 zend_persistent_script *persistent_script = zend_accel_hash_str_find(&ZCSG(hash), key, key_length);
 327                 if (persistent_script && !persistent_script->corrupted) {
 328                         zend_file_handle handle = {{0}, NULL, NULL, 0, 0};
 329 
 330                         handle.filename = ZSTR_VAL(filename);
 331                         handle.type = ZEND_HANDLE_FILENAME;
 332 
 333                         if (ZCG(accel_directives).validate_timestamps) {
 334                                 return validate_timestamp_and_record(persistent_script, &handle) == SUCCESS;
 335                         }
 336 
 337                         return 1;
 338                 }
 339         }
 340 
 341         return 0;
 342 }
 343 
 344 static int accel_file_in_cache(INTERNAL_FUNCTION_PARAMETERS)
 345 {
 346         zval zfilename;
 347 
 348         if (ZEND_NUM_ARGS() != 1 ||
 349             zend_get_parameters_array_ex(1, &zfilename) == FAILURE ||
 350             Z_TYPE(zfilename) != IS_STRING ||
 351             Z_STRLEN(zfilename) == 0) {
 352                 return 0;
 353         }
 354         return filename_is_in_cache(Z_STR(zfilename));
 355 }
 356 
 357 static void accel_file_exists(INTERNAL_FUNCTION_PARAMETERS)
 358 {
 359         if (accel_file_in_cache(INTERNAL_FUNCTION_PARAM_PASSTHRU)) {
 360                 RETURN_TRUE;
 361         } else {
 362                 orig_file_exists(INTERNAL_FUNCTION_PARAM_PASSTHRU);
 363         }
 364 }
 365 
 366 static void accel_is_file(INTERNAL_FUNCTION_PARAMETERS)
 367 {
 368         if (accel_file_in_cache(INTERNAL_FUNCTION_PARAM_PASSTHRU)) {
 369                 RETURN_TRUE;
 370         } else {
 371                 orig_is_file(INTERNAL_FUNCTION_PARAM_PASSTHRU);
 372         }
 373 }
 374 
 375 static void accel_is_readable(INTERNAL_FUNCTION_PARAMETERS)
 376 {
 377         if (accel_file_in_cache(INTERNAL_FUNCTION_PARAM_PASSTHRU)) {
 378                 RETURN_TRUE;
 379         } else {
 380                 orig_is_readable(INTERNAL_FUNCTION_PARAM_PASSTHRU);
 381         }
 382 }
 383 
 384 static ZEND_MINIT_FUNCTION(zend_accelerator)
 385 {
 386         (void)type; /* keep the compiler happy */
 387 
 388         REGISTER_INI_ENTRIES();
 389 
 390         return SUCCESS;
 391 }
 392 
 393 void zend_accel_override_file_functions(void)
 394 {
 395         zend_function *old_function;
 396         if (ZCG(enabled) && accel_startup_ok && ZCG(accel_directives).file_override_enabled) {
 397 #ifdef HAVE_OPCACHE_FILE_CACHE
 398                 if (ZCG(accel_directives).file_cache_only) {
 399                         zend_accel_error(ACCEL_LOG_WARNING, "file_override_enabled has no effect when file_cache_only is set");
 400                         return;
 401                 }
 402 #endif
 403                 /* override file_exists */
 404                 if ((old_function = zend_hash_str_find_ptr(CG(function_table), "file_exists", sizeof("file_exists")-1)) != NULL) {
 405                         orig_file_exists = old_function->internal_function.handler;
 406                         old_function->internal_function.handler = accel_file_exists;
 407                 }
 408                 if ((old_function = zend_hash_str_find_ptr(CG(function_table), "is_file", sizeof("is_file")-1)) != NULL) {
 409                         orig_is_file = old_function->internal_function.handler;
 410                         old_function->internal_function.handler = accel_is_file;
 411                 }
 412                 if ((old_function = zend_hash_str_find_ptr(CG(function_table), "is_readable", sizeof("is_readable")-1)) != NULL) {
 413                         orig_is_readable = old_function->internal_function.handler;
 414                         old_function->internal_function.handler = accel_is_readable;
 415                 }
 416         }
 417 }
 418 
 419 static ZEND_MSHUTDOWN_FUNCTION(zend_accelerator)
 420 {
 421         (void)type; /* keep the compiler happy */
 422 
 423         UNREGISTER_INI_ENTRIES();
 424         accel_shutdown();
 425         return SUCCESS;
 426 }
 427 
 428 void zend_accel_info(ZEND_MODULE_INFO_FUNC_ARGS)
 429 {
 430         php_info_print_table_start();
 431 
 432         if (ZCG(enabled) && accel_startup_ok &&
 433 #ifdef HAVE_OPCACHE_FILE_CACHE
 434                 ((ZCG(counted) || ZCSG(accelerator_enabled)) || ZCG(accel_directives).file_cache_only)
 435 #else
 436                 (ZCG(counted) || ZCSG(accelerator_enabled))
 437 #endif
 438         ) {
 439                 php_info_print_table_row(2, "Opcode Caching", "Up and Running");
 440         } else {
 441                 php_info_print_table_row(2, "Opcode Caching", "Disabled");
 442         }
 443         if (ZCG(enabled) && accel_startup_ok && ZCG(accel_directives).optimization_level) {
 444                 php_info_print_table_row(2, "Optimization", "Enabled");
 445         } else {
 446                 php_info_print_table_row(2, "Optimization", "Disabled");
 447         }
 448 #ifdef HAVE_OPCACHE_FILE_CACHE
 449         if (!ZCG(accel_directives).file_cache_only) {
 450                 php_info_print_table_row(2, "SHM Cache", "Enabled");
 451         } else {
 452                 php_info_print_table_row(2, "SHM Cache", "Disabled");
 453         }
 454         if (ZCG(accel_directives).file_cache) {
 455                 php_info_print_table_row(2, "File Cache", "Enabled");
 456         } else {
 457                 php_info_print_table_row(2, "File Cache", "Disabled");
 458         }
 459         if (ZCG(accel_directives).file_cache_only) {
 460                 if (!accel_startup_ok || zps_api_failure_reason) {
 461                         php_info_print_table_row(2, "Startup Failed", zps_api_failure_reason);
 462                 } else {
 463                         php_info_print_table_row(2, "Startup", "OK");
 464                 }
 465         } else
 466 #endif
 467         if (ZCG(enabled)) {
 468                 if (!accel_startup_ok || zps_api_failure_reason) {
 469                         php_info_print_table_row(2, "Startup Failed", zps_api_failure_reason);
 470                 } else {
 471                         char buf[32];
 472                         php_info_print_table_row(2, "Startup", "OK");
 473                         php_info_print_table_row(2, "Shared memory model", zend_accel_get_shared_model());
 474                         snprintf(buf, sizeof(buf), "%pd", (zend_ulong)ZCSG(hits));
 475                         php_info_print_table_row(2, "Cache hits", buf);
 476                         snprintf(buf, sizeof(buf), "%pd", ZSMMG(memory_exhausted)?ZCSG(misses):ZCSG(misses)-ZCSG(blacklist_misses));
 477                         php_info_print_table_row(2, "Cache misses", buf);
 478                         snprintf(buf, sizeof(buf), ZEND_LONG_FMT, ZCG(accel_directives).memory_consumption-zend_shared_alloc_get_free_memory()-ZSMMG(wasted_shared_memory));
 479                         php_info_print_table_row(2, "Used memory", buf);
 480                         snprintf(buf, sizeof(buf), "%pd", zend_shared_alloc_get_free_memory());
 481                         php_info_print_table_row(2, "Free memory", buf);
 482                         snprintf(buf, sizeof(buf), "%pd", ZSMMG(wasted_shared_memory));
 483                         php_info_print_table_row(2, "Wasted memory", buf);
 484                         if (ZCSG(interned_strings_start) && ZCSG(interned_strings_end) && ZCSG(interned_strings_top)) {
 485                                 snprintf(buf, sizeof(buf), "%pd", ZCSG(interned_strings_top) - ZCSG(interned_strings_start));
 486                                 php_info_print_table_row(2, "Interned Strings Used memory", buf);
 487                                 snprintf(buf, sizeof(buf), "%pd", ZCSG(interned_strings_end) - ZCSG(interned_strings_top));
 488                                 php_info_print_table_row(2, "Interned Strings Free memory", buf);
 489                         }
 490                         snprintf(buf, sizeof(buf), "%ld", ZCSG(hash).num_direct_entries);
 491                         php_info_print_table_row(2, "Cached scripts", buf);
 492                         snprintf(buf, sizeof(buf), "%ld", ZCSG(hash).num_entries);
 493                         php_info_print_table_row(2, "Cached keys", buf);
 494                         snprintf(buf, sizeof(buf), "%pd", ZCSG(hash).max_num_entries);
 495                         php_info_print_table_row(2, "Max keys", buf);
 496                         snprintf(buf, sizeof(buf), "%pd", ZCSG(oom_restarts));
 497                         php_info_print_table_row(2, "OOM restarts", buf);
 498                         snprintf(buf, sizeof(buf), "%pd", ZCSG(hash_restarts));
 499                         php_info_print_table_row(2, "Hash keys restarts", buf);
 500                         snprintf(buf, sizeof(buf), "%pd", ZCSG(manual_restarts));
 501                         php_info_print_table_row(2, "Manual restarts", buf);
 502                 }
 503         }
 504 
 505         php_info_print_table_end();
 506         DISPLAY_INI_ENTRIES();
 507 }
 508 
 509 static zend_module_entry accel_module_entry = {
 510         STANDARD_MODULE_HEADER,
 511         ACCELERATOR_PRODUCT_NAME,
 512         accel_functions,
 513         ZEND_MINIT(zend_accelerator),
 514         ZEND_MSHUTDOWN(zend_accelerator),
 515         NULL,
 516         NULL,
 517         zend_accel_info,
 518         ACCELERATOR_VERSION "FE",
 519         NO_MODULE_GLOBALS,
 520         accel_post_deactivate,
 521         STANDARD_MODULE_PROPERTIES_EX
 522 };
 523 
 524 int start_accel_module(void)
 525 {
 526         return zend_startup_module(&accel_module_entry);
 527 }
 528 
 529 /* {{{ proto array accelerator_get_scripts()
 530    Get the scripts which are accelerated by ZendAccelerator */
 531 static int accelerator_get_scripts(zval *return_value)
 532 {
 533         uint i;
 534         zval persistent_script_report;
 535         zend_accel_hash_entry *cache_entry;
 536         struct tm *ta;
 537         struct timeval exec_time;
 538         struct timeval fetch_time;
 539 
 540         if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled) || accelerator_shm_read_lock() != SUCCESS) {
 541                 return 0;
 542         }
 543 
 544         array_init(return_value);
 545         for (i = 0; i<ZCSG(hash).max_num_entries; i++) {
 546                 for (cache_entry = ZCSG(hash).hash_table[i]; cache_entry; cache_entry = cache_entry->next) {
 547                         zend_persistent_script *script;
 548                         char *str;
 549                         size_t len;
 550 
 551                         if (cache_entry->indirect) continue;
 552 
 553                         script = (zend_persistent_script *)cache_entry->data;
 554 
 555                         array_init(&persistent_script_report);
 556                         add_assoc_str(&persistent_script_report, "full_path", zend_string_dup(script->full_path, 0));
 557                         add_assoc_long(&persistent_script_report, "hits", (zend_long)script->dynamic_members.hits);
 558                         add_assoc_long(&persistent_script_report, "memory_consumption", script->dynamic_members.memory_consumption);
 559                         ta = localtime(&script->dynamic_members.last_used);
 560                         str = asctime(ta);
 561                         len = strlen(str);
 562                         if (len > 0 && str[len - 1] == '\n') len--;
 563                         add_assoc_stringl(&persistent_script_report, "last_used", str, len);
 564                         add_assoc_long(&persistent_script_report, "last_used_timestamp", script->dynamic_members.last_used);
 565                         if (ZCG(accel_directives).validate_timestamps) {
 566                                 add_assoc_long(&persistent_script_report, "timestamp", (zend_long)script->timestamp);
 567                         }
 568                         timerclear(&exec_time);
 569                         timerclear(&fetch_time);
 570 
 571                         zend_hash_str_update(Z_ARRVAL_P(return_value), cache_entry->key, cache_entry->key_length, &persistent_script_report);
 572                 }
 573         }
 574         accelerator_shm_read_unlock();
 575 
 576         return 1;
 577 }
 578 
 579 /* {{{ proto array accelerator_get_status([bool fetch_scripts])
 580    Obtain statistics information regarding code acceleration */
 581 static ZEND_FUNCTION(opcache_get_status)
 582 {
 583         zend_long reqs;
 584         zval memory_usage, statistics, scripts;
 585         zend_bool fetch_scripts = 1;
 586 
 587         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &fetch_scripts) == FAILURE) {
 588                 return;
 589         }
 590 
 591         if (!validate_api_restriction()) {
 592                 RETURN_FALSE;
 593         }
 594 
 595         if (!accel_startup_ok) {
 596                 RETURN_FALSE;
 597         }
 598 
 599         array_init(return_value);
 600 
 601         /* Trivia */
 602         add_assoc_bool(return_value, "opcache_enabled", ZCG(enabled) && (ZCG(counted) || ZCSG(accelerator_enabled)));
 603 
 604 #ifdef HAVE_OPCACHE_FILE_CACHE
 605         if (ZCG(accel_directives).file_cache) {
 606                 add_assoc_string(return_value, "file_cache", ZCG(accel_directives).file_cache);
 607         }
 608         if (ZCG(accel_directives).file_cache_only) {
 609                 add_assoc_bool(return_value, "file_cache_only", 1);
 610                 return;
 611         }
 612 #endif
 613 
 614         add_assoc_bool(return_value, "cache_full", ZSMMG(memory_exhausted));
 615         add_assoc_bool(return_value, "restart_pending", ZCSG(restart_pending));
 616         add_assoc_bool(return_value, "restart_in_progress", ZCSG(restart_in_progress));
 617 
 618         /* Memory usage statistics */
 619         array_init(&memory_usage);
 620         add_assoc_long(&memory_usage, "used_memory", ZCG(accel_directives).memory_consumption-zend_shared_alloc_get_free_memory()-ZSMMG(wasted_shared_memory));
 621         add_assoc_long(&memory_usage, "free_memory", zend_shared_alloc_get_free_memory());
 622         add_assoc_long(&memory_usage, "wasted_memory", ZSMMG(wasted_shared_memory));
 623         add_assoc_double(&memory_usage, "current_wasted_percentage", (((double) ZSMMG(wasted_shared_memory))/ZCG(accel_directives).memory_consumption)*100.0);
 624         add_assoc_zval(return_value, "memory_usage", &memory_usage);
 625 
 626         if (ZCSG(interned_strings_start) && ZCSG(interned_strings_end) && ZCSG(interned_strings_top)) {
 627                 zval interned_strings_usage;
 628 
 629                 array_init(&interned_strings_usage);
 630                 add_assoc_long(&interned_strings_usage, "buffer_size", ZCSG(interned_strings_end) - ZCSG(interned_strings_start));
 631                 add_assoc_long(&interned_strings_usage, "used_memory", ZCSG(interned_strings_top) - ZCSG(interned_strings_start));
 632                 add_assoc_long(&interned_strings_usage, "free_memory", ZCSG(interned_strings_end) - ZCSG(interned_strings_top));
 633                 add_assoc_long(&interned_strings_usage, "number_of_strings", ZCSG(interned_strings).nNumOfElements);
 634                 add_assoc_zval(return_value, "interned_strings_usage", &interned_strings_usage);
 635         }
 636 
 637         /* Accelerator statistics */
 638         array_init(&statistics);
 639         add_assoc_long(&statistics, "num_cached_scripts", ZCSG(hash).num_direct_entries);
 640         add_assoc_long(&statistics, "num_cached_keys",    ZCSG(hash).num_entries);
 641         add_assoc_long(&statistics, "max_cached_keys",    ZCSG(hash).max_num_entries);
 642         add_assoc_long(&statistics, "hits", (zend_long)ZCSG(hits));
 643         add_assoc_long(&statistics, "start_time", ZCSG(start_time));
 644         add_assoc_long(&statistics, "last_restart_time", ZCSG(last_restart_time));
 645         add_assoc_long(&statistics, "oom_restarts", ZCSG(oom_restarts));
 646         add_assoc_long(&statistics, "hash_restarts", ZCSG(hash_restarts));
 647         add_assoc_long(&statistics, "manual_restarts", ZCSG(manual_restarts));
 648         add_assoc_long(&statistics, "misses", ZSMMG(memory_exhausted)?ZCSG(misses):ZCSG(misses)-ZCSG(blacklist_misses));
 649         add_assoc_long(&statistics, "blacklist_misses", ZCSG(blacklist_misses));
 650         reqs = ZCSG(hits)+ZCSG(misses);
 651         add_assoc_double(&statistics, "blacklist_miss_ratio", reqs?(((double) ZCSG(blacklist_misses))/reqs)*100.0:0);
 652         add_assoc_double(&statistics, "opcache_hit_rate", reqs?(((double) ZCSG(hits))/reqs)*100.0:0);
 653         add_assoc_zval(return_value, "opcache_statistics", &statistics);
 654 
 655         if (fetch_scripts) {
 656                 /* accelerated scripts */
 657                 if (accelerator_get_scripts(&scripts)) {
 658                         add_assoc_zval(return_value, "scripts", &scripts);
 659                 }
 660         }
 661 }
 662 
 663 static int add_blacklist_path(zend_blacklist_entry *p, zval *return_value)
 664 {
 665         add_next_index_stringl(return_value, p->path, p->path_length);
 666         return 0;
 667 }
 668 
 669 /* {{{ proto array accelerator_get_configuration()
 670    Obtain configuration information */
 671 static ZEND_FUNCTION(opcache_get_configuration)
 672 {
 673         zval directives, version, blacklist;
 674 
 675         if (zend_parse_parameters_none() == FAILURE) {
 676                 RETURN_FALSE;
 677         }
 678 
 679         if (!validate_api_restriction()) {
 680                 RETURN_FALSE;
 681         }
 682 
 683         array_init(return_value);
 684 
 685         /* directives */
 686         array_init(&directives);
 687         add_assoc_bool(&directives, "opcache.enable",              ZCG(enabled));
 688         add_assoc_bool(&directives, "opcache.enable_cli",          ZCG(accel_directives).enable_cli);
 689         add_assoc_bool(&directives, "opcache.use_cwd",             ZCG(accel_directives).use_cwd);
 690         add_assoc_bool(&directives, "opcache.validate_timestamps", ZCG(accel_directives).validate_timestamps);
 691         add_assoc_bool(&directives, "opcache.inherited_hack",      ZCG(accel_directives).inherited_hack);
 692         add_assoc_bool(&directives, "opcache.dups_fix",            ZCG(accel_directives).ignore_dups);
 693         add_assoc_bool(&directives, "opcache.revalidate_path",     ZCG(accel_directives).revalidate_path);
 694 
 695         add_assoc_long(&directives,   "opcache.log_verbosity_level",    ZCG(accel_directives).log_verbosity_level);
 696         add_assoc_long(&directives,      "opcache.memory_consumption",     ZCG(accel_directives).memory_consumption);
 697         add_assoc_long(&directives,      "opcache.interned_strings_buffer",ZCG(accel_directives).interned_strings_buffer);
 698         add_assoc_long(&directives,      "opcache.max_accelerated_files",  ZCG(accel_directives).max_accelerated_files);
 699         add_assoc_double(&directives, "opcache.max_wasted_percentage",  ZCG(accel_directives).max_wasted_percentage);
 700         add_assoc_long(&directives,      "opcache.consistency_checks",     ZCG(accel_directives).consistency_checks);
 701         add_assoc_long(&directives,      "opcache.force_restart_timeout",  ZCG(accel_directives).force_restart_timeout);
 702         add_assoc_long(&directives,      "opcache.revalidate_freq",        ZCG(accel_directives).revalidate_freq);
 703         add_assoc_string(&directives, "opcache.preferred_memory_model", STRING_NOT_NULL(ZCG(accel_directives).memory_model));
 704         add_assoc_string(&directives, "opcache.blacklist_filename",     STRING_NOT_NULL(ZCG(accel_directives).user_blacklist_filename));
 705         add_assoc_long(&directives,   "opcache.max_file_size",          ZCG(accel_directives).max_file_size);
 706         add_assoc_string(&directives, "opcache.error_log",              STRING_NOT_NULL(ZCG(accel_directives).error_log));
 707 
 708         add_assoc_bool(&directives,   "opcache.protect_memory",         ZCG(accel_directives).protect_memory);
 709         add_assoc_bool(&directives,   "opcache.save_comments",          ZCG(accel_directives).save_comments);
 710         add_assoc_bool(&directives,   "opcache.fast_shutdown",          ZCG(accel_directives).fast_shutdown);
 711         add_assoc_bool(&directives,   "opcache.enable_file_override",   ZCG(accel_directives).file_override_enabled);
 712         add_assoc_long(&directives,      "opcache.optimization_level",     ZCG(accel_directives).optimization_level);
 713 
 714 #ifdef HAVE_OPCACHE_FILE_CACHE
 715         add_assoc_string(&directives, "opcache.file_cache",                    ZCG(accel_directives).file_cache ? ZCG(accel_directives).file_cache : "");
 716         add_assoc_bool(&directives,   "opcache.file_cache_only",               ZCG(accel_directives).file_cache_only);
 717         add_assoc_bool(&directives,   "opcache.file_cache_consistency_checks", ZCG(accel_directives).file_cache_consistency_checks);
 718 #endif
 719 
 720         add_assoc_zval(return_value, "directives", &directives);
 721 
 722         /*version */
 723         array_init(&version);
 724         add_assoc_string(&version, "version", ACCELERATOR_VERSION);
 725         add_assoc_string(&version, "opcache_product_name", ACCELERATOR_PRODUCT_NAME);
 726         add_assoc_zval(return_value, "version", &version);
 727 
 728         /* blacklist */
 729         array_init(&blacklist);
 730         zend_accel_blacklist_apply(&accel_blacklist, add_blacklist_path, &blacklist);
 731         add_assoc_zval(return_value, "blacklist", &blacklist);
 732 }
 733 
 734 /* {{{ proto void accelerator_reset()
 735    Request that the contents of the opcode cache to be reset */
 736 static ZEND_FUNCTION(opcache_reset)
 737 {
 738         if (zend_parse_parameters_none() == FAILURE) {
 739                 RETURN_FALSE;
 740         }
 741 
 742         if (!validate_api_restriction()) {
 743                 RETURN_FALSE;
 744         }
 745 
 746         if ((!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled))
 747 #if ENABLE_FILE_CACHE_FALLBACK
 748         && !fallback_process
 749 #endif
 750         ) {
 751                 RETURN_FALSE;
 752         }
 753 
 754         zend_accel_schedule_restart(ACCEL_RESTART_USER);
 755         RETURN_TRUE;
 756 }
 757 
 758 /* {{{ proto void opcache_invalidate(string $script [, bool $force = false])
 759    Invalidates cached script (in necessary or forced) */
 760 static ZEND_FUNCTION(opcache_invalidate)
 761 {
 762         char *script_name;
 763         size_t script_name_len;
 764         zend_bool force = 0;
 765 
 766         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &script_name, &script_name_len, &force) == FAILURE) {
 767                 return;
 768         }
 769 
 770         if (!validate_api_restriction()) {
 771                 RETURN_FALSE;
 772         }
 773 
 774         if (zend_accel_invalidate(script_name, script_name_len, force) == SUCCESS) {
 775                 RETURN_TRUE;
 776         } else {
 777                 RETURN_FALSE;
 778         }
 779 }
 780 
 781 static ZEND_FUNCTION(opcache_compile_file)
 782 {
 783         char *script_name;
 784         size_t script_name_len;
 785         zend_file_handle handle;
 786         zend_op_array *op_array = NULL;
 787         zend_execute_data *orig_execute_data = NULL;
 788 
 789         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &script_name, &script_name_len) == FAILURE) {
 790                 return;
 791         }
 792 
 793         if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) {
 794                 zend_error(E_NOTICE, ACCELERATOR_PRODUCT_NAME " seems to be disabled, can't compile file");
 795                 RETURN_FALSE;
 796         }
 797 
 798         handle.filename = script_name;
 799         handle.free_filename = 0;
 800         handle.opened_path = NULL;
 801         handle.type = ZEND_HANDLE_FILENAME;
 802 
 803         orig_execute_data = EG(current_execute_data);
 804 
 805         zend_try {
 806                 op_array = persistent_compile_file(&handle, ZEND_INCLUDE);
 807         } zend_catch {
 808                 EG(current_execute_data) = orig_execute_data;
 809                 zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " could not compile file %s", handle.filename);
 810         } zend_end_try();
 811 
 812         if(op_array != NULL) {
 813                 destroy_op_array(op_array);
 814                 efree(op_array);
 815                 RETVAL_TRUE;
 816         } else {
 817                 RETVAL_FALSE;
 818         }
 819         zend_destroy_file_handle(&handle);
 820 }
 821 
 822 /* {{{ proto bool opcache_is_script_cached(string $script)
 823    Return true if the script is cached in OPCache, false if it is not cached or if OPCache is not running. */
 824 static ZEND_FUNCTION(opcache_is_script_cached)
 825 {
 826         zend_string *script_name;
 827 
 828         if (!validate_api_restriction()) {
 829                 RETURN_FALSE;
 830         }
 831 
 832         if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) {
 833                 RETURN_FALSE;
 834         }
 835 
 836         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &script_name) == FAILURE) {
 837                 return;
 838         }
 839 
 840         RETURN_BOOL(filename_is_in_cache(script_name));
 841 }

/* [<][>][^][v][top][bottom][index][help] */