X-Git-Url: http://ftp.carnet.hr/carnet-debian/scm?p=php5-apc.git;a=blobdiff_plain;f=apc_main.c;fp=apc_main.c;h=0000000000000000000000000000000000000000;hp=3825399a906d34596344724f56b1d649d02bd3f6;hb=a34ea625346aecd2d2b227b8ca4f114eaa607213;hpb=b0895ef8074c6dd090f9b0a65d58179941541756 diff --git a/apc_main.c b/apc_main.c deleted file mode 100644 index 3825399..0000000 --- a/apc_main.c +++ /dev/null @@ -1,688 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | APC | - +----------------------------------------------------------------------+ - | Copyright (c) 2008 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Daniel Cowgill | - | Rasmus Lerdorf | - | Arun C. Murthy | - | Gopal Vijayaraghavan | - +----------------------------------------------------------------------+ - - This software was contributed to PHP by Community Connect Inc. in 2002 - and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. - Future revisions and derivatives of this source code must acknowledge - Community Connect Inc. as the original contributor of this module by - leaving this note intact in the source code. - - All other licensing and usage conditions are those of the PHP Group. - - */ - -/* $Id: apc_main.c,v 3.103.2.7 2008/05/11 18:57:00 rasmus Exp $ */ - -#include "apc_php.h" -#include "apc_main.h" -#include "apc.h" -#include "apc_lock.h" -#include "apc_cache.h" -#include "apc_compile.h" -#include "apc_globals.h" -#include "apc_sma.h" -#include "apc_stack.h" -#include "apc_zend.h" -#include "SAPI.h" -#if PHP_API_VERSION <= 20020918 -#if HAVE_APACHE -#ifdef APC_PHP4_STAT -#undef XtOffsetOf -#include "httpd.h" -#endif -#endif -#endif - -/* {{{ module variables */ - -/* pointer to the original Zend engine compile_file function */ -typedef zend_op_array* (zend_compile_t)(zend_file_handle*, int TSRMLS_DC); -static zend_compile_t *old_compile_file; - -/* }}} */ - -/* {{{ get/set old_compile_file (to interact with other extensions that need the compile hook) */ -static zend_compile_t* set_compile_hook(zend_compile_t *ptr) -{ - zend_compile_t *retval = old_compile_file; - - if (ptr != NULL) old_compile_file = ptr; - return retval; -} -/* }}} */ - -/* {{{ install_function */ -static int install_function(apc_function_t fn TSRMLS_DC) -{ - zend_function *func; - int status; - - func = apc_copy_function_for_execution(fn.function); - - status = zend_hash_add(EG(function_table), - fn.name, - fn.name_len+1, - func, - sizeof(fn.function[0]), - NULL); - - efree(func); - - if (status == FAILURE) { - /* apc_eprint("Cannot redeclare %s()", fn.name); */ - } - - return status; -} -/* }}} */ - -/* {{{ install_class */ -static int install_class(apc_class_t cl TSRMLS_DC) -{ - zend_class_entry* class_entry = cl.class_entry; - zend_class_entry* parent = NULL; - int status; -#ifdef ZEND_ENGINE_2 - zend_class_entry** allocated_ce = NULL; -#endif - - - /* Special case for mangled names. Mangled names are unique to a file. - * There is no way two classes with the same mangled name will occur, - * unless a file is included twice. And if in case, a file is included - * twice, all mangled name conflicts can be ignored and the class redeclaration - * error may be deferred till runtime of the corresponding DECLARE_CLASS - * calls. - */ - - if(cl.name_len != 0 && cl.name[0] == '\0') { - if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) { - return SUCCESS; - } - } - -#ifdef ZEND_ENGINE_2 - /* - * XXX: We need to free this somewhere... - */ - allocated_ce = apc_php_malloc(sizeof(zend_class_entry*)); - - if(!allocated_ce) { - return FAILURE; - } - - *allocated_ce = -#endif - class_entry = - apc_copy_class_entry_for_execution(cl.class_entry, - cl.is_derived); - - - /* restore parent class pointer for compile-time inheritance */ - if (cl.parent_name != NULL) { -#ifdef ZEND_ENGINE_2 - zend_class_entry** parent_ptr = NULL; - /* - * zend_lookup_class has to be due to presence of __autoload, - * just looking up the EG(class_table) is not enough in php5! - * Even more dangerously, thanks to __autoload and people using - * class names as filepaths for inclusion, this has to be case - * sensitive. zend_lookup_class automatically does a case_fold - * internally, but passes the case preserved version to __autoload. - * Aside: Do NOT pass *strlen(cl.parent_name)+1* because - * zend_lookup_class does it internally anyway! - */ - status = zend_lookup_class(cl.parent_name, - strlen(cl.parent_name), - &parent_ptr TSRMLS_CC); -#else - status = zend_hash_find(EG(class_table), - cl.parent_name, - strlen(cl.parent_name)+1, - (void**) &parent); -#endif - if (status == FAILURE) { - if(APCG(report_autofilter)) { - apc_wprint("Dynamic inheritance detected for class %s", cl.name); - } - class_entry->parent = NULL; - return status; - } - else { -#ifdef ZEND_ENGINE_2 - parent = *parent_ptr; -#endif - class_entry->parent = parent; -#ifdef ZEND_ENGINE_2 - zend_do_inheritance(class_entry, parent TSRMLS_CC); -#else - zend_do_inheritance(class_entry, parent); -#endif - } - - - } - -#ifdef ZEND_ENGINE_2 - status = zend_hash_add(EG(class_table), - cl.name, - cl.name_len+1, - allocated_ce, - sizeof(zend_class_entry*), - NULL); -#else - status = zend_hash_add(EG(class_table), - cl.name, - cl.name_len+1, - class_entry, - sizeof(zend_class_entry), - NULL); -#endif - - if (status == FAILURE) { - apc_eprint("Cannot redeclare class %s", cl.name); - } - return status; -} -/* }}} */ - -/* {{{ uninstall_class */ -static int uninstall_class(apc_class_t cl TSRMLS_DC) -{ - int status; - -#ifdef ZEND_ENGINE_2 - status = zend_hash_del(EG(class_table), - cl.name, - cl.name_len+1); -#else - status = zend_hash_del(EG(class_table), - cl.name, - cl.name_len+1); -#endif - if (status == FAILURE) { - apc_eprint("Cannot delete class %s", cl.name); - } - return status; -} -/* }}} */ - -/* {{{ compare_file_handles */ -static int compare_file_handles(void* a, void* b) -{ - zend_file_handle* fh1 = (zend_file_handle*)a; - zend_file_handle* fh2 = (zend_file_handle*)b; - return (fh1->type == fh2->type && - fh1->filename == fh2->filename && - fh1->opened_path == fh2->opened_path); -} -/* }}} */ - -/* {{{ cached_compile */ -static zend_op_array* cached_compile(zend_file_handle* h, - int type TSRMLS_DC) -{ - apc_cache_entry_t* cache_entry; - int i, ii; - - cache_entry = (apc_cache_entry_t*) apc_stack_top(APCG(cache_stack)); - assert(cache_entry != NULL); - - if (cache_entry->data.file.classes) { - for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) { - if(install_class(cache_entry->data.file.classes[i] TSRMLS_CC) == FAILURE) { - goto default_compile; - } - } - } - - if (cache_entry->data.file.functions) { - for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) { - install_function(cache_entry->data.file.functions[i] TSRMLS_CC); - } - } - - - return apc_copy_op_array_for_execution(NULL, cache_entry->data.file.op_array TSRMLS_CC); - -default_compile: - - if(APCG(report_autofilter)) { - apc_wprint("Autofiltering %s", h->opened_path); - } - - if(cache_entry->data.file.classes) { - for(ii = 0; ii < i ; ii++) { - uninstall_class(cache_entry->data.file.classes[ii] TSRMLS_CC); - } - } - - apc_stack_pop(APCG(cache_stack)); /* pop out cache_entry */ - - apc_cache_release(apc_cache, cache_entry); - - /* cannot free up cache data yet, it maybe in use */ - - zend_llist_del_element(&CG(open_files), h, compare_file_handles); /* We leak fds without this hack */ - - h->type = ZEND_HANDLE_FILENAME; - - return NULL; -} -/* }}} */ - -/* {{{ my_compile_file - Overrides zend_compile_file */ -static zend_op_array* my_compile_file(zend_file_handle* h, - int type TSRMLS_DC) -{ - apc_cache_key_t key; - apc_cache_entry_t* cache_entry; - zend_op_array* op_array; - int num_functions, num_classes, ret; - zend_op_array* alloc_op_array; - apc_function_t* alloc_functions; - apc_class_t* alloc_classes; - time_t t; - char *path; - size_t mem_size; - - if (!APCG(enabled) || apc_cache_busy(apc_cache)) { - return old_compile_file(h, type TSRMLS_CC); - } - - /* check our regular expression filters */ - if (APCG(filters) && apc_compiled_filters) { - int ret = apc_regex_match_array(apc_compiled_filters, h->filename); - if(ret == APC_NEGATIVE_MATCH || (ret != APC_POSITIVE_MATCH && !APCG(cache_by_default))) { - return old_compile_file(h, type TSRMLS_CC); - } - } else if(!APCG(cache_by_default)) { - return old_compile_file(h, type TSRMLS_CC); - } - -#if PHP_API_VERSION < 20041225 -#if HAVE_APACHE && defined(APC_PHP4_STAT) - t = ((request_rec *)SG(server_context))->request_time; -#else - t = time(0); -#endif -#else - t = sapi_get_request_time(TSRMLS_C); -#endif - -#ifdef __DEBUG_APC__ - fprintf(stderr,"1. h->opened_path=[%s] h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename); -#endif - - /* try to create a cache key; if we fail, give up on caching */ - if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) { - return old_compile_file(h, type TSRMLS_CC); - } - - - if(!APCG(force_file_update)) { - /* search for the file in the cache */ - cache_entry = apc_cache_find(apc_cache, key, t); - } else { - cache_entry = NULL; - } - - if (cache_entry != NULL) { - int dummy = 1; - if (h->opened_path == NULL) { - h->opened_path = estrdup(cache_entry->data.file.filename); - } - zend_hash_add(&EG(included_files), h->opened_path, strlen(h->opened_path)+1, (void *)&dummy, sizeof(int), NULL); - - zend_llist_add_element(&CG(open_files), h); /* We leak fds without this hack */ - - apc_stack_push(APCG(cache_stack), cache_entry); - op_array = cached_compile(h, type TSRMLS_CC); - if(op_array) { -#ifdef APC_FILEHITS - /* If the file comes from the cache, add it to the global request file list */ - add_next_index_string(APCG(filehits), h->filename, 1); -#endif - return op_array; - } - if(APCG(report_autofilter)) { - apc_wprint("Recompiling %s", h->opened_path); - } - /* TODO: check what happens with EG(included_files) */ - } - - /* remember how many functions and classes existed before compilation */ - num_functions = zend_hash_num_elements(CG(function_table)); - num_classes = zend_hash_num_elements(CG(class_table)); - - /* compile the file using the default compile function */ - op_array = old_compile_file(h, type TSRMLS_CC); - if (op_array == NULL) { - return NULL; - } - /* - * Basically this will cause a file only to be cached on a percentage - * of the attempts. This is to avoid cache slams when starting up a - * very busy server or when modifying files on a very busy live server. - * There is no point having many processes all trying to cache the same - * file at the same time. By introducing a chance of being cached - * we theoretically cut the cache slam problem by the given percentage. - * For example if apc.slam_defense is set to 66 then 2/3 of the attempts - * to cache an uncached file will be ignored. - */ - if(APCG(slam_defense)) { - if(APCG(slam_rand)==-1) { - APCG(slam_rand) = (int)(100.0*rand()/(RAND_MAX+1.0)); - } - if(APCG(slam_rand) < APCG(slam_defense)) { - return op_array; - } - } - - /* Make sure the mtime reflects the files last known mtime in the case of fpstat==0 */ - if(key.type == APC_CACHE_KEY_FPFILE) { - apc_fileinfo_t fileinfo; - struct stat *tmp_buf = NULL; - if(!strcmp(SG(request_info).path_translated, h->filename)) { - tmp_buf = sapi_get_stat(TSRMLS_C); /* Apache has already done this stat() for us */ - } - if(tmp_buf) { - fileinfo.st_buf.sb = *tmp_buf; - } else { - if (apc_search_paths(h->filename, PG(include_path), &fileinfo) != 0) { -#ifdef __DEBUG_APC__ - fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",filename,SG(request_info).path_translated); -#endif - return op_array; - } - } - key.mtime = fileinfo.st_buf.sb.st_mtime; - } - - HANDLE_BLOCK_INTERRUPTIONS(); - -#if NONBLOCKING_LOCK_AVAILABLE - if(APCG(write_lock)) { - if(!apc_cache_write_lock(apc_cache)) { - HANDLE_UNBLOCK_INTERRUPTIONS(); - return op_array; - } - } -#endif - - mem_size = 0; - APCG(mem_size_ptr) = &mem_size; - if(!(alloc_op_array = apc_copy_op_array(NULL, op_array, apc_sma_malloc, apc_sma_free TSRMLS_CC))) { - apc_cache_expunge(apc_cache,t); - apc_cache_expunge(apc_user_cache,t); - APCG(mem_size_ptr) = NULL; -#if NONBLOCKING_LOCK_AVAILABLE - if(APCG(write_lock)) { - apc_cache_write_unlock(apc_cache); - } -#endif - HANDLE_UNBLOCK_INTERRUPTIONS(); - return op_array; - } - - if(!(alloc_functions = apc_copy_new_functions(num_functions, apc_sma_malloc, apc_sma_free TSRMLS_CC))) { - apc_free_op_array(alloc_op_array, apc_sma_free); - apc_cache_expunge(apc_cache,t); - apc_cache_expunge(apc_user_cache,t); - APCG(mem_size_ptr) = NULL; -#if NONBLOCKING_LOCK_AVAILABLE - if(APCG(write_lock)) { - apc_cache_write_unlock(apc_cache); - } -#endif - HANDLE_UNBLOCK_INTERRUPTIONS(); - return op_array; - } - if(!(alloc_classes = apc_copy_new_classes(op_array, num_classes, apc_sma_malloc, apc_sma_free TSRMLS_CC))) { - apc_free_op_array(alloc_op_array, apc_sma_free); - apc_free_functions(alloc_functions, apc_sma_free); - apc_cache_expunge(apc_cache,t); - apc_cache_expunge(apc_user_cache,t); - APCG(mem_size_ptr) = NULL; -#if NONBLOCKING_LOCK_AVAILABLE - if(APCG(write_lock)) { - apc_cache_write_unlock(apc_cache); - } -#endif - HANDLE_UNBLOCK_INTERRUPTIONS(); - return op_array; - } - - path = h->opened_path; - if(!path) path=h->filename; - -#ifdef __DEBUG_APC__ - fprintf(stderr,"2. h->opened_path=[%s] h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename); -#endif - - if(!(cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes))) { - apc_free_op_array(alloc_op_array, apc_sma_free); - apc_free_functions(alloc_functions, apc_sma_free); - apc_free_classes(alloc_classes, apc_sma_free); - apc_cache_expunge(apc_cache,t); - apc_cache_expunge(apc_user_cache,t); - APCG(mem_size_ptr) = NULL; -#if NONBLOCKING_LOCK_AVAILABLE - if(APCG(write_lock)) { - apc_cache_write_unlock(apc_cache); - } -#endif - HANDLE_UNBLOCK_INTERRUPTIONS(); - return op_array; - } - APCG(mem_size_ptr) = NULL; - cache_entry->mem_size = mem_size; - - if ((ret = apc_cache_insert(apc_cache, key, cache_entry, t)) != 1) { - apc_cache_free_entry(cache_entry); - if(ret==-1) { - apc_cache_expunge(apc_cache,t); - apc_cache_expunge(apc_user_cache,t); - } - } - -#if NONBLOCKING_LOCK_AVAILABLE - if(APCG(write_lock)) { - apc_cache_write_unlock(apc_cache); - } -#endif - HANDLE_UNBLOCK_INTERRUPTIONS(); - - return op_array; -} -/* }}} */ - -/* {{{ module init and shutdown */ - -int apc_module_init(int module_number TSRMLS_DC) -{ - /* apc initialization */ -#if APC_MMAP - apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, APCG(mmap_file_mask)); -#else - apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, NULL); -#endif - apc_cache = apc_cache_create(APCG(num_files_hint), APCG(gc_ttl), APCG(ttl)); - apc_user_cache = apc_cache_create(APCG(user_entries_hint), APCG(gc_ttl), APCG(user_ttl)); - - apc_compiled_filters = apc_regex_compile_array(APCG(filters)); - - /* override compilation */ - old_compile_file = zend_compile_file; - zend_compile_file = my_compile_file; - REGISTER_LONG_CONSTANT("\000apc_magic", (long)&set_compile_hook, CONST_PERSISTENT | CONST_CS); - - APCG(initialized) = 1; - return 0; -} - -int apc_module_shutdown(TSRMLS_D) -{ - if (!APCG(initialized)) - return 0; - - /* restore compilation */ - zend_compile_file = old_compile_file; - - /* - * In case we got interrupted by a SIGTERM or something else during execution - * we may have cache entries left on the stack that we need to check to make - * sure that any functions or classes these may have added to the global function - * and class tables are removed before we blow away the memory that hold them. - * - * This is merely to remove memory leak warnings - as the process is terminated - * immediately after shutdown. The following while loop can be removed without - * affecting anything else. - */ - while (apc_stack_size(APCG(cache_stack)) > 0) { - int i; - apc_cache_entry_t* cache_entry = (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack)); - if (cache_entry->data.file.functions) { - for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) { - zend_hash_del(EG(function_table), - cache_entry->data.file.functions[i].name, - cache_entry->data.file.functions[i].name_len+1); - } - } - if (cache_entry->data.file.classes) { - for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) { - zend_hash_del(EG(class_table), - cache_entry->data.file.classes[i].name, - cache_entry->data.file.classes[i].name_len+1); - } - } - apc_cache_release(apc_cache, cache_entry); - } - - apc_cache_destroy(apc_cache); - apc_cache_destroy(apc_user_cache); - apc_sma_cleanup(); - - APCG(initialized) = 0; - return 0; -} - -/* }}} */ - -/* {{{ process init and shutdown */ -int apc_process_init(int module_number TSRMLS_DC) -{ - return 0; -} - -int apc_process_shutdown(TSRMLS_D) -{ - return 0; -} -/* }}} */ - -/* {{{ apc_deactivate */ -static void apc_deactivate(TSRMLS_D) -{ - /* The execution stack was unwound, which prevented us from decrementing - * the reference counts on active cache entries in `my_execute`. - */ - while (apc_stack_size(APCG(cache_stack)) > 0) { - int i; - zend_class_entry* zce = NULL; - void ** centry = (void*)(&zce); -#ifdef ZEND_ENGINE_2 - zend_class_entry** pzce = NULL; -#endif - - apc_cache_entry_t* cache_entry = - (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack)); - - if (cache_entry->data.file.classes) { - for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) { -#ifdef ZEND_ENGINE_2 - centry = (void**)&pzce; /* a triple indirection to get zend_class_entry*** */ -#endif - if(zend_hash_find(EG(class_table), - cache_entry->data.file.classes[i].name, - cache_entry->data.file.classes[i].name_len+1, - (void**)centry) == FAILURE) - { - /* double inclusion of conditional classes ends up failing - * this lookup the second time around. - */ - continue; - } - -#ifdef ZEND_ENGINE_2 - zce = *pzce; -#endif - zend_hash_del(EG(class_table), - cache_entry->data.file.classes[i].name, - cache_entry->data.file.classes[i].name_len+1); - - apc_free_class_entry_after_execution(zce); - } - } - apc_cache_release(apc_cache, cache_entry); - } - -} -/* }}} */ - -/* {{{ request init and shutdown */ - -int apc_request_init(TSRMLS_D) -{ - apc_stack_clear(APCG(cache_stack)); - APCG(slam_rand) = -1; - APCG(copied_zvals) = NULL; - -#ifdef APC_FILEHITS - ALLOC_INIT_ZVAL(APCG(filehits)); - array_init(APCG(filehits)); -#endif - - return 0; -} - -int apc_request_shutdown(TSRMLS_D) -{ - apc_deactivate(TSRMLS_C); - -#ifdef APC_FILEHITS - zval_ptr_dtor(&APCG(filehits)); -#endif - - return 0; -} - -/* }}} */ - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker - * vim<600: expandtab sw=4 ts=4 sts=4 - */