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 +----------------------------------------------------------------------+
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.2.5 2008/05/11 18:57:00 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->force_file_update = 0;
97 apc_globals->coredump_unmap = 0;
100 static void php_apc_shutdown_globals(zend_apc_globals* apc_globals TSRMLS_DC)
102 /* deallocate the ignore patterns */
103 if (apc_globals->filters != NULL) {
105 for (i=0; apc_globals->filters[i] != NULL; i++) {
106 apc_efree(apc_globals->filters[i]);
108 apc_efree(apc_globals->filters);
111 /* the stack should be empty */
112 assert(apc_stack_size(apc_globals->cache_stack) == 0);
115 apc_stack_destroy(apc_globals->cache_stack);
117 /* the rest of the globals are cleaned up in apc_module_shutdown() */
124 static PHP_INI_MH(OnUpdate_filters) /* {{{ */
126 APCG(filters) = apc_tokenize(new_value, ',');
131 static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */
134 if(atoi(new_value)!=1) {
135 php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_segments setting ignored in MMAP mode");
137 APCG(shm_segments) = 1;
139 APCG(shm_segments) = atoi(new_value);
145 #ifdef MULTIPART_EVENT_FORMDATA
146 static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */
149 tmp = zend_atoi(new_value, new_value_length);
151 apc_eprint("rfc1867_freq must be greater than or equal to zero.");
154 if(new_value[new_value_length-1] == '%') {
156 apc_eprint("rfc1867_freq cannot be over 100%%");
159 APCG(rfc1867_freq) = tmp / 100.0;
161 APCG(rfc1867_freq) = tmp;
169 #define OnUpdateInt OnUpdateLong
173 STD_PHP_INI_BOOLEAN("apc.enabled", "1", PHP_INI_SYSTEM, OnUpdateBool, enabled, zend_apc_globals, apc_globals)
174 STD_PHP_INI_ENTRY("apc.shm_segments", "1", PHP_INI_SYSTEM, OnUpdateShmSegments, shm_segments, zend_apc_globals, apc_globals)
175 STD_PHP_INI_ENTRY("apc.shm_size", "30", PHP_INI_SYSTEM, OnUpdateInt, shm_size, zend_apc_globals, apc_globals)
176 STD_PHP_INI_BOOLEAN("apc.include_once_override", "0", PHP_INI_SYSTEM, OnUpdateBool, include_once, zend_apc_globals, apc_globals)
177 STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", PHP_INI_SYSTEM, OnUpdateInt, num_files_hint, zend_apc_globals, apc_globals)
178 STD_PHP_INI_ENTRY("apc.user_entries_hint", "4096", PHP_INI_SYSTEM, OnUpdateInt, user_entries_hint, zend_apc_globals, apc_globals)
179 STD_PHP_INI_ENTRY("apc.gc_ttl", "3600", PHP_INI_SYSTEM, OnUpdateInt, gc_ttl, zend_apc_globals, apc_globals)
180 STD_PHP_INI_ENTRY("apc.ttl", "0", PHP_INI_SYSTEM, OnUpdateInt, ttl, zend_apc_globals, apc_globals)
181 STD_PHP_INI_ENTRY("apc.user_ttl", "0", PHP_INI_SYSTEM, OnUpdateInt, user_ttl, zend_apc_globals, apc_globals)
183 STD_PHP_INI_ENTRY("apc.mmap_file_mask", NULL, PHP_INI_SYSTEM, OnUpdateString, mmap_file_mask, zend_apc_globals, apc_globals)
185 PHP_INI_ENTRY("apc.filters", NULL, PHP_INI_SYSTEM, OnUpdate_filters)
186 STD_PHP_INI_BOOLEAN("apc.cache_by_default", "1", PHP_INI_ALL, OnUpdateBool, cache_by_default, zend_apc_globals, apc_globals)
187 STD_PHP_INI_ENTRY("apc.slam_defense", "0", PHP_INI_SYSTEM, OnUpdateInt, slam_defense, zend_apc_globals, apc_globals)
188 STD_PHP_INI_ENTRY("apc.file_update_protection", "2", PHP_INI_SYSTEM, OnUpdateInt,file_update_protection, zend_apc_globals, apc_globals)
189 STD_PHP_INI_BOOLEAN("apc.enable_cli", "0", PHP_INI_SYSTEM, OnUpdateBool, enable_cli, zend_apc_globals, apc_globals)
190 STD_PHP_INI_ENTRY("apc.max_file_size", "1M", PHP_INI_SYSTEM, OnUpdateInt, max_file_size, zend_apc_globals, apc_globals)
191 STD_PHP_INI_BOOLEAN("apc.stat", "1", PHP_INI_SYSTEM, OnUpdateBool, fpstat, zend_apc_globals, apc_globals)
192 STD_PHP_INI_BOOLEAN("apc.stat_ctime", "0", PHP_INI_SYSTEM, OnUpdateBool, stat_ctime, zend_apc_globals, apc_globals)
193 STD_PHP_INI_BOOLEAN("apc.write_lock", "1", PHP_INI_SYSTEM, OnUpdateBool, write_lock, zend_apc_globals, apc_globals)
194 STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool, report_autofilter,zend_apc_globals, apc_globals)
195 #ifdef MULTIPART_EVENT_FORMDATA
196 STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals)
197 STD_PHP_INI_ENTRY("apc.rfc1867_prefix", "upload_", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_prefix, zend_apc_globals, apc_globals)
198 STD_PHP_INI_ENTRY("apc.rfc1867_name", "APC_UPLOAD_PROGRESS", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_name, zend_apc_globals, apc_globals)
199 STD_PHP_INI_ENTRY("apc.rfc1867_freq", "0", PHP_INI_SYSTEM, OnUpdateRfc1867Freq, rfc1867_freq, zend_apc_globals, apc_globals)
201 STD_PHP_INI_BOOLEAN("apc.coredump_unmap", "0", PHP_INI_SYSTEM, OnUpdateBool, coredump_unmap, zend_apc_globals, apc_globals)
206 /* {{{ PHP_MINFO_FUNCTION(apc) */
207 static PHP_MINFO_FUNCTION(apc)
209 php_info_print_table_start();
210 php_info_print_table_row(2, "APC Support", APCG(enabled) ? "enabled" : "disabled");
211 php_info_print_table_row(2, "Version", APC_VERSION);
213 php_info_print_table_row(2, "MMAP Support", "Enabled");
214 php_info_print_table_row(2, "MMAP File Mask", APCG(mmap_file_mask));
216 php_info_print_table_row(2, "MMAP Support", "Disabled");
219 php_info_print_table_row(2, "Locking type", "IPC Semaphore");
220 #elif APC_FUTEX_LOCKS
221 php_info_print_table_row(2, "Locking type", "Linux Futex Locks");
222 #elif APC_PTHREADMUTEX_LOCKS
223 php_info_print_table_row(2, "Locking type", "pthread mutex Locks");
225 php_info_print_table_row(2, "Locking type", "spin Locks");
227 php_info_print_table_row(2, "Locking type", "File Locks");
229 php_info_print_table_row(2, "Revision", "$Revision: 3.154.2.5 $");
230 php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
231 php_info_print_table_end();
232 DISPLAY_INI_ENTRIES();
236 #ifdef MULTIPART_EVENT_FORMDATA
237 extern int apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC);
240 /* {{{ PHP_MINIT_FUNCTION(apc) */
241 static PHP_MINIT_FUNCTION(apc)
243 ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals);
245 REGISTER_INI_ENTRIES();
247 /* Disable APC in cli mode unless overridden by apc.enable_cli */
248 if(!APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) {
253 if(APCG(initialized)) {
254 apc_process_init(module_number TSRMLS_CC);
256 apc_module_init(module_number TSRMLS_CC);
257 apc_zend_init(TSRMLS_C);
258 apc_process_init(module_number TSRMLS_CC);
259 #ifdef MULTIPART_EVENT_FORMDATA
260 /* File upload progress tracking */
262 php_rfc1867_callback = apc_rfc1867_progress;
272 /* {{{ PHP_MSHUTDOWN_FUNCTION(apc) */
273 static PHP_MSHUTDOWN_FUNCTION(apc)
276 apc_process_shutdown(TSRMLS_C);
277 apc_zend_shutdown(TSRMLS_C);
278 apc_module_shutdown(TSRMLS_C);
280 php_apc_shutdown_globals(&apc_globals);
283 apc_shutdown_signals();
287 ts_free_id(apc_globals_id);
289 UNREGISTER_INI_ENTRIES();
294 /* {{{ PHP_RINIT_FUNCTION(apc) */
295 static PHP_RINIT_FUNCTION(apc)
298 apc_request_init(TSRMLS_C);
301 apc_set_signals(TSRMLS_C);
308 /* {{{ PHP_RSHUTDOWN_FUNCTION(apc) */
309 static PHP_RSHUTDOWN_FUNCTION(apc)
312 apc_request_shutdown(TSRMLS_C);
318 /* {{{ proto array apc_cache_info([string type] [, bool limited]) */
319 PHP_FUNCTION(apc_cache_info)
321 apc_cache_info_t* info;
328 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &cache_type, &ct_len, &limited) == FAILURE) {
332 if(ZEND_NUM_ARGS()) {
333 if(!strcasecmp(cache_type,"user")) {
334 info = apc_cache_info(apc_user_cache, limited);
335 } else if(!strcasecmp(cache_type,"filehits")) {
337 RETVAL_ZVAL(APCG(filehits), 1, 0);
343 info = apc_cache_info(apc_cache, limited);
345 } else info = apc_cache_info(apc_cache, limited);
348 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC info available. Perhaps APC is not enabled? Check apc.enabled in your ini file");
352 array_init(return_value);
353 add_assoc_long(return_value, "num_slots", info->num_slots);
354 add_assoc_long(return_value, "ttl", info->ttl);
355 add_assoc_long(return_value, "num_hits", info->num_hits);
356 add_assoc_long(return_value, "num_misses", info->num_misses);
357 add_assoc_long(return_value, "start_time", info->start_time);
358 add_assoc_long(return_value, "expunges", info->expunges);
359 add_assoc_long(return_value, "mem_size", info->mem_size);
360 add_assoc_long(return_value, "num_entries", info->num_entries);
361 add_assoc_long(return_value, "num_inserts", info->num_inserts);
362 #ifdef MULTIPART_EVENT_FORMDATA
363 add_assoc_long(return_value, "file_upload_progress", 1);
365 add_assoc_long(return_value, "file_upload_progress", 0);
368 add_assoc_stringl(return_value, "memory_type", "mmap", sizeof("mmap")-1, 1);
370 add_assoc_stringl(return_value, "memory_type", "IPC shared", sizeof("IPC shared")-1, 1);
373 add_assoc_stringl(return_value, "locking_type", "IPC semaphore", sizeof("IPC semaphore")-1, 1);
374 #elif APC_FUTEX_LOCKS
375 add_assoc_stringl(return_value, "locking_type", "Linux Futex", sizeof("Linux Futex")-1, 1);
376 #elif APC_PTHREADMUTEX_LOCKS
377 add_assoc_stringl(return_value, "locking_type", "pthread mutex", sizeof("pthread mutex")-1, 1);
379 add_assoc_stringl(return_value, "locking_type", "spin", sizeof("spin")-1, 1);
381 add_assoc_stringl(return_value, "locking_type", "file", sizeof("file")-1, 1);
384 apc_cache_free_info(info);
388 ALLOC_INIT_ZVAL(list);
391 for (p = info->list; p != NULL; p = p->next) {
394 ALLOC_INIT_ZVAL(link);
397 if(p->type == APC_CACHE_ENTRY_FILE) {
398 add_assoc_string(link, "filename", p->data.file.filename, 1);
399 add_assoc_long(link, "device", p->data.file.device);
400 add_assoc_long(link, "inode", p->data.file.inode);
401 add_assoc_string(link, "type", "file", 1);
402 } else if(p->type == APC_CACHE_ENTRY_USER) {
403 add_assoc_string(link, "info", p->data.user.info, 1);
404 add_assoc_long(link, "ttl", (long)p->data.user.ttl);
405 add_assoc_string(link, "type", "user", 1);
407 add_assoc_long(link, "num_hits", p->num_hits);
408 add_assoc_long(link, "mtime", p->mtime);
409 add_assoc_long(link, "creation_time", p->creation_time);
410 add_assoc_long(link, "deletion_time", p->deletion_time);
411 add_assoc_long(link, "access_time", p->access_time);
412 add_assoc_long(link, "ref_count", p->ref_count);
413 add_assoc_long(link, "mem_size", p->mem_size);
414 add_next_index_zval(list, link);
416 add_assoc_zval(return_value, "cache_list", list);
418 ALLOC_INIT_ZVAL(list);
421 for (p = info->deleted_list; p != NULL; p = p->next) {
424 ALLOC_INIT_ZVAL(link);
427 if(p->type == APC_CACHE_ENTRY_FILE) {
428 add_assoc_string(link, "filename", p->data.file.filename, 1);
429 add_assoc_long(link, "device", p->data.file.device);
430 add_assoc_long(link, "inode", p->data.file.inode);
431 add_assoc_string(link, "type", "file", 1);
432 } else if(p->type == APC_CACHE_ENTRY_USER) {
433 add_assoc_string(link, "info", p->data.user.info, 1);
434 add_assoc_long(link, "ttl", (long)p->data.user.ttl);
435 add_assoc_string(link, "type", "user", 1);
437 add_assoc_long(link, "num_hits", p->num_hits);
438 add_assoc_long(link, "mtime", p->mtime);
439 add_assoc_long(link, "creation_time", p->creation_time);
440 add_assoc_long(link, "deletion_time", p->deletion_time);
441 add_assoc_long(link, "access_time", p->access_time);
442 add_assoc_long(link, "ref_count", p->ref_count);
443 add_assoc_long(link, "mem_size", p->mem_size);
444 add_next_index_zval(list, link);
446 add_assoc_zval(return_value, "deleted_list", list);
448 apc_cache_free_info(info);
452 /* {{{ proto void apc_clear_cache([string cache]) */
453 PHP_FUNCTION(apc_clear_cache)
458 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache_type, &ct_len) == FAILURE) {
462 if(ZEND_NUM_ARGS()) {
463 if(!strcasecmp(cache_type,"user")) {
464 apc_cache_clear(apc_user_cache);
468 apc_cache_clear(apc_cache);
472 /* {{{ proto array apc_sma_info([bool limited]) */
473 PHP_FUNCTION(apc_sma_info)
475 apc_sma_info_t* info;
478 zend_bool limited = 0;
480 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &limited) == FAILURE) {
484 info = apc_sma_info(limited);
487 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC SMA info available. Perhaps APC is disabled via apc.enabled?");
491 array_init(return_value);
492 add_assoc_long(return_value, "num_seg", info->num_seg);
493 add_assoc_long(return_value, "seg_size", info->seg_size);
494 add_assoc_long(return_value, "avail_mem", apc_sma_get_avail_mem());
497 apc_sma_free_info(info);
501 #if ALLOC_DISTRIBUTION
503 size_t *adist = apc_sma_get_alloc_distribution();
505 ALLOC_INIT_ZVAL(list);
507 for(i=0; i<30; i++) {
508 add_next_index_long(list, adist[i]);
510 add_assoc_zval(return_value, "adist", list);
513 ALLOC_INIT_ZVAL(block_lists);
514 array_init(block_lists);
516 for (i = 0; i < info->num_seg; i++) {
520 ALLOC_INIT_ZVAL(list);
523 for (p = info->list[i]; p != NULL; p = p->next) {
526 ALLOC_INIT_ZVAL(link);
529 add_assoc_long(link, "size", p->size);
530 add_assoc_long(link, "offset", p->offset);
531 add_next_index_zval(list, link);
533 add_next_index_zval(block_lists, list);
535 add_assoc_zval(return_value, "block_lists", block_lists);
536 apc_sma_free_info(info);
541 int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC) {
542 apc_cache_entry_t *entry;
547 #if PHP_API_VERSION < 20041225
548 #if HAVE_APACHE && defined(APC_PHP4_STAT)
549 t = ((request_rec *)SG(server_context))->request_time;
554 t = sapi_get_request_time(TSRMLS_C);
557 if(!APCG(enabled)) return 0;
559 HANDLE_BLOCK_INTERRUPTIONS();
561 APCG(mem_size_ptr) = &mem_size;
562 if (!(entry = apc_cache_make_user_entry(strkey, strkey_len + 1, val, ttl))) {
563 APCG(mem_size_ptr) = NULL;
564 apc_cache_expunge(apc_cache,t);
565 apc_cache_expunge(apc_user_cache,t);
566 HANDLE_UNBLOCK_INTERRUPTIONS();
570 if (!apc_cache_make_user_key(&key, strkey, strkey_len + 1, t)) {
571 APCG(mem_size_ptr) = NULL;
572 apc_cache_free_entry(entry);
573 /* make_user_key doesn't allocate anything, so no expunge */
574 HANDLE_UNBLOCK_INTERRUPTIONS();
578 if (!apc_cache_user_insert(apc_user_cache, key, entry, t, exclusive TSRMLS_CC)) {
579 apc_cache_free_entry(entry);
580 APCG(mem_size_ptr) = NULL;
582 No expunge here - user_insert can fail for non-memory related reasons
583 The alloc-based expunge hook in 3.1 will do a better job here
584 (removing the expunge here also fixes bug #13336)
586 HANDLE_UNBLOCK_INTERRUPTIONS();
590 APCG(mem_size_ptr) = NULL;
592 HANDLE_UNBLOCK_INTERRUPTIONS();
598 /* {{{ proto int apc_store(string key, mixed var [, long 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, mixed var [, long 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);
639 /* {{{ RETURN_ZVAL for php4 */
640 #if !defined(ZEND_ENGINE_2) && !defined(RETURN_ZVAL)
641 #define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; }
642 #define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor)
643 #define ZVAL_ZVAL(z, zv, copy, dtor) { \
644 int is_ref, refcount; \
645 is_ref = (z)->is_ref; \
646 refcount = (z)->refcount; \
655 zval_ptr_dtor(&zv); \
657 (z)->is_ref = is_ref; \
658 (z)->refcount = refcount; \
663 /* {{{ proto mixed apc_fetch(mixed key[, bool &success])
665 PHP_FUNCTION(apc_fetch) {
667 zval *success = NULL;
675 apc_cache_entry_t* entry;
678 if(!APCG(enabled)) RETURN_FALSE;
680 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &key, &success) == 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);
695 ZVAL_BOOL(success, 0);
698 if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
699 convert_to_string(key);
702 if(Z_TYPE_P(key) == IS_STRING) {
703 strkey = Z_STRVAL_P(key);
704 strkey_len = Z_STRLEN_P(key);
705 if(!strkey_len) RETURN_FALSE;
706 entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
708 /* deep-copy returned shm zval to emalloc'ed return_value */
709 apc_cache_fetch_zval(return_value, entry->data.user.val, apc_php_malloc, apc_php_free);
710 apc_cache_release(apc_user_cache, entry);
714 } else if(Z_TYPE_P(key) == IS_ARRAY) {
715 hash = Z_ARRVAL_P(key);
716 MAKE_STD_ZVAL(result);
718 zend_hash_internal_pointer_reset_ex(hash, &hpos);
719 while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
720 if(Z_TYPE_PP(hentry) != IS_STRING) {
721 apc_wprint("apc_fetch() expects a string or array of strings.");
724 entry = apc_cache_user_find(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t);
726 /* deep-copy returned shm zval to emalloc'ed return_value */
727 MAKE_STD_ZVAL(result_entry);
728 apc_cache_fetch_zval(result_entry, entry->data.user.val, apc_php_malloc, apc_php_free);
729 apc_cache_release(apc_user_cache, entry);
730 zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL);
731 } /* don't set values we didn't find */
732 zend_hash_move_forward_ex(hash, &hpos);
734 RETVAL_ZVAL(result, 0, 1);
736 apc_wprint("apc_fetch() expects a string or array of strings.");
741 ZVAL_BOOL(success, 1);
748 /* {{{ proto mixed apc_delete(string key)
750 PHP_FUNCTION(apc_delete) {
754 if(!APCG(enabled)) RETURN_FALSE;
756 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &strkey, &strkey_len) == FAILURE) {
760 if(!strkey_len) RETURN_FALSE;
762 if(apc_cache_user_delete(apc_user_cache, strkey, strkey_len + 1)) {
770 static void _apc_define_constants(zval *constants, zend_bool case_sensitive TSRMLS_DC) {
772 unsigned int const_key_len;
776 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(constants), &pos);
777 while (zend_hash_get_current_data_ex(Z_ARRVAL_P(constants), (void**)&entry, &pos) == SUCCESS) {
782 key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(constants), &const_key, &const_key_len, &num_key, 0, &pos);
783 if(key_type != HASH_KEY_IS_STRING) {
784 zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
787 switch(Z_TYPE_PP(entry)) {
796 zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
800 zval_copy_ctor(&c.value);
801 c.flags = case_sensitive;
802 c.name = zend_strndup(const_key, const_key_len);
803 c.name_len = const_key_len;
805 c.module_number = PHP_USER_CONSTANT;
807 zend_register_constant(&c TSRMLS_CC);
809 zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
813 /* {{{ proto mixed apc_define_constants(string key, array constants [,bool case-sensitive])
815 PHP_FUNCTION(apc_define_constants) {
818 zval *constants = NULL;
819 zend_bool case_sensitive = 1;
820 int argc = ZEND_NUM_ARGS();
822 if (zend_parse_parameters(argc TSRMLS_CC, "sa|b", &strkey, &strkey_len, &constants, &case_sensitive) == FAILURE) {
826 if(!strkey_len) RETURN_FALSE;
828 _apc_define_constants(constants, case_sensitive TSRMLS_CC);
829 if(_apc_store(strkey, strkey_len, constants, 0, 0 TSRMLS_CC)) RETURN_TRUE;
833 /* {{{ proto mixed apc_load_constants(string key [, bool case-sensitive])
835 PHP_FUNCTION(apc_load_constants) {
838 apc_cache_entry_t* entry;
840 zend_bool case_sensitive = 1;
842 if(!APCG(enabled)) RETURN_FALSE;
843 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &strkey, &strkey_len, &case_sensitive) == FAILURE) {
847 if(!strkey_len) RETURN_FALSE;
849 #if PHP_API_VERSION < 20041225
850 #if HAVE_APACHE && defined(APC_PHP4_STAT)
851 t = ((request_rec *)SG(server_context))->request_time;
856 t = sapi_get_request_time(TSRMLS_C);
859 entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
862 _apc_define_constants(entry->data.user.val, case_sensitive TSRMLS_CC);
863 apc_cache_release(apc_user_cache, entry);
871 /* {{{ proto boolean apc_compile_file(string filename)
873 PHP_FUNCTION(apc_compile_file) {
876 zend_file_handle file_handle;
877 zend_op_array *op_array;
878 long slam_defense = 0;
879 char** filters = NULL;
880 zend_bool cache_by_default = 1;
881 HashTable cg_function_table, cg_class_table, eg_function_table, eg_class_table;
882 HashTable *cg_orig_function_table, *cg_orig_class_table, *eg_orig_function_table, *eg_orig_class_table;
884 if(!APCG(enabled)) RETURN_FALSE;
886 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
890 if(!filename) RETURN_FALSE;
892 /* reset slam defense, filters, and cache_by_default */
893 slam_defense = APCG(slam_defense);
894 APCG(slam_defense) = 0;
896 filters = APCG(filters);
897 APCG(filters) = NULL;
899 cache_by_default = APCG(cache_by_default);
900 APCG(cache_by_default) = 1;
902 /* Replace function/class tables to avoid namespace conflicts */
903 zend_hash_init_ex(&cg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
904 cg_orig_function_table = CG(function_table);
905 CG(function_table) = &cg_function_table;
906 zend_hash_init_ex(&cg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
907 cg_orig_class_table = CG(class_table);
908 CG(class_table) = &cg_class_table;
909 eg_orig_function_table = EG(function_table);
910 EG(function_table) = CG(function_table);
911 eg_orig_class_table = EG(class_table);
912 EG(class_table) = CG(class_table);
913 APCG(force_file_update) = 1;
915 /* Compile the file, loading it into the cache */
916 file_handle.type = ZEND_HANDLE_FILENAME;
917 file_handle.filename = filename;
918 file_handle.free_filename = 0;
919 file_handle.opened_path = NULL;
921 op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
923 apc_wprint("Error compiling %s in apc_compile_file.", filename);
927 /* Return class/function tables to previous states, destroy temp tables */
928 APCG(force_file_update) = 0;
929 CG(function_table) = cg_orig_function_table;
930 zend_hash_destroy(&cg_function_table);
931 CG(class_table) = cg_orig_class_table;
932 zend_hash_destroy(&cg_class_table);
933 EG(function_table) = eg_orig_function_table;
934 EG(class_table) = eg_orig_class_table;
936 /* Restore global settings */
937 APCG(slam_defense) = slam_defense;
938 APCG(filters) = filters;
939 APCG(cache_by_default) = cache_by_default;
941 if(op_array == NULL) { RETURN_FALSE; }
943 /* Free up everything */
944 zend_destroy_file_handle(&file_handle TSRMLS_CC);
946 destroy_op_array(op_array TSRMLS_CC);
948 destroy_op_array(op_array);
959 ZEND_BEGIN_ARG_INFO(php_apc_fetch_arginfo, 0)
960 ZEND_ARG_INFO(0, "key")
961 ZEND_ARG_INFO(1, "success")
965 #define php_apc_fetch_arginfo NULL
969 /* {{{ apc_functions[] */
970 function_entry apc_functions[] = {
971 PHP_FE(apc_cache_info, NULL)
972 PHP_FE(apc_clear_cache, NULL)
973 PHP_FE(apc_sma_info, NULL)
974 PHP_FE(apc_store, NULL)
975 PHP_FE(apc_fetch, php_apc_fetch_arginfo)
976 PHP_FE(apc_delete, NULL)
977 PHP_FE(apc_define_constants, NULL)
978 PHP_FE(apc_load_constants, NULL)
979 PHP_FE(apc_compile_file, NULL)
980 PHP_FE(apc_add, NULL)
985 /* {{{ module definition structure */
987 zend_module_entry apc_module_entry = {
988 STANDARD_MODULE_HEADER,
997 STANDARD_MODULE_PROPERTIES
1000 #ifdef COMPILE_DL_APC
1001 ZEND_GET_MODULE(apc)
1010 * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
1011 * vim<600: expandtab sw=4 ts=4 sts=4