2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006 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.2 2008/03/28 18:35:40 gopalv 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 h->type = ZEND_HANDLE_FILENAME;
289 /* {{{ my_compile_file
290 Overrides zend_compile_file */
291 static zend_op_array* my_compile_file(zend_file_handle* h,
295 apc_cache_entry_t* cache_entry;
296 zend_op_array* op_array;
297 int num_functions, num_classes, ret;
298 zend_op_array* alloc_op_array;
299 apc_function_t* alloc_functions;
300 apc_class_t* alloc_classes;
305 if (!APCG(enabled) || apc_cache_busy(apc_cache)) {
306 return old_compile_file(h, type TSRMLS_CC);
309 /* check our regular expression filters */
310 if (APCG(filters) && apc_compiled_filters) {
311 int ret = apc_regex_match_array(apc_compiled_filters, h->filename);
312 if(ret == APC_NEGATIVE_MATCH || (ret != APC_POSITIVE_MATCH && !APCG(cache_by_default))) {
313 return old_compile_file(h, type TSRMLS_CC);
315 } else if(!APCG(cache_by_default)) {
316 return old_compile_file(h, type TSRMLS_CC);
319 #if PHP_API_VERSION < 20041225
320 #if HAVE_APACHE && defined(APC_PHP4_STAT)
321 t = ((request_rec *)SG(server_context))->request_time;
326 t = sapi_get_request_time(TSRMLS_C);
330 fprintf(stderr,"1. h->opened_path=[%s] h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
333 /* try to create a cache key; if we fail, give up on caching */
334 if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) {
335 return old_compile_file(h, type TSRMLS_CC);
339 if(!APCG(force_file_update)) {
340 /* search for the file in the cache */
341 cache_entry = apc_cache_find(apc_cache, key, t);
346 if (cache_entry != NULL) {
348 int reset_opened_path = 0;
349 if (h->opened_path == NULL) {
350 h->opened_path = cache_entry->data.file.filename;
351 reset_opened_path = 1;
353 zend_hash_add(&EG(included_files), h->opened_path, strlen(h->opened_path)+1, (void *)&dummy, sizeof(int), NULL);
354 apc_stack_push(APCG(cache_stack), cache_entry);
355 op_array = cached_compile(h, type TSRMLS_CC);
358 /* If the file comes from the cache, add it to the global request file list */
359 add_next_index_string(APCG(filehits), h->filename, 1);
363 if(APCG(report_autofilter)) {
364 apc_wprint("Recompiling %s", h->opened_path);
366 if (reset_opened_path == 1) {
367 h->opened_path = NULL;
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 APCG(current_cache) = apc_cache;
434 if(!(alloc_op_array = apc_copy_op_array(NULL, op_array, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
435 APCG(mem_size_ptr) = NULL;
436 APCG(current_cache) = 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 APCG(mem_size_ptr) = NULL;
449 APCG(current_cache) = NULL;
450 #if NONBLOCKING_LOCK_AVAILABLE
451 if(APCG(write_lock)) {
452 apc_cache_write_unlock(apc_cache);
455 HANDLE_UNBLOCK_INTERRUPTIONS();
458 if(!(alloc_classes = apc_copy_new_classes(op_array, num_classes, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
459 apc_free_op_array(alloc_op_array, apc_sma_free);
460 apc_free_functions(alloc_functions, apc_sma_free);
461 APCG(mem_size_ptr) = NULL;
462 APCG(current_cache) = NULL;
463 #if NONBLOCKING_LOCK_AVAILABLE
464 if(APCG(write_lock)) {
465 apc_cache_write_unlock(apc_cache);
468 HANDLE_UNBLOCK_INTERRUPTIONS();
472 path = h->opened_path;
473 if(!path) path=h->filename;
476 fprintf(stderr,"2. h->opened_path=[%s] h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
479 if(!(cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes))) {
480 apc_free_op_array(alloc_op_array, apc_sma_free);
481 apc_free_functions(alloc_functions, apc_sma_free);
482 apc_free_classes(alloc_classes, apc_sma_free);
483 APCG(mem_size_ptr) = NULL;
484 APCG(current_cache) = NULL;
485 #if NONBLOCKING_LOCK_AVAILABLE
486 if(APCG(write_lock)) {
487 apc_cache_write_unlock(apc_cache);
490 HANDLE_UNBLOCK_INTERRUPTIONS();
493 APCG(mem_size_ptr) = NULL;
494 cache_entry->mem_size = mem_size;
496 if ((ret = apc_cache_insert(apc_cache, key, cache_entry, t)) != 1) {
497 apc_cache_free_entry(cache_entry);
500 APCG(current_cache) = NULL;
502 #if NONBLOCKING_LOCK_AVAILABLE
503 if(APCG(write_lock)) {
504 apc_cache_write_unlock(apc_cache);
507 HANDLE_UNBLOCK_INTERRUPTIONS();
513 /* {{{ module init and shutdown */
515 int apc_module_init(int module_number TSRMLS_DC)
517 /* apc initialization */
519 apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, APCG(mmap_file_mask));
521 apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, NULL);
523 apc_cache = apc_cache_create(APCG(num_files_hint), APCG(gc_ttl), APCG(ttl));
524 apc_user_cache = apc_cache_create(APCG(user_entries_hint), APCG(gc_ttl), APCG(user_ttl));
526 apc_compiled_filters = apc_regex_compile_array(APCG(filters));
528 /* override compilation */
529 old_compile_file = zend_compile_file;
530 zend_compile_file = my_compile_file;
531 REGISTER_LONG_CONSTANT("\000apc_magic", (long)&set_compile_hook, CONST_PERSISTENT | CONST_CS);
533 APCG(initialized) = 1;
537 int apc_module_shutdown(TSRMLS_D)
539 if (!APCG(initialized))
542 /* restore compilation */
543 zend_compile_file = old_compile_file;
546 * In case we got interrupted by a SIGTERM or something else during execution
547 * we may have cache entries left on the stack that we need to check to make
548 * sure that any functions or classes these may have added to the global function
549 * and class tables are removed before we blow away the memory that hold them.
551 * This is merely to remove memory leak warnings - as the process is terminated
552 * immediately after shutdown. The following while loop can be removed without
553 * affecting anything else.
555 while (apc_stack_size(APCG(cache_stack)) > 0) {
557 apc_cache_entry_t* cache_entry = (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
558 if (cache_entry->data.file.functions) {
559 for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
560 zend_hash_del(EG(function_table),
561 cache_entry->data.file.functions[i].name,
562 cache_entry->data.file.functions[i].name_len+1);
565 if (cache_entry->data.file.classes) {
566 for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
567 zend_hash_del(EG(class_table),
568 cache_entry->data.file.classes[i].name,
569 cache_entry->data.file.classes[i].name_len+1);
572 apc_cache_release(apc_cache, cache_entry);
575 apc_cache_destroy(apc_cache);
576 apc_cache_destroy(apc_user_cache);
579 APCG(initialized) = 0;
585 /* {{{ process init and shutdown */
586 int apc_process_init(int module_number TSRMLS_DC)
591 int apc_process_shutdown(TSRMLS_D)
597 /* {{{ apc_deactivate */
598 static void apc_deactivate(TSRMLS_D)
600 /* The execution stack was unwound, which prevented us from decrementing
601 * the reference counts on active cache entries in `my_execute`.
603 while (apc_stack_size(APCG(cache_stack)) > 0) {
605 zend_class_entry* zce = NULL;
606 void ** centry = (void*)(&zce);
608 zend_class_entry** pzce = NULL;
611 apc_cache_entry_t* cache_entry =
612 (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
614 if (cache_entry->data.file.classes) {
615 for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
617 centry = (void**)&pzce; /* a triple indirection to get zend_class_entry*** */
619 if(zend_hash_find(EG(class_table),
620 cache_entry->data.file.classes[i].name,
621 cache_entry->data.file.classes[i].name_len+1,
622 (void**)centry) == FAILURE)
624 /* double inclusion of conditional classes ends up failing
625 * this lookup the second time around.
633 zend_hash_del(EG(class_table),
634 cache_entry->data.file.classes[i].name,
635 cache_entry->data.file.classes[i].name_len+1);
637 apc_free_class_entry_after_execution(zce);
640 apc_cache_release(apc_cache, cache_entry);
646 /* {{{ request init and shutdown */
648 int apc_request_init(TSRMLS_D)
650 apc_stack_clear(APCG(cache_stack));
651 APCG(slam_rand) = -1;
652 APCG(copied_zvals) = NULL;
655 ALLOC_INIT_ZVAL(APCG(filehits));
656 array_init(APCG(filehits));
662 int apc_request_shutdown(TSRMLS_D)
664 apc_deactivate(TSRMLS_C);
667 zval_ptr_dtor(&APCG(filehits));
681 * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
682 * vim<600: expandtab sw=4 ts=4 sts=4