cvs: pecl /apc INSTALL apc_cache.c apc_cache.h apc_globals.h apc_main.c php_apc.c
| From: | Rasmus Lerdorf | Date: | Sun, 14 Nov 2004 18:07:25 +0000 |
| Subject: | cvs: pecl /apc INSTALL apc_cache.c apc_cache.h apc_globals.h apc_main.c php_apc.c | ||
| Groups: | php.pecl.cvs | ||
| Request: | Send a blank email to pecl-cvs+get-2033@lists.php.net to get a copy of this message | ||
rasmus Sun Nov 14 13:07:25 2004 EDT
Modified files:
/pecl/apc INSTALL apc_cache.c apc_cache.h apc_globals.h apc_main.c
php_apc.c
Log:
Defend against cache slams and non-atomic file writes
http://cvs.php.net/diff.php/pecl/apc/INSTALL?r1=3.38&r2=3.39&ty=u Index: pecl/apc/INSTALL diff -u pecl/apc/INSTALL:3.38 pecl/apc/INSTALL:3.39 --- pecl/apc/INSTALL:3.38 Sat Nov 6 13:15:53 2004 +++ pecl/apc/INSTALL Sun Nov 14 13:07:25 2004 @@ -280,3 +280,17 @@ kernel's /dev/zero interface to anonymous mmap'ed memory. Leaving it undefined will force an anonymous mmap. + (Default: "") + + apc.slam_defense On very busy servers whenever you start the server or + modify files you can create a race of many processes + all trying to cache the same file at the same time. + This option sets the percentage of processes that will + skip trying to cache an uncached file. Or think of it + as the probability of a single process to skip caching. + For example, setting this to 75 would mean that there is + a 75% chance that the process will not cache an uncached + file. So the higher the setting the greater the defense + against cache slams. Setting this to 0 disables this + feature. + (Default: 0) http://cvs.php.net/diff.php/pecl/apc/apc_cache.c?r1=3.73&r2=3.74&ty=u Index: pecl/apc/apc_cache.c diff -u pecl/apc/apc_cache.c:3.73 pecl/apc/apc_cache.c:3.74 --- pecl/apc/apc_cache.c:3.73 Thu Oct 28 13:41:12 2004 +++ pecl/apc/apc_cache.c Sun Nov 14 13:07:25 2004 @@ -15,11 +15,12 @@ +----------------------------------------------------------------------+ */ -/* $Id: apc_cache.c,v 3.73 2004/10/28 17:41:12 rasmus Exp $ */ +/* $Id: apc_cache.c,v 3.74 2004/11/14 18:07:25 rasmus Exp $ */ #include "apc_cache.h" #include "apc_lock.h" #include "apc_sma.h" +#include "apc_globals.h" #include "SAPI.h" /* TODO: rehash when load factor exceeds threshold */ @@ -514,7 +515,8 @@ /* {{{ apc_cache_make_file_key */ int apc_cache_make_file_key(apc_cache_key_t* key, const char* filename, - const char* include_path + const char* include_path, + time_t t TSRMLS_DC) { struct stat buf, *tmp_buf=NULL; @@ -534,6 +536,34 @@ return 0; } + /* + * This is a bit of a hack. + * + * Here I am checking to see if the file is at least 2 seconds old. + * The idea is that if the file is currently being written to then its + * mtime is going to match or at most be 1 second off of the current + * request time and we want to avoid caching files that have not been + * completely written. Of course, people should be using atomic + * mechanisms to push files onto live web servers, but adding this + * tiny safety is easier than educating the world. + */ + if(t - buf.st_mtime < 2) return 0; + + /* + * This is an even bigger hack than the above. + * + * 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) && (int)(100.0*rand()/(RAND_MAX+1.0)) < APCG(slam_defense)) + return 0; + key->data.file.device = buf.st_dev; key->data.file.inode = buf.st_ino; http://cvs.php.net/diff.php/pecl/apc/apc_cache.h?r1=3.22&r2=3.23&ty=u Index: pecl/apc/apc_cache.h diff -u pecl/apc/apc_cache.h:3.22 pecl/apc/apc_cache.h:3.23 --- pecl/apc/apc_cache.h:3.22 Thu Oct 28 13:41:12 2004 +++ pecl/apc/apc_cache.h Sun Nov 14 13:07:25 2004 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: apc_cache.h,v 3.22 2004/10/28 17:41:12 rasmus Exp $ */ +/* $Id: apc_cache.h,v 3.23 2004/11/14 18:07:25 rasmus Exp $ */ #ifndef APC_CACHE_H #define APC_CACHE_H @@ -167,10 +167,15 @@ * filename is the path to the source file. * * include_path is a colon-separated list of directories to search. + * + * and finally we pass in the current request time so we can avoid + * caching files with a current mtime which tends to indicate that + * they are still being written to. */ extern int apc_cache_make_file_key(apc_cache_key_t* key, const char* filename, - const char* include_path + const char* include_path, + time_t t TSRMLS_DC); /* http://cvs.php.net/diff.php/pecl/apc/apc_globals.h?r1=3.9&r2=3.10&ty=u Index: pecl/apc/apc_globals.h diff -u pecl/apc/apc_globals.h:3.9 pecl/apc/apc_globals.h:3.10 --- pecl/apc/apc_globals.h:3.9 Sat Sep 11 22:56:58 2004 +++ pecl/apc/apc_globals.h Sun Nov 14 13:07:25 2004 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: apc_globals.h,v 3.9 2004/09/12 02:56:58 rasmus Exp $ */ +/* $Id: apc_globals.h,v 3.10 2004/11/14 18:07:25 rasmus Exp $ */ #ifndef APC_GLOBALS_H #define APC_GLOBALS_H @@ -48,6 +48,7 @@ void* compiled_filters; /* compiled filters */ int cache_by_default; /* true if files should be cached unless filtered out */ /* false if files should only be cached if filtered in */ + int slam_defense; /* Probability of a process not caching an uncached file */ ZEND_END_MODULE_GLOBALS(apc) /* (the following declaration is defined in php_apc.c) */ http://cvs.php.net/diff.php/pecl/apc/apc_main.c?r1=3.25&r2=3.26&ty=u Index: pecl/apc/apc_main.c diff -u pecl/apc/apc_main.c:3.25 pecl/apc/apc_main.c:3.26 --- pecl/apc/apc_main.c:3.25 Thu Oct 28 13:47:53 2004 +++ pecl/apc/apc_main.c Sun Nov 14 13:07:25 2004 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: apc_main.c,v 3.25 2004/10/28 17:47:53 rasmus Exp $ */ +/* $Id: apc_main.c,v 3.26 2004/11/14 18:07:25 rasmus Exp $ */ #include "apc_php.h" #include "apc_main.h" @@ -152,7 +152,7 @@ #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) TSRMLS_CC)) { + if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) { return old_compile_file(h, type TSRMLS_CC); } http://cvs.php.net/diff.php/pecl/apc/php_apc.c?r1=3.40&r2=3.41&ty=u Index: pecl/apc/php_apc.c diff -u pecl/apc/php_apc.c:3.40 pecl/apc/php_apc.c:3.41 --- pecl/apc/php_apc.c:3.40 Thu Oct 28 13:56:01 2004 +++ pecl/apc/php_apc.c Sun Nov 14 13:07:25 2004 @@ -15,7 +15,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_apc.c,v 3.40 2004/10/28 17:56:01 rasmus Exp $ */ +/* $Id: php_apc.c,v 3.41 2004/11/14 18:07:25 rasmus Exp $ */ #ifdef PHP_WIN32 /* XXX lame hack, for some reason, the ini entries are all messed @@ -66,6 +66,7 @@ apc_globals->cache_stack = NULL; apc_globals->compiled_filters = NULL; apc_globals->cache_by_default = 1; + apc_globals->slam_defense = 0; } #ifdef ZTS @@ -109,6 +110,7 @@ #endif PHP_INI_ENTRY("apc.filters", "", PHP_INI_SYSTEM, OnUpdate_filters) STD_PHP_INI_ENTRY("apc.cache_by_default", "1", PHP_INI_SYSTEM, OnUpdateInt, cache_by_default, zend_apc_globals, apc_globals) +STD_PHP_INI_ENTRY("apc.slam_defense", "0", PHP_INI_SYSTEM, OnUpdateInt, slam_defense, zend_apc_globals, apc_globals) PHP_INI_END() /* }}} */ @@ -125,7 +127,7 @@ #else php_info_print_table_row(2, "MMAP Support", "Disabled"); #endif - php_info_print_table_row(2, "Revision", "$Revision: 3.40 $"); + php_info_print_table_row(2, "Revision", "$Revision: 3.41 $"); php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__); php_info_print_table_end(); DISPLAY_INI_ENTRIES();
http://cvs.php.net/diff.php/pecl/apc/INSTALL?r1=3.38&r2=3.39&ty=u Index: pecl/apc/INSTALL diff -u pecl/apc/INSTALL:3.38 pecl/apc/INSTALL:3.39 --- pecl/apc/INSTALL:3.38 Sat Nov 6 13:15:53 2004 +++ pecl/apc/INSTALL Sun Nov 14 13:07:25 2004 @@ -280,3 +280,17 @@ kernel's /dev/zero interface to anonymous mmap'ed memory. Leaving it undefined will force an anonymous mmap. + (Default: "") + + apc.slam_defense On very busy servers whenever you start the server or + modify files you can create a race of many processes + all trying to cache the same file at the same time. + This option sets the percentage of processes that will + skip trying to cache an uncached file. Or think of it + as the probability of a single process to skip caching. + For example, setting this to 75 would mean that there is + a 75% chance that the process will not cache an uncached + file. So the higher the setting the greater the defense + against cache slams. Setting this to 0 disables this + feature. + (Default: 0) http://cvs.php.net/diff.php/pecl/apc/apc_cache.c?r1=3.73&r2=3.74&ty=u Index: pecl/apc/apc_cache.c diff -u pecl/apc/apc_cache.c:3.73 pecl/apc/apc_cache.c:3.74 --- pecl/apc/apc_cache.c:3.73 Thu Oct 28 13:41:12 2004 +++ pecl/apc/apc_cache.c Sun Nov 14 13:07:25 2004 @@ -15,11 +15,12 @@ +----------------------------------------------------------------------+ */ -/* $Id: apc_cache.c,v 3.73 2004/10/28 17:41:12 rasmus Exp $ */ +/* $Id: apc_cache.c,v 3.74 2004/11/14 18:07:25 rasmus Exp $ */ #include "apc_cache.h" #include "apc_lock.h" #include "apc_sma.h" +#include "apc_globals.h" #include "SAPI.h" /* TODO: rehash when load factor exceeds threshold */ @@ -514,7 +515,8 @@ /* {{{ apc_cache_make_file_key */ int apc_cache_make_file_key(apc_cache_key_t* key, const char* filename, - const char* include_path + const char* include_path, + time_t t TSRMLS_DC) { struct stat buf, *tmp_buf=NULL; @@ -534,6 +536,34 @@ return 0; } + /* + * This is a bit of a hack. + * + * Here I am checking to see if the file is at least 2 seconds old. + * The idea is that if the file is currently being written to then its + * mtime is going to match or at most be 1 second off of the current + * request time and we want to avoid caching files that have not been + * completely written. Of course, people should be using atomic + * mechanisms to push files onto live web servers, but adding this + * tiny safety is easier than educating the world. + */ + if(t - buf.st_mtime < 2) return 0; + + /* + * This is an even bigger hack than the above. + * + * 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) && (int)(100.0*rand()/(RAND_MAX+1.0)) < APCG(slam_defense)) + return 0; + key->data.file.device = buf.st_dev; key->data.file.inode = buf.st_ino; http://cvs.php.net/diff.php/pecl/apc/apc_cache.h?r1=3.22&r2=3.23&ty=u Index: pecl/apc/apc_cache.h diff -u pecl/apc/apc_cache.h:3.22 pecl/apc/apc_cache.h:3.23 --- pecl/apc/apc_cache.h:3.22 Thu Oct 28 13:41:12 2004 +++ pecl/apc/apc_cache.h Sun Nov 14 13:07:25 2004 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: apc_cache.h,v 3.22 2004/10/28 17:41:12 rasmus Exp $ */ +/* $Id: apc_cache.h,v 3.23 2004/11/14 18:07:25 rasmus Exp $ */ #ifndef APC_CACHE_H #define APC_CACHE_H @@ -167,10 +167,15 @@ * filename is the path to the source file. * * include_path is a colon-separated list of directories to search. + * + * and finally we pass in the current request time so we can avoid + * caching files with a current mtime which tends to indicate that + * they are still being written to. */ extern int apc_cache_make_file_key(apc_cache_key_t* key, const char* filename, - const char* include_path + const char* include_path, + time_t t TSRMLS_DC); /* http://cvs.php.net/diff.php/pecl/apc/apc_globals.h?r1=3.9&r2=3.10&ty=u Index: pecl/apc/apc_globals.h diff -u pecl/apc/apc_globals.h:3.9 pecl/apc/apc_globals.h:3.10 --- pecl/apc/apc_globals.h:3.9 Sat Sep 11 22:56:58 2004 +++ pecl/apc/apc_globals.h Sun Nov 14 13:07:25 2004 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: apc_globals.h,v 3.9 2004/09/12 02:56:58 rasmus Exp $ */ +/* $Id: apc_globals.h,v 3.10 2004/11/14 18:07:25 rasmus Exp $ */ #ifndef APC_GLOBALS_H #define APC_GLOBALS_H @@ -48,6 +48,7 @@ void* compiled_filters; /* compiled filters */ int cache_by_default; /* true if files should be cached unless filtered out */ /* false if files should only be cached if filtered in */ + int slam_defense; /* Probability of a process not caching an uncached file */ ZEND_END_MODULE_GLOBALS(apc) /* (the following declaration is defined in php_apc.c) */ http://cvs.php.net/diff.php/pecl/apc/apc_main.c?r1=3.25&r2=3.26&ty=u Index: pecl/apc/apc_main.c diff -u pecl/apc/apc_main.c:3.25 pecl/apc/apc_main.c:3.26 --- pecl/apc/apc_main.c:3.25 Thu Oct 28 13:47:53 2004 +++ pecl/apc/apc_main.c Sun Nov 14 13:07:25 2004 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: apc_main.c,v 3.25 2004/10/28 17:47:53 rasmus Exp $ */ +/* $Id: apc_main.c,v 3.26 2004/11/14 18:07:25 rasmus Exp $ */ #include "apc_php.h" #include "apc_main.h" @@ -152,7 +152,7 @@ #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) TSRMLS_CC)) { + if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) { return old_compile_file(h, type TSRMLS_CC); } http://cvs.php.net/diff.php/pecl/apc/php_apc.c?r1=3.40&r2=3.41&ty=u Index: pecl/apc/php_apc.c diff -u pecl/apc/php_apc.c:3.40 pecl/apc/php_apc.c:3.41 --- pecl/apc/php_apc.c:3.40 Thu Oct 28 13:56:01 2004 +++ pecl/apc/php_apc.c Sun Nov 14 13:07:25 2004 @@ -15,7 +15,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_apc.c,v 3.40 2004/10/28 17:56:01 rasmus Exp $ */ +/* $Id: php_apc.c,v 3.41 2004/11/14 18:07:25 rasmus Exp $ */ #ifdef PHP_WIN32 /* XXX lame hack, for some reason, the ini entries are all messed @@ -66,6 +66,7 @@ apc_globals->cache_stack = NULL; apc_globals->compiled_filters = NULL; apc_globals->cache_by_default = 1; + apc_globals->slam_defense = 0; } #ifdef ZTS @@ -109,6 +110,7 @@ #endif PHP_INI_ENTRY("apc.filters", "", PHP_INI_SYSTEM, OnUpdate_filters) STD_PHP_INI_ENTRY("apc.cache_by_default", "1", PHP_INI_SYSTEM, OnUpdateInt, cache_by_default, zend_apc_globals, apc_globals) +STD_PHP_INI_ENTRY("apc.slam_defense", "0", PHP_INI_SYSTEM, OnUpdateInt, slam_defense, zend_apc_globals, apc_globals) PHP_INI_END() /* }}} */ @@ -125,7 +127,7 @@ #else php_info_print_table_row(2, "MMAP Support", "Disabled"); #endif - php_info_print_table_row(2, "Revision", "$Revision: 3.40 $"); + php_info_print_table_row(2, "Revision", "$Revision: 3.41 $"); php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__); php_info_print_table_end(); DISPLAY_INI_ENTRIES();