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 +----------------------------------------------------------------------+
19 This software was contributed to PHP by Community Connect Inc. in 2002
20 and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
21 Future revisions and derivatives of this source code must acknowledge
22 Community Connect Inc. as the original contributor of this module by
23 leaving this note intact in the source code.
25 All other licensing and usage conditions are those of the PHP Group.
29 /* $Id: php_apc.c,v 3.154 2007/12/26 22:31:20 rasmus Exp $ */
32 #include "apc_cache.h"
36 #include "php_globals.h"
38 #include "ext/standard/info.h"
42 #if PHP_API_VERSION <= 20020918
52 #include "apc_signal.h"
55 /* {{{ PHP_FUNCTION declarations */
56 PHP_FUNCTION(apc_cache_info);
57 PHP_FUNCTION(apc_clear_cache);
58 PHP_FUNCTION(apc_sma_info);
59 PHP_FUNCTION(apc_store);
60 PHP_FUNCTION(apc_fetch);
61 PHP_FUNCTION(apc_delete);
62 PHP_FUNCTION(apc_compile_file);
63 PHP_FUNCTION(apc_define_constants);
64 PHP_FUNCTION(apc_load_constants);
65 PHP_FUNCTION(apc_add);
68 /* {{{ ZEND_DECLARE_MODULE_GLOBALS(apc) */
69 ZEND_DECLARE_MODULE_GLOBALS(apc)
72 apc_cache_t* apc_cache = NULL;
73 apc_cache_t* apc_user_cache = NULL;
74 void* apc_compiled_filters = NULL;
76 static void php_apc_init_globals(zend_apc_globals* apc_globals TSRMLS_DC)
78 apc_globals->filters = NULL;
79 apc_globals->initialized = 0;
80 apc_globals->cache_stack = apc_stack_create(0);
81 apc_globals->cache_by_default = 1;
82 apc_globals->slam_defense = 0;
83 apc_globals->mem_size_ptr = NULL;
84 apc_globals->fpstat = 1;
85 apc_globals->stat_ctime = 0;
86 apc_globals->write_lock = 1;
87 apc_globals->report_autofilter = 0;
88 apc_globals->apc_optimize_function = NULL;
89 #ifdef MULTIPART_EVENT_FORMDATA
90 apc_globals->rfc1867 = 0;
92 apc_globals->copied_zvals = NULL;
94 apc_globals->reserved_offset = -1;
96 apc_globals->localcache = 0;
97 apc_globals->localcache_size = 0;
98 apc_globals->lcache = NULL;
99 apc_globals->force_file_update = 0;
100 apc_globals->coredump_unmap = 0;
103 static void php_apc_shutdown_globals(zend_apc_globals* apc_globals TSRMLS_DC)
105 /* deallocate the ignore patterns */
106 if (apc_globals->filters != NULL) {
108 for (i=0; apc_globals->filters[i] != NULL; i++) {
109 apc_efree(apc_globals->filters[i]);
111 apc_efree(apc_globals->filters);
114 /* the stack should be empty */
115 assert(apc_stack_size(apc_globals->cache_stack) == 0);
118 apc_stack_destroy(apc_globals->cache_stack);
120 /* the rest of the globals are cleaned up in apc_module_shutdown() */
127 static PHP_INI_MH(OnUpdate_filters) /* {{{ */
129 APCG(filters) = apc_tokenize(new_value, ',');
134 static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */
137 if(atoi(new_value)!=1) {
138 php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_segments setting ignored in MMAP mode");
140 APCG(shm_segments) = 1;
142 APCG(shm_segments) = atoi(new_value);
148 #ifdef MULTIPART_EVENT_FORMDATA
149 static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */
152 tmp = zend_atoi(new_value, new_value_length);
154 apc_eprint("rfc1867_freq must be greater than or equal to zero.");
157 if(new_value[new_value_length-1] == '%') {
159 apc_eprint("rfc1867_freq cannot be over 100%%");
162 APCG(rfc1867_freq) = tmp / 100.0;
164 APCG(rfc1867_freq) = tmp;
172 #define OnUpdateInt OnUpdateLong
176 STD_PHP_INI_BOOLEAN("apc.enabled", "1", PHP_INI_SYSTEM, OnUpdateBool, enabled, zend_apc_globals, apc_globals)
177 STD_PHP_INI_ENTRY("apc.shm_segments", "1", PHP_INI_SYSTEM, OnUpdateShmSegments, shm_segments, zend_apc_globals, apc_globals)
178 STD_PHP_INI_ENTRY("apc.shm_size", "30", PHP_INI_SYSTEM, OnUpdateInt, shm_size, zend_apc_globals, apc_globals)
179 STD_PHP_INI_BOOLEAN("apc.include_once_override", "0", PHP_INI_SYSTEM, OnUpdateBool, include_once, zend_apc_globals, apc_globals)
180 STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", PHP_INI_SYSTEM, OnUpdateInt, num_files_hint, zend_apc_globals, apc_globals)
181 STD_PHP_INI_ENTRY("apc.user_entries_hint", "4096", PHP_INI_SYSTEM, OnUpdateInt, user_entries_hint, zend_apc_globals, apc_globals)
182 STD_PHP_INI_ENTRY("apc.gc_ttl", "3600", PHP_INI_SYSTEM, OnUpdateInt, gc_ttl, zend_apc_globals, apc_globals)
183 STD_PHP_INI_ENTRY("apc.ttl", "0", PHP_INI_SYSTEM, OnUpdateInt, ttl, zend_apc_globals, apc_globals)
184 STD_PHP_INI_ENTRY("apc.user_ttl", "0", PHP_INI_SYSTEM, OnUpdateInt, user_ttl, zend_apc_globals, apc_globals)
186 STD_PHP_INI_ENTRY("apc.mmap_file_mask", NULL, PHP_INI_SYSTEM, OnUpdateString, mmap_file_mask, zend_apc_globals, apc_globals)
188 PHP_INI_ENTRY("apc.filters", NULL, PHP_INI_SYSTEM, OnUpdate_filters)
189 STD_PHP_INI_BOOLEAN("apc.cache_by_default", "1", PHP_INI_ALL, OnUpdateBool, cache_by_default, zend_apc_globals, apc_globals)
190 STD_PHP_INI_ENTRY("apc.slam_defense", "0", PHP_INI_SYSTEM, OnUpdateInt, slam_defense, zend_apc_globals, apc_globals)
191 STD_PHP_INI_ENTRY("apc.file_update_protection", "2", PHP_INI_SYSTEM, OnUpdateInt,file_update_protection, zend_apc_globals, apc_globals)
192 STD_PHP_INI_BOOLEAN("apc.enable_cli", "0", PHP_INI_SYSTEM, OnUpdateBool, enable_cli, zend_apc_globals, apc_globals)
193 STD_PHP_INI_ENTRY("apc.max_file_size", "1M", PHP_INI_SYSTEM, OnUpdateInt, max_file_size, zend_apc_globals, apc_globals)
194 STD_PHP_INI_BOOLEAN("apc.stat", "1", PHP_INI_SYSTEM, OnUpdateBool, fpstat, zend_apc_globals, apc_globals)
195 STD_PHP_INI_BOOLEAN("apc.stat_ctime", "0", PHP_INI_SYSTEM, OnUpdateBool, stat_ctime, zend_apc_globals, apc_globals)
196 STD_PHP_INI_BOOLEAN("apc.write_lock", "1", PHP_INI_SYSTEM, OnUpdateBool, write_lock, zend_apc_globals, apc_globals)
197 STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool, report_autofilter,zend_apc_globals, apc_globals)
198 #ifdef MULTIPART_EVENT_FORMDATA
199 STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals)
200 STD_PHP_INI_ENTRY("apc.rfc1867_prefix", "upload_", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_prefix, zend_apc_globals, apc_globals)
201 STD_PHP_INI_ENTRY("apc.rfc1867_name", "APC_UPLOAD_PROGRESS", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_name, zend_apc_globals, apc_globals)
202 STD_PHP_INI_ENTRY("apc.rfc1867_freq", "0", PHP_INI_SYSTEM, OnUpdateRfc1867Freq, rfc1867_freq, zend_apc_globals, apc_globals)
204 STD_PHP_INI_BOOLEAN("apc.localcache", "0", PHP_INI_SYSTEM, OnUpdateBool, localcache, zend_apc_globals, apc_globals)
205 STD_PHP_INI_ENTRY("apc.localcache.size", "512", PHP_INI_SYSTEM, OnUpdateInt, localcache_size, zend_apc_globals, apc_globals)
206 STD_PHP_INI_BOOLEAN("apc.coredump_unmap", "0", PHP_INI_SYSTEM, OnUpdateBool, coredump_unmap, zend_apc_globals, apc_globals)
211 /* {{{ PHP_MINFO_FUNCTION(apc) */
212 static PHP_MINFO_FUNCTION(apc)
214 php_info_print_table_start();
215 php_info_print_table_row(2, "APC Support", APCG(enabled) ? "enabled" : "disabled");
216 php_info_print_table_row(2, "Version", APC_VERSION);
218 php_info_print_table_row(2, "MMAP Support", "Enabled");
219 php_info_print_table_row(2, "MMAP File Mask", APCG(mmap_file_mask));
221 php_info_print_table_row(2, "MMAP Support", "Disabled");
224 php_info_print_table_row(2, "Locking type", "IPC Semaphore");
225 #elif APC_FUTEX_LOCKS
226 php_info_print_table_row(2, "Locking type", "Linux Futex Locks");
227 #elif APC_PTHREADMUTEX_LOCKS
228 php_info_print_table_row(2, "Locking type", "pthread mutex Locks");
230 php_info_print_table_row(2, "Locking type", "spin Locks");
232 php_info_print_table_row(2, "Locking type", "File Locks");
234 php_info_print_table_row(2, "Revision", "$Revision: 3.154 $");
235 php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
236 php_info_print_table_end();
237 DISPLAY_INI_ENTRIES();
241 #ifdef MULTIPART_EVENT_FORMDATA
242 extern int apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC);
245 /* {{{ PHP_MINIT_FUNCTION(apc) */
246 static PHP_MINIT_FUNCTION(apc)
248 ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals);
250 REGISTER_INI_ENTRIES();
252 /* Disable APC in cli mode unless overridden by apc.enable_cli */
253 if(!APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) {
258 if(APCG(initialized)) {
259 apc_process_init(module_number TSRMLS_CC);
261 apc_module_init(module_number TSRMLS_CC);
262 apc_zend_init(TSRMLS_C);
263 apc_process_init(module_number TSRMLS_CC);
264 #ifdef MULTIPART_EVENT_FORMDATA
265 /* File upload progress tracking */
267 php_rfc1867_callback = apc_rfc1867_progress;
277 /* {{{ PHP_MSHUTDOWN_FUNCTION(apc) */
278 static PHP_MSHUTDOWN_FUNCTION(apc)
281 apc_process_shutdown(TSRMLS_C);
282 apc_zend_shutdown(TSRMLS_C);
283 apc_module_shutdown(TSRMLS_C);
285 php_apc_shutdown_globals(&apc_globals);
289 ts_free_id(apc_globals_id);
291 UNREGISTER_INI_ENTRIES();
296 /* {{{ PHP_RINIT_FUNCTION(apc) */
297 static PHP_RINIT_FUNCTION(apc)
300 apc_request_init(TSRMLS_C);
310 /* {{{ PHP_RSHUTDOWN_FUNCTION(apc) */
311 static PHP_RSHUTDOWN_FUNCTION(apc)
314 apc_request_shutdown(TSRMLS_C);
320 /* {{{ proto array apc_cache_info([string type] [, bool limited]) */
321 PHP_FUNCTION(apc_cache_info)
323 apc_cache_info_t* info;
330 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &cache_type, &ct_len, &limited) == FAILURE) {
334 if(ZEND_NUM_ARGS()) {
335 if(!strcasecmp(cache_type,"user")) {
336 info = apc_cache_info(apc_user_cache, limited);
337 } else if(!strcasecmp(cache_type,"filehits")) {
339 RETVAL_ZVAL(APCG(filehits), 1, 0);
345 info = apc_cache_info(apc_cache, limited);
347 } else info = apc_cache_info(apc_cache, limited);
350 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC info available. Perhaps APC is not enabled? Check apc.enabled in your ini file");
354 array_init(return_value);
355 add_assoc_long(return_value, "num_slots", info->num_slots);
356 add_assoc_long(return_value, "ttl", info->ttl);
357 add_assoc_long(return_value, "num_hits", info->num_hits);
358 add_assoc_long(return_value, "num_misses", info->num_misses);
359 add_assoc_long(return_value, "start_time", info->start_time);
360 add_assoc_long(return_value, "expunges", info->expunges);
361 add_assoc_long(return_value, "mem_size", info->mem_size);
362 add_assoc_long(return_value, "num_entries", info->num_entries);
363 add_assoc_long(return_value, "num_inserts", info->num_inserts);
364 #ifdef MULTIPART_EVENT_FORMDATA
365 add_assoc_long(return_value, "file_upload_progress", 1);
367 add_assoc_long(return_value, "file_upload_progress", 0);
370 add_assoc_stringl(return_value, "memory_type", "mmap", sizeof("mmap")-1, 1);
372 add_assoc_stringl(return_value, "memory_type", "IPC shared", sizeof("IPC shared")-1, 1);
375 add_assoc_stringl(return_value, "locking_type", "IPC semaphore", sizeof("IPC semaphore")-1, 1);
376 #elif APC_FUTEX_LOCKS
377 add_assoc_stringl(return_value, "locking_type", "Linux Futex", sizeof("Linux Futex")-1, 1);
378 #elif APC_PTHREADMUTEX_LOCKS
379 add_assoc_stringl(return_value, "locking_type", "pthread mutex", sizeof("pthread mutex")-1, 1);
381 add_assoc_stringl(return_value, "locking_type", "spin", sizeof("spin")-1, 1);
383 add_assoc_stringl(return_value, "locking_type", "file", sizeof("file")-1, 1);
386 apc_cache_free_info(info);
390 ALLOC_INIT_ZVAL(list);
393 for (p = info->list; p != NULL; p = p->next) {
396 ALLOC_INIT_ZVAL(link);
399 if(p->type == APC_CACHE_ENTRY_FILE) {
400 add_assoc_string(link, "filename", p->data.file.filename, 1);
401 add_assoc_long(link, "device", p->data.file.device);
402 add_assoc_long(link, "inode", p->data.file.inode);
403 add_assoc_string(link, "type", "file", 1);
404 } else if(p->type == APC_CACHE_ENTRY_USER) {
405 add_assoc_string(link, "info", p->data.user.info, 1);
406 add_assoc_long(link, "ttl", (long)p->data.user.ttl);
407 add_assoc_string(link, "type", "user", 1);
409 add_assoc_long(link, "num_hits", p->num_hits);
410 add_assoc_long(link, "mtime", p->mtime);
411 add_assoc_long(link, "creation_time", p->creation_time);
412 add_assoc_long(link, "deletion_time", p->deletion_time);
413 add_assoc_long(link, "access_time", p->access_time);
414 add_assoc_long(link, "ref_count", p->ref_count);
415 add_assoc_long(link, "mem_size", p->mem_size);
416 add_next_index_zval(list, link);
418 add_assoc_zval(return_value, "cache_list", list);
420 ALLOC_INIT_ZVAL(list);
423 for (p = info->deleted_list; p != NULL; p = p->next) {
426 ALLOC_INIT_ZVAL(link);
429 if(p->type == APC_CACHE_ENTRY_FILE) {
430 add_assoc_string(link, "filename", p->data.file.filename, 1);
431 add_assoc_long(link, "device", p->data.file.device);
432 add_assoc_long(link, "inode", p->data.file.inode);
433 add_assoc_string(link, "type", "file", 1);
434 } else if(p->type == APC_CACHE_ENTRY_USER) {
435 add_assoc_string(link, "info", p->data.user.info, 1);
436 add_assoc_long(link, "ttl", (long)p->data.user.ttl);
437 add_assoc_string(link, "type", "user", 1);
439 add_assoc_long(link, "num_hits", p->num_hits);
440 add_assoc_long(link, "mtime", p->mtime);
441 add_assoc_long(link, "creation_time", p->creation_time);
442 add_assoc_long(link, "deletion_time", p->deletion_time);
443 add_assoc_long(link, "access_time", p->access_time);
444 add_assoc_long(link, "ref_count", p->ref_count);
445 add_assoc_long(link, "mem_size", p->mem_size);
446 add_next_index_zval(list, link);
448 add_assoc_zval(return_value, "deleted_list", list);
450 apc_cache_free_info(info);
454 /* {{{ proto void apc_clear_cache() */
455 PHP_FUNCTION(apc_clear_cache)
460 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache_type, &ct_len) == FAILURE) {
464 if(ZEND_NUM_ARGS()) {
465 if(!strcasecmp(cache_type,"user")) {
466 apc_cache_clear(apc_user_cache);
470 apc_cache_clear(apc_cache);
474 /* {{{ proto array apc_sma_info([bool limited]) */
475 PHP_FUNCTION(apc_sma_info)
477 apc_sma_info_t* info;
480 zend_bool limited = 0;
482 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &limited) == FAILURE) {
486 info = apc_sma_info(limited);
489 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC SMA info available. Perhaps APC is disabled via apc.enabled?");
493 array_init(return_value);
494 add_assoc_long(return_value, "num_seg", info->num_seg);
495 add_assoc_long(return_value, "seg_size", info->seg_size);
496 add_assoc_long(return_value, "avail_mem", apc_sma_get_avail_mem());
499 apc_sma_free_info(info);
503 #if ALLOC_DISTRIBUTION
505 size_t *adist = apc_sma_get_alloc_distribution();
507 ALLOC_INIT_ZVAL(list);
509 for(i=0; i<30; i++) {
510 add_next_index_long(list, adist[i]);
512 add_assoc_zval(return_value, "adist", list);
515 ALLOC_INIT_ZVAL(block_lists);
516 array_init(block_lists);
518 for (i = 0; i < info->num_seg; i++) {
522 ALLOC_INIT_ZVAL(list);
525 for (p = info->list[i]; p != NULL; p = p->next) {
528 ALLOC_INIT_ZVAL(link);
531 add_assoc_long(link, "size", p->size);
532 add_assoc_long(link, "offset", p->offset);
533 add_next_index_zval(list, link);
535 add_next_index_zval(block_lists, list);
537 add_assoc_zval(return_value, "block_lists", block_lists);
538 apc_sma_free_info(info);
543 int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC) {
544 apc_cache_entry_t *entry;
549 #if PHP_API_VERSION < 20041225
550 #if HAVE_APACHE && defined(APC_PHP4_STAT)
551 t = ((request_rec *)SG(server_context))->request_time;
556 t = sapi_get_request_time(TSRMLS_C);
559 if(!APCG(enabled)) return 0;
561 HANDLE_BLOCK_INTERRUPTIONS();
563 APCG(mem_size_ptr) = &mem_size;
564 if (!(entry = apc_cache_make_user_entry(strkey, strkey_len + 1, val, ttl))) {
565 APCG(mem_size_ptr) = NULL;
566 apc_cache_expunge(apc_cache,t);
567 apc_cache_expunge(apc_user_cache,t);
568 HANDLE_UNBLOCK_INTERRUPTIONS();
572 if (!apc_cache_make_user_key(&key, strkey, strkey_len + 1, t)) {
573 APCG(mem_size_ptr) = NULL;
574 apc_cache_free_entry(entry);
575 apc_cache_expunge(apc_cache,t);
576 apc_cache_expunge(apc_user_cache,t);
577 HANDLE_UNBLOCK_INTERRUPTIONS();
581 if (!apc_cache_user_insert(apc_user_cache, key, entry, t, exclusive TSRMLS_CC)) {
582 APCG(mem_size_ptr) = NULL;
583 apc_cache_free_entry(entry);
584 apc_cache_expunge(apc_cache,t);
585 apc_cache_expunge(apc_user_cache,t);
586 HANDLE_UNBLOCK_INTERRUPTIONS();
590 APCG(mem_size_ptr) = NULL;
592 HANDLE_UNBLOCK_INTERRUPTIONS();
598 /* {{{ proto int apc_store(string key, zval var [, ttl ])
600 PHP_FUNCTION(apc_store) {
606 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
610 if(!strkey_len) RETURN_FALSE;
612 if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 0 TSRMLS_CC)) RETURN_TRUE;
617 /* {{{ proto int apc_add(string key, zval var [, ttl ])
619 PHP_FUNCTION(apc_add) {
625 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
629 if(!strkey_len) RETURN_FALSE;
631 if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 1 TSRMLS_CC)) RETURN_TRUE;
636 void *apc_erealloc_wrapper(void *ptr, size_t size) {
637 return _erealloc(ptr, size, 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
640 /* {{{ RETURN_ZVAL for php4 */
641 #if !defined(ZEND_ENGINE_2) && !defined(RETURN_ZVAL)
642 #define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; }
643 #define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor)
644 #define ZVAL_ZVAL(z, zv, copy, dtor) { \
645 int is_ref, refcount; \
646 is_ref = (z)->is_ref; \
647 refcount = (z)->refcount; \
656 zval_ptr_dtor(&zv); \
658 (z)->is_ref = is_ref; \
659 (z)->refcount = refcount; \
664 /* {{{ proto mixed apc_fetch(mixed key)
666 PHP_FUNCTION(apc_fetch) {
675 apc_cache_entry_t* entry;
678 if(!APCG(enabled)) RETURN_FALSE;
680 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == FAILURE) {
684 #if PHP_API_VERSION < 20041225
685 #if HAVE_APACHE && defined(APC_PHP4_STAT)
686 t = ((request_rec *)SG(server_context))->request_time;
691 t = sapi_get_request_time(TSRMLS_C);
694 if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
695 convert_to_string(key);
698 if(Z_TYPE_P(key) == IS_STRING) {
699 strkey = Z_STRVAL_P(key);
700 strkey_len = Z_STRLEN_P(key);
701 if(!strkey_len) RETURN_FALSE;
702 entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
704 /* deep-copy returned shm zval to emalloc'ed return_value */
705 apc_cache_fetch_zval(return_value, entry->data.user.val, apc_php_malloc, apc_php_free);
706 apc_cache_release(apc_user_cache, entry);
710 } else if(Z_TYPE_P(key) == IS_ARRAY) {
711 hash = Z_ARRVAL_P(key);
712 MAKE_STD_ZVAL(result);
714 zend_hash_internal_pointer_reset_ex(hash, &hpos);
715 while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
716 if(Z_TYPE_PP(hentry) != IS_STRING) {
717 apc_wprint("apc_fetch() expects a string or array of strings.");
720 entry = apc_cache_user_find(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t);
722 /* deep-copy returned shm zval to emalloc'ed return_value */
723 MAKE_STD_ZVAL(result_entry);
724 apc_cache_fetch_zval(result_entry, entry->data.user.val, apc_php_malloc, apc_php_free);
725 apc_cache_release(apc_user_cache, entry);
726 zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL);
727 } /* don't set values we didn't find */
728 zend_hash_move_forward_ex(hash, &hpos);
730 RETURN_ZVAL(result, 0, 1);
732 apc_wprint("apc_fetch() expects a string or array of strings.");
740 /* {{{ proto mixed apc_delete(string key)
742 PHP_FUNCTION(apc_delete) {
746 if(!APCG(enabled)) RETURN_FALSE;
748 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &strkey, &strkey_len) == FAILURE) {
752 if(!strkey_len) RETURN_FALSE;
754 if(apc_cache_user_delete(apc_user_cache, strkey, strkey_len + 1)) {
762 static void _apc_define_constants(zval *constants, zend_bool case_sensitive TSRMLS_DC) {
764 unsigned int const_key_len;
768 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(constants), &pos);
769 while (zend_hash_get_current_data_ex(Z_ARRVAL_P(constants), (void**)&entry, &pos) == SUCCESS) {
774 key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(constants), &const_key, &const_key_len, &num_key, 0, &pos);
775 if(key_type != HASH_KEY_IS_STRING) {
776 zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
779 switch(Z_TYPE_PP(entry)) {
788 zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
792 zval_copy_ctor(&c.value);
793 c.flags = case_sensitive;
794 c.name = zend_strndup(const_key, const_key_len);
795 c.name_len = const_key_len;
797 c.module_number = PHP_USER_CONSTANT;
799 zend_register_constant(&c TSRMLS_CC);
801 zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
805 /* {{{ proto mixed apc_define_constants(string key, array constants [,bool case-sensitive])
807 PHP_FUNCTION(apc_define_constants) {
810 zval *constants = NULL;
811 zend_bool case_sensitive = 1;
812 int argc = ZEND_NUM_ARGS();
814 if (zend_parse_parameters(argc TSRMLS_CC, "sa|b", &strkey, &strkey_len, &constants, &case_sensitive) == FAILURE) {
818 if(!strkey_len) RETURN_FALSE;
820 _apc_define_constants(constants, case_sensitive TSRMLS_CC);
821 if(_apc_store(strkey, strkey_len, constants, 0, 0 TSRMLS_CC)) RETURN_TRUE;
825 /* {{{ proto mixed apc_load_constants(string key [, bool case-sensitive])
827 PHP_FUNCTION(apc_load_constants) {
830 apc_cache_entry_t* entry;
832 zend_bool case_sensitive = 1;
834 if(!APCG(enabled)) RETURN_FALSE;
835 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &strkey, &strkey_len, &case_sensitive) == FAILURE) {
839 if(!strkey_len) RETURN_FALSE;
841 #if PHP_API_VERSION < 20041225
842 #if HAVE_APACHE && defined(APC_PHP4_STAT)
843 t = ((request_rec *)SG(server_context))->request_time;
848 t = sapi_get_request_time(TSRMLS_C);
851 entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
854 _apc_define_constants(entry->data.user.val, case_sensitive TSRMLS_CC);
855 apc_cache_release(apc_user_cache, entry);
863 /* {{{ proto boolean apc_compile_file(string filename)
865 PHP_FUNCTION(apc_compile_file) {
868 zend_file_handle file_handle;
869 zend_op_array *op_array;
870 long slam_defense = 0;
871 char** filters = NULL;
872 zend_bool cache_by_default = 1;
873 HashTable cg_function_table, cg_class_table, eg_function_table, eg_class_table;
874 HashTable *cg_orig_function_table, *cg_orig_class_table, *eg_orig_function_table, *eg_orig_class_table;
876 if(!APCG(enabled)) RETURN_FALSE;
878 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
882 if(!filename) RETURN_FALSE;
884 /* reset slam defense, filters, and cache_by_default */
885 slam_defense = APCG(slam_defense);
886 APCG(slam_defense) = 0;
888 filters = APCG(filters);
889 APCG(filters) = NULL;
891 cache_by_default = APCG(cache_by_default);
892 APCG(cache_by_default) = 1;
894 /* Replace function/class tables to avoid namespace conflicts */
895 zend_hash_init_ex(&cg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
896 cg_orig_function_table = CG(function_table);
897 CG(function_table) = &cg_function_table;
898 zend_hash_init_ex(&cg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
899 cg_orig_class_table = CG(class_table);
900 CG(class_table) = &cg_class_table;
901 eg_orig_function_table = EG(function_table);
902 EG(function_table) = CG(function_table);
903 eg_orig_class_table = EG(class_table);
904 EG(class_table) = CG(class_table);
905 APCG(force_file_update) = 1;
907 /* Compile the file, loading it into the cache */
908 file_handle.type = ZEND_HANDLE_FILENAME;
909 file_handle.filename = filename;
910 file_handle.free_filename = 0;
911 file_handle.opened_path = NULL;
913 op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
915 apc_wprint("Error compiling %s in apc_compile_file.", filename);
919 /* Return class/function tables to previous states, destroy temp tables */
920 APCG(force_file_update) = 0;
921 CG(function_table) = cg_orig_function_table;
922 zend_hash_destroy(&cg_function_table);
923 CG(class_table) = cg_orig_class_table;
924 zend_hash_destroy(&cg_class_table);
925 EG(function_table) = eg_orig_function_table;
926 EG(class_table) = eg_orig_class_table;
928 /* Restore global settings */
929 APCG(slam_defense) = slam_defense;
930 APCG(filters) = filters;
931 APCG(cache_by_default) = cache_by_default;
933 if(op_array == NULL) { RETURN_FALSE; }
935 /* Free up everything */
936 zend_destroy_file_handle(&file_handle TSRMLS_CC);
938 destroy_op_array(op_array TSRMLS_CC);
940 destroy_op_array(op_array);
948 /* {{{ apc_functions[] */
949 function_entry apc_functions[] = {
950 PHP_FE(apc_cache_info, NULL)
951 PHP_FE(apc_clear_cache, NULL)
952 PHP_FE(apc_sma_info, NULL)
953 PHP_FE(apc_store, NULL)
954 PHP_FE(apc_fetch, NULL)
955 PHP_FE(apc_delete, NULL)
956 PHP_FE(apc_define_constants, NULL)
957 PHP_FE(apc_load_constants, NULL)
958 PHP_FE(apc_compile_file, NULL)
959 PHP_FE(apc_add, NULL)
964 /* {{{ module definition structure */
966 zend_module_entry apc_module_entry = {
967 STANDARD_MODULE_HEADER,
976 STANDARD_MODULE_PROPERTIES
979 #ifdef COMPILE_DL_APC
989 * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
990 * vim<600: expandtab sw=4 ts=4 sts=4