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

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