2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2008 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: Daniel Cowgill <dcowgill@communityconnect.com> |
16 | Rasmus Lerdorf <rasmus@php.net> |
17 | Arun C. Murthy <arunc@yahoo-inc.com> |
18 | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
19 +----------------------------------------------------------------------+
21 This software was contributed to PHP by Community Connect Inc. in 2002
22 and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
23 Future revisions and derivatives of this source code must acknowledge
24 Community Connect Inc. as the original contributor of this module by
25 leaving this note intact in the source code.
27 All other licensing and usage conditions are those of the PHP Group.
31 /* $Id: apc_main.c,v 3.103.2.7 2008/05/11 18:57:00 rasmus Exp $ */
37 #include "apc_cache.h"
38 #include "apc_compile.h"
39 #include "apc_globals.h"
41 #include "apc_stack.h"
44 #if PHP_API_VERSION <= 20020918
53 /* {{{ module variables */
55 /* pointer to the original Zend engine compile_file function */
56 typedef zend_op_array* (zend_compile_t)(zend_file_handle*, int TSRMLS_DC);
57 static zend_compile_t *old_compile_file;
61 /* {{{ get/set old_compile_file (to interact with other extensions that need the compile hook) */
62 static zend_compile_t* set_compile_hook(zend_compile_t *ptr)
64 zend_compile_t *retval = old_compile_file;
66 if (ptr != NULL) old_compile_file = ptr;
71 /* {{{ install_function */
72 static int install_function(apc_function_t fn TSRMLS_DC)
77 func = apc_copy_function_for_execution(fn.function);
79 status = zend_hash_add(EG(function_table),
83 sizeof(fn.function[0]),
88 if (status == FAILURE) {
89 /* apc_eprint("Cannot redeclare %s()", fn.name); */
96 /* {{{ install_class */
97 static int install_class(apc_class_t cl TSRMLS_DC)
99 zend_class_entry* class_entry = cl.class_entry;
100 zend_class_entry* parent = NULL;
103 zend_class_entry** allocated_ce = NULL;
107 /* Special case for mangled names. Mangled names are unique to a file.
108 * There is no way two classes with the same mangled name will occur,
109 * unless a file is included twice. And if in case, a file is included
110 * twice, all mangled name conflicts can be ignored and the class redeclaration
111 * error may be deferred till runtime of the corresponding DECLARE_CLASS
115 if(cl.name_len != 0 && cl.name[0] == '\0') {
116 if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) {
123 * XXX: We need to free this somewhere...
125 allocated_ce = apc_php_malloc(sizeof(zend_class_entry*));
134 apc_copy_class_entry_for_execution(cl.class_entry,
138 /* restore parent class pointer for compile-time inheritance */
139 if (cl.parent_name != NULL) {
141 zend_class_entry** parent_ptr = NULL;
143 * zend_lookup_class has to be due to presence of __autoload,
144 * just looking up the EG(class_table) is not enough in php5!
145 * Even more dangerously, thanks to __autoload and people using
146 * class names as filepaths for inclusion, this has to be case
147 * sensitive. zend_lookup_class automatically does a case_fold
148 * internally, but passes the case preserved version to __autoload.
149 * Aside: Do NOT pass *strlen(cl.parent_name)+1* because
150 * zend_lookup_class does it internally anyway!
152 status = zend_lookup_class(cl.parent_name,
153 strlen(cl.parent_name),
154 &parent_ptr TSRMLS_CC);
156 status = zend_hash_find(EG(class_table),
158 strlen(cl.parent_name)+1,
161 if (status == FAILURE) {
162 if(APCG(report_autofilter)) {
163 apc_wprint("Dynamic inheritance detected for class %s", cl.name);
165 class_entry->parent = NULL;
170 parent = *parent_ptr;
172 class_entry->parent = parent;
174 zend_do_inheritance(class_entry, parent TSRMLS_CC);
176 zend_do_inheritance(class_entry, parent);
184 status = zend_hash_add(EG(class_table),
188 sizeof(zend_class_entry*),
191 status = zend_hash_add(EG(class_table),
195 sizeof(zend_class_entry),
199 if (status == FAILURE) {
200 apc_eprint("Cannot redeclare class %s", cl.name);
206 /* {{{ uninstall_class */
207 static int uninstall_class(apc_class_t cl TSRMLS_DC)
212 status = zend_hash_del(EG(class_table),
216 status = zend_hash_del(EG(class_table),
220 if (status == FAILURE) {
221 apc_eprint("Cannot delete class %s", cl.name);
227 /* {{{ compare_file_handles */
228 static int compare_file_handles(void* a, void* b)
230 zend_file_handle* fh1 = (zend_file_handle*)a;
231 zend_file_handle* fh2 = (zend_file_handle*)b;
232 return (fh1->type == fh2->type &&
233 fh1->filename == fh2->filename &&
234 fh1->opened_path == fh2->opened_path);
238 /* {{{ cached_compile */
239 static zend_op_array* cached_compile(zend_file_handle* h,
242 apc_cache_entry_t* cache_entry;
245 cache_entry = (apc_cache_entry_t*) apc_stack_top(APCG(cache_stack));
246 assert(cache_entry != NULL);
248 if (cache_entry->data.file.classes) {
249 for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
250 if(install_class(cache_entry->data.file.classes[i] TSRMLS_CC) == FAILURE) {
251 goto default_compile;
256 if (cache_entry->data.file.functions) {
257 for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
258 install_function(cache_entry->data.file.functions[i] TSRMLS_CC);
263 return apc_copy_op_array_for_execution(NULL, cache_entry->data.file.op_array TSRMLS_CC);
267 if(APCG(report_autofilter)) {
268 apc_wprint("Autofiltering %s", h->opened_path);
271 if(cache_entry->data.file.classes) {
272 for(ii = 0; ii < i ; ii++) {
273 uninstall_class(cache_entry->data.file.classes[ii] TSRMLS_CC);
277 apc_stack_pop(APCG(cache_stack)); /* pop out cache_entry */
279 apc_cache_release(apc_cache, cache_entry);
281 /* cannot free up cache data yet, it maybe in use */
283 zend_llist_del_element(&CG(open_files), h, compare_file_handles); /* We leak fds without this hack */
285 h->type = ZEND_HANDLE_FILENAME;
291 /* {{{ my_compile_file
292 Overrides zend_compile_file */
293 static zend_op_array* my_compile_file(zend_file_handle* h,
297 apc_cache_entry_t* cache_entry;
298 zend_op_array* op_array;
299 int num_functions, num_classes, ret;
300 zend_op_array* alloc_op_array;
301 apc_function_t* alloc_functions;
302 apc_class_t* alloc_classes;
307 if (!APCG(enabled) || apc_cache_busy(apc_cache)) {
308 return old_compile_file(h, type TSRMLS_CC);
311 /* check our regular expression filters */
312 if (APCG(filters) && apc_compiled_filters) {
313 int ret = apc_regex_match_array(apc_compiled_filters, h->filename);
314 if(ret == APC_NEGATIVE_MATCH || (ret != APC_POSITIVE_MATCH && !APCG(cache_by_default))) {
315 return old_compile_file(h, type TSRMLS_CC);
317 } else if(!APCG(cache_by_default)) {
318 return old_compile_file(h, type TSRMLS_CC);
321 #if PHP_API_VERSION < 20041225
322 #if HAVE_APACHE && defined(APC_PHP4_STAT)
323 t = ((request_rec *)SG(server_context))->request_time;
328 t = sapi_get_request_time(TSRMLS_C);
332 fprintf(stderr,"1. h->opened_path=[%s] h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
335 /* try to create a cache key; if we fail, give up on caching */
336 if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) {
337 return old_compile_file(h, type TSRMLS_CC);
341 if(!APCG(force_file_update)) {
342 /* search for the file in the cache */
343 cache_entry = apc_cache_find(apc_cache, key, t);
348 if (cache_entry != NULL) {
350 if (h->opened_path == NULL) {
351 h->opened_path = estrdup(cache_entry->data.file.filename);
353 zend_hash_add(&EG(included_files), h->opened_path, strlen(h->opened_path)+1, (void *)&dummy, sizeof(int), NULL);
355 zend_llist_add_element(&CG(open_files), h); /* We leak fds without this hack */
357 apc_stack_push(APCG(cache_stack), cache_entry);
358 op_array = cached_compile(h, type TSRMLS_CC);
361 /* If the file comes from the cache, add it to the global request file list */
362 add_next_index_string(APCG(filehits), h->filename, 1);
366 if(APCG(report_autofilter)) {
367 apc_wprint("Recompiling %s", h->opened_path);
369 /* TODO: check what happens with EG(included_files) */
372 /* remember how many functions and classes existed before compilation */
373 num_functions = zend_hash_num_elements(CG(function_table));
374 num_classes = zend_hash_num_elements(CG(class_table));
376 /* compile the file using the default compile function */
377 op_array = old_compile_file(h, type TSRMLS_CC);
378 if (op_array == NULL) {
382 * Basically this will cause a file only to be cached on a percentage
383 * of the attempts. This is to avoid cache slams when starting up a
384 * very busy server or when modifying files on a very busy live server.
385 * There is no point having many processes all trying to cache the same
386 * file at the same time. By introducing a chance of being cached
387 * we theoretically cut the cache slam problem by the given percentage.
388 * For example if apc.slam_defense is set to 66 then 2/3 of the attempts
389 * to cache an uncached file will be ignored.
391 if(APCG(slam_defense)) {
392 if(APCG(slam_rand)==-1) {
393 APCG(slam_rand) = (int)(100.0*rand()/(RAND_MAX+1.0));
395 if(APCG(slam_rand) < APCG(slam_defense)) {
400 /* Make sure the mtime reflects the files last known mtime in the case of fpstat==0 */
401 if(key.type == APC_CACHE_KEY_FPFILE) {
402 apc_fileinfo_t fileinfo;
403 struct stat *tmp_buf = NULL;
404 if(!strcmp(SG(request_info).path_translated, h->filename)) {
405 tmp_buf = sapi_get_stat(TSRMLS_C); /* Apache has already done this stat() for us */
408 fileinfo.st_buf.sb = *tmp_buf;
410 if (apc_search_paths(h->filename, PG(include_path), &fileinfo) != 0) {
412 fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",filename,SG(request_info).path_translated);
417 key.mtime = fileinfo.st_buf.sb.st_mtime;
420 HANDLE_BLOCK_INTERRUPTIONS();
422 #if NONBLOCKING_LOCK_AVAILABLE
423 if(APCG(write_lock)) {
424 if(!apc_cache_write_lock(apc_cache)) {
425 HANDLE_UNBLOCK_INTERRUPTIONS();
432 APCG(mem_size_ptr) = &mem_size;
433 if(!(alloc_op_array = apc_copy_op_array(NULL, op_array, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
434 apc_cache_expunge(apc_cache,t);
435 apc_cache_expunge(apc_user_cache,t);
436 APCG(mem_size_ptr) = NULL;
437 #if NONBLOCKING_LOCK_AVAILABLE
438 if(APCG(write_lock)) {
439 apc_cache_write_unlock(apc_cache);
442 HANDLE_UNBLOCK_INTERRUPTIONS();
446 if(!(alloc_functions = apc_copy_new_functions(num_functions, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
447 apc_free_op_array(alloc_op_array, apc_sma_free);
448 apc_cache_expunge(apc_cache,t);
449 apc_cache_expunge(apc_user_cache,t);
450 APCG(mem_size_ptr) = NULL;
451 #if NONBLOCKING_LOCK_AVAILABLE
452 if(APCG(write_lock)) {
453 apc_cache_write_unlock(apc_cache);
456 HANDLE_UNBLOCK_INTERRUPTIONS();
459 if(!(alloc_classes = apc_copy_new_classes(op_array, num_classes, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
460 apc_free_op_array(alloc_op_array, apc_sma_free);
461 apc_free_functions(alloc_functions, apc_sma_free);
462 apc_cache_expunge(apc_cache,t);
463 apc_cache_expunge(apc_user_cache,t);
464 APCG(mem_size_ptr) = NULL;
465 #if NONBLOCKING_LOCK_AVAILABLE
466 if(APCG(write_lock)) {
467 apc_cache_write_unlock(apc_cache);
470 HANDLE_UNBLOCK_INTERRUPTIONS();
474 path = h->opened_path;
475 if(!path) path=h->filename;
478 fprintf(stderr,"2. h->opened_path=[%s] h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
481 if(!(cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes))) {
482 apc_free_op_array(alloc_op_array, apc_sma_free);
483 apc_free_functions(alloc_functions, apc_sma_free);
484 apc_free_classes(alloc_classes, apc_sma_free);
485 apc_cache_expunge(apc_cache,t);
486 apc_cache_expunge(apc_user_cache,t);
487 APCG(mem_size_ptr) = NULL;
488 #if NONBLOCKING_LOCK_AVAILABLE
489 if(APCG(write_lock)) {
490 apc_cache_write_unlock(apc_cache);
493 HANDLE_UNBLOCK_INTERRUPTIONS();
496 APCG(mem_size_ptr) = NULL;
497 cache_entry->mem_size = mem_size;
499 if ((ret = apc_cache_insert(apc_cache, key, cache_entry, t)) != 1) {
500 apc_cache_free_entry(cache_entry);
502 apc_cache_expunge(apc_cache,t);
503 apc_cache_expunge(apc_user_cache,t);
507 #if NONBLOCKING_LOCK_AVAILABLE
508 if(APCG(write_lock)) {
509 apc_cache_write_unlock(apc_cache);
512 HANDLE_UNBLOCK_INTERRUPTIONS();
518 /* {{{ module init and shutdown */
520 int apc_module_init(int module_number TSRMLS_DC)
522 /* apc initialization */
524 apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, APCG(mmap_file_mask));
526 apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, NULL);
528 apc_cache = apc_cache_create(APCG(num_files_hint), APCG(gc_ttl), APCG(ttl));
529 apc_user_cache = apc_cache_create(APCG(user_entries_hint), APCG(gc_ttl), APCG(user_ttl));
531 apc_compiled_filters = apc_regex_compile_array(APCG(filters));
533 /* override compilation */
534 old_compile_file = zend_compile_file;
535 zend_compile_file = my_compile_file;
536 REGISTER_LONG_CONSTANT("\000apc_magic", (long)&set_compile_hook, CONST_PERSISTENT | CONST_CS);
538 APCG(initialized) = 1;
542 int apc_module_shutdown(TSRMLS_D)
544 if (!APCG(initialized))
547 /* restore compilation */
548 zend_compile_file = old_compile_file;
551 * In case we got interrupted by a SIGTERM or something else during execution
552 * we may have cache entries left on the stack that we need to check to make
553 * sure that any functions or classes these may have added to the global function
554 * and class tables are removed before we blow away the memory that hold them.
556 * This is merely to remove memory leak warnings - as the process is terminated
557 * immediately after shutdown. The following while loop can be removed without
558 * affecting anything else.
560 while (apc_stack_size(APCG(cache_stack)) > 0) {
562 apc_cache_entry_t* cache_entry = (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
563 if (cache_entry->data.file.functions) {
564 for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
565 zend_hash_del(EG(function_table),
566 cache_entry->data.file.functions[i].name,
567 cache_entry->data.file.functions[i].name_len+1);
570 if (cache_entry->data.file.classes) {
571 for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
572 zend_hash_del(EG(class_table),
573 cache_entry->data.file.classes[i].name,
574 cache_entry->data.file.classes[i].name_len+1);
577 apc_cache_release(apc_cache, cache_entry);
580 apc_cache_destroy(apc_cache);
581 apc_cache_destroy(apc_user_cache);
584 APCG(initialized) = 0;
590 /* {{{ process init and shutdown */
591 int apc_process_init(int module_number TSRMLS_DC)
596 int apc_process_shutdown(TSRMLS_D)
602 /* {{{ apc_deactivate */
603 static void apc_deactivate(TSRMLS_D)
605 /* The execution stack was unwound, which prevented us from decrementing
606 * the reference counts on active cache entries in `my_execute`.
608 while (apc_stack_size(APCG(cache_stack)) > 0) {
610 zend_class_entry* zce = NULL;
611 void ** centry = (void*)(&zce);
613 zend_class_entry** pzce = NULL;
616 apc_cache_entry_t* cache_entry =
617 (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
619 if (cache_entry->data.file.classes) {
620 for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
622 centry = (void**)&pzce; /* a triple indirection to get zend_class_entry*** */
624 if(zend_hash_find(EG(class_table),
625 cache_entry->data.file.classes[i].name,
626 cache_entry->data.file.classes[i].name_len+1,
627 (void**)centry) == FAILURE)
629 /* double inclusion of conditional classes ends up failing
630 * this lookup the second time around.
638 zend_hash_del(EG(class_table),
639 cache_entry->data.file.classes[i].name,
640 cache_entry->data.file.classes[i].name_len+1);
642 apc_free_class_entry_after_execution(zce);
645 apc_cache_release(apc_cache, cache_entry);
651 /* {{{ request init and shutdown */
653 int apc_request_init(TSRMLS_D)
655 apc_stack_clear(APCG(cache_stack));
656 APCG(slam_rand) = -1;
657 APCG(copied_zvals) = NULL;
660 ALLOC_INIT_ZVAL(APCG(filehits));
661 array_init(APCG(filehits));
667 int apc_request_shutdown(TSRMLS_D)
669 apc_deactivate(TSRMLS_C);
672 zval_ptr_dtor(&APCG(filehits));
686 * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
687 * vim<600: expandtab sw=4 ts=4 sts=4