This source file includes following definitions.
- validate_api_restriction
- ZEND_INI_MH
- ZEND_INI_MH
- ZEND_INI_MH
- ZEND_INI_MH
- ZEND_INI_MH
- ZEND_INI_BEGIN
- accel_file_in_cache
- accel_file_exists
- accel_is_file
- accel_is_readable
- ZEND_MINIT_FUNCTION
- zend_accel_override_file_functions
- ZEND_MSHUTDOWN_FUNCTION
- zend_accel_info
- start_accel_module
- accelerator_get_scripts
- ZEND_FUNCTION
- add_blacklist_path
- ZEND_FUNCTION
- ZEND_FUNCTION
- ZEND_FUNCTION
- ZEND_FUNCTION
- ZEND_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
65 static ZEND_FUNCTION(opcache_reset);
66 static ZEND_FUNCTION(opcache_invalidate);
67 static ZEND_FUNCTION(opcache_is_script_cached);
68
69
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
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
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
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
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
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
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
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
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;
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
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;
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
530
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
580
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
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
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
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
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
670
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
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
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
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
735
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
759
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
823
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 }