--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | APC |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006 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 <dcowgill@communityconnect.com> |
+ | Rasmus Lerdorf <rasmus@php.net> |
+ | Arun C. Murthy <arunc@yahoo-inc.com> |
+ | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
+ +----------------------------------------------------------------------+
+
+ 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 2007/11/14 19:46:46 shire 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)
+{
+ int status =
+ zend_hash_add(EG(function_table),
+ fn.name,
+ fn.name_len+1,
+ apc_copy_function_for_execution(fn.function),
+ sizeof(fn.function[0]),
+ NULL);
+
+ 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); /* XXX: kludge */
+
+ 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) && !APCG(localcache))) {
+ 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)) {
+ if(APCG(localcache)) {
+ /* search for the file in the local cache */
+ cache_entry = apc_local_cache_find(APCG(lcache), key, t);
+ } else {
+ /* 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); /* XXX kludge */
+ 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) */
+ }
+
+ if(apc_cache_busy(apc_cache) && APCG(localcache)) {
+ /* possibly local cache returned NULL because cache is busy */
+ return old_compile_file(h, type TSRMLS_CC);
+ }
+
+ /* 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 = *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.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)
+{
+ int minttl = (APCG(gc_ttl) > APCG(ttl) ? APCG(ttl) : APCG(gc_ttl))/2;
+ int size = APCG(localcache_size);
+ if(APCG(initialized) && APCG(localcache)) {
+ /* TTL is 2 mins by default */
+ APCG(lcache) = apc_local_cache_create(apc_cache, size, minttl ? minttl : 120);
+ }
+ return 0;
+}
+
+int apc_process_shutdown(TSRMLS_D)
+{
+ if(APCG(initialized) && APCG(localcache) && APCG(lcache)) {
+ apc_local_cache_destroy(APCG(lcache));
+ APCG(lcache) = NULL;
+ }
+ return 0;
+}
+/* }}} */
+
+/* {{{ 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;
+}
+
+/* }}} */
+
+/* {{{ apc_deactivate */
+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);
+ }
+ if(APCG(localcache)) {
+ apc_local_cache_cleanup(APCG(lcache));
+ }
+}
+/* }}} */
+
+/*
+ * 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
+ */